2010-02-14 84 views

Respuesta

14

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

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

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

ROTATE_90_CLOCKWISE 
ROTATE_180 
ROTATE_90_COUNTERCLOCKWISE 
10

actualización de transposición:

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

Cualquier rotación:

que puedes usar cvWarpAffine mediante la definición de 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 puede usar warpAffine a lo anterior.

+0

Gracias! ¿Estás seguro de que no es menos eficiente que simplemente transponer la matriz de píxeles? La cuestión es que no estaba seguro de si OpenCV incluso representa internamente la imagen como una matriz de píxeles, es decir, algo así como un int * de 32 bits, y si lo hizo, cómo obtener un puntero a esa matriz. –

+0

Lo siento, no leí su pregunta correctamente, he actualizado mi respuesta. – Jacob

+22

La transposición debe ir seguida de un giro (cvFlip) para girar correctamente la imagen – Amnon

1

Bueno, estaba buscando algunos detalles y no encontré ningún ejemplo. Así que estoy publicando una función transposeImage que, espero, ayudará a otras personas que están buscando una manera directa para girar 90 ° y sin perder los 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.

+1

La razón de sus cálculos probablemente se deba a una división entera. Lo que quiere hacer es: float center_val = (float) image-> width/2.0f. –

+0

Tenga en cuenta que el método cvTranspose + cvFlip es un poco más rápido si solo necesita rotación en incrementos de 90 grados. –

55

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

R_{+90} = F_x \circ T

R_{-90} = F_y \circ T

Qué en OpenCV puede ser escrito como esto (ejemplo 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) 
+0

vea mi 'cv2' a continuación: http://stackoverflow.com/questions/2259678/easiest-way-to-rotate-by-90-degrees-an-image-using-opencv/42359233#42359233 –

+0

Volteando verticalmente (flipMode = 0) debe ser un poco más caro que voltear horizontalmente, porque está utilizando mejor el caché. Por lo tanto, la rotación en el sentido contrario a las agujas del reloj debería ser algo más rápida haciendo primero un giro horizontal, y luego la transposición. –

4

Este es un ejemplo sin la nueva interfaz de C++ (funciona para 90, 180 y 270 grados, usando param = 1, 2 y 3). Recuerde llamar al 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; 
} 
2

Aquí es mi EmguCV (AC# puerto de OpenCV) solución:

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 de traducir de nuevo en C++.

2

Aquí es mi pitón cv2 aplicación:

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

su código ccw transforma a la cw. – Jason

+0

corregido. Gracias @Jason! –

Cuestiones relacionadas