2016-09-09 3 views
0

Вот код, который я использовал для преобразования CVMat в UIImage с использованием OpenCV. В этом коде все работает отлично, в этом нет НИКАКОГО сбоя. Но цвет меняется.Ошибка в UIImageFromCVMat() в iOS

-(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; 
} 

В качестве обходного пути я заметил cvtColor() функцию из кода. Теперь он может сохранять оригинальный цвет, но теперь проблема - это случайное сбой случайности. Я даже пытался использовать UIImageFromCvMat() от opencv2/imgcodecs/ios.h, но он срабатывает одинаково.

Так что, если я хочу предотвратить Crash, мне нужно сохранить cvtColor() в коде, но он меняет фактические цвета. Есть ли какая-то ошибка, которую я здесь сделал?

enter image description here

EDIT

Я только что узнал, что это происходит, когда я прохожу особый cvMat для UIImage преобразования в методе. Я отправляю свой код обработки изображений, откуда я звоню на Mat -> UIImage

Он отлично работает при передаче grayImage (cvMat), но он сбой, когда я передаю croppedImage (cvMat) для преобразования.

-(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

+0

Какая ошибка при ее сбое? – Larme

+0

Я просто добавил изображение. – Mrug

ответ

1

Преобразовать мат из BGR2RGB, а затем RGB2BGR снова, он будет работать. Причина этого краха не знает, но попытка такого способа работает. Добавить строку cvtColor(cvMat, cvMat, CV_RGB2BGR) после cvtColor(cvMat, cvMat, CV_BGR2RGB);.

+0

О, ничего себе! Я знаю, что это всего лишь трюк. но это сработало .. Тон благодарности – Mrug