Mrug Mrug - 11 months ago 74
Objective-C Question

Crashing app at UIImageFromCVMat() in iOS

Here is the Code I have used to Convert

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 length:cvMat.elemSize()*];
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];


return finalImage;

As a workaround I commented
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
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


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.


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]);
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

return result;

enter image description here

Answer Source

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);.