tiagocoutinho / linuxpy

Human friendly interface to linux subsystems using python
https://tiagocoutinho.github.io/linuxpy/
GNU General Public License v3.0
28 stars 3 forks source link

How to Reduce Latency for First Frame Capture with UVC Camera? #13

Closed kboseong closed 3 months ago

kboseong commented 3 months ago

First of all, thank you for the excellent work you are doing with this project.

I am currently working on a project where I need to capture a photo as soon as an object is detected by a specific sensor. After capturing the photo, the system should wait for the next trigger. I am using a regular UVC camera instead of a machine vision camera and need the fastest possible frame acquisition method in Python.

With the code below, it takes about 1 second to obtain the first frame from the device. While the time to acquire subsequent frames is significantly reduced, I need to speed up the acquisition of the first frame.

cam = Device.from_id(0) cam.open() source = VideoCapture(cam)

with source: for frame in source: data = frame.data break

tiagocoutinho commented 3 months ago

That's a very good question. IMHO, there are 2 things that take time:

  1. opening the device object
  2. initialize a capture stream

The first you already solved by preemptively opening the device.

The second can be solved by acquiring a dumb image at the start:

cam = Device.from_id(0)
cam.open()  # takes ~0.12s on my laptop uvc cam
stream = iter(cam)
next(stream) # take a dumb frame just to arm de camera (takes ~0.3s for me)

# now, each time you receive a trigger you can take the image with:
def on_trigger():
    frame = next(stream)

# Don't forget to close the stream and device when you're done with it!
def at_end():
    stream.close()
    cam.close()

In the example above I didn't use VideoCapture because there was no need to adjust capture parameters but you could do the same with VideoCapture if you need it. In this case you don't need the initial dumb image because arming the camera is done on video capture open:

cam = Device.from_id(0)
cam.open()
source = VideoCapture(cam)
source.open()
stream = iter(source)

def at_end():
    stream.close()
    source.close()
    cam.close()
kboseong commented 3 months ago

Great! Your explanation and code suggestions are incredibly helpful.

Thanks again for your assistance and for the great work on this project.

kboseong commented 1 month ago

Hi, how can I free camera buffer memory before I call next(stream)? Thanks