OpenCV.imshow会导致Jupyter Notebook崩溃。

94

我在谷歌或者stackoverflow上查看了其他的问题,他们都是关于如何在脚本中运行cv2.imshow函数的,但我的代码是在jupyter notebook上运行的。

以下是我的配置:

  1. ubuntu 16.4x64

  2. python 3.5

  3. opencv 3.1.0

我在jupyter notebook上运行了如下代码:

%pylab notebook
import cv2

cvim2disp = cv2.imread('data/home.jpg')
cv2.imshow('HelloWorld', cvim2disp)
cv2.waitKey() #image will not show until this is called
cv2.destroyWindow('HelloWorld') #make sure window closes cleanly
当我执行这些代码时,图片将在弹出窗口中显示,但我无法通过点击右上角的x关闭此窗口,过了一会儿,系统会提示我该窗口未响应,它将给我两个选择:“等待”和“强制退出”。如果我选择等待,那么稍后将会显示相同的提示。如果我选择“强制退出”,则Jupyter笔记本内核会死机,我必须重新开始。
我在谷歌上查找,许多解决方案建议我添加这段代码。
cv2.startWindowThread()

imshow之前出现问题,但情况变得更糟了,内核永远挂起!有人知道发生了什么。

这是我的错误图片:enter image description here


11
在类似Jupyter这样的客户端/服务器环境中,cv.imshow并没有实际意义。你需要找到一种方法在笔记本的页面上显示图像(在客户端),而不是在服务器端运行GUI窗口——当客户端和服务器在同一台机器上时,这种做法可能有些“奏效”,但只限于此。| 你已经使用了matplotlib的imshow函数(不是你认为的numpy),因此建议继续使用它(请注意,该函数使用RGB而不是BGR颜色平面顺序)。 - Dan Mašek
你找到解决方案了吗?我也遇到了同样的问题。我已经使用过OpenCV很长时间了,所以这不是waitkey的问题。它只会在程序结束前的最后一个imshow()发生,所以你可以显示和销毁窗口,直到你需要关闭最后一个窗口(即使它与之前的所有窗口都相同,比如在循环的最后一次迭代中)。 - aheigins
14个回答

100
%matplotlib inline
#The line above is necesary to show Matplotlib's plots inside a Jupyter Notebook

import cv2
from matplotlib import pyplot as plt

#Import image
image = cv2.imread("input_path")

#Show the image with matplotlib
plt.imshow(image)
plt.show()

8
请问您能否添加更多详细信息呢? - CodeF0x
1
它使用matplotlib Python库以内联模式(因此您可以在笔记本上看到它)。然后,它使用cv2加载图像,然后使用matplotlib显示图形。 - Mitodina
如果您感兴趣,此代码片段提供了更多信息。 - Masud
3
这不是回答,而是展示如何使用matplotlib而不是opencv。 - eric
1
matplotlib是一个很好的解决方案,因为似乎不可能在jupyter笔记本中内联显示opencv图像。 - user391339
18
由于OpenCV使用BGR数组而非RGB数组,因此这会产生图像输出不正确的问题。在使用plt之前,我们需要使用cv2.cvtColor(image, cv2.COLOR_BGR2RGB)将BGR转换为RGB。 - Krishnakanth Allika

84

我遇到了类似的问题,在Jupyter Notebook中使用cv2.imshow()时无法得出好的解决方案。我按照这个stackoverflow答案,仅使用matplotlib来显示图像。

import matplotlib.pyplot as plt
# load image using cv2....and do processing.
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
# as opencv loads in BGR format by default, we want to show it in RGB.
plt.show()

7
cv2.BGR2RGB现在被称为cv2.COLOR_BGR2RGB。 - sebas
当我尝试在循环中显示太多的大图时,我遇到了相同的问题。这个问题会出现在plt.show()和简单的display(image)上。 - Jason

16

cv2.waitKey()的API文档中指出:

该函数是HighGUI中唯一能够获取和处理事件的方法,因此需要定期调用以进行正常事件处理,除非HighGUI在处理事件方面使用了其他环境。

因此,也许在无限循环中调用该函数会使窗口响应?我还没有测试过,但您也许想尝试以下内容:

import cv2

cvim2disp = cv2.imread('data/home.jpg')
cv2.imshow('img', cvim2disp)
while(True):
    k = cv2.waitKey(33)
    if k == -1:  # if no key was pressed, -1 is returned
        continue
    else:
        break
cv2.destroyWindow('img')

3
最后,您还可以使用cv2.destroyAllWindows()来关闭所有窗口。 - markroxor

11

这将帮助您理解正在发生的事情:

import cv2
cvim2disp = cv2.imread('data/home.jpg')
cv2.imshow('HelloWorld', cvim2disp)
cv2.waitKey(0) 
cv2.destroyWindow('HelloWorld')

waitKey(0)方法会无限期地等待输入。当您看到相应图像的帧时,请不要尝试使用右上角的关闭按钮关闭图像。

相反,按下某个键。 waitkey方法将将其作为输入,并返回一个值。此外,您还可以检查按下了哪个键以关闭帧。

另外,waitKey(33)将使帧保持活动状态33毫秒,然后自动关闭。

destroyWindow()将销毁当前帧(如果有)。 destroyAllWindows()将销毁所有当前存在的帧。

这将解决问题。


不确定waitkey是问题的原因,我也遇到了这个问题。 - aheigins
这对我来说也是一样的。这里发布的 matplotlib 答案似乎只是一种解决方法,而不是真正解释为什么会崩溃/冻结。 - shriek
4
加入等待键和关闭窗口并不能解决问题。笔记本电脑仍然崩溃。 - manish Prasad
1
这在Jupyter Notebook中不起作用,仍然会冻结。 - eric

6

如果你在使用谷歌Colab时遇到问题,可以尝试使用这个补丁。

from google.colab.patches import cv2_imshow
cv2_imshow(img)

3
%matplotlib inline
from matplotlib import pyplot as plt

img = cv2.imread(valid_img_paths[1])
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()

3
这是一个将Ritu dhoot和mannyglover的回答结合在一起的好答案。虽然这样做没问题,但是当你复制他人回答的部分内容时,请注明出处。 - joanis

2

我刚刚开发了一个库,它与cv2.imshow完全相似,并且可以在Jupytercolab中使用。它可以更新窗口,因此您可以轻松地在其中查看视频。它使用HTML画布并且浏览器友好 :)

安装:

pip install opencv_jupyter_ui

用法:

这是Jupiter的cv2.imshow的替换方法。您只需要用jcv2.imshow替换cv2.imshow即可。它将在Jupiter中工作。

第一步:

请导入库

import opencv_jupyter_ui as jcv2

然后:

cv2.imshow更改为jcv2.imshow

有关更多详细信息,请访问GitHub存储库绑定器 演示gif

它还支持jcv2.waitKey(100)jcv2.destroyAllWindows()。如果没有Jupyter,则会退回到原始的cv2功能。 要更改默认键,您可以使用jcv2.setKeys(['a','b','esc'])。有关更多信息,请参阅文档


1
image = cv2.imread(file_path)
while True:
    # Press 'q' for exit
    exit_key = ord('q')
    if cv2.waitKey(exit_key) & 255 == exit_key:
        cv2.destroyAllWindows()
        break
    cv2.imshow('Image_title', image)

3
虽然这段代码可能能够解决问题,但最好加入上下文来说明它的原理和工作方式。这有助于未来的用户学习,并将这些知识应用到自己的代码中。当解释清楚代码时,您也可能会得到其他用户的积极反馈,例如点赞。 - borchvm
除了@borchvm所说的之外,当回答旧帖子时,如果有很多现有答案,解释为什么您的方法是其他提议的良好替代方案也很有用。这样,当人们浏览答案时,他们可以快速了解为什么应该考虑此方法而不是其他方法。 - Jeremy Caney

1
以下代码在Jupyter中可正常显示一张图片。
%matplotlib inline
import cv2
from matplotlib import pyplot as plt
cap = cv2.VideoCapture(videoFName)
ret, image = cap.read()
image=cv2.resize(image,None,fx=0.25,fy=0.25,interpolation=cv2.INTER_AREA)
plt.imshow(image)
plt.show()

如果您想在单独的窗口中显示视频而不是图像,请使用以下代码:
import cv2
cap = cv2.VideoCapture(videoFName)
while cap.isOpened():
    ret, image = cap.read()
    image=cv2.resize(image,None,fx=0.25,fy=0.25,interpolation=cv2.INTER_AREA)
    cv2.imshow('image',image)

    k = cv2.waitKey(30) & 0xff # press ESC to exit
    if k == 27 or cv2.getWindowProperty('image', 0)<0:
        break
cv2.destroyAllWindows()
cap.release()

确保窗口名称匹配,否则它将无法工作。在这种情况下,我使用'image'作为窗口名称。


1
新打开的Jupyter窗口使用与笔记本相同的内核。只需将以下代码添加到代码中即可正常工作。
cv2.waitKey(0)
cv2.destroyAllWindows()

欢迎来到SO!您能否编辑您的帖子并简要解释一下您正在做什么吗? - B--rian
不太好用。打开的窗口就是无法退出。 - lalitm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接