108 votes

OpenCV Python fait pivoter l'image de X degrés autour d'un point spécifique

J'ai du mal à trouver des exemples de rotation d'une image autour d'un point spécifique selon un angle spécifique (souvent très petit) en Python avec OpenCV.

C'est ce que j'ai fait jusqu'à présent, mais cela produit une image résultante très étrange, mais elle est quelque peu tournée :

def rotateImage( image, angle ):
    if image != None:
        dst_image = cv.CloneImage( image )

        rotate_around = (0,0)
        transl = cv.CreateMat(2, 3, cv.CV_32FC1 )

        matrix = cv.GetRotationMatrix2D( rotate_around, angle, 1.0, transl )
        cv.GetQuadrangleSubPix( image, dst_image, transl )
        cv.GetRectSubPix( dst_image, image, rotate_around )

    return dst_image

176voto

Alex Rodrigues Points 679
import numpy as np
import cv2

def rotate_image(image, angle):
  image_center = tuple(np.array(image.shape[1::-1]) / 2)
  rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
  result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
  return result

En supposant que vous utilisez la version cv2, ce code trouve le centre de l'image que vous voulez faire pivoter, calcule la matrice de transformation et l'applique à l'image.

0 votes

Merci pour votre aide, cependant j'utilise le module "cv" et vous utilisez "cv2", donc il se plaint spécifiquement de l'inexistence de "image.shape". Je n'ai utilisé que le module "cv" jusqu'à présent, donc je ne comprends pas encore tous les changements apportés par "cv2". Je sais que mon image est (140,140), donc j'ai essayé de coder en dur à la place de image.shape, mais ça n'a pas du tout marché non plus.

1 votes

Je pense avoir fait quelques progrès, mais je rencontre toujours un problème. Voici le dernier code : result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) Traceback (dernier appel le plus récent) : result = cv2.warpAffine(image, rot_mat, cv.GetSize(image), flags=cv2.INTER_LINEAR) TypeError : <inconnu> n'est pas un tableau numpy

15 votes

J'ai un problème pour exécuter cv2.getRotationMatrix2D(center=image_center ,angle=angle,scale=1) TypeError : function takes exactly 2 arguments (3 given)

83voto

fivef Points 1124

Ou une utilisation beaucoup plus simple SciPy

from scipy import ndimage

#rotation angle in degree
rotated = ndimage.rotate(image_to_rotate, 45)

voir ici pour plus d'informations sur l'utilisation.

1 votes

Je boucle à travers un répertoire de png et je fais ceci mais j'obtiens un RuntimeError : invalid rotation plane specified. Des solutions ?

0 votes

Est-ce que vous passez dans une image cv ouverte ? comme de : img = cv2.imread('messi5.jpg',0)

15 votes

C'est assez lent pour moi

24voto

Omnipresent Points 6477
def rotate(image, angle, center = None, scale = 1.0):
    (h, w) = image.shape[:2]

    if center is None:
        center = (w / 2, h / 2)

    # Perform the rotation
    M = cv2.getRotationMatrix2D(center, angle, scale)
    rotated = cv2.warpAffine(image, M, (w, h))

    return rotated

19voto

JTIM Points 331

J'ai eu des problèmes avec certaines des solutions ci-dessus, pour obtenir la "bounding_box" correcte ou la nouvelle taille de l'image. Voici donc ma version

def rotation(image, angleInDegrees):
    h, w = image.shape[:2]
    img_c = (w / 2, h / 2)

    rot = cv2.getRotationMatrix2D(img_c, angleInDegrees, 1)

    rad = math.radians(angleInDegrees)
    sin = math.sin(rad)
    cos = math.cos(rad)
    b_w = int((h * abs(sin)) + (w * abs(cos)))
    b_h = int((h * abs(cos)) + (w * abs(sin)))

    rot[0, 2] += ((b_w / 2) - img_c[0])
    rot[1, 2] += ((b_h / 2) - img_c[1])

    outImg = cv2.warpAffine(image, rot, (b_w, b_h), flags=cv2.INTER_LINEAR)
    return outImg

0 votes

C'était pour la détection des visages ? Je veux faire tourner les images vidéo de 90 degrés et utiliser MTCNN parce qu'il ne détecte pas les visages frontaux couchés sur le côté (personne couchée sur le sol).

0 votes

@mLstudent33 Non je l'ai utilisé dans un autre but, mais là il s'agit juste de faire tourner une image. Donc si vous avez l'angle, ça devrait aller ?

1 votes

Je pense que oui. Je peux faire une rotation, lancer la détection, puis dessiner cv2.rectangle() et le faire pivoter en arrière. Merci de votre réponse.

13voto

nicodjimenez Points 66

La fonction cv2.warpAffine prend le paramètre shape dans l'ordre inverse : (col,row) ce que les réponses ci-dessus ne mentionnent pas. Voici ce qui a fonctionné pour moi :

import numpy as np

def rotateImage(image, angle):
    row,col = image.shape
    center=tuple(np.array([row,col])/2)
    rot_mat = cv2.getRotationMatrix2D(center,angle,1.0)
    new_image = cv2.warpAffine(image, rot_mat, (col,row))
    return new_image

0 votes

GetRotationMatrix2D semble également nécessiter (col,row). center devrait également utiliser (col,row), comme cela est fait dans la réponse de @Omnipresent.

0 votes

Je suis d'accord que ce n'était pas clair. @alex-rodrigues ' answer effectue un découpage en tranches de l'image.shape pour obtenir la largeur et la hauteur dans le bon ordre pour warpAffine : image.shape[1::-1] fait cela. Ce que cela fait, c'est prendre une tranche en commençant par le 1er élément, avec une valeur d'étape de -1, donc en procédant vers la gauche, de sorte que vous vous retrouvez avec une tranche avec [1][0], qui est la largeur (colonnes), suivie de la hauteur (lignes).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X