2014-04-24 12 views
11

Ich versuche, meine Kamera-Kalibrierung zu überprüfen, also möchte ich die Kalibrierung Bilder korrigieren. Ich erwarte, dass dies die Verwendung eines Anrufs zu warpPerspective beinhaltet, aber ich sehe keine offensichtliche Funktion, die die Kameramatrix und die Rotations-und Translationsvektoren nimmt, um die perspektivische Matrix für diesen Aufruf zu erzeugen.OpenCV: Perspektive Matrix aus Übersetzung und Rotation

Im Wesentlichen möchte ich den beschriebenen Prozess here (siehe vor allem die Bilder gegen Ende), aber beginnend mit einem bekannten Kameramodell und Pose.

Gibt es einen einfachen Funktionsaufruf, der die intrinsischen und extrinsischen Parameter der Kamera übernimmt und die Perspektivenmatrix zur Verwendung in warpPerspective berechnet?

Ich werde warpPerspective aufrufen, nachdem undistort auf dem Bild aufgerufen wurde.

Im Prinzip könnte ich die Lösung durch Lösen des oben definierten Systems der Gleichungen opencv camera calibration documentation nach Angabe der Bedingung Z=0 ableiten, aber ich denke, dass es eine vordefinierte Routine geben muss, die es mir erlaubt, meine Testbilder zu orthorektifizieren .

In meinen Suchergebnissen finde ich es schwierig, alle Stereokalibrierungsergebnisse zu durchforsten - ich habe nur eine Kamera, möchte aber das Bild unter der Einschränkung korrigieren, dass ich nur ein planares Testmuster betrachte .

+0

also durch rectify meinen Sie Rotation Effekte entfernen?Das heißt, Sie haben nur eine Ansicht, nicht zwei Ansichten relativ zueinander, die Sie korrigieren möchten (Epipolarlinien ausrichten). –

+0

@DavidNilosek Ja, ich habe ein schräges Bild von einem Array von Kalibrierungskreisen, ich möchte die Ansicht "von oben nach unten" wiederherstellen. – Dave

+0

Ich versuche, darüber nachzudenken, aber ich habe leider wenig Zeit. Versuchen Sie, die Umkehrung der Rotationsmatrix als perspektivische Matrix für WarpPerspective zu verwenden. Wenn das funktioniert, kann ich etwas schreiben, das es ein wenig besser erklärt. –

Antwort

13

Eigentlich ist es nicht nötig, eine orthographische Kamera einzubeziehen. Hier ist, wie Sie die passende Perspektive transformieren können.

Wenn die Kamera unter Verwendung cv::calibrateCamera kalibriert, erhalten Sie einen Kameramatrix K ein Vektor von Linsenverzerrungskoeffizienten D für die Kamera und für jedes Bild, das verwendet wird, einen Rotationsvektor rvec (die man auf eine 3x3-Matrix konvertieren R unter Verwendung von cv::rodrigues, doc) und einem Translationsvektor T. Betrachten Sie eines dieser Bilder und die damit verbundenen R und T. Nachdem Sie cv::undistort mit den Verzerrungskoeffizienten aufgerufen haben, wird das Bild so aussehen, wie es von einer Kamera der Projektionsmatrix K * [ R | T ] aufgenommen wurde.

Grundsätzlich (wie @DavidNilosek erahnt), möchten Sie die Rotation abbrechen und erhalten das Bild, als ob es durch die Projektionsmatrix von Formular K * [ I | -C ] wo C=-R.inv()*T ist die Kameraposition erworben wurde. Dafür müssen Sie die folgende Transformation anwenden:

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

Das einzige mögliche Problem ist, dass das verzerrte Bild außerhalb des sichtbaren Teils der Bildebene gehen könnte. Daher können Sie eine zusätzliche Übersetzung verwenden, um dieses Problem zu lösen, wie folgt:

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

wo Cz die Komponente von C entlang der Oz-Achse ist.

Schließlich ist H = Ht * Hr mit den obigen Definitionen eine korrigierende perspektivische Transformation für das betrachtete Bild.

+1

Um das Bild zentriert zu bekommen, musste ich folgendes tun: lasst 'u0 = -K * C/Cz' (der Übersetzungsteil von' Ht' oben); verschiebe es um die Hälfte der Eingabebildgröße: 'u [0] = u0 [0] - image_size [0]', 'u [1] = u0 [1] -image_größe [1]', 'u [2] = u0 [2] 'und dann diesen verschobenen" u "-Vektor anstelle von" -K * C/Cz "in der Konstruktion von Ht verwenden. Das hängt damit zusammen, dass der Ursprung meines Weltkoordinatensystems im Zentrum meines Kalibrierungsrasters steht. – Dave

+0

Es gibt in den Code-Schnipsel Typen, die ich vorher kommentiert habe: Ich schiebe um 1/2 der Bildgröße. – Dave

+0

Schön, das ist eine gute Erklärung –

1

Dies ist eine Skizze von dem, was ich damit meine (in Python) „um das System von Gleichungen zu lösen“:

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

Ich vermute, dass dies eine unelegante Möglichkeit ist, den gleichen Effekt wie @ AldurDisciple Antwort zu erreichen – Dave

Verwandte Themen