OpenCV -> UIImage
cv::Mat mat /* = ... */;
UIImage* image = [UIImage fromCvMat:mat];
UIImage -> OpenCV
UIImage* image /* = ... */;
cv::Mat mat = [UIImage toCvMat:image];
Original conversion code from OpenCV iOS tutorial, video processing
OpenCV -> UIImage
cv::Mat mat /* = ... */;
UIImage* image = [UIImage fromCvMat:mat];
UIImage -> OpenCV
UIImage* image /* = ... */;
cv::Mat mat = [UIImage toCvMat:image];
Original conversion code from OpenCV iOS tutorial, video processing
#import <UIKit/UIKit.h> | |
#ifdef __cplusplus | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wdocumentation" | |
#import <opencv2/core/core.hpp> | |
#pragma clang pop | |
#endif | |
@interface UIImage (UIImage_OpenCvConversion) | |
#ifdef __cplusplus | |
+ (cv::Mat)toCvMat:(UIImage *)image; | |
+ (cv::Mat)toCvMatGray:(UIImage *)image; | |
+ (UIImage *)fromCvMat:(cv::Mat)cvMat; | |
#endif | |
@end |
#import "UIImage+OpenCvConversion.h" | |
#ifdef __cplusplus | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wdocumentation" | |
#import <opencv2/core/core.hpp> | |
#import <opencv2/imgproc/imgproc.hpp> | |
#pragma clang pop | |
#endif | |
@implementation UIImage (UIImage_OpenCvConversion) | |
#ifdef __cplusplus | |
+ (cv::Mat)toCvMat:(UIImage *)image | |
{ | |
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 (color channels + alpha) | |
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to 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)toCvMatGray:(UIImage *)image | |
{ | |
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage); | |
CGFloat cols = image.size.width; | |
CGFloat rows = image.size.height; | |
cv::Mat cvMat(rows, cols, CV_8UC1); // 8 bits per component, 1 channels | |
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to 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; | |
} | |
+ (UIImage *)fromCvMat:(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 | |
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; | |
} | |
#endif | |
@end |