Girar la imagen 90, 180 o 270 grados

Necesito rotar una imagen 90, 180 o 270 grados. En OpenCV4Android puedo usar:

Imgproc.getRotationMatrix2D(new Point(center, center), degrees, 1); Imgproc.warpAffine(src, dst, rotationMatrix, dst.size()); 

Sin embargo, este es un gran cuello de botella en mi algoritmo de procesamiento de imágenes. Por supuesto, una simple rotación por un múltiplo de 90 grados es mucho más simple que el caso más general de warpAffine , y se puede hacer de manera mucho más eficiente. Para 180 grados, por ejemplo, podría usar:

 Core.flip(src, dst, -1); 

donde -1 significa dar la vuelta a los ejes horizontal y vertical. ¿Existe una optimización similar que pueda usar para rotaciones de 90 o 270 grados?

Este es el primer resultado cuando Google y ninguna de estas soluciones realmente responde la pregunta o es correcta o sucinta.

 Core.rotate(Mat src, Mat dst, Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE 

No sé muy bien la API de Java, estos códigos están desarrollados por c ++. Las lógicas deben ser las mismas, use transpose + flip para rotar la imagen con 90n (n pertenece a N = valor mínimo de int, ….., -3, -2, -1, 0, 1, 2, 3, …, valor máximo de int)

 /* *@brief rotate image by multiple of 90 degrees * *@param source : input image *@param dst : output image *@param angle : factor of 90, even it is not factor of 90, the angle * will be mapped to the range of [-360, 360]. * {angle = 90n; n = {-4, -3, -2, -1, 0, 1, 2, 3, 4} } * if angle bigger than 360 or smaller than -360, the angle will * be map to -360 ~ 360. * mapping rule is : angle = ((angle / 90) % 4) * 90; * * ex : 89 will map to 0, 98 to 90, 179 to 90, 270 to 3, 360 to 0. * */ void rotate_image_90n(cv::Mat &src, cv::Mat &dst, int angle) { if(src.data != dst.data){ src.copyTo(dst); } angle = ((angle / 90) % 4) * 90; //0 : flip vertical; 1 flip horizontal bool const flip_horizontal_or_vertical = angle > 0 ? 1 : 0; int const number = std::abs(angle / 90); for(int i = 0; i != number; ++i){ cv::transpose(dst, dst); cv::flip(dst, dst, flip_horizontal_or_vertical); } } 

Editar: mejorar el rendimiento, gracias por los comentarios de TimZaman y la implementación de 1 ”

 void rotate_90n(cv::Mat const &src, cv::Mat &dst, int angle) { CV_Assert(angle % 90 == 0 && angle <= 360 && angle >= -360); if(angle == 270 || angle == -90){ // Rotate clockwise 270 degrees cv::transpose(src, dst); cv::flip(dst, dst, 0); }else if(angle == 180 || angle == -180){ // Rotate clockwise 180 degrees cv::flip(src, dst, -1); }else if(angle == 90 || angle == -270){ // Rotate clockwise 90 degrees cv::transpose(src, dst); cv::flip(dst, dst, 1); }else if(angle == 360 || angle == 0 || angle == -360){ if(src.data != dst.data){ src.copyTo(dst); } } } 

Esto rotará una imagen en cualquier número de grados, utilizando los medios más eficientes para múltiplos de 90.

  void rotate_cw(const cv::Mat& image, cv::Mat& dest, int degrees) { switch (degrees % 360) { case 0: dest = image.clone(); break; case 90: cv::flip(image.t(), dest, 1); break; case 180: cv::flip(image, dest, -1); break; case 270: cv::flip(image.t(), dest, 0); break; default: cv::Mat r = cv::getRotationMatrix2D({image.cols/2.0F, image.rows/2.0F}, degrees, 1.0); int len = std::max(image.cols, image.rows); cv::warpAffine(image, dest, r, cv::Size(len, len)); break; //image size will change } } 

Pero con opencv 3.0, esto se hace solo a través del comando cv :: rotate :

 cv::rotate(image, dest, eg cv::ROTATE_90_COUNTERCLOCKWISE); 

Aquí hay una solución que usa la API de Android. Aquí, lo estoy usando para rotar imágenes de una cámara que podría montarse en varias orientaciones.

 if (mCameraOrientation == 270) { // Rotate clockwise 270 degrees Core.flip(src.t(), dst, 0); } else if (mCameraOrientation == 180) { // Rotate clockwise 180 degrees Core.flip(src, dst, -1); } else if (mCameraOrientation == 90) { // Rotate clockwise 90 degrees Core.flip(src.t(), dst, 1); } else if (mCameraOrientation == 0) { // No rotation dst = src; } 

Aquí está mi traducción de Python (y gracias a todos los carteles):

 import cv2 def rot90(img, rotflag): """ rotFlag 1=CW, 2=CCW, 3=180""" if rotflag == 1: img = cv2.transpose(img) img = cv2.flip(img, 1) # transpose+flip(1)=CW elif rotflag == 2: img = cv2.transpose(img) img = cv2.flip(img, 0) # transpose+flip(0)=CCW elif rotflag ==3: img = cv2.flip(img, -1) # transpose+flip(-1)=180 elif rotflag != 0: # if not 0,1,2,3 raise Exception("Unknown rotation flag({})".format(rotflag)) return img 

Escribí esta versión de Python usando solo Numpy , que es mucho más rápido que usar cv2.transpose() y cv2.flip() .

 def rotate_image_90(im, angle): if angle % 90 == 0: angle = angle % 360 if angle == 0: return im elif angle == 90: return im.transpose((1,0, 2))[:,::-1,:] elif angle == 180: return im[::-1,::-1,:] elif angle == 270: return im.transpose((1,0, 2))[::-1,:,:] else: raise Exception('Error') 

Puede rotar la imagen usando la función numpy rot90

me gusta

 def rotate_image(image,deg): if deg ==90: return np.rot90(image) if deg ==180: return np.rot90(image,2) if deg == 270: return np.rot90(image,-1) #Reverse 90 deg rotation 

Espero que esto ayude ..

Usa numpy.rot90 , si quieres 180 grados, solo hazlo dos veces.

 import numpy as np import cv2 img = cv2.imread('img.png',1) cv2.imshow('',img) cv2.waitKey(0) img90 = np.rot90(img) cv2.imshow('',img90) cv2.waitKey(0) 

En Python:

 # import the necessary packages import numpy as np import cv2 # initialize the camera and grab a reference to the raw camera capture vs = cv2.VideoCapture(0) (ret, image_original) = vs.read() image_rotated_90 = np.rot90(image_original) image_rotated_180 = np.rot90(image_rotated_90) # show the frame and press any key to quit the image frame cv2.imshow("Frame", image_rotated_180) cv2.waitKey(0)