我想创建一个 NSData-to-cv::Mat-conversion,而不是 UIImage-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)开始,然后转换如下:
- 从原始图像 (self.image) 创建 NSData
- 将此 NSData 转换为 cv::Mat
- 将 cv::Mat 转换回 UIImage
- 再次将 UIImage 转换为 cv::Mat
这个迂回只是为了检查与初始工作代码的相等性......我最终需要的只是转换 2(即 NSData 到 cv::Mat)。不幸的是,第一个代码片段中的“cv_src”与第二个代码片段相比并不相同,为什么?我的假设是“imdecode”在这里无法正常工作 - 非常感谢任何建议!
最佳答案
我尝试使用 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
关于opencv - NSData 到 cv::Mat 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26848133/