La façon la plus facile de tourner de 90 degrés une image en utilisant OpenCV?

Quelle est la meilleure façon (en C++) de faire tourner un IplImage/cv::Mat de 90 degrés? Je suppose qu'il doit y avoir quelque chose de mieux que de le transformer à l'aide d'une matrice, mais je n'arrive pas à trouver autre chose que cela dans L'API et en ligne.

35
demandé sur Antonio 2010-02-14 03:27:08

7 réponses

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

pour la direction vous pouvez choisir l'une des suivantes:

ROTATE_90_CLOCKWISE
ROTATE_180
ROTATE_90_COUNTERCLOCKWISE
20
répondu Morris Franken 2017-06-23 01:45:41

Rotation est une composition d'une transposition et d'un couvercle.

R_{+90} = F_x \circ T

R_{-90} = F_y \circ T

qui dans OpenCV peut être écrit comme ceci (exemple Python ci-dessous):

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)
55
répondu sastanin 2011-05-06 14:27:12

mise à jour pour la transposition:

Vous devez utiliser cvTranspose() ou cv::transpose() parce que (comme vous l'avez souligné à juste titre) c'est plus efficace. Encore une fois, je recommande la mise à niveau vers OpenCV2.0 depuis la plupart des cvXXX les fonctions convertissent juste IplImage* structures àMat objets (pas de copies). Si vous avez stocké l'image dans un Mat objet Mat.t() retournerait la transposition.

toute rotation:

vous devez utiliser cvWarpAffine par la définition de la matrice de rotation dans le cadre général de la matrice de transformation. Je recommande fortement la mise à niveau vers OpenCV2.0 qui possède plusieurs caractéristiques ainsi qu'un Mat classe qui encapsule des matrices et des images. Avec 2.0 vous pouvez utiliser warpAffine à ce qui précède.

10
répondu Jacob 2010-02-15 18:35:42

ceci est un exemple sans la nouvelle interface c++ (fonctionne à 90, 180 et 270 degrés, en utilisant param = 1, 2 et 3). Rappelez-vous d'appeler cvReleaseImage sur l'image retournée après l'avoir utilisé.

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
répondu Andres Hurtis 2011-12-21 09:56:39

voici ma solution EmguCV (A C# port of OpenCV):

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;
}

Ne devrait pas être trop difficile à traduire dans C++.

2
répondu mpen 2012-04-18 01:51:57

Voici mon python cv2 mise en oeuvre:

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)
2
répondu Eran W 2017-06-08 20:49:07

Eh bien, je cherchais quelques détails et je n'ai trouvé aucun exemple. Donc, je mets en ligne un transposeImage fonction qui, je l'espère, aidera les autres qui sont à la recherche d'un moyen direct de tourner 90° sans perdre de données:

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;
}

Question: Pourquoi cela?

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

réponse: Parce que cela fonctionne :) le seul centre que j'ai trouvé qui ne traduit pas l'image. Mais si quelqu'un a une explication, je serais intéressé.

1
répondu Artem 2012-06-09 11:21:27