笔者在进行人脸识别实验时,调用了 cv2
模块的相关函数,但是在使用时遇到了一些问题,现记录如下。
利用 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)
即意味着:
opencv-python
只包含了一些主要模块;opencv-contrib-python
则同时包含了主要模块和一些扩展模块,其中的扩展模块包含了一些专门的算法以及新的算法,如受目前专利保护的shift算法等等;opencv-contrib-python
中扩展模块的一些算法稳定后会合并到主要模块中;opencv-contrib-python
的内置函数更多,功能更加强大和丰富,但是显然稳定性不如 opencv-python
;opencv-contrib-python
里的函数。自然是安装 opencv-contrib-python
即可,不过一定要注意版本,后续笔者遇到的各种问题也是由于 opencv-contrib-python
不同版本的bug。
笔者在进行人脸检测实验时,发现写的程序完成所有功能后一直在运行,具体表现如下:
run
运行程序,完成人脸检测之后没有出现平时的 Process finished with exit code 0
,程序依旧在运行;stop
之后程序依旧运行,不停使唤,同时甚至在下面 run 的界面出现了红色骷髅头;笔者的人脸检测代码是这样的:
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:
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
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
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
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类的版本即可。不过笔者实测发现,其实就算用了第二、三类的版本,程序也没有报出警告,但是问题确实解决了。
随便在三类中挑了一个 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版本,解决了无法自动停止问题。
和前几次一样,笔者在运行图像拼接函数时,发现出现了和前述问题二、三中一样的情况,即程序运行完毕后卡死,无法自动退出。笔者的 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内部为了加速计算,某些算法使用了多线程机制,但是却没有退出线程,或者多线程出现段错误导致死锁,进而导致程序卡住,线程阻塞,无法自动停止。
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)
则亲测无效。
急!!!opencv-python做人脸模型建立,程序运行完毕,但是不会结束进程,为什么? ↩︎
关于python版opencv 运行人脸检测函数classfier.detectMultiScale会卡主的问题 ↩︎
OpenCV with Python wont exit properly when using detectMultiScale on CascadeClassifier ↩︎ ↩︎
cv2.waitKey用鼠标点击一直执行 ↩︎ ↩︎
python调用stitcher类自动实现多个图像拼接融合功能 ↩︎
Pytorch Dataloader、OpenCV出现死锁可能的解决方案 ↩︎