show OpenCV frames without while loop - python

I'm trying to add a camera image showing component to an existing python program that shows multiple input in real time from various hardware devices.
To that end, I need to use openCV's imshow() function on the main thread to show frames from separate frame capture and processing threads (since imshow() doesn't work outside it).
From what I understand I can't use a while loop to do that, since the program would be stuck on it and everything else would not run. What could be a solution? I wondered about putting everything else on a separate thread (including the frame grab 'sub-threads') and keeping only imshow on the main one. But that doesn't seem right.
EDIT
The problem with the imshow() function on the frame capture/display thread was apparently not adding a cv2.waitKey(1) function. Not including that line causes the window to freeze even in the main thread.

I don't have rep enough to comment, so I am writing here. I think you can use simple ROS structure to publish frames as ros-topic then do what ever you want with different ros-nodes.

Related

How can I access a single videostream multiple Times parallel?

I asked that Question already, but I think I asked the wrong Way. So this Time I will try it with very short pseudo code.
I use a Class with 2 Threads and Event Dependency to Capture and Display a Webcamstream:
(Meanwhile I commented out the Event)
Thread1 (Capture)
capture.read()
ready.set()
Thread2 (Display):
ready.wait()
"working on the Frame"
label2.configure(image=framex)
label2.image=framex
ready.clear()
I need to display the Stream in a Frame, thats why I use a Label for it. In Performance it is not the same like imshow(), so I need it in a single Thread.
If anyone knows an better Way to put the Stream in to a Frame, let me know :)
Now I want to write the Stream to a File while displaying it.
But I don't know how to access the Webcam Stream multiple Times parallel.
I tried to put the Frame into a global Variable and use that for Displaying but it didnt work.
So at the Moment the Displaying of the Stream freezes, while Recording the Stream.
I would be very happy if someone have an Idea.
Mhmm I think I solved it. I wrote a second Displaying Function in the While Loop for the Recording.

Python : How to deal with threads priority in Gtk3

I am building an user interface using Python, Gtk3 and Glade. I want to change several things on the UI at the same time (i.e start an animation and display a new text) which leads to the application freezing.
I have read that Gtk wasn't thread safe so I didn't used the Thread module.
Instead, I used Glib.idle_add and Gdk.threads_add_idle functions. I am tryig to update a treeview, display some text and show an animated logo at the same time. The application works but it freezes a few seconds and then everything appears at the same time. I try to set different priorities to the threads but it does'nt seem to fix it.
Gtk.threads_add_idle(Glib.PRIORITY_DEFAULT, label.set_text, "text_to_set")
Gtk.threads_add_igle(GLib.PRIORITY_DEFAULT, function_to_display_logo)
I expect the different texts and the treeview and the logo to be displayed without any freeze. Does anyone know how I can fix that ?
Please have a look here at a script example in https://github.com/f4iteightiz/UWR_scoreboard : a GTK window is updated all 0,2s for example (countdowns of several timers appearing in labels; I think anything else could be updated) and it stay reactiv the whole time. No freezing noticeable.
I found out what my error was. I was using the GLib.idle_add function too many times even in some cases where I had no use for it.
For example in the main code I had :
Glib.idle_add(my_function,buffer)
but my_function looked like this :
def myfuntion(buffer):
GLib.idle_add(buffer.set_text,"text")
I deleted the GLib.idle_add call in the main code and now it works perfectly.

Force update GUI in kivy

I am writing an app in kivy which does cpu-heavy calculations at launch. I want the app to display what it's doing at the moment along with the progress, however, since the main loop is not reached yet, it just displays empty white screen until it finishes working. Can I force kivy to update the interface?
Basically I'm looking for kivy's equivalent of Tkinter's root.update()
I could create a workaround by defining a series of functions with each calling the next one through Clock.schedule_once(nextFunction, 1), but that would be very sloppy.
Thanks in advance.
Leaving aside the question of whether you should be using threading or something instead (which possibly you should), the answer is just that you should move your cpu calculations to somewhere else. Display something simple initially (i.e. returning a simple widget from your build method), then do the calculations after that, such as by clock scheduling them.
Your calculations will still block the gui in this case. You can work around this by doing them in a thread or by manually breaking them up into small pieces that can be sequentially scheduled.
It might be possible to update the gui by manually calling something like Clock.tick(), but I'm not sure if this will work right, and even if so it won't be able to display graphics before they have been initialised.

Strategy for managing long GUI construction times (wxPython)

I have a wxPython application with a multi-stage GUI. First a simple form pops for selecting from one of many (> 100) options (it's a part number list with a search box). Once the user has made their selection it builds the appropriate form and shows it, hiding the initial selection dialog. Due to the nature of this project, each secondary form has several matplotlib figures in a Notebook, around 7 or 8 figures each with 2-5 axes each. Because of this, the form takes several seconds between initialization and when it can be shown on the screen.
Does wxPython have a way to build a frame in the background? I don't mind forcing the user to wait a short while before it can be shown, but as it is right now building the form hogs the event loop and everything becomes unresponsive. If I use a thread to build the form, it completes successfully but when I call .Show() nothing happens and there's no error message.
As you can imagine, such a GUI has fairly complex code so it would be difficult to show a SSCCE (and it's not open source). If needed I can try to hack together something that would approximate my problem.
I have used BusyInfo before to tell the user that something is happening. You would put that in your frame's init() BEFORE you actually start creating the matplotlib figures. You can read about it here:
http://wiki.wxpython.org/BusyInfo
Another idea would be to create a second frame with a progressbar in it and a message. The progressbar would be set to just bounce back and forth and when you got done creating the matplot stuff, you would close the second frame.
Mike's idea of using wxBusyInfo is useful when something takes a long time, but it's possible you could make it take less time instead (or at least as well).
First, when inserting many (although I wouldn't say that 100 is that many, 1000 however definitely is) items into a wxChoice, freeze it before adding them -- and thaw it afterwards. This should cut down the time needed for the insertion drastically.
Second, creating all controls of a multi-page wxNotebook (or another wxBookCtrl) can be long, even in C++. So the idea is to not do it immediately but only create the controls of the page you are going to initially show to the user. And then create the other pages controls only when the user is about to select them, i.e. in your wxEVT_BOOKCTRL_PAGE_CHANGING event handler.
If you put this in place, you might not need wxBusyInfo any longer...

Running Tkinter dependent code alongside mainloop without GUI freeze

I am writing a simple image viewer that lets the user flip very quickly through tens of thousands of images, about 100 at a time. The images are files on disk.
In order for the viewer to function, it must continuously preload images ahead of the user's current one (or the viewer would be unusably sluggish).
The basic recipe that I'm using to display the images in a grid of Tkinter labels, is the following (this has been tested and works):
def load_image(fn):
image = Image.open(fn)
print "Before photoimage"
img = ImageTk.PhotoImage(image)
print "After photoimage"
label.config(image=load_image("some_image.png")
I need the ImageTk.PhotoImage instance to display the image on a label. I have implemented two different approaches, each with an associated problem.
First approach:
Launch a separate thread which pre-loads the images:
def load_ahead():
for fn in images:
cache[fn] = load_image()
threading.Thread(target=load_ahead).start()
top.mainloop()
This works quite well on my Linux machine. However, on another machine (which happens to be running Windows, and compiled with pyinstaller), a deadlock seems to happen. "Before Photoimage" is printed, and then the program freezes, which suggests that the loader thread gets stuck at creating the ImageTk.PhotoImage object. Musst the creation of an ImageTk.PhotoImage object happen within the main (Tkinter mainloop's) thread? Is the creation of PhotoImage computationally expensive, or is negligible compared to actually loading the image from disk?
Second approach:
In order to circumvent this possible requirement of PhotoImage objects being created from within Tkiner's mainloop thread, I resorted to Tk.after:
def load_some_images():
#load only 10 images. function must return quickly to prevent freezing GUI
for i in xrange(10):
fn = get_next_image()
cache[fn] = load_image(fn)
top.after_idle(load_some_images)
top.after_idle(load_some_images)
The problem with this is that, appart from creating additional overhead (ie the image-loading procedure must be broken up into very small chunks since it is competing with the GUI) that it periodically freezes the GUI for the duration of the call, and it seems to consume any keyboard events that happened during its execution.
Third approach
Is there a way I can detect pending user events? How can I accomplish something like this?
def load_some_images():
while True:
try: top.pending_gui_events.get_nowait()
except: break
#user is still idle! continuing caching of images
fn = get_next_image()
cache[fn] = load_image(fn)
top.after_idle(load_some_images)
top.after(5,load_some_images)
Edit: I have tried using top.tk.call('after','info') to check pending keyboard events. This doesn't always reliably, and the interface is still sluggish/unresponsive.
Thanks in advance for any ideas
I recommend creating an load_one_image function rather than a load_some_images function. It will be less likely to interfere with the event loop.
Also, as a rule of thumb, a function called via after_idle shouldn't reschedule it self with after_idle. The reason is that after_idle will block until the idle event queue is drained. If you keep adding stuff on to the queue while the queue is being processed, it never gets completely drained. This could be the reason why your GUI seems to hang once in a while with your second approach.
Try after(5, ...) rather than after_idle(...). If your system can create an image in less than 5ms, you can process 100 images in about half a second, which is probably fast enough to give a pretty snappy interface. You can tweak the delay to see how it affects the overall feel of the app.

Categories

Resources