如何避免使用opencv&麻木 [英] How do I avoid looping through an image pixel by pixel with opencv & numpy

查看:75
本文介绍了如何避免使用opencv&麻木的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在逐个像素循环浏览图像,这确实很慢.我将要比较的2张图像进行了切片和展平,因此每个元素都是一个名为e1e2的3维rgb值.但是,它非常慢.是否有使用opencvnumpy的方法可以加快速度?

I'm looping through this image pixel by pixel and it's really slow. I have the 2 images I'm comparing sliced and flattened so each element is a 3 dimensional rgb value named e1 and e2. It is very slow though. Is there some method using opencv or numpy that can speed this up?

我在这里正在对具有二进制颜色(8种颜色)的图像执行像素比较.
我正在从jpeg中读取内容,因此[255,0,0]应该变成[230,12,11],所以clean_key要做的是将值限制为更干净的值.然后,我将这种组合出现的次数附加到字典中.因此,例如dict["255,0,0 0,0,255"]可能在此图像中出现300次,这意味着在300个实例中,im1具有红色像素,而im2具有蓝色像素.

What I'm doing here is performing pixel comparisons on images with binned colors (8 colors).
I'm reading from a jpeg though so what should be [255,0,0] becomes [230,12,11] so what clean_key does is threshold the values to the cleaner ones. Then I append the number of times this combination occurs to a dictionary. So for example dict["255,0,0 0,0,255"] might occur 300 times in this image which means there were 300 instances where im1 had a red pixel and im2 had a blue pixel.

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)

推荐答案

您要执行此操作的方法是,首先将每个图像与要在该图像中看到的颜色进行比较,这将创建一个布尔蒙版,其中该图像是给定颜色.您无需展平图像即可执行此操作.可以这样说:

The way you want to do this is first compare each image to the color you want to see in that image, which makes a boolean mask where that image is the given color. You don't need to flatten the images to do this. This can be done by saying:

image == color

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

This works fine for grayscale images, but if color is actually along a third dimension, you want to make sure everything along that dimension matches (i.e., you want all of the r, g, and b components to match, so you use np.all along the last axis (-1 gives the last axis):

np.all(image == color, axis=-1)

这将给出一个二维布尔数组,如果该像素与colorFalse匹配,则每个元素为True.对两个图像(和两个颜色)都执行此操作,然后您将得到一个遮罩,其中颜色与都是图像匹配:

Which gives a 2d array of booleans where each element is True if that pixel matches color and False if not. Do this for both images (and both colors) and then you'll have a mask where the color matches both images:

np.all(im1==c1, -1) & np.all(im2==c2, -1)

这不仅告诉您有多少像素匹配,还告诉它们它们在哪里(您可以绘制上面的线,并在它们匹配的点上看到点).如果只想计数,只需在掩码上使用np.sum即可,将True计为1,将False计为0.在一起:

This not only tells you how many pixels match, but where they are (you could plot the above line and see dot at the points where they match). If you just want the count, just use np.sum on the mask which counts True as 1, and False as 0. All together:

def compare_colors(im1, im2, c1, c2):
    matches = np.all(im1==c1, -1) & np.all(im2==c2, -1)
    return matches.sum()

并使用/测试随机数据:

And to use/test it with random data:

>>> 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:

But before you do that, with your real input, you want to "clean" your colors by a threshold. You could easily do that with np.where which looks at each element of an array, and if a condition is met, gives one thing, and if not, gives another. Here, if the value is less than 128, it uses 0, and otherwise uses 255:

np.where(a<128, 0, 255)

通常,您可以编写一个函数,上面的值是默认值:

In general, you could write a function like this, with the values above as defaults:

def clean(a, thresh=128, under=0, over=255):
    return np.where(a<128, under, over)

当然,要建立计数法则,您仍然必须遍历每种颜色组合,但这只是一个短循环(8*8).这是一个完整的过程:

Of course to build up your dict of counts, you still have to loop through each color combination, but that's a short loop (8*8). Here's a full run through:

# 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的键实际上是元组的元组,在我看来,它比字符串更容易处理.这是您访问示例密钥的方法:

Then, the keys for col_dict are actually tuples of tuples, which are much easier to deal with than strings, in my opinion. Here's how you'd access an example key:

>>> col_dict[((0, 255, 255), (255, 0, 255))]
8

这篇关于如何避免使用opencv&amp;麻木的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆