python - 如何避免使用opencv和numpy逐像素循环遍历图像

标签 python opencv numpy

我正在逐个像素地循环浏览这个图像,它真的很慢。我有 2 张我正在比较切片和展平的图像,因此每个元素都是一个名为 e1 的 3 维 rgb 值和 e2 .虽然它很慢。有没有使用opencv的方法?或 numpy那可以加快速度吗?

我在这里所做的是对具有分箱颜色(8 种颜色)的图像进行像素比较。
我正在阅读 jpeg,所以应该是 [255,0,0]变成 [230,12,11]那么clean_key确实是将值设置为更清洁的值。然后我将这种组合出现的次数附加到字典中。例如 dict["255,0,0 0,0,255"]在这张图片中可能会出现 300 次,这意味着有 300 个实例出现 im1有一个红色像素和 im2有一个蓝色像素。

for e1,e2 in itertools.izip(im1_slice.reshape(-1,3),im2_slice.reshape(-1,3)):
      key = str(clean_key(e1_row)) + str(clean_key(e2_row))
      if key in proportion_dict:
        proportion_dict[key] += 1
      else:
        proportion_dict[key] = 1           

return (proportion_dict,total)

最佳答案

您要执行此操作的方法是首先将每个图像与您希望在该图像中看到的颜色进行比较,这会生成一个 bool 掩码,其中该图像是给定的颜色。您无需拼合图像即可执行此操作。这可以通过说:

image == color

这适用于灰度图像,但如果 color实际上是沿第三个维度,您要确保该维度上的所有内容都匹配(即,您希望所有 r、g 和 b 分量都匹配,因此您使用 np.all 沿最后一个轴( -1 给出最后一个轴):
np.all(image == color, axis=-1)

这给出了一个二维 bool 数组,其中每个元素是 True如果该像素匹配 colorFalse如果不。对两个图像(和两种颜色)执行此操作,然后您将拥有一个颜色与两个图像匹配的蒙版:
np.all(im1==c1, -1) & np.all(im2==c2, -1)

这不仅告诉你有多少像素匹配,还告诉你它们在哪里(你可以绘制上面的线并在它们匹配的点上看到点)。如果您只想要计数,只需使用 np.sum在计数 True 的面具上如1 , 和 False0 .全部一起:
def compare_colors(im1, im2, c1, c2):
    matches = np.all(im1==c1, -1) & np.all(im2==c2, -1)
    return matches.sum()

并使用/测试随机数据:
>>> a = np.random.choice([0, 255], (20,20,3))
>>> b = np.random.choice([0, 255], (20,20,3))
>>> compare_colors(a, b, [255, 0, 255], [0, 255, 0])
12

但在你这样做之前,通过你的真实输入,你想通过一个阈值来“清理”你的颜色。您可以使用 np.where 轻松做到这一点它查看数组的每个元素,如果满足条件,则给出一件事,如果不满足,则给出另一件事。这里,如果值小于128 , 它使用 0 ,否则使用 255 :
np.where(a<128, 0, 255)

通常,您可以编写这样的函数,并将上述值作为默认值:
def clean(a, thresh=128, under=0, over=255):
    return np.where(a<128, under, over)

当然,要建立您的计数字典,您仍然必须遍历每种颜色组合,但这是一个短循环( 8*8 )。这是一个完整的运行:
# some fake data (has values between 0 and 255 for r, g, and b)
H, W = 20, 20
a = np.random.randint(0, 256, (H,W,3))
b = np.random.randint(0, 256, (H,W,3))

# clean the images:
ac = clean(a)
bc = clean(b)

# build a list of all pairs of all 8 colors using itertools.product:
col_combos = itertools.product(itertools.product((0,255), repeat=3), repeat=2)

# now apply the comparison to the images for each pair of colors
col_dict = { (c1,c2): compare_colors(ac, bc, c1, c2) for c1,c2 in col_combos }

然后,col_dict 的 key 在我看来,实际上是元组的元组,比字符串更容易处理。以下是访问示例 key 的方式:
>>> col_dict[((0, 255, 255), (255, 0, 255))]
8

关于python - 如何避免使用opencv和numpy逐像素循环遍历图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20359192/

相关文章:

python - 如何用装饰器绕过python函数定义?

python-3.x - 文本检测 : Getting Bounding boxes

来自两个数组的 Python linspace 限制

python - 有没有办法在 opencv-python 中显示最后一帧?

python - 使用python处理来自多个目录的同名数据

python - Python 库 cvxpy 中非严格不等式作为约束

python - 为什么包装类不继承基本数据类型?

python - 使用for循环在numpy中填充二维矩阵

python - 为什么 Python 列表乘法创建一个包含多个元素的列表?

python - opencv2 中阈值 32 uint 图像的轮廓和凸包