opencv-python 使用中遇到的问题

前言

笔者在进行人脸识别实验时,调用了 cv2 模块的相关函数,但是在使用时遇到了一些问题,现记录如下。

1. opencv-python 与 opencv-contrib-python 的关系

- 问题描述

利用 pip 安装好 opencv-python 之后,发现有一些函数无法调用。例如:cv2.face.EigenFaceRecognizer_create() 等等。

- 原因分析

参考 Opencv-contrib-python与opencv-python有何不同? - 知乎用户的回答 - 知乎 可知,

  • run pip install opencv-python if you need only main modules
  • run pip install opencv-contrib-python if you need both main and contrib modules (check extra modules listing from OpenCV documentation)

即意味着:

  1. opencv-python 只包含了一些主要模块;
  2. opencv-contrib-python 则同时包含了主要模块和一些扩展模块,其中的扩展模块包含了一些专门的算法以及新的算法,如受目前专利保护的shift算法等等;
  3. opencv-contrib-python 中扩展模块的一些算法稳定后会合并到主要模块中;
  4. 从功能上看, opencv-contrib-python 的内置函数更多,功能更加强大和丰富,但是显然稳定性不如 opencv-python
  5. 从实验来看,python会优先使用 opencv-contrib-python 里的函数。

- 解决方法

自然是安装 opencv-contrib-python 即可,不过一定要注意版本,后续笔者遇到的各种问题也是由于 opencv-contrib-python 不同版本的bug。

2. 人脸检测函数 detectMultiScale 调用后卡住,程序无法停止

- 问题描述

笔者在进行人脸检测实验时,发现写的程序完成所有功能后一直在运行,具体表现如下:

  1. 使用 Pycharm 的 run 运行程序,完成人脸检测之后没有出现平时的 Process finished with exit code 0,程序依旧在运行;
  2. stop 之后程序依旧运行,不停使唤,同时甚至在下面 run 的界面出现了红色骷髅头;
  3. 最后强行关闭下图红色标注的 run 界面才把程序给停掉,但是 Pycharm 后台暂停和取消的进程还要手动取消。
    在这里插入图片描述
  4. 在命令行中运行这段代码,同样在完成功能之后无法停止,程序一直在后台运行,并且没有任何输出。

笔者的人脸检测代码是这样的:

import cv2

# 读取待检测的图像
image = cv2.imread('test1.jpg')
# 获取xml文件,加载人脸检测器
faceCascade = cv2.CascadeClassifier('opencv-files/lbpcascade_frontalface.xml')
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 调用函数detectMultiScale
faces = faceCascade.detectMultiScale(
    gray,
    scaleFactor=1.2,
    minNeighbors=5,
    minSize=(5, 5),
)

print(faces)
# 打印输出测试结果
print("发现{0}个人脸!".format(len(faces)))
# 逐个标记人脸
for (x, y, w, h) in faces:
    cv2.circle(image, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 2)
# 显示结果
cv2.imshow("dect", image)
# 保存检测结果
cv2.waitKey(0)
cv2.destroyAllWindows()

经过debug,最终发现是 opencv 自带的人脸检测函数 detectMultiScale 导致了程序无法停止,它虽然正确输出了人脸的正确坐标,其后续的命令也正常运行,但是这个函数在某种程度上阻塞了整个程序,使得程序在完成功能后无法自动停止。查询资料发现,有网友遇到了相同的问题1,其问题也定位在 detectMultiScale 函数上。

- 原因分析

查询资料发现,有网友给出了方法2:他认为原因是少写了一个 flags 参数,并且重启电脑就好了。但是,笔者尝试之后发现并没有任何效果。

笔者尝试在代码中加入 sys.exit() 等强制停止的命令,但是这个强制停止的命令却无法执行。笔者还尝试了 cv2.setNumThreads(0) 等强行使得程序单进程运行的命令,但是依旧无效。

最后,在 stackoverflow 找了同样的问题3。这应该是模块的一个bug,虽然提问者没有最终解决问题,但是他发现了只有opencv-contrib-python在特定版本才会出现这种问题。其发现如下3

  1. 下面版本的opencv-contrib-python可以正常工作
pip install opencv-contrib-python==3.4.2.16
pip install opencv-contrib-python==3.4.2.17
pip install opencv-contrib-python==3.4.3.18
  1. 下面版本的opencv-contrib-python虽然报出警告但是依旧可以正常工作
[ WARN:1] terminating async callback

pip install opencv-contrib-python==3.4.4.19
pip install opencv-contrib-python==3.4.5.20
pip install opencv-contrib-python==3.4.6.27
pip install opencv-contrib-python==3.4.7.28
pip install opencv-contrib-python==3.4.8.29
pip install opencv-contrib-python==4.0.0.21
pip install opencv-contrib-python==4.0.1.23
pip install opencv-contrib-python==4.0.1.24
pip install opencv-contrib-python==4.1.0.25
  1. 下面版本的opencv-contrib-python报出另一种警告但是依旧可以正常工作
[ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback

pip install opencv-contrib-python==4.1.1.26
pip install opencv-contrib-python==4.1.2.30
  1. 下面版本的 opencv-contrib-python 导致程序运行后无法退出和停止
pip install opencv-contrib-python==3.4.9.31
pip install opencv-contrib-python==3.4.9.33
pip install opencv-contrib-python==4.2.0.32
pip install opencv-contrib-python==4.2.0.34  # 中文网友使用的版本
pip install opencv-contrib-python==4.5.2.54  # 笔者使用的最新版本

虽然外国网友将此bug反馈给了官方,不过笔者使用目前(2021年6月)最新的版本时依然存在这个问题。

- 解决方法

发现是 opencv-contrib-python 版本的问题后,解决的方法也很简单,安装前文中前3类的版本即可。不过笔者实测发现,其实就算用了第二、三类的版本,程序也没有报出警告,但是问题确实解决了。

3. cv2.waitKey(0) 关闭窗口后程序不自动停止

- 问题描述

随便在三类中挑了一个 opencv-contrib-python 3.x 版本之后,随即又遇到了另一种情况。笔者手动关闭了弹出来的图片窗口,但是程序却还在执行,而之前在程序功能运行完之后,只要把所有的图片窗口关闭,程序会自动结束运行。有网友也遇到了相似的问题4
在这里插入图片描述

这里涉及到的代码为:

# 显示结果
cv2.imshow("dect", image)
# 保存检测结果
cv2.waitKey(0)
cv2.destroyAllWindows()

- 原因分析

经过试验,网友的解答4也是正确的。

使用高版本opencv就不会这样,比如4以上的

- 解决方法

笔者最终安装了 opencv-contrib-python 的4.1.2.30版本,解决了无法自动停止问题。

4. cv2.Stitcher_create(False).stitch() 图像拼接函数卡住无法停止(2022.11.02更新)

- 问题描述

和前几次一样,笔者在运行图像拼接函数时,发现出现了和前述问题二、三中一样的情况,即程序运行完毕后卡死,无法自动退出。笔者的 OpenCV 版本为 4.2.0.32,涉及的卡死代码大致为5

import sys
import cv2
...
 
# stitcher = cv2.createStitcher(False)    # OpenCV 3.x
stitcher = cv2.Stitcher.create(cv2.Stitcher_PANORAMA)  # OpenCV 4.x
 
(status, pano) = stitcher.stitch((img1, img2))
if status != cv2.Stitcher_OK:
	print("不能拼接图片, error code = %d" % status)
	sys.exit(-1)
print("拼接成功.")

通过定位,发现原因在于 stitcher.stitch((img1, img2)) 一句中,但是笔者发现加入常用的python退出语句也不起作用。

- 原因分析

这次遇到的是和前几次相同的问题,最终程序无法自动停止的原因是由于 OpenCV 自身的BUG导致。根本原因是OpenCV内部为了加速计算,某些算法使用了多线程机制,但是却没有退出线程,或者多线程出现段错误导致死锁,进而导致程序卡住,线程阻塞,无法自动停止。

- 解决方法

  1. 按照之前的思路,可以通过升级或降级 OpenCV 的版本来解决这种BUG。(治标不治本,不建议)
  2. 通过查阅资料,发现 PyTorch 里面使用 OpenCV 读取图片进入 Dataloader 里面经常也会出现卡死的现象6,通过借鉴其中的设置方法发现,在问题语句之前设置关闭OpenCV的多线程可以有效地解决本次问题,即
import sys
import cv2
...
 
# stitcher = cv2.createStitcher(False)    # OpenCV 3.x
stitcher = cv2.Stitcher.create(cv2.Stitcher_PANORAMA)  # OpenCV 4.x
cv2.ocl.setUseOpenCL(False)   #设置opencv不使用多进程运行,但这句命令只在本作用域有效。 
(status, pano) = stitcher.stitch((img1, img2))
if status != cv2.Stitcher_OK:
	print("不能拼接图片, error code = %d" % status)
	sys.exit(-1)
print("拼接成功.")

其中核心语句为:cv2.ocl.setUseOpenCL(False)
而另一个语句 cv2.setNumThreads(0) 则亲测无效。


  1. 急!!!opencv-python做人脸模型建立,程序运行完毕,但是不会结束进程,为什么? ↩︎

  2. 关于python版opencv 运行人脸检测函数classfier.detectMultiScale会卡主的问题 ↩︎

  3. OpenCV with Python wont exit properly when using detectMultiScale on CascadeClassifier ↩︎ ↩︎

  4. cv2.waitKey用鼠标点击一直执行 ↩︎ ↩︎

  5. python调用stitcher类自动实现多个图像拼接融合功能 ↩︎

  6. Pytorch Dataloader、OpenCV出现死锁可能的解决方案 ↩︎

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值