我正在自学计算机图像处理的基础知识,同时我也在自学Python。
给定尺寸为2048x1354的图像x
,具有3个通道,有效地计算像素强度的直方图。
import numpy as np, cv2 as cv
img = cv.imread("image.jpg")
bins = np.zeros(256, np.int32)
for i in range(0, img.shape[0]):
for j in range(0, img.shape[1]):
intensity = 0
for k in range(0, len(img[i][j])):
intensity += img[i][j][k]
bins[intensity/3] += 1
print bins
我的问题是这段代码运行得很慢,大约30秒。我如何加快速度,更像Python?
5条答案
按热度按时间eqoofvh91#
你可以使用新的OpenCV python接口,它本身就使用numpy数组,并使用matplotlib
hist
绘制像素强度的直方图。在我的电脑上,这需要不到一秒钟的时间。更新:以上指定数量的箱并不总是提供所需的结果,因为最小值和最大值是从实际值计算的。此外,值254和255的计数在最后一个箱中求和。这里是更新的代码,它总是正确地绘制直方图,条形以值0..255为中心
yzuktlbb2#
如果你只想计算数组中每个值的出现次数,
numpy
可以使用numpy.bincount
来完成。在你的例子中:我在这里使用
numpy.asarray
来确保img
是一个numpy数组,所以我可以将它扁平化为bincount
需要的一维数组。如果img
已经是一个数组,你可以跳过这一步。计数本身会非常快。这里的大部分时间可能会花在将cv矩阵转换为数组上。编辑:根据this answer,您可能需要使用
numpy.asarray(img[:,:])
(或可能的img[:,:,:]
)才能成功将图像转换为数组。另一方面,根据this,您从较新版本的openCV中得到的已经是一个numpy数组。因此,在这种情况下,您可以完全跳过asarray
。niknxzdl3#
这是不可能的(即不删除for循环)。Python的for循环结构有太多的事情要做,速度很快。如果你真的想保留for循环,唯一的解决方案是numba或cython,但它们有自己的一系列问题。通常,这样的循环是用c/c++编写的。(在我看来是最直接的),然后从Python调用,它的主要角色是脚本语言。
话虽如此,opencv+numpy提供了足够有用的例程,因此在90%的情况下,可以简单地使用内置函数,而不必求助于编写自己的像素级代码。
这里有一个在numba中的解决方案,不需要改变你的循环代码。在我的电脑上,它比纯python快150倍。
gcxthw6b4#
看一下at MatPlotLib。这应该会带你完成所有你想做的事情,而且没有for循环。
kq0g1dla5#
OpenCV docs:
单通道直方图(图像转换为灰度):
RGB直方图(每个通道单独)