web-dev-qa-db-ja.com

OpenCVを使用して画像を90度回転させる最も簡単な方法は?

IplImage/cv :: Matを90度回転させる最良の方法(c/c ++)は何ですか?マトリックスを使用して変換するよりも優れたものがあるに違いないと思いますが、APIとオンラインでそれ以外のものを見つけることはできません。

45
Ben H

OpenCV3.2の時点では、生活が少し楽になりました。1行のコードで画像を回転できるようになりました。

cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);

方向については、次のいずれかを選択できます。

ROTATE_90_CLOCKWISE
ROTATE_180
ROTATE_90_COUNTERCLOCKWISE
41
Morris Franken

回転は、トランスポーズとフリップの合成です。

R_{+90} = F_x \circ T

R_{-90} = F_y \circ T

OpenCVでは、次のように記述できます(以下のPythonの例):

img = cv.LoadImage("path_to_image.jpg")
timg = cv.CreateImage((img.height,img.width), img.depth, img.channels) # transposed image

# rotate counter-clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=0)
cv.SaveImage("rotated_counter_clockwise.jpg", timg)

# rotate clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=1)
cv.SaveImage("rotated_clockwise.jpg", timg)
60
sastanin

転置の更新:

(正しく指摘したように)cvTranspose()またはcv::transpose()を使用する方が効率的です。繰り返しますが、ほとんどのcvXXX関数は_IplImage*_構造体をMatオブジェクト(ディープコピーなし)に変換するだけなので、OpenCV2.0にアップグレードすることをお勧めします。画像をMatオブジェクトに保存した場合、Mat.t()は転置を返します。

任意の回転:

変換行列の一般的なフレームワークで回転行列を定義することにより、cvWarpAffineを使用する必要があります。 OpenCV2. にアップグレードすることを強くお勧めします。これには、いくつかの機能と、マトリックスと画像をカプセル化するMatクラスがあります。 2.0では、上記に warpAffine を使用できます。

10
Jacob

これは、新しいC++インターフェイスがない場合の例です(param = 1、2、3を使用して90、180、270度で動作します)。返された画像を使用した後、cvReleaseImageを忘れずに呼び出してください。

IplImage *rotate_image(IplImage *image, int _90_degrees_steps_anti_clockwise)
{
    IplImage *rotated;

    if(_90_degrees_steps_anti_clockwise != 2)
        rotated = cvCreateImage(cvSize(image->height, image->width), image->depth, image->nChannels);
    else
        rotated = cvCloneImage(image);

    if(_90_degrees_steps_anti_clockwise != 2)
        cvTranspose(image, rotated);

    if(_90_degrees_steps_anti_clockwise == 3)
        cvFlip(rotated, NULL, 1);
    else if(_90_degrees_steps_anti_clockwise == 1)
        cvFlip(rotated, NULL, 0);
    else if(_90_degrees_steps_anti_clockwise == 2)
        cvFlip(rotated, NULL, -1);

    return rotated;
}
4
Andres Hurtis

ここに私のpython cv2実装:

import cv2

img=cv2.imread("path_to_image.jpg")

# rotate ccw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=0)

# rotate cw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=1)

cv2.imwrite("rotated.jpg", out)
4
Eran W

EmguCV(OpenCVのC#ポート)ソリューションは次のとおりです。

public static Image<TColor, TDepth> Rotate90<TColor, TDepth>(this Image<TColor, TDepth> img)
    where TColor : struct, IColor
    where TDepth : new()
{
    var rot = new Image<TColor, TDepth>(img.Height, img.Width);
    CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
    rot._Flip(FLIP.HORIZONTAL);
    return rot;
}

public static Image<TColor, TDepth> Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
    where TColor : struct, IColor
    where TDepth : new()
{
    var rot = img.CopyBlank();
    rot = img.Flip(FLIP.VERTICAL);
    rot._Flip(FLIP.HORIZONTAL);
    return rot;
}

public static void _Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
    where TColor : struct, IColor
    where TDepth : new()
{
    img._Flip(FLIP.VERTICAL);
    img._Flip(FLIP.HORIZONTAL);
}

public static Image<TColor, TDepth> Rotate270<TColor, TDepth>(this Image<TColor, TDepth> img)
    where TColor : struct, IColor
    where TDepth : new()
{
    var rot = new Image<TColor, TDepth>(img.Height, img.Width);
    CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
    rot._Flip(FLIP.VERTICAL);
    return rot;
}

それをC++に変換し直すのは難しくないはずです。

2
mpen

さて、私はいくつかの詳細を探していましたが、例は見つかりませんでした。だから、データを失うことなく90°回転させる直接的な方法を探している人を助けるtransposeImage関数を投稿しています:

IplImage* transposeImage(IplImage* image) {

    IplImage *rotated = cvCreateImage(cvSize(image->height,image->width),   
        IPL_DEPTH_8U,image->nChannels);
    CvPoint2D32f center;
    float center_val = (float)((image->width)-1) / 2;
    center.x = center_val;
    center.y = center_val;
    CvMat *mapMatrix = cvCreateMat( 2, 3, CV_32FC1 );        
    cv2DRotationMatrix(center, 90, 1.0, mapMatrix);
    cvWarpAffine(image, rotated, mapMatrix, 
        CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, 
        cvScalarAll(0));      
    cvReleaseMat(&mapMatrix);

    return rotated;
}

質問:これはなぜですか?

float center_val = (float)((image->width)-1) / 2; 

答え:それが動作するため:)私が見つけた唯一の中心は画像を翻訳しません。誰かが説明をしていたら興味がありますが。

1
Artem