2010-02-14 387 views
34

將IplImage/cv :: Mat旋轉90度的最佳方式是什麼(在c/C++中)?我認爲必須有比使用矩陣轉換它更好的東西,但我似乎無法在API和在線中找到其他任何東西。使用OpenCV將圖像旋轉90度的最簡單方法?

+0

C++的答案是[這裏](http://stackoverflow.com/a/16278334/2436175)。 – Antonio 2016-02-17 10:00:57

回答

14

由於OpenCV3的。2,生活剛剛得到一個更容易一點,你現在可以在一個單一的代碼行旋轉圖像:

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

爲方向,您可以選擇以下任何一種:

ROTATE_90_CLOCKWISE 
ROTATE_180 
ROTATE_90_COUNTERCLOCKWISE 
10

更新置換:

您應該使用cvTranspose()cv::transpose()因爲(你正確地指出),它的效率更高。同樣,我建議升級到OpenCV2.0,因爲大部分cvXXX函數只是將IplImage*結構轉換爲Mat對象(無深度副本)。如果將圖像存儲在Mat對象中,則Mat.t()將返回轉置。

任何旋轉:

應該通過變換矩陣的總體框架確定旋轉矩陣使用cvWarpAffine。我強烈建議升級到OpenCV2.0,它有幾個功能,以及一個封裝矩陣和圖像的Mat類。使用2.0時,您可以使用warpAffine以上。

+0

謝謝!你確定這不僅僅是簡單地移調像素陣列嗎?問題是,我不確定OpenCV是否內部將圖像表示爲像素數組,即像32位int *那樣的圖像,如果是這樣,則如何獲取指向該數組的指針。 – 2010-02-15 16:20:02

+0

對不起,我沒有正確地閱讀你的問題,我已經更新了我的答案。 – Jacob 2010-02-15 18:30:57

+22

轉置後必須翻轉(cvFlip)以正確旋轉圖像 – Amnon 2010-12-30 14:22:37

1

嗯,我正在尋找一些細節,並沒有找到任何示例。所以我張貼transposeImage函數,我希望可以幫助其他人誰正在尋找一種直接的方式旋轉90°,而不會丟失數據:

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

您的數學原因可能是由於整數除法。你想要做的是:float center_val =(float)image-> width/2.0f。 – 2010-07-02 22:22:24

+0

請注意,如果您只需要以90度增量旋轉,則cvTranspose + cvFlip方法稍微快一點。 – 2012-08-13 21:32:09

55

旋轉是轉置和翻轉的組合。

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) 
+0

請參閱下面的「cv2」:http://stackoverflow.com/questions/2259678/easiest-way-to-rotate-by-90-degrees-an-image-using-opencv/42359233#42359233 – 2017-02-21 05:19:12

+0

垂直翻轉(flipMode = 0)應該比水平翻轉要貴一些,因爲你更好地使用緩存。因此,首先進行水平翻轉,然後進行轉置,逆時針旋轉應該稍微快一些。 – 2017-04-04 17:20:40

4

這是一個沒有新的C++接口的例子(適用於90,180和270度,使用param = 1,2和3)。請記住在使用後返回的圖像上調用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; 
} 
2

這裏是我的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

這裏是我的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) 
+0

您的ccw代碼進行cw轉換。 – Jason 2017-06-08 02:51:42

+0

已更正。謝謝@Jason! – 2017-06-08 20:49:32