rotate c++ image opencv rotation

c++ - rotate image opencv python



La forma más fácil de girar 90 grados una imagen usando OpenCV? (7)

A partir de OpenCV3.2, la vida se hizo un poco más fácil, ahora puede rotar una imagen en una sola línea de código:

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

Para la dirección, puede elegir cualquiera de los siguientes:

ROTATE_90_CLOCKWISE ROTATE_180 ROTATE_90_COUNTERCLOCKWISE

¿Cuál es la mejor forma (en c / c ++) de rotar un IplImage / cv :: Mat 90 grados? Asumiría que debe haber algo mejor que transformarlo usando una matriz, pero parece que no puedo encontrar nada más que eso en la API y en línea.


Aquí está mi implementación 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)


Aquí está mi solución EmguCV (un puerto C # de 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; }

No debería ser demasiado difícil traducirlo nuevamente a C ++.


Bueno, estaba buscando algunos detalles y no encontré ningún ejemplo. Así que estoy publicando una función transposeImage que, espero, ayudará a otros que están buscando una forma directa de rotar 90 ° sin perder datos:

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

Pregunta: ¿Por qué esto?

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

Respuesta: Porque funciona :) El único centro que encontré que no traduce la imagen. Aunque si alguien tiene una explicación, me interesaría.


Este es un ejemplo sin la nueva interfaz C ++ (funciona para 90, 180 y 270 grados, usando param = 1, 2 y 3). Recuerde llamar a cvReleaseImage en la imagen devuelta después de usarla.

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


La rotación es una composición de una transposición y una voltereta.

Que en OpenCV se puede escribir así (ejemplo de Python a continuación):

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)


Actualización para transposición:

Debería usar cvTranspose() o cv::transpose() porque (como señaló correctamente) es más eficiente. De nuevo, recomiendo actualizar a OpenCV2.0 ya que la mayoría de las funciones de cvXXX solo convierten las estructuras de IplImage* en objetos Mat (sin copias de fondo). Si almacenó la imagen en un objeto Mat , Mat.t() devolvería la transposición.

Cualquier rotación:

Debe usar cvWarpAffine definiendo la matriz de rotación en el marco general de la matriz de transformación. Recomiendo encarecidamente actualizar a OpenCV2.0 que tiene varias características, así como una clase Mat que encapsula matrices e imágenes. Con 2.0 puedes usar warpAffine para lo anterior.