我一直在寻找许多不同的资源,试图找到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。
然后当改变的图像出现时,它严重倾斜。
左下:视频频道。右下角:灰色饲料找到角落。 左上角的图像应该是正确的。 我上次运行程序时,实际上严重扭曲了图像看起来像鱼缸。
有没有其他人有这方面的经验,可以告诉我我做错了什么?
一些附加信息: 当我使用.calibratecamera时,我在网上找到的所有其他代码都不在VB中,此外还少了一个参数。 “termCriteria”是一个变量,我必须弄清楚如何设置,而且我从来没有见过其他必须使用它的代码。
对于代码转换我用这个网站: Code converter.