There's a subtle yet significant difference that becomes more obvious when taking a closer look at the documentation for each of the two methods.

  • grab "only" gets the image from the camera and holds it for further processing:

    The methods/functions grab the next frame from video file or camera and return true (non-zero) in the case of success. [...] you call VideoCapture::grab() for each camera and after that call the slower method VideoCapture::retrieve() to decode and get frame from each camera.

    In this case, you still have to retrieve the frame (i.e. "decode and get") from OpenCV so that you can work with it. grab only returns a boolean that indicates whether OpenCV was able to get the frame from the camera - the return parameter in this case is not the frame.

  • read combines both grab and retrieve operations into one command and returns the already decoded frame:

    The methods/functions combine VideoCapture::grab() and VideoCapture::retrieve() in one call. This is the most convenient method for reading video files or capturing data from decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer.

    This method returns the actual frame back to your application so you don't have to worry about checking the boolean parameter and writing an additional line of code to get the frame back by OpenCV.

Depending on your application it may be easier to just use read as it will likely save you one or two lines of code.

Answer from m_____z on Stack Overflow
🌐
OpenCV
docs.opencv.org › 3.0-beta › modules › videoio › doc › reading_and_writing_video.html
Reading and Writing Video — OpenCV 3.0.0-dev documentation
Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the correct way of retrieving data from it is to call VideoCapture::grab first and then call VideoCapture::retrieve() one or more times with different values of the channel parameter.
🌐
GitHub
gist.github.com › aarmea › 629e59ac7b640a60340145809b1c9013
OpenCV Python example · GitHub
Hi aarmea, Thanks for the post. It is really helpful. I'm also using ELP dual camera but unable to capture both the images simultaneously. I tried to run your code capture.py but it is exiting from the condition check by printing "No more frames" since it is unable to get both left and right grab.
Discussions

python - Difference between video capture read and grab - Stack Overflow
I'm not doing nothing in particular, but i'm reading the opencv documentation and I can't understand the difference between the method read and grab from the VideoCapture, here this what they do: ... More on stackoverflow.com
🌐 stackoverflow.com
cv2.VideoCapture.retrieve handles passed index contrary to documentation
System information (version) OpenCV => 4.0.0-beta Operating System / Platform => OSX 10.14.1 Beta (18B45d) Compiler => Xcode (ver 10.0.0.10001145) Python => 3.7.0 Detailed description W... More on github.com
🌐 github.com
0
October 27, 2018
c++ - OpenCV Videocapture Grab and Retrieve - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Stack Overflow for Teams is now called Stack Internal. Bring the best of human thought and AI automation together at your work More on stackoverflow.com
🌐 stackoverflow.com
python - How do I use the grab and retrieve open cv functions? - Stack Overflow
I'm currently using opencv with python to run two webcams. These webcams will each take a picture. I'd like to run them on separate threads in order to sync the pictures as closely as possible. I'm using videocapture::grab() and videocapture::retreive() but I'm not sure if I'm using them properly ... More on stackoverflow.com
🌐 stackoverflow.com
October 13, 2015
🌐
OpenCV
docs.opencv.org › 3.4.20 › d8 › dfe › classcv_1_1VideoCapture.html
OpenCV: cv::VideoCapture Class Reference
That is, you call VideoCapture::grab() for each camera and after that call the slower method VideoCapture::retrieve() to decode and get frame from each camera. This way the overhead on demosaicing or motion jpeg decompression etc. is eliminated and the retrieved frames from different cameras ...
Top answer
1 of 2
28

There's a subtle yet significant difference that becomes more obvious when taking a closer look at the documentation for each of the two methods.

  • grab "only" gets the image from the camera and holds it for further processing:

    The methods/functions grab the next frame from video file or camera and return true (non-zero) in the case of success. [...] you call VideoCapture::grab() for each camera and after that call the slower method VideoCapture::retrieve() to decode and get frame from each camera.

    In this case, you still have to retrieve the frame (i.e. "decode and get") from OpenCV so that you can work with it. grab only returns a boolean that indicates whether OpenCV was able to get the frame from the camera - the return parameter in this case is not the frame.

  • read combines both grab and retrieve operations into one command and returns the already decoded frame:

    The methods/functions combine VideoCapture::grab() and VideoCapture::retrieve() in one call. This is the most convenient method for reading video files or capturing data from decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer.

    This method returns the actual frame back to your application so you don't have to worry about checking the boolean parameter and writing an additional line of code to get the frame back by OpenCV.

Depending on your application it may be easier to just use read as it will likely save you one or two lines of code.

2 of 2
10

Adding some info on accepted answer: Also reading from openCV documentation, you should use grab if you need to synchronize images from different devices and don't have triggers connecting cameras.

grab() takes less time than read(), so you should grab() all devices (reading times would be closer) and them retrieve() each frame later. Again, this is useful f you need your feeds synchronized, for applications like a custom made stereo camera.

    while True:
      # grab all devices
      device1.grab()
      device2.grab()
      ...
      # retrieve them later
      device1.retrieve(frame_dev1)
      device2.retrieve(frame_dev2)
      ...
🌐
GitHub
github.com › opencv › opencv › issues › 12968
cv2.VideoCapture.retrieve handles passed index contrary to documentation · Issue #12968 · opencv/opencv
October 27, 2018 - capture = cv2.VideoCapture(cv2.CAP_OPENNI2) capture.grab() ret_d, depth_map = capture.retrieve(None, cv2.CAP_OPENNI_DEPTH_MAP) ret_f, frame = capture.retrieve(None, cv2.CAP_OPENNI_BGR_IMAGE) print(cv2.CAP_OPENNI_BGR_IMAGE, cv2.CAP_OPENNI_DEPTH_MAP) print(frame == depth_map)
Author: opencv
🌐
Jancy Standard Library
vovkos.github.io › doxyrest-showcase › opencv › sphinx_rtd_theme › class_cv_VideoCapture.html
class cv::VideoCapture — OpenCV Documentation
Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the correct way of retrieving data from it is to call VideoCapture::grab() first and then call VideoCapture::retrieve() one or more times with different values of the channel parameter.
🌐
Stack Overflow
stackoverflow.com › questions › 37364490 › opencv-videocapture-grab-and-retrieve
c++ - OpenCV Videocapture Grab and Retrieve - Stack Overflow
OpenCV 4.0 -- Waiting to capture from VideoCapture (1 answer) Closed 6 months ago. I have a loop from which nextFrame is called, now the issue lies with what the imshow actually shows. I specifically want one image every time i call cap.grab() and cap.retrieve(), but it seems to have this buffer internally in the "cap" object, so instead on getting individual instantaneous images i would get a sequence/images of images when i click through the images, then after 3/4 frames a new sequence.
🌐
OpenCV
docs.opencv.org › 4.x › javadoc › org › opencv › videoio › VideoCapture.html
VideoCapture (OpenCV 4.14.0 Java documentation)
That is, you call VideoCapture::grab() for each camera and after that call the slower method VideoCapture::retrieve() to decode and get frame from each camera. This way the overhead on demosaicing or motion jpeg decompression etc. is eliminated and the retrieved frames from different cameras ...
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 33107981 › how-do-i-use-the-grab-and-retrieve-open-cv-functions
python - How do I use the grab and retrieve open cv functions? - Stack Overflow
October 13, 2015 - import threading import time import sys import cv2 from multiprocessing.pool import ThreadPool count = 0 video_capture1 = cv2.VideoCapture(1) video_capture2 = cv2.VideoCapture(2) #camera1 class myThread1(threading.Thread): def __init__(self, threadID, name, device): threading.Thread.__init__(self) self.threadID = threadID self.name = name def run(self): print "Starting " + self.name # Get lock to synchronize threads # threadLock.acquire() camCapture(self.name, 1) # Free lock to release next thread # threadLock.release() def camCapture(threadName, device): if video_capture1.grab(): print "frame
🌐
Huihoo
docs.huihoo.com › opencv › 3.0 › d8 › dfe › classcv_1_1VideoCapture.html
OpenCV: cv::VideoCapture Class Reference - Huihoo
The methods/functions combine VideoCapture::grab and VideoCapture::retrieve in one call. This is the most convenient method for reading video files or capturing data from decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer. ... OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video capturing structure...
🌐
Gregorkovalcik
gregorkovalcik.github.io › opencv_contrib › d8 › dfe › classcv_1_1VideoCapture.html
OpenCV: cv::VideoCapture Class Reference
September 4, 2016 - The methods/functions combine VideoCapture::grab and VideoCapture::retrieve in one call. This is the most convenient method for reading video files or capturing data from decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer. ... OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video capturing structure...
Top answer
1 of 5
49

I think the solution mentioned in the question, namely having a separate thread that clears the buffer, is the easiest non-brittle solution for this. Here reasonably nice (I think) code for this:

import cv2, queue, threading, time

# bufferless VideoCapture
class VideoCapture:

  def __init__(self, name):
    self.cap = cv2.VideoCapture(name)
    self.q = queue.Queue()
    t = threading.Thread(target=self._reader)
    t.daemon = True
    t.start()

  # read frames as soon as they are available, keeping only most recent one
  def _reader(self):
    while True:
      ret, frame = self.cap.read()
      if not ret:
        break
      if not self.q.empty():
        try:
          self.q.get_nowait()   # discard previous (unprocessed) frame
        except queue.Empty:
          pass
      self.q.put(frame)

  def read(self):
    return self.q.get()

cap = VideoCapture(0)
while True:
  time.sleep(.5)   # simulate time between events
  frame = cap.read()
  cv2.imshow("frame", frame)
  if chr(cv2.waitKey(1)&255) == 'q':
    break

The frame reader thread is encapsulated inside the custom VideoCapture class, and communication with the main thread is via a queue.

I posted very similar code for a node.js question, where a JavaScript solution would have been better. My comments on another answer to that question give details why a non-brittle solution without separate thread seems difficult.

An alternative solution that is easier but supported only for some OpenCV backends is using CAP_PROP_BUFFERSIZE. The 2.4 docs state it is "only supported by DC1394 [Firewire] v 2.x backend currently." For Linux backend V4L, according to a comment in the 3.4.5 code, support was added on 9 Mar 2018, but I got VIDEOIO ERROR: V4L: Property <unknown property string>(38) not supported by device for exactly this backend. It may be worth a try first; the code is as easy as this:

cap.set(cv2.CAP_PROP_BUFFERSIZE, 0)
2 of 5
15

Here's a simplified version of Ulrich's solution. OpenCV's read() function combines grab() and retrieve() in one call, where grab just loads the next frame in memory, and retrieve decodes the latest grabbed frame (demosaicing & motion jpeg decompression).

We're only interested in decoding the frame we're actually reading, so this solution saves some CPU, and removes the need for a queue

import cv2
import threading


# bufferless VideoCapture
class VideoCapture:
    def __init__(self, name):
        self.cap = cv2.VideoCapture(name)
        self.lock = threading.Lock()
        self.t = threading.Thread(target=self._reader)
        self.t.daemon = True
        self.t.start()

    # grab frames as soon as they are available
    def _reader(self):
        while True:
            with self.lock:
                ret = self.cap.grab()
            if not ret:
                break

    # retrieve latest frame
    def read(self):
        with self.lock:
            _, frame = self.cap.retrieve()
        return frame

EDIT: Following Arthur Tacca's comment, added a lock to avoid simultaneous grab & retrieve, which could lead to a crash as OpenCV isn't thread-safe.

🌐
Rust
docs.rs › opencv › latest › opencv › videoio › struct.VideoCapture.html
VideoCapture in opencv::videoio - Rust
The primary use of the function is in multi-camera environments. The method fills the ready state vector, grabs video frame, if camera is ready. After this call use VideoCapture::retrieve() to decode and fetch frame data.
🌐
OpenCV
forum.opencv.org › t › grab-raw-data-in-videocapture › 508
Grab raw data in VideoCapture - videoio - OpenCV
December 23, 2020 - In VideoCapture class one can only get decoded image, but I want to grab raw jpg data. Grab method seems can do this but the output is only a status flag. Can you kindly add a method that can get the raw data of grab met…
🌐
Cloudinary
cloudinary.com › home › getting started with cv2 video capture in python
Getting Started with cv2 Video Capture in Python | Cloudinary
April 12, 2026 - OpenCV buffers frames internally, and if you’re storing frames for future analysis, you’ll need to explicitly copy them to avoid corrupted data or memory errors. In Python, the cv2.VideoCapture() function from the OpenCV library is commonly used to work with video.
🌐
Reddit
reddit.com › r/opencv › [question] how do i get a fresh frame taken after calling cv.videocapture.read ?
r/opencv on Reddit: [Question] How do I get a fresh frame taken AFTER calling cv.VideoCapture.read ?
August 14, 2021 -

I'm reading a frame from a usb webcam, but I need the frame to be guaranteed to be taken by the camera after I request it. Unfortunately, I get the last buffed frame. What I'm doing now is calling read twice, once to flush the buffer, and once to wait for and get another image. This works pretty well but seems to fail 2% of the time or so, and cuts my frame rate in half (under ideal circumstances it would be slower but not by that much if I'm thinking clearly). I just don't understand what it's actually doing. How do I make sure to get the next available frame that wasn't taken before I called cv.VideoCapture.read ?

Top answer
1 of 2
1
Do a search for CAP_PROP_BUFFERSIZE. You want to set this to 1. For example: https://stackoverflow.com/a/63057626/13022
2 of 2
1
There are two possibilities here: Reduce the frame buffer length to 1, so you can only ever have the latest frame (unfortunately not always obvious or even possible to do, and sometimes costs framerate (e.g. achieving it by only requesting stills when you need them isn’t always a viable solution if you want to stream and process video)) grab frames repeatedly in the background at faster than the video framerate and then only retrieve the latest frame when you need your next one If you’re using Python you can do option 2 with the Camera class of my library pythonic-cv , which uses a thread for grabbing frames and provides an iterator that retrieves just the latest frame when you need it/ask for it. If you’re not using python then you can set up your own thread for that, or if you know how long your processing tends to take you can potentially add grabs at multiple points throughout, which is likely easier to set up when starting out but harder to maintain as you change your processing or add extra functionality around it. Edit: as a note, a read in OpenCV is just a grab followed by a retrieve, which is often convenient if you need to view/process every frame that you get. It’s useful to split out the calls if you don’t need some of the frames (grab just says “I want a frame”, retrieve actually decides it into an array of pixels in memory), or if you’re doing things where the timing of when each image is taken needs to be precise relative to something else (e.g. for a stereo camera setup you want both images taken at exactly the same time, so don’t want to decode one before starting to take the next one)
🌐
Python Programming
pythonprogramming.net › loading-video-python-opencv-tutorial
Loading Video Source OpenCV Python Tutorial
First, we import numpy and cv2, nothing fancy there. Next, we cay cap = cv2.VideoCapture(0). This will return video from the first webcam on your computer.
🌐
OpenCV
docs.opencv.org › 3.4.20 › dd › d43 › tutorial_py_video_display.html
OpenCV: Getting Started with Videos
Full details can be seen here: cv::VideoCapture::get(). Some of these values can be modified using cap.set(propId, value). Value is the new value you want. For example, I can check the frame width and height by cap.get(cv.CAP_PROP_FRAME_WIDTH) and cap.get(cv.CAP_PROP_FRAME_HEIGHT).