web-dev-qa-db-fra.com

Faire pivoter l'image de 90, 180 ou 270 degrés

Je dois faire pivoter une image de 90, 180 ou 270 degrés. Dans OpenCV4Android, je peux utiliser:

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

Cependant, ceci est un énorme goulot d'étranglement dans mon algorithme de traitement d'image. Bien entendu, une simple rotation par un multiple de 90 degrés est beaucoup plus simple que le cas le plus général de warpAffine et peut être effectuée beaucoup plus efficacement. Pour 180 degrés, par exemple, je pourrais utiliser:

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

où -1 signifie basculer entre les axes horizontal et vertical. Existe-t-il une optimisation similaire que je pourrais utiliser pour des rotations de 90 ou 270 degrés?

23
1''

Il s’agit du premier résultat obtenu avec Google et aucune de ces solutions ne répond réellement à la question, ni n’est correcte ni succincte.

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

Je ne connais pas très bien l’API Java, ces codes sont développés par c ++ . Les logiques doivent être identiques, utilisez transpose + flip pour faire pivoter l’image avec 90n (n appartient à N = -valeur minimale de int, ....., -3, -2, -1, 0, 1, 2, 3, ..., valeur maximale 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);
   }
}

Edit: Améliorer les performances, merci pour les commentaires de TimZaman et la mise en œuvre 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);
        }
    }
}
45
StereoMatching

Cela fera pivoter une image d’un nombre quelconque de degrés, en utilisant le moyen le plus efficace pour des multiples 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
        }
    }

Mais avec opencv 3.0, cela se fait simplement via la commande cv :: rotate :

cv::rotate(image, dest, e.g. cv::ROTATE_90_COUNTERCLOCKWISE);
9
Joel Teply

Voici une solution utilisant l'API Android. Ici, je l’utilise pour faire pivoter les images d’une caméra pouvant être montées dans différentes orientations.

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;
}
6
1''

Voici ma traduction en Python (et merci à toutes les affiches):

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
3
hum3

J'ai écrit cette version Python en utilisant uniquement Numpy, qui sont beaucoup plus rapides qu'en utilisant cv2.transpose() et 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')
2
Kun

Vous pouvez faire pivoter l'image à l'aide de la fonction numpy rot90 

comme 

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

J'espère que cette aide .. 

1
Vivek Ananthan

Utilisez le numpy.rot90, si vous voulez 180 degrés, faites-le deux fois.

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

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