Opencv imshow () se congela al actualizar

Para mi algoritmo de procesamiento de imágenes, estoy usando python / OpenCV. La salida de mi algoritmo se actualizará en la misma ventana una y otra vez.

Sin embargo, a veces la ventana se congela y no se actualiza en absoluto, pero el algoritmo todavía se está ejecutando y se actualiza la imagen varias veces mientras tanto. La ventana se vuelve gris oscuro en esta máquina de Ubuntu.

Aquí hay un extracto del código involucrado:

for i in range(0,1000): img = loadNextImg() procImg = processImg(img) cv2.imshow("The result", procImg) cv2.waitKey(1) 

NB : processImg () tarda aproximadamente 1-2 s para sus procedimientos. La línea cv2.imshow(procImg) crea la ventana en primera instancia (es decir, no hay invocación precedente)

Aumentar el tiempo de espera resuelve este problema. Sin embargo, en mi opinión, es un tiempo innecesario para dormir (20 ms / cuadro), aunque no sea mucho.

Cambiando

 cv2.waitKey(1) 

a

 cv2.waitKey(20) 

Evita que la ventana se congele en mi caso. La duración de este tiempo de espera requerido puede variar en diferentes máquinas.

Mi sugerencia es utilizar la ttwig de Matplotlib para mostrar la imagen. Lo hago de la siguiente manera.

 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() 

Sé que no resuelve el problema de cv2.imshow, pero resuelve nuestro problema.

Tengo el mismo problema y noté que el fps que se actualiza la ventana se está volviendo cada vez más lento hasta que se congela por completo. Aumentar el waitKey (x) a algo más alto solo extiende la duración en la que se actualizan las imágenes, pero cuando el tiempo que debe calcular cv2.imshow () excede el tiempo de espera (Key), simplemente deja de actualizarse.

(Omita esta queja 🙂 Creo que la combinación cv2.imshow () con waitKey () es un error de diseño completo, ¿por qué imshow () no bloquea hasta que se actualiza la interfaz de usuario? Eso haría la vida mucho más fácil sin tener que llamar a waitKey () cada vez …

PD: existe la posibilidad de iniciar un subproceso propio para las ventanas abiertas dentro de opencv:

 import cv2 img = cv2.imread("image.jpg") cv2.startWindowThread() cv2.namedWindow("preview") cv2.imshow("preview", img) 

fuente: el comando cv2.imshow no funciona correctamente en opencv-python

Bueno, esto no me funciona porque siempre recibo estos errores cuando lo ejecuto:

 (python3:1177): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed Attempt to unlock mutex that was not locked Aborted 

Tal vez usted podría intentarlo e informar si está funcionando para usted?

Edit: está bien, resolví el problema por mí creando un script separado 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) 

Y estoy escribiendo la imagen en mi otro progtwig con: cv2.imwrite("image.pgm", image) Y estoy llamando a la secuencia de comandos de esta manera:

 import subprocess subprocess.Popen(["python3", "imshow.py"]) 

Aunque esto está creando algunas lecturas sucias, a veces es suficiente para mí, una mejor solución sería utilizar tuberías o colas entre los dos procesos.

Entonces, lo que creo que está sucediendo aquí es que la ventana, (un elemento de highGUI) que todavía está activa después de la primera llamada a imshow, está esperando algún tipo de respuesta de su función waitKey, pero se está desactivando desde que el progtwig Se ha atascado el cálculo en cualquiera de las funciones processImg de loadNextImg. Si no le importa un ligero desperdicio de eficiencia (es decir, no se está ejecutando en un sistema integrado donde cada operación cuenta), solo debe destruir la ventana después de waitKey y volver a crearla antes de imshow. Debido a que la ventana ya no existe durante el tiempo que está procesando y cargando imágenes, la highGUI no se quedará atascada esperando una llamada de waitKey, y no dejará de responder.

Simplemente agregue cv2.destroyAllWindows() justo después de cv2.waitKey()

Si la ventana se pone gris, puede que tenga más capacidad de procesamiento. Así que trata de cambiar el tamaño de la imagen a una imagen de tamaño más pequeño y ejecuta. Algunas veces se congela mientras se ejecuta en portátiles ipython debido a que se presiona cualquier tecla mientras se realiza la operación. Personalmente había ejecutado tu problema pero no obtuve la pantalla gris mientras lo hacía. Lo hice ejecutando directamente usando terminal. El código y los pasos se muestran a continuación.

 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) 

Ejecutarlo en la terminal:

  1. fuente activar env_name
  2. python Filename.py –image Imagename.png

Esto obtendrá su resultado solo en una ventana (se actualizará cada vez) sin congelar y si desea obtener una imagen separada en cada nueva ventana, agregue .format (i) como se indica a continuación. Pero recuerde que debe ejecutarse en el terminal, no en los portátiles jupyter .

Puede verificar usando los comandos de la terminal en este enlace de video 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) 

Esto puede ayudar a conseguir 1000 imágenes por separado.

Agregue las siguientes dos líneas de código después de la función cv2.imshow (),

cv2.waitKey ()

cv2.destroyAllWindows ()