将UIImage转换为cv :: Mat

我有一个UIImage这是从iPhone相机捕获的图片,现在我想UIImage被转换为cv :: Mat(OpenCV)。 我正在使用以下代码行来完成此操作:

-(cv::Mat)CVMat { CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage); CGFloat cols = self.size.width; CGFloat rows = self.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), self.CGImage); CGContextRelease(contextRef); return cvMat; } 

此代码适用于横向模式下的UIImage,但是当我使用与从肖像模式拍摄的图像相同的代码时,图像向右旋转90度。

我是iOS和Objective C的新手,因此我无法弄清楚什么是错的。

有人可以告诉我代码有什么问题,或者我错过了一些东西。

这将是因为UIImage实际上不是肖像。 使用iPhone相机拍摄的所有照片都是在原始位图状态下的横向,例如3264宽x 2488高。 通过在图像中设置的方向EXIF标志来显示“肖像”照片,例如由根据该标志和照相机的观看方向来旋转图像的照片库应用所兑现。

该标志还影响UIImage报告其宽度和高度属性,将它们从位图值转换为标记为肖像的图像。

cv::Mat不会打扰任何的。 这意味着(i)当翻译成cv::Mat一幅肖像图像的size.widthsize.heightsize.widthsize.height值将被调换,(ii)当从cv::Mat翻译时,你将失去方向标志。

当从UIImagecv::Mat时,处理这个最简单的方法是,如果图像被标记为肖像,则交换宽度和高度值:

 if (self.imageOrientation == UIImageOrientationLeft || self.imageOrientation == UIImageOrientationRight) { cols = self.size.height; rows = self.size.width; } 

当从cv::Mat翻译回UIImage ,您将需要恢复方向标志。 假设你的cv::Mat -> UIImage代码包含这个:

 self = [self initWithCGImage:imageRef]; 

您可以使用此方法,并根据原始重置方向。

 self = [self initWithCGImage:imageRef scale:1 orientation:orientation]; 

您应该考虑使用本机OpenCV函数来转换和返回:

 #import <opencv2/imgcodecs/ios.h> ... UIImage* MatToUIImage(const cv::Mat& image); void UIImageToMat(const UIImage* image, cv::Mat& m, bool alphaExist = false); 

注意:如果你的UIImage来自相机,那么在转换为cv::Mat之前,你应该“正常化”它(上传后的iOS UIImagePickerController结果图像方向),因为OpenCV没有考虑到Exif数据。 如果你不这样做,结果应该是错误的。