我有一个图像的直方图,基本上,图像的直方图是一个图表,显示了转换为0—255值的像素在图像中出现的次数.Y轴为出现次数,X轴为像素值.

enter image description here

而我需要的是像素值的总数从75—125

image= cv2.imread('grade_0.jpg')
listOfNumbers = image.ravel() #generates the long list of 0-255 values from the image) type numpy.ndarray

现在,我的代码通过将numpy.ndarray转换为一个列表并逐个计数每个值来实现这一点

start = time.time()
numberlist = list(list0fNumbers)

sum = 0
for x in range(75,125):
    sum = sum + numberlist.count(x)
end = time.time()

print('Sum: ' + str(sum))
print('Execution time_ms: ' + str((end-start) * 10**3))

结果:

Sum: 57111
Execution time_ms: 13492.571830749512

我会对数以千计的图片做这样的事情,仅这张图片就花了13秒.这实在是太低效了.有什么建议可以把速度提高到10毫秒以下吗?我不会只得到75-125的总和,还会得到其他范围的和,例如0-80、75-125、120-220、210-255.假设处理一张256x256像素的图像也需要13秒,那么处理一张256x256像素的图像需要大约60秒,即使对于速度较慢的计算机来说,这也有点长.

下面是一个示例图像:

enter image description here

推荐答案

可以使用简单的布尔运算符:

import cv2

image = cv2.imread('grade_0.jpg')

out = ((image>=75)&(image<125)).sum()

# 57032

或者,正如@ jared所建议的:

out = np.count_nonzero((image>=75)&(image<125))

计数时间:

# sum
170 µs ± 2.81 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

# count_non_zero
47.6 µs ± 2.94 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

编辑:我知道您想要处理几个垃圾箱,这可以使用以下方法完成:

bins = [(0,80),(75,125),(120,220),(210,255)]
out = {f'{a}-{b}': np.count_nonzero((image>=a)&(image<b)) for a, b in bins}
# {'0-80': 26274, '75-125': 57032, '120-220': 86283, '210-255': 40967}

但这将再次读取图像的数据 for each 仓.

在本例中,@Andrej建议使用bincount,因为它只计算像素一次:

bins = [(0,80),(75,125),(120,220),(210,255)]

counts = np.bincount(image.ravel())
out = {'-'.join(map(str, t)): counts[slice(*t)].sum() for t in bins}
# {'0-80': 26274, '75-125': 57032, '120-220': 86283, '210-255': 40967}

时间将取决于图像的大小和箱的数量.对于小图像,再次计数可能更有效,而对于大图像,bincount可能更好(但令人惊讶的是,并不总是如此).

256 x 256

# count_nonzero in loop
198 µs ± 8.75 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

# bincount
440 µs ± 6.82 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

512 x 512:

# count_nonzero in loop
918 µs ± 31 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

# bincount
1.76 ms ± 26.1 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

1024 x 1024:

# count_nonzero in loop
11 ms ± 210 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# bincount
8.15 ms ± 437 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

2048 x 2048:

# count_nonzero in loop
47.1 ms ± 3.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# bincount
48.8 ms ± 3.02 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Python相关问答推荐

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

使用FASTCGI在IIS上运行Django频道

DataFrame groupby函数从列返回数组而不是值

在Python Attrs包中,如何在field_Transformer函数中添加字段?

2D空间中的反旋算法

如何获取TFIDF Transformer中的值?

运输问题分支定界法&

使用密钥字典重新配置嵌套字典密钥名

递归访问嵌套字典中的元素值

计算每个IP的平均值

Django RawSQL注释字段

未调用自定义JSON编码器

Python—转换日期:价目表到新行

OpenCV轮廓.很难找到给定图像的所需轮廓

如何在海上配对图中使某些标记周围的黑色边框

read_csv分隔符正在创建无关的空列

Groupby并在组内比较单独行上的两个时间戳

有什么方法可以在不对多索引DataFrame的列进行排序的情况下避免词法排序警告吗?

对列中的数字进行迭代,得到n次重复开始的第一个行号

如何有效地计算所有输出相对于参数的梯度?