2014-08-29 153 views
0

我一直在寻找许多不同的资源,试图找到VB的相机校准信息。EMGU CV,Visual Basic CameraCalibration.CalibrateCamera导致非常高的错误

我最好的运气迄今已经阅读网站上的例子为C# shown in this link with pictures and source files.

我已经转换尽可能多的代码,因为我可以从C#到VB,并试图找到尽可能多的工作代码一切。到目前为止,我MainWindow.vb代码:

Imports System.Drawing 
Imports System.Threading 

Imports Emgu.CV 
Imports Emgu.CV.Util 
Imports Emgu.CV.Structure 



Class MainWindow 
'Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) _ 
'  Handles Me.Loaded 
' Dim capturez As Capture = New Capture 

'End Sub 
#Region "Class Variables" 
Declare Sub Sleep Lib "kernel32.dll" (ByRef Milliseconds As Integer) 
Dim capturez As Capture = New Capture 
Dim Start_Flag As Boolean = False 

Dim BoxUnitHeight As Integer = 9 'EDIT THESE VALUES BASED ON THE BOARD PATTERN 
Dim BoxUnitWidth As Integer = 6 

Dim Frame_array_buffer As Image(Of Gray, [Byte])() = New Image(Of Gray, Byte)(99) {} 
Dim BufferSavePoint As Integer = 0 
Dim Corner_Object_List As MCvPoint3D32f()() = New  MCvPoint3D32f(Frame_array_buffer.Length - 1)() {} 
Dim Corner_Points_List As PointF()() = New PointF(Frame_array_buffer.Length - 1)() {} 
Dim IC As New IntrinsicCameraParameters() 
Dim EX_Param As ExtrinsicCameraParameters() = New ExtrinsicCameraParameters() {} 

Dim patternSize As Size = New Size(BoxUnitHeight, BoxUnitWidth) 

Dim Gray_Frame As Image(Of Gray, Byte) = capturez.QueryGrayFrame 
Dim BGR_Frame As Image(Of Bgr, Byte) = capturez.RetrieveBgrFrame 
Dim calImage As Image(Of Gray, Byte) = New Image(Of Gray, Byte) ("C:\Users\\\\\\Image_Correction_Test_V2\OpenCV_Chessboard.png") 

Dim corners As PointF() = New PointF() {} 
Dim newCornerz As PointF() = New PointF() {} 

Dim difError As Double 
Dim termCriteria As New MCvTermCriteria 


Public Enum Mode 
    SavingFrames 
    Caluculating_Intrinsics 
    Calibrated 
End Enum 
#End Region 
Private currentMode As Mode = Mode.SavingFrames 

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) _ 
    Handles Me.Loaded 
    termCriteria.max_iter = 1 
    termCriteria.epsilon = 0.0 
    termCriteria.type = CvEnum.TERMCRIT.CV_TERMCRIT_ITER 

End Sub 
' Sink the "Exit MenuItem" click event 
Private Sub mnuExit_Click(ByVal sender As Object, ByVal e As  System.Windows.RoutedEventArgs) _ 
     Handles mnuExit.Click 
    Application.Current.Shutdown() 
End Sub 

Private Sub Button_Click(ByVal sender As Object, ByVal e As  System.Windows.RoutedEventArgs) _ 
    Handles Button.Click 
    Start_Flag = True 
End Sub 

' Sink the "Exit MenuItem" click event 
Private Sub mnuFix_Click(ByVal sender As Object, ByVal e As  System.Windows.RoutedEventArgs) _ 
     Handles mnuFix.Click 
    Gray_Frame = capturez.RetrieveGrayFrame 
    newCornerz = CameraCalibration.FindChessboardCorners(calImage, patternSize,  Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH Or Emgu.CV.CvEnum.CALIB_CB_TYPE.FILTER_QUADS) 

    corners = CameraCalibration.FindChessboardCorners(Gray_Frame, patternSize,  Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH Or Emgu.CV.CvEnum.CALIB_CB_TYPE.FILTER_QUADS) 

    If corners IsNot Nothing Then 
     Dim perM As HomographyMatrix 
     perM = CameraCalibration.FindHomography(corners, newCornerz,  CvEnum.HOMOGRAPHY_METHOD.DEFAULT, 1) 
     Dim Test As Image(Of Gray, Byte) = Gray_Frame.WarpPerspective(perM,  CvEnum.INTER.CV_INTER_NN, CvEnum.WARP.CV_WARP_DEFAULT, New Gray) 
     Cal1.Source = ToBitmapSource(Test) 
    End If 

End Sub 


Public Sub StartTimer(ByVal o As Object, ByVal sender As RoutedEventArgs) 
    Dim myDispatcherTimer As System.Windows.Threading.DispatcherTimer = New  System.Windows.Threading.DispatcherTimer 
    myDispatcherTimer.Interval = New TimeSpan(0, 0, 0, 0, 30) 
    ' 100 Milliseconds 
    AddHandler myDispatcherTimer.Tick, AddressOf Me.Each_Tick 
    myDispatcherTimer.Start() 
End Sub 

' Raised every 100 miliseconds while the DispatcherTimer is active. 
Public Sub Each_Tick(ByVal o As Object, ByVal sender As EventArgs) 

    Dim imagez As Image(Of Bgr, Byte) = capturez.QueryFrame() 'Instead of QueryFrame, you may need to do RetrieveBgrFrame depending on the version of EmguCV you download. 
    Stream.Source = ToBitmapSource(imagez) 

    BGR_Frame = capturez.RetrieveBgrFrame 
    Gray_Frame = BGR_Frame.Convert(Of Gray, Byte)() 

    If currentMode = Mode.SavingFrames Then 

     corners = CameraCalibration.FindChessboardCorners(Gray_Frame, patternSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH Or Emgu.CV.CvEnum.CALIB_CB_TYPE.FILTER_QUADS) 

     If corners IsNot Nothing Then 
      'Debug.Print("Filling Array Buffer") 

      'The Find chessboardCorners will try to find them, but if it doesn't it still runs. If it fails DrawChessboard will fail and crash the program. 

      If Start_Flag Then 
       Gray_Frame.FindCornerSubPix(New PointF(0)() {corners}, New Size(11, 11), New Size(-1, -1), New MCvTermCriteria(30, 0.1)) 
       Frame_array_buffer(BufferSavePoint) = Gray_Frame.Copy 
       BufferSavePoint = BufferSavePoint + 1 
       If BufferSavePoint = Frame_array_buffer.Length Then currentMode = Mode.Caluculating_Intrinsics 'Buffer has been filled 
      End If 


      'Draw the reults 

      CameraCalibration.DrawChessboardCorners(Gray_Frame, patternSize, corners) 
      Cal2.Source = ToBitmapSource(Gray_Frame) 
      Thread.Sleep(100) 

     End If 
     corners = Nothing 
    End If 

    If currentMode = Mode.Caluculating_Intrinsics Then 
     'Debug.Print("Filling Object and Point Arrays") 
     For k As Integer = 0 To Frame_array_buffer.Length - 1 

      Corner_Points_List(k) = CameraCalibration.FindChessboardCorners(Frame_array_buffer(k), patternSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH) 
      'for accuracy 
      Gray_Frame.FindCornerSubPix(Corner_Points_List, New Size(11, 11), New Size(-1, -1), New MCvTermCriteria(30, 0.1)) 

      'Fill our objects list with the real world mesurments for the intrinsic calculations 
      Dim object_list As New List(Of MCvPoint3D32f)() 
      For i As Integer = 0 To BoxUnitHeight - 1 
       For j As Integer = 0 To BoxUnitWidth - 1 
        object_list.Add(New MCvPoint3D32f(j * 20.0F, i * 20.0F, 0.0F)) 
       Next 
      Next 
      Corner_Object_List(k) = object_list.ToArray() 
     Next 
     Debug.Print("Reached Calibration") 

     'our error should be as close to 0 as possible 

     difError = CameraCalibration.CalibrateCamera(Corner_Object_List, Corner_Points_List, Gray_Frame.Size, IC, Emgu.CV.CvEnum.CALIB_TYPE.CV_CALIB_RATIONAL_MODEL, termCriteria, EX_Param) 
     'If Emgu.CV.CvEnum.CALIB_TYPE == CV_CALIB_USE_INTRINSIC_GUESS and/or CV_CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be initialized before calling the function 
     'if you use FIX_ASPECT_RATIO and FIX_FOCAL_LEGNTH options, these values needs to be set in the intrinsic parameters before the CalibrateCamera function is called. Otherwise 0 values are used as default. 
     'display the results to the user 
     MsgBox("Your calibration error is:" & difError) 
     currentMode = Mode.Calibrated 
    End If 

    If currentMode = Mode.Calibrated Then 
     'Debug.Print("Attempting Picture fix") 


     'calculate the camera intrinsics 
     Dim Map1 As Matrix(Of Single), Map2 As Matrix(Of Single) 
     IC.InitUndistortMap(BGR_Frame.Width, BGR_Frame.Height, Map1, Map2) 

     'remap the image to the particular intrinsics 
     'In the current version of EMGU any pixel that is not corrected is set to transparent allowing the original image to be displayed if the same 
     'image is mapped backed, in the future this should be controllable through the flag '0' 
     Dim temp As Image(Of Bgr, [Byte]) = BGR_Frame.CopyBlank() 
     CvInvoke.cvRemap(BGR_Frame, temp, Map1, Map2, 0, New MCvScalar(0)) 
     BGR_Frame = temp.Copy 


     Imgz.Source = ToBitmapSource(BGR_Frame) 
     Start_Flag = False 
    End If 

    Debug.Print(currentMode) 
End Sub 

''' <summary> 
''' Delete a GDI object 
''' </summary> 
''' <param name="o">The poniter to the GDI object to be deleted</param> 
''' <returns></returns> 
<DllImport("gdi32")> _ 
Private Shared Function DeleteObject(o As IntPtr) As Integer 
End Function 

''' <summary> 
''' Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source 
''' </summary> 
''' <param name="image">The Emgu CV Image</param> 
''' <returns>The equivalent BitmapSource</returns> 
Public Shared Function ToBitmapSource(image As IImage) As BitmapSource 
    Using source As System.Drawing.Bitmap = image.Bitmap 
     Dim ptr As IntPtr = source.GetHbitmap() 
     'obtain the Hbitmap 
     Dim bs As BitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()) 

     DeleteObject(ptr) 
     'release the HBitmap 
     Return bs 
    End Using 
End Function 

End Class 

说明:当MainWindow.xaml启动的主要系统参数发起并在定时器踢每30毫秒(不是100)主程序循环运行。我在这里复制了示例代码中的大部分代码。看起来像一台状态机,他们使用模式在校准阶段之间切换。现在使用“GO”按钮通过切换一个标志开始校准,但视频输入持续运行。底部的功能是补偿旧的picturebox.image喜欢.tobitmap(),但image.source不是我正在使用的事实。

因此,点击GO按钮,等待100个图像被保存,计算点并保存所有的数据。计算外部因素和内在因素,查找倾斜地图,并将地图应用于Feed。

当CameraCalibration.CalibrateCamera完成时,它会将错误显示为double,并且MsgBox会显示它是什么。 当MsgBox触发并告诉我我的错误时,我看到数字高达85-105,其中指南告诉我它应尽可能接近0。

然后当改变的图像出现时,它严重倾斜。

Video feed on the calibration

左下:视频频道。右下角:灰色饲料找到角落。 左上角的图像应该是正确的。 我上次运行程序时,实际上严重扭曲了图像看起来像鱼缸。

有没有其他人有这方面的经验,可以告诉我我做错了什么?

一些附加信息: 当我使用.calibratecamera时,我在网上找到的所有其他代码都不在VB中,此外还少了一个参数。 “termCriteria”是一个变量,我必须弄清楚如何设置,而且我从来没有见过其他必须使用它的代码。

对于代码转换我用这个网站: Code converter.

回答

0

OK,这样的人谁遇到这个线程。我混合了高度和宽度变量。该规范开始阅读宽度,然后是高度,并且在病房运行后,将高度和宽度进行校准。

我确保它的格式与示例代码一样,现在我的错误是〜1。