Why does the cv2.imshow() does not render without cv2.waitkey()? - python-3.x

Without the cv2.waitkey() method the cv2.imshow() displays black window. Why does the rendering does not happen properly without the wait?
cap = cv2.VideoCapture(video_path)
while cap.isOpened():
ret,frame = cap.read()
cv2.imshow('window-name',frame)
# without the following cv2.waitkey(1) statement the cv2.imshow() displays a blank window
if cv2.waitKey(1) & 0xFF == ord('q'): # wait for 1 millisecond
break
continue

From the documentation of cv2.imshow(), the NOTE section mentions that the window is displayed for the amount of time indicated by the argument in cv2.waitKey(). An argument of 0 indicates wait forever, so the image will be displayed forever unless you handle the keypress.
Controlling the duration for which the window needs to displayed is a useful aspect while debugging, displaying intermediate images, etc.
From the documentation of cv2.waitKey(), the NOTE section mentions that 'This function is the only method in HighGUI that can fetch and handle events, so it needs to be called periodically for normal event processing unless HighGUI is used within an environment that takes care of event processing.'
You can notice that without the cv2.waitKey(), if you hover over the window that is displayed, the 'busy' cursor with the rolling wheel is displayed, indicating that the window is busy.

Related

detect when window size changed

I am making a web browser with gtk-rs. I am trying to do a check for fullscreen. I can get the screen size and compare that to the window size, if they are the same it is in fullscreen and I can hide the unnecessary widgets. Though this works, I can only get it to work when I bind it some key event (so when I press a key it will check if the window and screen sizes are the same again). I want to be able to get this to work by simply noticing the window size has changed.

Inconsistent serial fails

I am trying to develop a python tkinter based app that would read the data from my arduino sensor platform.
I am getting inconsistent errors that i can't understand why this happens.
First of all, this is the code that is to blame:
def readSerial():
print("1")
global after_id
print("2")
ser_bytes = ser.readline()
print("3")
ser_bytes = ser_bytes.decode("utf-8")
print("4")
text.insert("end", ser_bytes)
print("5")
after_id = root.after(50, readSerial)
Sometimes this works. The data appear on my tkinter frame, as the characters 1,2,3,4,5 keep scrolling down in the terminal. This is the rarest case.
Other times the terminal printing keeps on going down, but nothing appears on my tkinter text frame. When i press the read button again, the numbers stop printing in the terminal, but the text from the serial appear on my tkinter frame. How is this possible i cannot understand.
Some times the terminal printing keeps on going down, but nothing appears on my tkinter text frame. If i press the 'start reading' button again, the program will get stuck, the button will remain gray, the print in the terminal will stop.
Other times i get freeze for some reason. Make the program will freeze, or the stop button will make it freeze.
Not only i cannot understand why the behaviors except (1) - the normal case occur, i don't understand why there is no consistency in what behavior will be triggered. When behavior 2, or 3 or 4 will happen and why? What triggers each specific behavior?
Can someone understand what is going on?
I would ask myself about your setup (which I don't know what the circuit is):
have you tested your code with test data that works independently of a link to your Arduino.
have you checked the validity of the data coming from the Arduino.
what measures are you taking to avoid noise being introduce with your data input.

How to stop screen flicker when updating an Image control in a userform

I am trying to stop the image in a userform image control flashing when one image is overwrittem by another.
Context
I am working with images from a CCTV camera which is set up to take a still image every 10 seconds, saved as .jpg files to a specified location. The intention is to work through images and select a sub list of images which are transfered to another location for subsequent processing into a time lapse video file. The selection routine parses through the images in various ways displaying each image in a large image control on a userform. One of the means of parsing the images is a loop that writes images sequentially to the control effectively emulating the finished time lapse video.
The line of code that displays the image is:
Me.Image1.Picture = LoadPicture(UserForm1.TextBox1.Value & "\" & NewFil)
where TextBox1 contains the path to the folder containing the image files and 'NewFil' is the full name of the image file.
In general, the code is working quite well and doing everything I want it to... however...
The issue
When one image is overwritten by another, the image control often flashes with the background colour. This doesn't happen with every frame and appears to be at random intervals... On average, I would say it happens for one in every three or four image changes. Needless to say, the effect can be quite disruptive almost migraine inducing. What I want to achieve is a flicker free transition form one image to another.
Tried so far:
Stopping screenupdating while the image is in process of being displayed - No effect
Having two Image Controls sharing the smae foorprint on the form, one visible, one not and writing the image to the invisible control before toggling the controls to mahe the invisible control visible and vice versa - No effect.
I'm wondering if this is a limitation of the system and if I'll have to live with it... any suggestions?
RF
Switch visibility of image control off, then on.
Hi I encountered a similar problem where the image control would 'flicker' and show the background until my mouse cursor went out of the image control and then back in. Resolved this flickering issue by turning the visibility of the image control off, then on again.
E.g. In your case:
Me.Image1.Picture = LoadPicture(UserForm1.TextBox1.Value & "\" & NewFil)
Me.Image1.Visible = False
Me.Image1.Visible = True
Let me know if it worked.

Multiple Displays in Pygame

I'm making a little game and I want to make another window separately from my main one.
I have the the main game in a main window, and I want to open a new window and do a little animation when the user does something.
In my example code below, when the user presses "a" I want it to open a new window and blit to there.
Here I set up the two windows: (I know this doesnt work, its what I'm asking how to do)
SCREEN_X = 400
SCREEN_Y = 400
BSCREEN_X = 240
BSCREEN_Y = 160
BATTLE_SCENE = pygame.display.set_mode((BSCREEN_X, BSCREEN_Y))
SCREEN = pygame.display.set_mode((SCREEN_X, SCREEN_Y))
and then the program:
def run_ani ():
#Do animation, blitting to BATTLE_SCENE
return
def main_game():
ending=False
while ending==False:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT: ending=True
if event.type == KEYDOWN: # key down or up?
if event.key == K_ESCAPE:
ending=True # Time to leave
print("Stopped Early by user")
elif event.key == K_a:
run_ani()
#Normal screen motion, blitting to SCREEN
if ending: pygame.quit()
return
So far what this does is draws the main screen, then when A is pressed, it stops drawing the main screen animations, but still draws the other animations on the main screen and draws in the top left corner.
I'm pretty sure it does this because I am setting BATTLE_SCENE to be smaller than the main screen, thus when blitting to BATTLE_SCENE it blits to the area I created (240x160) in the top corner of the main screen.
However I want BATTLE_SCENE to be a seperate window, so that when I press 'a' it will pop up, do its thing, then close or at least go behind the main screen.
How to do this? Is it even possible?
Do you really need multiple windows? I mean, do you really need them?
If yes, then you should probably use pyglet/cocos2d instead.
To have multiple windows in pygame, you need multiple processes (one for each window). While this is doable, it's not worth the efford. You'll need IPC to exchange data between the windows, and I guess your code will become error-prone and ugly.
Go with pyglet when you need more than one window.
The better solution is probably to divide your game into scenes. Create multiple scenes so that each one represent one stage of the game, something like MenuScene, MainScene, BattleScene, GameOverScene, OptionScene etc.
Then let each of those scenes handle input/drawing of that very part of the game.
MenuScene handles drawing and input etc. of the game's menu
MainScene handles drawing and input etc. of the running game
BattleScene handles drawing and input etc. of whatever you do in run_ani
In your mainloop, just pass control over to the current scene by implementing the methods draw(), handle_event(), and update().
Some example code to get the idea:
scenes = {'Main': MainScene(),
'Battle': BattleScene()} #etc
scene = scenes['Main']
class MainScene():
...
def handle_event(self, event):
if event.type == KEYUP:
if event.key == K_a:
scene = scenes['Battle']
...
class BattleScene():
...
def draw(self):
# draw your animation
def update(self):
# if animation is over:
scene = scenes['Main']
...
def main_game():
ending=False
While Not ending:
clock.tick(30)
for event in pygame.event.get():
scene.handle_event(event)
scene.update()
scene.draw()
This is an easy way to cleanly seperate the game logic and allow context switching.
======================================Edit=========================================
Actually it won't work. Apperantly pygame only supports one display screen, and when you initialize another, it will close the first. You will stay with two varibles, which in fact are the same surface. You can have instead the game increasing the window size and playing the battle scene on the side of it, to do this, you can call the pygame.display.set_mode() again with different values. The varible which references the display screen will still be usable, as it change its reference to the new one. After the scene is over you can decrease the window back the same way.
==================================================================================
What basically happens is you run a loop, and each iteration of it is rendering and displaying a new frame.
When you call a function inside a loop, it doesn't continue to run until you finish running the function.
One way to solve this problen is just keep calling the function that updates the battle scene in the main loop.
Another way is by using threading. Threading is basically running multiple scripts ("Threads") in the same time.
Luckily, python already implemented this for us with the threading module.
It's too long for me to explain the module here, but you can learn it here. It might be a little complex if you haven't use threads before, but after some time it will be easier.
And If you want to learn more about threading you can go here.
Specificly here, you can have two threads, one for each loop/window, and run them in the same time.
Hope I helped you!
Yes, that is possible. SDL2 is able to open multiple windows. In the example folder you can take a look at "video.py".
https://github.com/pygame/pygame/blob/main/examples/video.py
"This example requires pygame 2 and SDL2. _sdl2 is experimental and will change."

I need to draw a line moving with the cursor, but I want to avoid redrawing the whole window every 100ms

I have a program which displays a ruler on the screen, and with Xlib it polls for the cursor position every 100ms and updates the display. The display consists of numbers/lines etc, in particular a line indicating the position of the cursor (which is why it updates).
The problem is that the old line needs to be erased and the content underneath restored, so I have to redraw the whole window to reflect a change in position. Doing this 10 times a second results in a very flickery program.
I could only redraw the ruler after I have confirmed that the cursor is in a position to change the indicator line (i.e. within the bounds of the ruler), but it would still flicker pretty bad when it was updating.
Sort of a noob to GTK and Xlib and all, any advice would be appreciated.
Code is at https://github.com/zjmichen/zRuler
Well you have arrived at one of the earliest problems faced when cursors were being implemented!! Cursor changes are so frequent that redrawing full window every time just doesn't make any sense! Coming to your problem, look at what is needed & what exactly you are doing. Do you need to update the full window when cursor moves? No. You need to update only a section of the window so don't update the whole window. Off the top, I can think of 2 ways of reducing flicker:
1. Simple way is to make use of GdkCursor. Create a new cursor from the pixmap (Sample provided on the developer page) with the shape of your need, a line in your case. Associate cursor with the GdkWindow of your application's main window. This way you don't have to track cursor & draw the line. The cursor itself will appear as the line (so you don't to bother about clearing & redrawing it). Now in the timer callback where you redraw the complete window, redraw only the component which has to be updated on cursor position change. This should hopefully reduce the flicker as you are not drawing all the components.
2. In case you don't want to use GdkCursor, you could create a separate transparent window on top of application window dedicated to cursor. In this approach you can update only the cursor window & the component in the application window which is to updated on change in cursor position. This way other components in the application window are not redrawn each time & this hopefully should also be able to reduce flicker.
Hope this helps!

Resources