Mrug Mrug - 2 months ago 29
Objective-C Question

Crashing app at UIImageFromCVMat() in iOS

Here is the Code I have used to Convert

CVMat
to
UIImage
using OpenCV. With this Code everything works fine there is NO Crash in that. But Color gets changed.

-(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
{
cvtColor(cvMat, cvMat, CV_BGR2RGB);

NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
CGColorSpaceRef colorSpace;

if (cvMat.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}

CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(cvMat.cols, //width
cvMat.rows, //height
8, //bits per component
8 * cvMat.elemSize(), //bits per pixel
cvMat.step[0], //bytesPerRow
colorSpace, //colorspace
kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info
provider, //CGDataProviderRef
NULL, //decode
false, //should interpolate
kCGRenderingIntentDefault //intent
);


// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);

return finalImage;
}


As a workaround I commented
cvtColor()
function from code. It is now able to retain original color but Now Issue is App is crashing randomly sometimes. I even tried to use
UIImageFromCvMat()
from
opencv2/imgcodecs/ios.h
but it crashes same way.

So if I want to prevent Crash I have to keep cvtColor() in code but it changes actual colors. Is there any mistake I have done here ?

enter image description here

EDIT

I just found that this is happening when I pass particular cvMat for UIImage Conversion in a method. I am posting my image processing code from where I am making call for Mat-->UIImage

It works fine when I pass grayImage (cvMat), but it crashes when I pass croppedImage (cvMat) for conversion.

-(UIImage*)processImage:(UIImage*)sourceImage{

cv::Mat processMat = [self cvMatFromUIImage:sourceImage];




cv::Mat grayImage;
cvtColor(processMat, grayImage, CV_BGR2GRAY);


/// Generate grad_x and grad_y
cv::Mat grad_x, grad_y;
cv::Mat abs_grad_x, abs_grad_y;

/// Gradient X
//Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
cv::Sobel( grayImage, grad_x, CV_16S, 1, 0, 3, 1 , 0);
convertScaleAbs( grad_x, abs_grad_x );

/// Gradient Y
//Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );
Sobel( grayImage, grad_y, CV_16S, 0, 1, 3, 1, 0);
convertScaleAbs( grad_y, abs_grad_y );

// Total Gradient (approximate)
cv::Mat grad;
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );



std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours( grad, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_TC89_KCOS);

double maxArea = 0;
size_t maxIndex=0;
for ( size_t i=0; i<contours.size(); ++i )
{
double area = cv::contourArea(contours[i]);
if(area>maxArea){
maxIndex = i;
maxArea = area;
}
}

cv::Rect brect = cv::boundingRect(contours[maxIndex]);
cv::Mat croppedImage = processMat(brect);

//It Works when I pass any other cvMat like grayImage
//UIImage *result2 = [self UIImageFromCVMat:grayImage]; // MatToUIImage(grayImage);

//This line causes Crash..
UIImage *result = [self UIImageFromCVMat:croppedImage]; // MatToUIImage(grayImage);




//Tried to Comment this part
croppedImage.release();
grad.release();
grayImage.release();
grad_x.release();
grad_y.release();
processMat.release();

return result;
}


enter image description here

Answer

Convert mat from BGR2RGB and then RGB2BGR again, it will work. The reason behind this crash dont know, but trying this way is working. Add line cvtColor(cvMat, cvMat, CV_RGB2BGR) after cvtColor(cvMat, cvMat, CV_BGR2RGB);.