簡體   English   中英

將 UIImage 轉換為 cv::Mat

[英]Converting UIImage to 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.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];

您應該考慮使用本機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數據。 如果你不這樣做,結果應該是錯誤的。

我試圖將人像UIImage轉換為Mat並返回,但我對這篇文章的兩種方法都有問題。

  • MatToUIImageUIImageToMat本機方法導致旋轉圖像。
  • CGContext的自定義方法最終出現了一個奇怪的顏色錯誤(不僅僅是 RGB / BGR 交換)。 紅色是紅色,藍色是粉紅色,綠色是黃色。

我最終使用了帶有旋轉的原生OpenCV

#import <opencv2/imgcodecs/ios.h>

- (cv::Mat)convertUIImageToCVMat:(UIImage *)image
{
    cv::Mat imageMat;
    UIImageToMat(image, imageMat);
    cv::rotate(imageMat, imageMat, cv::ROTATE_90_CLOCKWISE);
    return imageMat;
}

- (UIImage *)convertCVMatToUIImage:(cv::Mat)cvMat
{
    UIImage *image = MatToUIImage(cvMat);
    return image;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM