jeffbass / imagezmq

A set of Python classes that transport OpenCV images from one computer to another using PyZMQ messaging.
MIT License
1.01k stars 160 forks source link

ImageHub `while` loop waits? #85

Closed brett-doffing closed 7 months ago

brett-doffing commented 7 months ago

I have modified the code a little bit on my end (made a Hub class), but this is generally the same implementation, so when running the hub,

image_hub = imagezmq.ImageHub()
while True:  # show streamed images until Ctrl-C
    rpi_name, image = image_hub.recv_image()

is it the case that the while loop should not continue to run if the hub has yet to receive an image? It seems to be the case for me, and I am curious how I might be able somehow bypass this sort of "waiting"? I am creating a GUI, and it seems to hang while waiting for an image, although once an image has been received, all is well.

jeffbass commented 7 months ago

The rpi_name, image = image_hub.recv_image() statement is a "blocking" statement. That is, the statement will wait to return the text, image tuple until one is actually received. Each time a text, image tuple is received, the statement completes and the while loop iterates. In my own applications, I specifically want the loop to wait until the next image is received.

There may be other ways to call image_hub.recv_image() so that it is not blocking, such as putting it in a thread that updates a queue. But I haven't tried that.

In all my programs, the blocking nature of the image_hub.recv_image() is the desired behavior.

shumwaymark commented 7 months ago

ZMQ supports a polling operation against sockets. This allows for not calling your recv( ) until there is actually something waiting.

https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/multisocket/zmqpoller.html

brett-doffing commented 7 months ago

Working on threading, which has alleviated the problem of blocking, however the image frames seem to be a bit glitchy with very small interruptions. Trying to slap together a GUI with Tkinter.

brett-doffing commented 7 months ago

Thought it might be useful on SO with respect to Tkinter and threading:

https://stackoverflow.com/q/77565550/22099779

shumwaymark commented 7 months ago

I have had great success with using this also. All UI controls and updating take place in the main thread. A single background thread does the blocking I/O.

https://gist.github.com/shumwaymark/16787e48d4917bbeefc3d469f0636da1

See line 141 for the read and process loop with the blocking I/O. The imageZMQ recv() is encapsulated by the DataFeed class. The background thread sets a "Data Ready" event whenever new image data is available. See the update() routine at the bottom of the module for how this is consumed.

brett-doffing commented 7 months ago

Threading alone seemed to work in my case. Oddly enough, to solve my flickering issue, I merely use a Label or a Button in Tkinter, and set its image property to the frame, versus using a Canvas?!?