C++ 将UIImage转换为cv::Mat,然后再转换回UIImage会降低图像质量
我正在使用OpenCV for iOS,并使用以下两个函数将UIImage转换为cv::Mat,反之亦然 UIImage到cv::Mat:C++ 将UIImage转换为cv::Mat,然后再转换回UIImage会降低图像质量,c++,ios,objective-c,opencv,uiimage,C++,Ios,Objective C,Opencv,Uiimage,我正在使用OpenCV for iOS,并使用以下两个函数将UIImage转换为cv::Mat,反之亦然 UIImage到cv::Mat: + (cv::Mat)toCVMat:(UIImage*)image { // (1) Get image dimensions CGFloat cols = image.size.width; CGFloat rows = image.size.height; // (2) Create OpenCV image cont
+ (cv::Mat)toCVMat:(UIImage*)image
{
// (1) Get image dimensions
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
// (2) Create OpenCV image container, 8 bits per component, 4 channels
cv::Mat cvMat(rows, cols, CV_8UC4);
// (3) Create CG context and draw the image
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,
cols,
rows,
8,
cvMat.step[0],
CGImageGetColorSpace(image.CGImage),
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault);
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
// (4) Return OpenCV image container reference
return cvMat;
}
cv::Mat到UIImage:
+ (UIImage*)fromCVMat:(const cv::Mat&)cvMat
{
// (1) Construct the correct color space
CGColorSpaceRef colorSpace;
if ( cvMat.channels() == 1 ) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
// (2) Create image data reference
CFDataRef data = CFDataCreate(kCFAllocatorDefault, cvMat.data, (cvMat.elemSize() * cvMat.total()));
// (3) Create CGImage from cv::Mat container
CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
CGImageRef imageRef = CGImageCreate(cvMat.cols,
cvMat.rows,
8,
8 * cvMat.elemSize(),
cvMat.step[0],
colorSpace,
kCGImageAlphaNone | kCGBitmapByteOrderDefault,
provider,
NULL,
false,
kCGRenderingIntentDefault);
// (4) Create UIImage from CGImage
UIImage * finalImage = [UIImage imageWithCGImage:imageRef];
// (5) Release the references
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CFRelease(data);
CGColorSpaceRelease(colorSpace);
// UIImage * imgNew = [self cloneWithAlpha:finalImage :.3];
// (6) Return the UIImage instance
return finalImage;
}
然后将UIImage转换为cv::Mat,然后使用以下代码将其转换回UIImage
cv::Mat currentCVFrame=[img toCVMat];
UIImage* testImage = [UIImage fromCVMat:currentCVFrame];
如果我在转换UIImage之前保存它,然后在将其转换回UIImage后再次保存它,我会注意到文件大小的差异(第二个文件的大小大约减少20%)。我知道在进行转换时会有一些质量损失。任何人都可以确认这一点,并告诉我转换函数是否有问题?尝试使用以下代码
+ (UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
{
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
kCGImageAlphaNoneSkipLast|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;
}
+ (cv::Mat)cvMatFromUIImage:(UIImage *)image
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols,rows;
if (image.imageOrientation == UIImageOrientationLeft
|| image.imageOrientation == UIImageOrientationRight) {
cols = image.size.height;
rows = image.size.width;
}
else{
cols = image.size.width;
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);
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
cv::Mat cvMatTest;
cv::transpose(cvMat, cvMatTest);
if (image.imageOrientation == UIImageOrientationLeft
|| image.imageOrientation == UIImageOrientationRight) {
}
else{
return cvMat;
}
cvMat.release();
cv::flip(cvMatTest, cvMatTest, 1);
return cvMatTest;
}
它非常适合我…谢谢,刚刚测试过,它提供了与我的旧代码相同的结果:如果我在转换之前保存UIImage,它的大小是1.4MB,如果我将其转换为cv::Mat并将其转换回UIImage,然后保存,它的大小是1.2MB