NSData到cv :: Mat的转换

时间:2014-11-10 16:17:40

标签: opencv nsdata

而不是UIImage-to-cv :: Mat-conversion,我想创建一个NSData-to-cv :: Mat-conversion:

有效的代码:

// converts original image to cv::Mat
cv::Mat cv_src = [self.image CVMat];

测试代码(暂时不起作用:( ......可能出错?)

// converts original image to NSData
NSData *data = UIImageJPEGRepresentation(self.image, 1.0);

// converts NSData to cv::Mat
cv::Mat cv_src_TESTTEST = cv::imdecode(cv::Mat(1,
                                      (int)[data length],
                                      CV_8UC1,
                                      (void*)data.bytes),
                              cv::IMREAD_COLOR);

// converts cv::Mat to a Test-image
UIImage *TestImage = [[UIImage alloc] UIImageFromCVMat:(cv_src_TESTTEST)];

// convert Test-image to cv::Mat
cv::Mat cv_src = [TestImage CVMat];

这个测试代码实际上是绕道而行,从原始图像(self.image)开始,然后转换如下:

  1. 从原始图像创建NSData(self.image)
  2. 将此NSData转换为cv :: Mat
  3. 将cv :: Mat转换回UIImage
  4. 转换,如果UIImage再次转到cv :: Mat
  5. 这种绕行只是为了检查初始工作代码是否相等......我最终需要的只是转换2(即NSData到cv :: Mat)。不幸的是,从第一个代码剪切的“cv_src”与第二个相比,遗憾的是不一样,为什么?我的假设是“imdecode”在这里没有正确工作 - 非常感谢任何建议!

2 个答案:

答案 0 :(得分:2)

我试过NSData-Category(参见下面的代码......)。不确定一切是否正确。请给我一些评论? (...尤其是最后一个方法“ - (NSData *)NSDataFromCVMat:(cv :: Mat)cvMat”(任何建议,如果通过图像评论绕道更好或没有?谢谢!

的NSData + OpenCV.h

#import <Foundation/Foundation.h>

@interface NSData (NSData_OpenCV)

- (NSData *)NSDataFromCVMat:(cv::Mat)cvMat;

@property(nonatomic, readonly) cv::Mat CVMat;
@property(nonatomic, readonly) cv::Mat CVGrayscaleMat;

@end

的NSData + OpenCV.mm

#import "NSData+OpenCV.h"

@implementation NSData (NSData_OpenCV)

// cv::Mat from NSMutableData
- (cv::Mat)CVMat {

UIImage *image = [UIImage imageWithData:self];

CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;

cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels

CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to backing data
                                                cols,                       // Width of bitmap
                                                rows,                       // Height of bitmap
                                                8,                          // Bits per component
                                                cvMat.step[0],              // Bytes per row
                                                colorSpace,                 // Colorspace
                                                kCGImageAlphaNoneSkipLast |
                                                kCGBitmapByteOrderDefault); // Bitmap info flags

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);

return cvMat;
}

- (cv::Mat)CVGrayscaleMat {

UIImage *image = [UIImage imageWithData:self];

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;

cv::Mat cvMat = cv::Mat(rows, cols, CV_8UC1); // 8 bits per component, 1 channel

CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to backing data
                                                cols,                       // Width of bitmap
                                                rows,                       // Height of bitmap
                                                8,                          // Bits per component
                                                cvMat.step[0],              // Bytes per row
                                                colorSpace,                 // Colorspace
                                                kCGImageAlphaNone |
                                                kCGBitmapByteOrderDefault); // Bitmap info flags

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);

return cvMat;
}

// NSData from cv::Mat
- (NSData *)NSDataFromCVMat:(cv::Mat)cvMat {

return [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];

/*
    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 UIImageJPEGRepresentation(finalImage, 1.0);
 */

}

@end

答案 1 :(得分:0)

cv::Mat 可以通过以下方式转换为 NSData:

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

并且要转换回使用以下初始值设定项,您必须提供图像的宽度(列)、高度(行)和类型

cv::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP)

cv::Mat cvMat = cv::Mat(1280, 720, CV_8UC4, (uchar*)data.bytes);