问题
I am having a special problem with capturing a picture using my webcam, opencv and emgucv.
I have used this function before, and always worked well, but now, I don't know why, the picturebox is showing me the picture taken before. Let me explain:
I start the program - I press the button and wait some seconds before the picture is taken - I take the picture using img = capturez.QueryFrame() - I display the picture in the PictureBox. Here is the code:
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
The function wait() looks like this:
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
Maybe you can ask, why don't you use a timer for that? It is because with the timer I am having exactly the same problem. Here is the code using the timer:
'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
The function SetForm() only enables some buttons.
The problem is: I take the first picture - The picturebox shows the first picture. I take the second picture - The picturebox shows the first picture again. I take the third picture - The picturebox shows the second picture. I take the fourth picture - The picturebox shows the third picture. ... ... After taking the picture, I'm only recognizing a colour and show that colour in white and the rest of the picture in black (if someone needs this explanation)
Thanks for any help you could give me!
EDIT: if I add this line at the end of the function: Dim image As Image(Of Bgr, Byte) = capturez.QueryFrame(), it works well:
...
...
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
End Class
I don't use this last variable for nothing, only I am declaring it without use it. I don't understand why with this line it works well, and when I erase it, it doesn´t works..
回答1:
It took me a while to figure this about, but I believe the problem is that you don't Dispose
your capture. Since you only capture one frame on a button click (and you don't have a live webcam stream) you should Dispose
of your Capture
object after you use it. What happens now is that you ask for a new frame, the Capture
object will return the old frame and then starts retrieving another one that's ready for next use. Therefore, if you put another QueryFrame()
at the end of your method it works again, since the old frame is overwritten.
This should solve your problem:
'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!
来源:https://stackoverflow.com/questions/43211664/taking-one-capture-and-displaying-the-one-before-vb-opencv