Py学习  »  Python

踩坑记录 | 发现了OpenCV-Python执行比C++慢几百倍的原因

OpenCV学堂 • 6 月前 • 434 次点击  

点击上方蓝字关注我们

微信公众号:OpenCV学堂

关注获取更多计算机视觉与深度学习知识

联通组件算子(CCL)

连接组件标记算法(connected component labeling algorithm)是图像分析中最常用的算法之一,算法的实质是扫描一幅图像的每个像素,对于像素值相同的分为相同的组(group),最终得到图像中所有的像素连通组件。扫描的方式可以是从上到下,从左到右,对于一幅有N个像素的图像来说,最大连通组件个数为N/2。扫描是基于每个像素单位,对于二值图像而言,连通组件集合可以是V={1|白色}或者V={0|黑色}, 取决于前景色与背景色的不同。对于灰度图像来说,连图组件像素集合可能是一系列在0 ~ 255之间k的灰度值。OpenCV中相关的两个函数分别是:
int cv::connectedComponents(  InputArray  image, // 输入二值图像,黑色背景  OutputArray     labels, // 输出的标记图像,背景index=0  int     connectivity = 8, // 连通域,默认是8连通  int     ltype = CV_32S // 输出的labels类型,默认是CV_32S)

 带统计信息的联通组件标记函数

int cv::connectedComponentsWithStats(InputArray  image, // 输入二值图像,黑色背景OutputArray     labels, // 输出的标记图像,背景index=0OutputArray     stats, // 统计信息,包括每个组件的位置、宽、高与面积OutputArray     centroids, // 每个组件的中心位置坐标cx, cyint     connectivity, // 寻找连通组件算法的连通域,默认是8连通int     ltype, // 输出的labels的Mat类型CV_32Sint     ccltype // 连通组件算法)

在OpenCV实验大师中封装的第二个函数支持。

不同速度 现象对比

最近用户群里有个人跟我说,它有个二值化的图像,然用了OpenCV实验大师的联通组件算子,发现特别耗时,3200x3200大小的图像,耗时居然是几十秒,然后我让他把图发我,我自己测试了一下,发现的确是的。

然后我就把这个保存为流程文件,到的C++引擎库中又测试了一下,发现速度很快,截图如下:

只需要不到50毫秒,而Python版本的居然比C++版本慢了几百倍,我觉得肯定是Python版本哪里实现有不合理的代码,于是我开启了端点执行,单步打印调试….

查找问题与代码修改

通过我一通对比自己实现的C++ 与Python代码发现,无论是C++ 还是Python里面调用OpenCV函数都在十几毫秒可以完成,所以Python实现中20多秒的时间损耗肯定来自于Python代码本身,应该与OpenCV无关,一通DEBUG之后我发现是我最后给标签图像赋值颜色的代码造成的,代码如下:

执行耗时如下:
ccl time :  22649.269342422485  ms
然后我看了一下代码,发现了最可能的原因是
result[labels==t] = colors[t]
这行代码导致的,因为我有很多标签,每个标签它都要全图搜索一次,几百个标签,它就全图搜索几百次了,想想在3200x3200的图上遍历搜索几百次,能不成瓶颈吗?我哭,我最初写这个代码觉得这个语法很高大上,鬼斧神工,现在是回旋镖打自己。然后我改成下面这样:

执行时间变成:
ccl time :  4321.542501449585  ms
没办法,Python里面遍历数组就是慢,我有限水平已经尽力,想快还是用C++吧。最后上传一下我的测试图像:


OpenCV4系统化学习


深度学习系统化学习

推荐阅读

OpenCV4.8+YOLOv8对象检测C++推理演示

ZXING+OpenCV打造开源条码检测应用

攻略 | 学习深度学习只需要三个月的好方法

三行代码实现 TensorRT8.6 C++ 深度学习模型部署

实战 | YOLOv8+OpenCV 实现DM码定位检测与解析

对象检测边界框损失 – 从IOU到ProbIOU

初学者必看 | 学习深度学习的五个误区


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/173767
 
434 次点击