2014-04-24 7 views
11

J'essaie de vérifier le calibrage de la caméra, donc je voudrais rectifier les images d'étalonnage. Je suppose que cela impliquera d'utiliser un appel à warpPerspective mais je ne vois pas une fonction évidente qui prend la matrice de la caméra, et les vecteurs de rotation et de translation pour générer la matrice de perspective pour cet appel.OpenCV: obtenir la matrice de perspective à partir de la translation et de la rotation

Essentiellement, je veux faire le processus décrit here (voir en particulier les images vers la fin), mais en commençant par un modèle de caméra connu et pose.

Existe-t-il un appel de fonction simple qui prend les paramètres intrinsèques et extrinsèques de la caméra et calcule la matrice de perspective à utiliser dans warpPerspective? Je vais appeler le warpPerspective après avoir appelé undistort sur l'image.

En principe, je pourrais tirer la solution en résolvant le système d'équations définies au sommet du opencv camera calibration documentation après avoir spécifié la contrainte Z=0, mais je me dis que qu'il doit y avoir une routine en boîte qui me permettra de orthorectifier mes images de test . Dans mes recherches, j'ai du mal à parcourir tous les résultats d'étalonnage stéréo - je n'ai qu'un seul appareil photo, mais je veux rectifier l'image sous la contrainte que je ne cherche qu'un motif de test planaire .

+0

Alors, par rectifient voulez-vous dire éliminer les effets de rotation?C'est-à-dire que vous n'avez qu'une vue, pas deux vues les unes par rapport aux autres, que vous voulez rectifier (aligner les lignes épipolaires). –

+0

@DavidNilosek oui, j'ai une image oblique d'un tableau de cercles d'étalonnage, je voudrais récupérer la vue "haut". – Dave

+0

J'essaie d'y réfléchir, mais je suis malheureusement à court de temps. Essayez d'utiliser l'inverse de la matrice de rotation comme la matrice de perspective pour warpPerspective, si cela fonctionne, je peux écrire quelque chose qui explique un peu mieux. –

Répondre

13

En fait, il n'est pas nécessaire d'impliquer une caméra orthographique. Voici comment vous pouvez transformer la perspective appropriée.

Si la calibration de l'appareil photo à l'aide cv::calibrateCamera, vous avez obtenu une matrice de la caméra K un vecteur de coefficients de distorsion de l'objectif D pour votre appareil photo et, pour chaque image que vous avez utilisé, un vecteur de rotation rvec (que vous pouvez convertir en une matrice 3x3 R en utilisant cv::rodrigues, doc) et un vecteur de traduction T. Considérons l'une de ces images et les R et T associés. Après avoir appelé cv::undistort en utilisant les coefficients de distorsion, l'image sera comme elle a été acquise par une caméra de matrice de projection K * [ R | T ].

Fondamentalement (comme @DavidNilosek intuited), vous voulez annuler la rotation et obtenir l'image comme si elle a été acquise par la matrice de projection de la forme K * [ I | -C ]C=-R.inv()*T est la position de la caméra. Pour cela, vous devez appliquer la transformation suivante:

Hr = K * R.inv() * K.inv() 

Le seul problème potentiel est que l'image gauchie peut aller en dehors de la partie visible du plan d'image. Par conséquent, vous pouvez utiliser une traduction supplémentaire pour résoudre cette question, comme suit:

 [ 1 0 |   ] 
Ht = [ 0 1 | -K*C/Cz ] 
    [ 0 0 |   ] 

où Cz est le composant de C le long de l'axe Oz. Enfin, avec les définitions ci-dessus, H = Ht * Hr est une transformation de perspective rectificatrice pour l'image considérée.

+1

Pour obtenir l'image centrée, je devais faire ce qui suit: soit 'u0 = -K * C/Cz' (la partie traduction de' Ht' ci-dessus); déplacez-le de la moitié de la taille de l'image d'entrée: 'u [0] = u0 [0] - taille_image [0]', 'u [1] = u0 [1] -image_size [1]', 'u [2] = u0 [2] ', puis utilise ce vecteur' u' décalé à la place de '-K * C/Cz' dans la construction de Ht. Ceci est lié au fait que l'origine de mon système de coordonnées monde est au centre de ma grille d'étalonnage – Dave

+0

Il y a des types dans les extraits de code mon commentaire précédent: Je décale par 1/2 de la taille de l'image. – Dave

+0

Nice, c'est une bonne explication –

1

C'est une esquisse de ce que je veux dire par « la résolution du système d'équations » (en Python):

import cv2 
import scipy # I use scipy by habit; numpy would be fine too 
#rvec= the rotation vector 
#tvec = the translation *emphasized text*matrix 
#A = the camera intrinsic 

def unit_vector(v): 
    return v/scipy.sqrt(scipy.sum(v*v)) 

(fx,fy)=(A[0,0], A[1,1]) 
Ainv=scipy.array([ [1.0/fx, 0.0, -A[0,2]/fx], 
        [ 0.0, 1.0/fy, -A[1,2]/fy], 
        [ 0.0, 0.0,  1.0] ], dtype=scipy.float32) 
R=cv2.Rodrigues(rvec) 
Rinv=scipy.transpose(R) 

u=scipy.dot(Rinv, tvec) # displacement between camera and world coordinate origin, in world coordinates 


# corners of the image, for here hard coded 
pixel_corners=[ scipy.array(c, dtype=scipy.float32) for c in [ (0+0.5,0+0.5,1), (0+0.5,640-0.5,1), (480-0.5,640-0.5,1), (480-0.5,0+0.5,1)] ] 
scene_corners=[] 
for c in pixel_corners: 
    lhat=scipy.dot(Rinv, scipy.dot(Ainv, c)) #direction of the ray that the corner images, in world coordinates 
    s=u[2]/lhat[2] 
    # now we have the case that (s*lhat-u)[2]==0, 
    # i.e. s is how far along the line of sight that we need 
    # to move to get to the Z==0 plane. 
    g=s*lhat-u 
    scene_corners.append((g[0], g[1])) 

# now we have: 4 pixel_corners (image coordinates), and 4 corresponding scene_coordinates 
# can call cv2.getPerspectiveTransform on them and so on.. 
+0

Je pense que c'est une façon inélégante d'obtenir le même effet que la réponse de @ AldurDisciple – Dave

Questions connexes