我有一个 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.width
和 size.height
值, (ii) 当从 cv::Mat
翻译回来时,你将丢失方向标志。
从 UIImage
到 cv::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];
关于ios - 将 UIImage 转换为 cv::Mat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14332687/