Ruotare l’immagine di 90, 180 o 270 gradi

Ho bisogno di ruotare un’immagine di 90, 180 o 270 gradi. In OpenCV4Android posso usare:

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

Tuttavia, questo è un enorme collo di bottiglia nel mio algoritmo di elaborazione delle immagini. Naturalmente, una semplice rotazione di un multiplo di 90 gradi è molto più semplice rispetto al caso più generale di warpAffine, e può essere fatto in modo molto più efficiente. Per 180 gradi, per esempio, potrei usare:

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

dove -1 significa capovolgere su entrambi gli assi orizzontale e verticale. C’è un’ottimizzazione simile potrei usare per 90 o 270 gradi rotazioni?

  • hai concluso la soluzione java , puoi postare la stessa
  • sia Core.rotate(mRgba, mRgba, Core.ROTATE_180); & Core.flip(mRgba, mRgba, -1); mangiare su ~12-14 ms CPU sul mio Xiaomi Redmi 4 Prime. molto cattive prestazioni. Volevo inversa fotocamera byte fotogrammi, ma è troppo
InformationsquelleAutor 1” | 2013-04-28

 

9 Replies
  1. 14

    Questo è il primo risultato quando si Google e nessuna di queste soluzioni davvero rispondere alla domanda, oppure è corretto o sintetica.

    Core.rotate(Mat src, Mat dst, Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE
    
    • Wow, una ri-ricevuto risposta!!!
  2. 45

    Non conosco le api java molto bene, questi codici sono sviluppati in c++.
    La logica dovrebbe essere la stessa, utilizzare transpose + flip per ruotare l’immagine con
    90n(n appartiene a N = -valore minimo di int, ….., -3, -2, -1, 0, 1, 2, 3, …, max valore di tipo 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);
       }
    }

    Modifica : Migliorare le prestazioni, grazie per i commenti di TimZaman e l’attuazione di 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);
            }
        }
    }
    • Il ciclo rende più costoso del necessario mate.
    • Io non sono appassionato di temporanea immagine creata da src.t(): fa si che ogni volta che un’allocazione che potrebbe essere costoso soprattutto in Android
    • La funzione crea solo allocare un nuovo buffer quando necessario. In altre parole, non sarebbe allocare nulla se le dimensioni e il tipo di dst stesso src
    • Certo, ma io sto parlando di matrice creato quando si chiama src.t()
    • Grazie per aver ricordato src.t(), io uso il recepimento di sostituirlo, ora non allocare un nuovo buffer se l’ora legale e src hanno la stessa dimensione e tipo
    • Ho paura flip con la stessa origine e di destinazione causerà un’allocazione. Posso sbagliarmi, sarebbe necessario verificare opencv codice sorgente.
    • Non ti preoccupare, flip non è necessario allocare la memoria se la dimensione e il tipo di dst stesso src. I codici si trovano a core/copy.cpp
    • Hai completamente ragione! Una nota divertente: L’unica cosa che non funziona è che se il 2 ingresso Tappetini sono 2 parzialmente sovrapposti sub-Tappetini della stessa Mat, ma è solo un caso folle!
    • (1) dst.create(src.size(), src.type()); non è necessaria. (2) se un torto di laurea intero è passato, dst verrà creato con la memoria di immondizia. o affermare o di cattura o di utilizzare il flag di numeri interi (3) utilizzare const passando src variabile.

  3. 9

    Questo ruotare un’immagine in un qualsiasi numero di gradi, utilizzando il mezzo più efficace per multipli di 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
            }
        }
    

    Ma con opencv 3.0, questo è fatto da solo tramite il cv::rotate comando:

    cv::rotate(image, dest, e.g. cv::ROTATE_90_COUNTERCLOCKWISE);
    
    • Di solito l’immagine di output deve essere passato come parametro, altrimenti assegnazione avverrà a ogni chiamata. (Con l’implementazione hai solo un vantaggio in caso di rotazione = 0)
    • Pff questo codice è pericoloso. Si ritorna la stessa alla base di dati come è passato in image, a meno che la rotazione è di default. Inoltre, la tela generato è troppo grande a causa cv::Size(len, len).
    • grazie mille! Ho modificato e portato la tua prima soluzione [0,90,180,270] per android dove ho avuto un OpenCV app e ho potuto mostrare il JavaCameraView nel modo giusto. Buona giornata!
  4. 6

    Qui è una soluzione che utilizza l’API di Android. Qui, lo sto usando per ruotare le immagini da una fotocamera che può essere montato in diversi orientamenti.

    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;
    }
    
  5. 3

    Qui è il mio Pitone di traduzione (e grazie per tutti i poster):

    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
    
  6. 2

    Ho scritto questa versione di Python che utilizza Numpy solo, che sono molto più veloce rispetto all’utilizzo di cv2.transpose() e 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')
    
  7. 2

    È possibile ruotare un’immagine utilizzando numpy rot90 funzione

    come

    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
    

    Spero che questo aiuto ..

    • Sia il rot90 funzione e il suo k (volte) parametri sono superbi. Questo significa reverse 90 gradi può essere scritto anche come np.rot90(image, 3).
    • C’è un po ‘ gotcha – il risultato è un array di vista, che non è contiguo. imshow ha alcun problema con questo, ma le funzioni di disegno può buttare a questo: il Layout della matrice di output img è incompatibile con cv::Mat (passaggio[ndims-1] != elemsize o passaggio[1] != elemsize*nchannels). Può essere fissato con np.ascontiguousarray.
  8. 0

    Utilizzare il numpy.rot90,se si desidera di 180 gradi,è sufficiente farlo due volte.

    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)
    
  9. 0

    In 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)
    

Lascia un commento