2011-09-21 3 views
3

2 개의 이미지에서 카메라 외부 정보를 찾으려고합니다. CameraCalibration의 내장 함수가 있고 장면에 알려진 치수가 있습니다 (3DSMAX로 생성됨).카메라 외래 계산 잘못됨

체스 판은 1000 * 1000이며 각 사각형은 125 * 125입니다. 카메라는 원점을 중심으로 한 체스 판을 똑바로 내려다 보며 (0,0,3000)입니다. camera setup

가 GoodFeaturesToTrack 정확하게 81 개 코너를 식별한다 : 두 번째 이미지에서 카메라의 번역 (-1500, 0, -402) 및 체스 판의 중심에 다시 점에 Y 축에 30 ° 회전 chessboards

체스 보드 모서리의 3 차원 점, cvFindExtrinsicCameraParams2를 사용하여 내장 함수를 계산하고 cvRodrigues2를 사용하여 회전 행렬을 만듭니다. 여기

Imports Emgu.CV 
Imports Emgu.CV.Structure 
Imports Emgu.CV.CvInvoke 
Imports Emgu.CV.CvEnum 
Imports Emgu.CV.UI 
Imports System.Drawing 
Imports System.IO 
Imports System.Diagnostics 
Imports System.Math 
Module main_ 

    Sub Main() 

     Const MAXFEATURES As Integer = 100 
     Dim featuresA(0)() As PointF 
     Dim featuresB(0)() As PointF 
     Dim features As Integer = 0 
     Dim imgA As Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte) 
     Dim imgB As Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte) 
     Dim grayA As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) 
     Dim grayB As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) 
     Dim pyrBufferA As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) 
     Dim pyrBufferB As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) 
     Dim pointsA As Matrix(Of Single) 
     Dim pointsB As Matrix(Of Single) 
     Dim flags As Emgu.CV.CvEnum.LKFLOW_TYPE = Emgu.CV.CvEnum.LKFLOW_TYPE.DEFAULT 
     Dim imagesize As Size 
     Dim termcrit As New Emgu.CV.Structure.MCvTermCriteria(20, 0.03D) 
     Dim status As Byte() = Nothing 
     Dim errors As Single() = Nothing 
     Dim red As Bgr = New Bgr(Color.Red) 

     ' Load chessboards 
     imgA = New Image(Of [Structure].Bgr, Byte)("chessboard centre.jpg") 
     imgB = New Image(Of [Structure].Bgr, Byte)("chessboard left.jpg") 
     grayA = imgA.Convert(Of Gray, Byte)() 
     grayB = imgB.Convert(Of Gray, Byte)() 

     ' setup for feature detection 
     imagesize = cvGetSize(grayA) 
     pyrBufferA = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte)(imagesize.Width + 8, imagesize.Height/3) 
     pyrBufferB = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte)(imagesize.Width + 8, imagesize.Height/3) 
     features = MAXFEATURES 

     ' Find features 
     featuresA = grayA.GoodFeaturesToTrack(features, 0.01, 25, 3) 
     grayA.FindCornerSubPix(featuresA, New System.Drawing.Size(10, 10), New System.Drawing.Size(-1, -1), termcrit) 
     features = featuresA(0).Length 

     ' Compute optical flow. Not necessary here but good to remember 
     Emgu.CV.OpticalFlow.PyrLK(grayA, grayB, pyrBufferA, pyrBufferB, featuresA(0), New Size(25, 25), 3, termcrit, flags, featuresB(0), status, errors) 
     Debug.Assert(featuresA(0).GetUpperBound(0) = featuresB(0).GetUpperBound(0)) 

     ' Copy features to an easier-to-use matrix and get min/max to create 3d points 
     Dim minx As Double = Double.MaxValue 
     Dim miny As Double = Double.MaxValue 
     Dim maxx As Double = Double.MinValue 
     Dim maxy As Double = Double.MinValue 
     pointsA = New Matrix(Of Single)(features, 2) 
     pointsB = New Matrix(Of Single)(features, 2) 
     For i As Integer = 0 To features - 1 
      pointsA(i, 0) = featuresA(0)(i).X 
      pointsA(i, 1) = featuresA(0)(i).Y 
      pointsB(i, 0) = featuresB(0)(i).X 
      pointsB(i, 1) = featuresB(0)(i).Y 
      If pointsA(i, 0) < minx Then 
       minx = pointsA(i, 0) 
      End If 
      If pointsA(i, 1) < miny Then 
       miny = pointsA(i, 1) 
      End If 
      If pointsA(i, 0) > maxx Then 
       maxx = pointsA(i, 0) 
      End If 
      If pointsA(i, 1) > maxy Then 
       maxy = pointsA(i, 1) 
      End If 
     Next 

     ' Create 3D object points that correspond to chessboard corners 
     ' (The chessboard is 1000*1000, squares are 125*125) 
     Dim corners As Integer = Sqrt(features) 
     Dim obj As New Matrix(Of Double)(features, 3) 
     Dim squaresize2dx As Double = (maxx - minx)/8 ' pixel width of a chessboard square 
     Dim squaresize2dy As Double = (maxy - miny)/8 ' pixel height of a chessboard square 
     For i As Integer = 0 To features - 1 
      obj(i, 0) = Math.Round((pointsA(i, 0) - minx)/squaresize2dx) * 125 ' X=0, 125, 250, 375 ... 1000 
      obj(i, 1) = Math.Round((pointsA(i, 1) - miny)/squaresize2dy) * 125 ' idem in Y 
      obj(i, 2) = 0 
      ' Debug.WriteLine(pointsA(i, 0) & " " & pointsA(i, 1) & " " & obj(i, 0) & " " & obj(i, 1) & " " & obj(i, 2)) ' Just to verify 
     Next 

     ' These were calculated with CalibrateCamera using the same images 
     Dim intrinsics As New Matrix(Of Double)({{889.1647, 0.0, 318.3721}, 
               {0.0, 888.5134, 238.4254}, 
               {0.0, 0.0, 1.0}}) 
     ' Find extrinsics 
     Dim distortion As New Matrix(Of Double)({-0.036302, 2.008797, -29.674306, -29.674306}) 
     Dim translation As New Matrix(Of Double)(3, 1) 
     Dim rotation As New Matrix(Of Double)(3, 1) 
     cvFindExtrinsicCameraParams2(obj, pointsA, intrinsics, distortion, rotation, translation, False) 

     ' Convert rotation vector to rotation matrix 
     Dim rotmat As New Matrix(Of Double)(3, 3) 
     Dim jacobian As New Matrix(Of Double)(9, 3) 
     cvRodrigues2(rotation, rotmat, jacobian) 

     ' From http://en.wikipedia.org/wiki/Rotation_representation paragraph "Conversion formulae between representations" 
     Dim yr As Double = Asin(-rotmat(2, 0)) 
     Dim xr As Double = Asin(rotmat(2, 1)/Cos(yr)) 
     Dim zr As Double = Asin(rotmat(1, 0)/Cos(yr)) 

    End Sub 
End Module 

결과가 정확하지 않는 것, 내가 번역/회전을 기대했던 코드는하지만 난이 얻을 :

translation 
208.394425348956 
-169.447506344527 
-654.273807995629 
rotation 
-0.0224937226554797 
-2.13660350939653 
-1.10542281290682 
rotmat 
-0.741100224945266 0.322885083546921 -0.588655824237707 
-0.293966101915684 0.632206237134128 0.716867633983572 
0.603617749499279 0.704315622822328 -0.373610915174894 
xr=1.08307908108382 yr=-0.648031006135158 zr=-0.377625254910525 
xr=62.0558602250101° yr=-37.1294416451609° zr=-21.636333343925° 

누군가가 내가 잘못 뭘하는지 생각이겠습니까을? 감사!

+0

+1 나를 cvRodrigues2()에 소개합니다. 건배! – coder9

답변

1

발견. 왜곡 계수

k1, k2, p1, p2, k3 

및 I로했다 부호화되지

k1, k2, k3, k4, k5 

이다. 제가

-0.05716, 2.519006, -0.001674, -0.001021, -33.372798 

로 설정하면 응답이 대략적

올바른
1

핀 홀 카메라 방정식 보면주세요

[u, v, 1]' ~ A * R|T * [x, y, z, 1]'을 여기서 외적 행렬 R | T 치수의 3 × 4를 가진다. [1.0,0,0]과 같이 무한대의 'ideal'또는 소실점에 곱하면 R | T의 해당 열을 얻을 수 있습니다. 이것은 단순히 R | T의 모든 열을 찾으려면 최소한 3 개의 소실점을 사용자 바둑판 패턴에서 쉽게 찾을 수 있어야 함을 의미합니다.

지금은 1 장 밖에 없으므로 결과가 합리적으로 보인다면 운이 좋았을 것입니다. 다시 시도하고 교정 장비의 최소 10-20 개의 다른 경사, 거리 및 기울기를 선택하십시오.