10

I am using OpenCV2 to take some timelapse photos with a webcam. I want to extract the most recent view seen by the webcam. I try to accomplish this like so.

import cv2
a = cv2.VideoCapture(1)
ret, frame = a.read()
#The following garbage just shows the image and waits for a key press
#Put something in front of the webcam and then press a key
cv2.imshow('a',frame); cv2.waitKey(0); cv2.destroyAllWindows(); [cv2.waitKey(25) for i in range(10)]
#Since something was placed in front of the webcam we naively expect
#to see it when we read in the next image. We would be wrong.
ret, frame = a.read()
cv2.imshow('a',frame); cv2.waitKey(0); cv2.destroyAllWindows(); [cv2.waitKey(25) for i in range(10)]

Except that the image placed in front of the webcam does not show. It's almost as if there's some kind of buffer...

So I purge that buffer, like so:

import cv2
a = cv2.VideoCapture(1)
ret, frame = a.read()
#Place something in front of the webcam and then press a key
cv2.imshow('a',frame); cv2.waitKey(0); cv2.destroyAllWindows(); [cv2.waitKey(25) for i in range(10)]

#Purge the buffer
for i in range(10): #Annoyingly arbitrary constant
  a.grab()

#Get the next frame. Joy!
ret, frame = a.read()
cv2.imshow('a',frame); cv2.waitKey(0); cv2.destroyAllWindows(); [cv2.waitKey(25) for i in range(10)]

Now this works, but it's annoyingly unscientific and slow. Is there a way to ask specifically for only the most recent image in the buffer? Or, baring that, a better way to purge the buffer?

Richard
  • 56,349
  • 34
  • 180
  • 251

2 Answers2

1

I have read that in the VideoCapture object there is a 5 frame buffer, and there is the .grab method that takes the frame but does not decode it.

So you can

cap = cv2.VideoCapture(0)
for i in xrange(4):
    cap.grab()
ret, frame = cap.read()
...
Richard
  • 56,349
  • 34
  • 180
  • 251
Ilya Pukhov
  • 153
  • 1
  • 11
  • 2
    Well here is the mentioning of the buffer and the way to set up it's size (did not work for me) https://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-set – Ilya Pukhov Jan 18 '18 at 12:33
  • 2
    Here is the mentionig of 5 frames in particular http://answers.opencv.org/question/29957/highguivideocapture-buffer-introducing-lag/ – Ilya Pukhov Jan 18 '18 at 12:34
  • this response mentions a buffer of length 5 that can't be changed from CV http://answers.opencv.org/question/100129/how-to-clear-frames-from-buffer-with-usb-webcam/?answer=100133#post-id-100133 – Cory Jul 25 '18 at 17:55
  • This wouldnt work for me since when I grab I want the image right at that instant and the loop would slow down that grab. – Lightsout Aug 16 '18 at 21:30
  • xrange? Really? Python 2 is dead! – Megan Caithlyn Jul 13 '20 at 20:13
-2

I found a bit of code from Capture single picture with opencv that helps. I modified it so that it continuously displays the most recent image captured. It doesn't seem to have a buffer problem, but I might have misunderstood your question.

import numpy as np
import cv2

cap = cv2.VideoCapture(0) # video capture source camera (Here webcam of laptop) 
ret,frame = cap.read() # return a single frame in variable `frame`


while(True):
    ret,frame = cap.read() # return a single frame in variable `frame
    cv2.imshow('img1',frame) #display the captured image
    if cv2.waitKey(1) & 0xFF == ord('y'): #save on pressing 'y' 
        cv2.imwrite('images/c1.png',frame)
        cv2.destroyAllWindows()
        break

cap.release()
Community
  • 1
  • 1
user27443
  • 424
  • 4
  • 10
  • It may not have a buffer problem because it is continuously emptying the buffer. The buffering issue shows up for me because there's a delay between image captures. – Richard Jan 01 '17 at 10:01