Reputation: 1803
For my image processing algorithm I'm using python / OpenCV. The output of my algorithm shall be updated im the same window over and over again.
However sometimes the window freezes and doesn't update at all, but the algorithm is still running and updated the picture a multiple times in the meantime. The window turns dark gray on this Ubuntu machine.
Here is an excerpt of the involved code:
for i in range(0,1000):
img = loadNextImg()
procImg = processImg(img)
cv2.imshow("The result", procImg)
cv2.waitKey(1)
N.B.: processImg() takes about 1-2 s for its procedures. The line cv2.imshow(procImg)
creates the window in first instance (i.e. there is no preceding invocation)
Upvotes: 22
Views: 40562
Reputation: 11
This is an old thread but in case someone else encounters it, normally the issue happen when you update opencv/opencv-contrib versions with pip and still some of their dependencies are unmet (for example you might have numpy already installed so it wont reinstall it and this causes it to crash in the back).
Simply do
pip install opencv-python opencv-contrib-python --no-cache --force-reinstall
Version 4.5.2.52 is working fine on ubuntu 20.04 and 18.04 with python > 3.8
Upvotes: 1
Reputation: 1
You can use while loop to take burst images without freezing. Here is an example for taking 10 images. You can also try to increase waitkey
number and sleep
time in while loop. This work for me.
key = cv2.waitKey(1)
webcam = cv2.VideoCapture(0)
sleep(1)
while True:
try:
check, frame = webcam.read()
cv2.imshow("Capturing", frame)
key = cv2.waitKey(1)
img_counter = 0
if key & 0xFF == ord('s'): #press s to take images
while img_counter < 10:
check, frame = webcam.read()
cv2.imshow("Capturing", frame)
key = cv2.waitKey(1)
path = 'F:/Projects/' #folder path to save burst images
img_name = "burst_{}.png".format(img_counter)
cv2.imwrite(os.path.join(path, img_name), img=frame)
print("Processing image...")
img_ = cv2.imread(img_name, cv2.IMREAD_ANYCOLOR) #save as RGB color format
print("{} written!".format(img_name))
img_counter += 1
sleep(0.2)
webcam.release()
cv2.destroyAllWindows()
break
elif key == ord('q'): #press q to quit without taking images
webcam.release()
cv2.destroyAllWindows()
break
except(KeyboardInterrupt):
print("Turning off camera.")
webcam.release()
print("Camera off.")
print("Program ended.")
cv2.destroyAllWindows()
break
Upvotes: 0
Reputation: 21
try:
import cv2
except:
print("You need to install Opencv \n Run this command \n pip install python-opencv")
exit()
print('Press q to quit frame')
def viewer(name,frame):
while True:
cv2.imshow(name,frame)
if cv2.waitKey(10) & 0xff ==ord('q'):
break
return
cv2.destroyWindow(name)
Save this program and from now onwards, import this and use the function viewer to display any frame/image and your display windows will not hang or crash.
Upvotes: 2
Reputation: 2710
Add the following two lines of code after cv2.imshow()
function,
cv2.waitKey()
cv2.destroyAllWindows()
Upvotes: 1
Reputation: 101
If your window is going grey then it might be take more processing power. So try to resize image into smaller size image and execute. Sometimes times it freezes while running in ipython notebooks due to pressing any key while performing operation. I had personally executed your problem but I didn't get grey screen while doing it. I did executing directly using terminal. Code and steps are shown below.
import argparse
import cv2
import numpy as np
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())
# load the image, grab its dimensions, and show it
image = cv2.imread(args["image"])
(h, w) = image.shape[:2]
cv2.imshow("Original", image)
cv2.waitKey(0)
for i in range(0,1000):
image = cv2.imread(args["image"])
cv2.imshow("The result",image);
cv2.waitKey(0)
Run it in terminal:
This will get to your result in one window only(updating each time) without freezing and if you want seperate image in every new window then add .format(i) as given below. But Remember to run in terminal only not in jupyter notebooks.
You can check using terminal commands in this video link https://www.youtube.com/watch?v=8O-FW4Wm10s
for i in range(0,1000):
image = cv2.imread(args["image"])
cv2.imshow("The result{}".format(i),image);
cv2.waitKey(0)
This may help to get you 1000 images separately.
Upvotes: 2
Reputation: 2653
My suggestion is to use Matplotlib pyplot for displaying the image. I do it the following way.
import matplotlib.pyplot as plt
# load image using cv2....and do processing.
plt.imshow(cv2.cvtColor(image, cv2.BGR2RGB))
# as opencv loads in BGR format by default, we want to show it in RGB.
plt.show()
I know it does not solve the problem of cv2.imshow, but it solves our problem.
Upvotes: 21
Reputation: 31
I have the very same issue and I noticed that the fps the window is updated is getting slower and slower until it freezes completely. Increasing the waitKey(x) to something higher just extends the duration where the images are updated but when the time that cv2.imshow() needs to calculate exceeds the time from wait(Key) it just stops updating.
(Skip this complainment:) I think the cv2.imshow() with waitKey() combination is a complete design error, why isn't imshow() just blocking until the UI is updated? That would make life so much easier without having to call waitKey() everytime...
P.S.: There is a possibility to start an own thread for opencv windows inside opencv:
import cv2
img = cv2.imread("image.jpg")
cv2.startWindowThread()
cv2.namedWindow("preview")
cv2.imshow("preview", img)
source: cv2.imshow command doesn't work properly in opencv-python
Well this doesn't work for me because I always get this errors when I run it:
(python3:1177): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Attempt to unlock mutex that was not locked
Aborted
Maybe you could try it and report if it is working for you?
Edit: Okay I solved the problem for me by creating a separate script imshow.py:
import cv2
import os.path
while True:
if os.path.exists("image.pgm"):
image = cv2.imread("image.pgm")
if not image is None and len(image) > 0:
cv2.imshow("Frame", image)
cv2.waitKey(20)
And I am writing the image out in my other program with: cv2.imwrite("image.pgm", image)
And I am calling the script like this:
import subprocess
subprocess.Popen(["python3", "imshow.py"])
Although this is creating some dirty reads sometimes it is sufficient enough for me, a better solution would be to use pipes or queues between the two processes.
Upvotes: 3
Reputation: 1803
Increasing the wait time solves this issue. However in my opinion this is unnecessary time spent on sleeping (20 ms / frame), even though it's not much.
Changing
cv2.waitKey(1)
to
cv2.waitKey(20)
prevents the window from freezing in my case. The duration of this required waiting time may vary on different machines.
Upvotes: 11
Reputation: 146
So what I think is going on here is that the window,(an element of the highGUI) which is still active after the first call to imshow, is waiting for some sort of response from your waitKey function, but is becoming inactive since the program is stuck calculating in either the processImg of loadNextImg functions. If you don't care about a slight waste of efficiency (i.e. you're not running on an embedded system where every operation counts), you should just destroy the window after waitKey, and recreate before imshow. Since the window no longer exists during the time you are processing and loading images, the highGUI wont get stuck waiting for a call from waitKey, and it won't become unresponsive.
Upvotes: 2