After changing resolution, capture.read() usually fails unless I first call capture.isOpened()

New user, so apologies in advance if this is stupid/known.
I am using version 3.4.16 running under python 3.9 in a jupyter notebook.

I am grabbing frames from a cheap USB microscope (DNT DigiMicro Scale, 2M pixels).
Everything works fine at supported resolutions up to 800x600 pixels. However, if I set the resolution to higher (supported) values, capture.read() usually fails UNLESS I first call capture.isOpened(). To be more precise, the following works correctly every time:

capture = cv2.VideoCapture(cam_port)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1600)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 1200)
check = capture.isOpened()
grabbed, frame = capture.read()

My issue: if I comment out the capture.isOpened() line, then the capture.read() fails about 80% of the time. About 20% of the time, the code works correctly if the capture.isOpened() line is commented out.

I wanted to report this and ask if it is a known issue. Could it be a timing problem or race condition? I have not tried to insert a sleep() in place of the capture.isOpened() but would be happy to experiment if that’s helpful.

Thanks,
Bruce

Adding sleep() anywhere is to be avoided, because there will be time when the delay is not long enough… If isOpened works, that’s fine - a deterministic way to finalize the change.

sleeping should not do anything. all the involved calls, if they have to, will wait for appropriate events/completion. if a sleep() did affect the behavior, that would be a bug in OpenCV. please perform that experiment. I think it won’t do anything.

perhaps calling capture.get(...) might affect the situation similarly to the isOpened() call though?

if you really need to call isOpened(), that is a curious behavior. It’s not supposed to “do” anything, yet it seems to. that also would be a bug in OpenCV.

consider filing an issue about this. be as detailed as you can about what’s required to reproduce this behavior. if possible, do actually reproduce this on a different system, to make sure you’ve got the relevant factors figured out.

oh, and 3.4.16 is a year or two out of date. reproduce with a current build. there should be no issues moving from 3.x to 4.x, apart from one little thing related to findContours()

Thanks for the helpful comments. I will see if I can reproduce the behaviour with 4.x. If so, I will write a minimal program to reproduce it, and come back here for advice about how to file an issue.

Meanwhile I played around a bit more with my 3.4.16 installation. The code below shows that often two to four calls to capture.read() are needed before it returns correctly. Any idea why that would be? Am I correct that this should be a deterministic finite-state machine? Or is there some “random” element which I am unaware of?

Cheers,
Bruce

capture = cv2.VideoCapture(cam_port)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1600)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 1200)
grabbed = False
counter = 0
while (grabbed == False):
     grabbed, frame = capture.read()
     counter += 1
print("succeeded on attempt: ", counter)

hahaha computers are the most complex things ever produced by humanity. everyone wishes that these things behaved predictably… but they’re made by humans and we leave a trail of faults on everything we make.

repeating a read() call until it works? sounds like something’s kinda broken somewhere in there.

sounds like some “random element”, race conditions, I don’t know.

did you state your operating system yet?

does this happen with any other USB-attached video camera (webcam)?

would be useful if you could nail down the video backend (pass apiPreference to VideoCapture creation). without that one is selected automatically, which is usually okay. the result of the selection can be queried with capture.getBackendName(). if that says "FOO", the backend would be CAP_FOO

I am happy to report that this problem does NOT appear on 4.6.0. Instead, the device opens correctly, every time, as it should.