Python和OpenCV创建超快的“for”像素循环

236 篇文章 43 订阅
50 篇文章 2 订阅

这篇博客将介绍如何使用Python和OpenCV创建超快的“for”像素循环(逐像素循环),即Cython快速优化for循环;

使用Python和OpenCV逐像素循环图像是一个非常缓慢的操作,即使图像在内部由NumPy数组表示。

为什么会这样?为什么NumPy中的单个像素访问速度如此之慢?
NumPy操作是用C实现的。这使得能够避免Python循环的昂贵开销。在使用NumPy时,性能会提高多个数量级(与标准Python列表相比)。一般来说,如果可以使用NumPy数组将问题框定为向量操作,将能够较大提升速度。
这里的问题是访问单个像素不是向量操作。因此即使NumPy可以说是几乎任何编程语言都可以使用的最好的数值处理库,但当与Python的for循环+单个元素访问相结合时,失去了很多性能增益。

在计算机视觉之旅中,需要实现一些算法,无论是需要从头开始实现局部二进制模式、创建自定义卷积算法,还是仅仅不能依赖矢量化操作,都需要了解如何使用OpenCV和Python优化循环。

1. 效果图

在这里插入图片描述

python:2.7 s ± 38.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
cython:4.14 ms ± 28.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
使用Python耗时2700ms,Cython实现了每次调用4.14ms。这意味着通过使用Cython,可以将逐像素循环的速度提高2个数量级以上!

受萨蒂亚·马利克(SatyaMallick)最初的博客文章的启发,我决定使用Python来完成同样的事情。
不幸的是,Python只有一小部分函数调用可用作绑定(与C++相比)。因此需要使用Cython“滚动自己的”更快的“for”循环方法。
结果非常引人注目——仅使用CPU的一个内核,通过使用Cython能够将阈值函数从每次函数调用244ms(纯Python)提高到小于40.8μs(Cython)。
还可以进行一些优化。通过启用OpenMP支持,实际上可以将for-loop计算分布在多个CPU/内核上-这样做能进一步提高速度。
下一篇博客将介绍如何使用OpenMP通过OpenCV和Python增强我们的for-pixel循环。

2. 原理

pip install numpy
pip install cython
pip install matplotlib
pip install jupyter

Cython是什么以及如何使用它来加速Python内部的操作

可以将Cython视为Python与C语言的结合,它提供了类似C语言的性能。
Cython与Python的不同之处在于,代码是使用CPython解释器翻译成C的。这允许脚本主要用Python编写,并带有一些装饰符和类型声明。

使用Cython的最佳时机是在图像中逐像素循环。OpenCV和scikit image已经优化了——对模板匹配之类的函数的调用,就像在OCR银行支票和信用卡时所做的那样,已经在底层C中进行了优化。仅函数调用中有少量开销。

用Python编写任何自定义图像处理函数来逐像素(可能是使用内核)分析或修改图像,那么函数运行得非常慢。然而如果利用Cython,它使用主要的C/C++编译器进行编译,可以获得显著的性能提升。

如何使用OpenCV和Python将逐像素循环提升两个数量级以上。将实现一个简单的阈值函数。对于图像中的每个像素,将检查输入像素是否大于或等于某个阈值T。
如果像素通过阈值测试,将输出值设置为255。否则,输出像素将设置为0。
使用此函数,将能够对输入图像进行二值化,这与OpenCV和scikit image的内置阈值方法的工作原理非常相似。
将使用一个简单的阈值函数作为示例,因为它将(1)不关注实际的图像处理代码,(2)学习如何在手动循环图像中的每个像素时获得速度提升。

源码

def threshold_slow(T, image):
    # grab the image dimensions
    h = image.shape[0]
    w = image.shape[1]

    # loop over the image, pixel by pixel
    for y in range(0, h):
        for x in range(0, w):
    # threshold the pixel
    image[y, x] = 255 if image[y, x] >= T else 0

    # return the thresholded image
    return image


%timeit threshold_slow(5, image)

参考

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值