1 OpenCV iOS - Image Processing {#tutorial_image_manipulation} 2 ============================= 3 4 Goal 5 ---- 6 7 In this tutorial we will learn how to do basic image processing using OpenCV in iOS. 8 9 Introduction 10 ------------ 11 12 In *OpenCV* all the image processing operations are usually carried out on the *Mat* structure. In 13 iOS however, to render an image on screen it have to be an instance of the *UIImage* class. To 14 convert an *OpenCV Mat* to an *UIImage* we use the *Core Graphics* framework available in iOS. Below 15 is the code needed to covert back and forth between Mat's and UIImage's. 16 @code{.m} 17 - (cv::Mat)cvMatFromUIImage:(UIImage *)image 18 { 19 CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage); 20 CGFloat cols = image.size.width; 21 CGFloat rows = image.size.height; 22 23 cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels (color channels + alpha) 24 25 CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data 26 cols, // Width of bitmap 27 rows, // Height of bitmap 28 8, // Bits per component 29 cvMat.step[0], // Bytes per row 30 colorSpace, // Colorspace 31 kCGImageAlphaNoneSkipLast | 32 kCGBitmapByteOrderDefault); // Bitmap info flags 33 34 CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage); 35 CGContextRelease(contextRef); 36 37 return cvMat; 38 } 39 @endcode 40 @code{.m} 41 - (cv::Mat)cvMatGrayFromUIImage:(UIImage *)image 42 { 43 CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage); 44 CGFloat cols = image.size.width; 45 CGFloat rows = image.size.height; 46 47 cv::Mat cvMat(rows, cols, CV_8UC1); // 8 bits per component, 1 channels 48 49 CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data 50 cols, // Width of bitmap 51 rows, // Height of bitmap 52 8, // Bits per component 53 cvMat.step[0], // Bytes per row 54 colorSpace, // Colorspace 55 kCGImageAlphaNoneSkipLast | 56 kCGBitmapByteOrderDefault); // Bitmap info flags 57 58 CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage); 59 CGContextRelease(contextRef); 60 61 return cvMat; 62 } 63 @endcode 64 After the processing we need to convert it back to UIImage. The code below can handle both 65 gray-scale and color image conversions (determined by the number of channels in the *if* statement). 66 @code{.m} 67 cv::Mat greyMat; 68 cv::cvtColor(inputMat, greyMat, COLOR_BGR2GRAY); 69 @endcode 70 After the processing we need to convert it back to UIImage. 71 @code{.m} 72 -(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat 73 { 74 NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()]; 75 CGColorSpaceRef colorSpace; 76 77 if (cvMat.elemSize() == 1) { 78 colorSpace = CGColorSpaceCreateDeviceGray(); 79 } else { 80 colorSpace = CGColorSpaceCreateDeviceRGB(); 81 } 82 83 CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); 84 85 // Creating CGImage from cv::Mat 86 CGImageRef imageRef = CGImageCreate(cvMat.cols, //width 87 cvMat.rows, //height 88 8, //bits per component 89 8 * cvMat.elemSize(), //bits per pixel 90 cvMat.step[0], //bytesPerRow 91 colorSpace, //colorspace 92 kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info 93 provider, //CGDataProviderRef 94 NULL, //decode 95 false, //should interpolate 96 kCGRenderingIntentDefault //intent 97 ); 98 99 100 // Getting UIImage from CGImage 101 UIImage *finalImage = [UIImage imageWithCGImage:imageRef]; 102 CGImageRelease(imageRef); 103 CGDataProviderRelease(provider); 104 CGColorSpaceRelease(colorSpace); 105 106 return finalImage; 107 } 108 @endcode 109 110 Output 111 -------- 112 113 ![](images/output.jpg) 114 115 Check out an instance of running code with more Image Effects on 116 [YouTube](http://www.youtube.com/watch?v=Ko3K_xdhJ1I) . 117 118 \htmlonly 119 <div align="center"> 120 <iframe width="560" height="350" src="http://www.youtube.com/embed/Ko3K_xdhJ1I" frameborder="0" allowfullscreen></iframe> 121 </div> 122 \endhtmlonly 123