拍摄一张并显示之前的一张 - VB - OpenCV
Taking one capture and displaying the one before - VB - OpenCV
我在使用网络摄像头、opencv 和 emgucv 拍摄照片时遇到了一个特殊问题。
我以前用过这个功能,一直很好用,但是现在不知道为什么,图片框显示的是之前拍的照片。让我解释一下:
我启动程序 - 我按下按钮并在拍照前等待几秒钟 - 我使用 img = capturez.QueryFrame() 拍照 - 我在 PictureBox 中显示图片。这是代码:
Private Sub startButton_Click() Handles startButton.Click
Dim timeToWait As Integer
PictureBox1.Image = Nothing
If globalGMT <> Nothing And globalLatitude <> Nothing And globalLongitude <> Nothing Then
'If TextBox_GMT.Text IsNot Nothing And TextBox_LAT.Text IsNot Nothing And TextBox_LON.Text IsNot Nothing Then
SunPosition(globalGMT, globalLatitude, globalLongitude, ELEVACIONDELSOL, AZIMUTDELSOL)
End If
startButton.Enabled = False
SetDefaultTimeButton.Enabled = False
SetParameters.Enabled = False
TextBoxTime.Text = System.DateTime.UtcNow
timeToWait = globalTimeLeft
For i = 0 To timeLeft
wait()
i += 1
timeToWait -= 1
timeLabel.Text = timeToWait & " seconds"
Next
Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
For x = 0 To img.Width - 1
For y = 0 To img.Height - 1
Dim pixelColor As Bgr = img(y, x)
If (pixelColor.Blue >= 200 And pixelColor.Blue <= 255) And
(pixelColor.Green >= 200 And pixelColor.Green <= 255) And (pixelColor.Red >= 200 And pixelColor.Red <= 255) Then
pixelColor.Blue = 255
pixelColor.Green = 255
pixelColor.Red = 255
img(y, x) = pixelColor
Else
pixelColor.Blue = 0
pixelColor.Green = 0
pixelColor.Red = 0
img(y, x) = pixelColor
End If
Next
Next
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End Sub
函数 wait() 如下所示:
Private Sub wait()
Dim seconds As Integer = 1
For i As Integer = 0 To seconds * 100
System.Threading.Thread.Sleep(10)
'Application.DoEvents()
Next
End Sub
也许你会问,为什么不用定时器呢?这是因为使用计时器我遇到了完全相同的问题。下面是使用定时器的代码:
'This function will start the activity of the form
Private Sub startButton_Click() Handles startButton.Click
Dim timeToWait As Integer
PictureBox1.Image = Nothing
If globalGMT <> Nothing And globalLatitude <> Nothing And globalLongitude <> Nothing Then
'If TextBox_GMT.Text IsNot Nothing And TextBox_LAT.Text IsNot Nothing And TextBox_LON.Text IsNot Nothing Then
SunPosition(globalGMT, globalLatitude, globalLongitude, ELEVACIONDELSOL, AZIMUTDELSOL)
End If
startButton.Enabled = False
SetDefaultTimeButton.Enabled = False
SetParameters.Enabled = False
TextBoxTime.Text = System.DateTime.UtcNow
StartButtonTimer.Start()
End Sub
'This function will start the timer of the form
Private Sub StartButtonTimer_Tick() Handles StartButtonTimer.Tick
Dim X As Integer
Dim Y As Integer
If timeLeft > 0 Then
timeLeft -= 1
timeLabel.Text = timeLeft & " seconds"
'DLE prueba tomar foto después del tiempo especificado - pongo a negro el fondo del picturebox
PictureBox1.BackColor = Color.Black
Else
'DLE prueba tomar foto después del tiempo especificado - hago foto de lo que ve la camara
Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
For X = 0 To img.Width - 1
For Y = 0 To img.Height - 1
Dim pixelColor As Bgr = img(Y, X)
If (pixelColor.Blue >= 200 And pixelColor.Blue <= 255) And
(pixelColor.Green >= 200 And pixelColor.Green <= 255) And
(pixelColor.Red >= 200 And pixelColor.Red <= 255) Then
pixelColor.Blue = 255
pixelColor.Green = 255
pixelColor.Red = 255
img(Y, X) = pixelColor
Else
pixelColor.Blue = 0
pixelColor.Green = 0
pixelColor.Red = 0
img(Y, X) = pixelColor
End If
Next
Next
StartButtonTimer.Stop()
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End If
End Sub
函数 SetForm() 只启用部分按钮。
问题是:
我拍第一张照片 - 图片框显示第一张照片。
我拍第二张照片 - 图片框再次显示第一张照片。
我拍了第三张照片 - 图片框显示了第二张照片。
我拍了第四张照片 - 图片框显示了第三张照片。
...
...
拍照后,我只识别出一种颜色,并以白色显示该颜色,将图片的其余部分显示为黑色(如果有人需要此解释)
感谢您能给我的任何帮助!
编辑:如果我在函数末尾添加这一行:Dim image As Image(Of Bgr, Byte) = capturez.QueryFrame(),效果很好:
...
...
Next
StartButtonTimer.Stop()
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End If
Dim image As Image(Of Bgr, Byte) = capturez.QueryFrame()
End Sub
结束Class
我不是无缘无故地使用最后一个变量,只是我在没有使用它的情况下声明它。我不明白为什么用这条线效果很好,当我擦掉它时,它不起作用..
我花了一段时间才弄明白这一点,但我认为问题在于您没有 Dispose
捕获。由于您仅在单击按钮时捕获一帧(并且您没有实时网络摄像头流),因此您应该在使用 Capture
对象后 Dispose
。现在发生的是你请求一个新框架,Capture
对象将 return 旧框架,然后开始检索另一个为下一次使用做好准备的框架。因此,如果您在方法的末尾放置另一个 QueryFrame()
它会再次起作用,因为旧框架已被覆盖。
这应该可以解决您的问题:
'Make sure you can use your retrieved image even after the dispose
Dim img As Image(Of Bgr, Byte);
'Create a new capture object
Using capturez As New Capture
'Since it's a new object the webcam is forced to retrieve a frame now
'Also, use Copy() to make sure your image is still available after diposing
img = capturez.QueryFrame().Copy()
End Using 'Dispose the object now
'Now do with your img object whatever you want!
我在使用网络摄像头、opencv 和 emgucv 拍摄照片时遇到了一个特殊问题。
我以前用过这个功能,一直很好用,但是现在不知道为什么,图片框显示的是之前拍的照片。让我解释一下:
我启动程序 - 我按下按钮并在拍照前等待几秒钟 - 我使用 img = capturez.QueryFrame() 拍照 - 我在 PictureBox 中显示图片。这是代码:
Private Sub startButton_Click() Handles startButton.Click
Dim timeToWait As Integer
PictureBox1.Image = Nothing
If globalGMT <> Nothing And globalLatitude <> Nothing And globalLongitude <> Nothing Then
'If TextBox_GMT.Text IsNot Nothing And TextBox_LAT.Text IsNot Nothing And TextBox_LON.Text IsNot Nothing Then
SunPosition(globalGMT, globalLatitude, globalLongitude, ELEVACIONDELSOL, AZIMUTDELSOL)
End If
startButton.Enabled = False
SetDefaultTimeButton.Enabled = False
SetParameters.Enabled = False
TextBoxTime.Text = System.DateTime.UtcNow
timeToWait = globalTimeLeft
For i = 0 To timeLeft
wait()
i += 1
timeToWait -= 1
timeLabel.Text = timeToWait & " seconds"
Next
Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
For x = 0 To img.Width - 1
For y = 0 To img.Height - 1
Dim pixelColor As Bgr = img(y, x)
If (pixelColor.Blue >= 200 And pixelColor.Blue <= 255) And
(pixelColor.Green >= 200 And pixelColor.Green <= 255) And (pixelColor.Red >= 200 And pixelColor.Red <= 255) Then
pixelColor.Blue = 255
pixelColor.Green = 255
pixelColor.Red = 255
img(y, x) = pixelColor
Else
pixelColor.Blue = 0
pixelColor.Green = 0
pixelColor.Red = 0
img(y, x) = pixelColor
End If
Next
Next
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End Sub
函数 wait() 如下所示:
Private Sub wait()
Dim seconds As Integer = 1
For i As Integer = 0 To seconds * 100
System.Threading.Thread.Sleep(10)
'Application.DoEvents()
Next
End Sub
也许你会问,为什么不用定时器呢?这是因为使用计时器我遇到了完全相同的问题。下面是使用定时器的代码:
'This function will start the activity of the form
Private Sub startButton_Click() Handles startButton.Click
Dim timeToWait As Integer
PictureBox1.Image = Nothing
If globalGMT <> Nothing And globalLatitude <> Nothing And globalLongitude <> Nothing Then
'If TextBox_GMT.Text IsNot Nothing And TextBox_LAT.Text IsNot Nothing And TextBox_LON.Text IsNot Nothing Then
SunPosition(globalGMT, globalLatitude, globalLongitude, ELEVACIONDELSOL, AZIMUTDELSOL)
End If
startButton.Enabled = False
SetDefaultTimeButton.Enabled = False
SetParameters.Enabled = False
TextBoxTime.Text = System.DateTime.UtcNow
StartButtonTimer.Start()
End Sub
'This function will start the timer of the form
Private Sub StartButtonTimer_Tick() Handles StartButtonTimer.Tick
Dim X As Integer
Dim Y As Integer
If timeLeft > 0 Then
timeLeft -= 1
timeLabel.Text = timeLeft & " seconds"
'DLE prueba tomar foto después del tiempo especificado - pongo a negro el fondo del picturebox
PictureBox1.BackColor = Color.Black
Else
'DLE prueba tomar foto después del tiempo especificado - hago foto de lo que ve la camara
Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
For X = 0 To img.Width - 1
For Y = 0 To img.Height - 1
Dim pixelColor As Bgr = img(Y, X)
If (pixelColor.Blue >= 200 And pixelColor.Blue <= 255) And
(pixelColor.Green >= 200 And pixelColor.Green <= 255) And
(pixelColor.Red >= 200 And pixelColor.Red <= 255) Then
pixelColor.Blue = 255
pixelColor.Green = 255
pixelColor.Red = 255
img(Y, X) = pixelColor
Else
pixelColor.Blue = 0
pixelColor.Green = 0
pixelColor.Red = 0
img(Y, X) = pixelColor
End If
Next
Next
StartButtonTimer.Stop()
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End If
End Sub
函数 SetForm() 只启用部分按钮。
问题是: 我拍第一张照片 - 图片框显示第一张照片。 我拍第二张照片 - 图片框再次显示第一张照片。 我拍了第三张照片 - 图片框显示了第二张照片。 我拍了第四张照片 - 图片框显示了第三张照片。 ... ... 拍照后,我只识别出一种颜色,并以白色显示该颜色,将图片的其余部分显示为黑色(如果有人需要此解释)
感谢您能给我的任何帮助!
编辑:如果我在函数末尾添加这一行:Dim image As Image(Of Bgr, Byte) = capturez.QueryFrame(),效果很好:
...
...
Next
StartButtonTimer.Stop()
PictureBox1.Image = img.ToBitmap
startButton.Enabled = True
SetParameters.Enabled = True
SetDefaultTimeButton.Enabled = True
SetForm()
End If
Dim image As Image(Of Bgr, Byte) = capturez.QueryFrame()
End Sub
结束Class
我不是无缘无故地使用最后一个变量,只是我在没有使用它的情况下声明它。我不明白为什么用这条线效果很好,当我擦掉它时,它不起作用..
我花了一段时间才弄明白这一点,但我认为问题在于您没有 Dispose
捕获。由于您仅在单击按钮时捕获一帧(并且您没有实时网络摄像头流),因此您应该在使用 Capture
对象后 Dispose
。现在发生的是你请求一个新框架,Capture
对象将 return 旧框架,然后开始检索另一个为下一次使用做好准备的框架。因此,如果您在方法的末尾放置另一个 QueryFrame()
它会再次起作用,因为旧框架已被覆盖。
这应该可以解决您的问题:
'Make sure you can use your retrieved image even after the dispose
Dim img As Image(Of Bgr, Byte);
'Create a new capture object
Using capturez As New Capture
'Since it's a new object the webcam is forced to retrieve a frame now
'Also, use Copy() to make sure your image is still available after diposing
img = capturez.QueryFrame().Copy()
End Using 'Dispose the object now
'Now do with your img object whatever you want!