32

iPhoneカメラからキャプチャした写真であるUIImageを持っているので、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 の初心者なので、何が問題なのかわかりません。

誰かがコードの何が問題なのか教えてもらえますか、それとも何かを見逃していますか?

4

3 に答える 3

45

これは、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];
于 2013-01-15T10:52:55.050 に答える