2013-05-04 112 views
0

我想在python中扫描阈值编辑的图像来检测白色像素并存储它们的位置的简单嵌套循环。的问题是,虽然它是从读取该阵列是只有160×120(19200),它仍然需要大约6秒来执行,我的代码如下所示和任何帮助或指导将不胜感激:Python简单的嵌套循环

im = Image.open('PYGAMEPIC') 

r, g, b = np.array(im).T 
x = np.zeros_like(b) 

height = len(x[0]) 
width = len(x) 

x[r > 120] = 255           
x[g > 100] = 0          
x[b > 100] = 0    

row_array = np.zeros(shape = (19200,1)) 
col_array = np.zeros(shape = (19200,1)) 

z = 0 
for i in range (0,width-1): 
    for j in range (0,height-1): 
     if x[i][j] == 255: 
      z = z+1 
      row_array[z] = i 

      col_array[z] = j 

回答

2

首先,它不应该需要6秒钟。在160x120图片上试用你的代码需要0.2秒。

这就是说,对于良好的numpy性能,你通常希望避免循环。有时候,除了最小轴和沿着它的所有循环外,沿着所有的方向矢量化更简单,但是如果可能的话,你应该尽量一次完成所有的工作。这通常会使事情变得更快(将循环向下推到C)并且更容易。

您的循环本身似乎有点陌生,我 - 你似乎有一个差一错误都在你开始存储结果,其中的条款(第一个值放入z=1,不z=0 )以及在多大程度上你正在寻找(range(0, x-1)不包括x-1方面,所以你错过了最后一排/ column--可能是你想要range(x)。)

如果你想要的是指数,其中r > 120但既不g > 100也不b > 100,有更简单的方法。我们可以创建布尔数组。例如,第一,我们可以做一些假的数据:

>>> r = np.random.randint(0, 255, size=(8,8)) 
>>> g = np.random.randint(0, 255, size=(8,8)) 
>>> b = np.random.randint(0, 255, size=(8,8)) 

然后,我们可以在其中找到我们的条件得到满足的地方:

>>> (r > 120) & ~(g > 100) & ~(b > 100) 
array([[False, True, False, False, False, False, False, False], 
     [False, False, True, False, False, False, False, False], 
     [False, True, False, False, False, False, False, False], 
     [False, False, False, True, False, True, False, False], 
     [False, False, False, False, False, False, False, False], 
     [False, True, False, False, False, False, False, False], 
     [False, False, False, False, False, False, False, False], 
     [False, False, False, False, False, False, False, False]], dtype=bool) 

然后我们可以使用np.where得到的坐标:

>>> r_idx, c_idx = np.where((r > 120) & ~(g > 100) & ~(b > 100)) 
>>> r_idx 
array([0, 1, 2, 3, 3, 5]) 
>>> c_idx 
array([1, 2, 1, 3, 5, 1]) 

而且我们可以通过索引回rgb

>>> r[r_idx, c_idx] 
array([166, 175, 155, 150, 241, 222]) 
>>> g[r_idx, c_idx] 
array([ 6, 29, 19, 62, 85, 31]) 
>>> b[r_idx, c_idx] 
array([67, 97, 30, 4, 50, 71]) 
+0

为了您的回应,我忘记提及我正在使用Raspberry Pi来实现此目的。用你的方法实现布尔数组非常容易,但它仍然不能解决这个问题,我必须确定这个图像中的白色像素并存储它们的位置。我仍然需要一种扫描图像的方式,我可以识别白色像素并存储它们,而不需要花费6秒左右来实现 – RR1 2013-05-04 18:38:02

+0

我不明白。上面的代码使用你的规则来构成一个白色像素 - '(r> 120)&〜(g> 100)&〜(b> 100))' - 并且给出白色像素所在的索引, r_idx'和'c_idx'是你的'row_array'和'col_array',没有浪费的零空间。无论如何,希望别人能够帮助你! – DSM 2013-05-04 18:43:55

+0

哦,哇,对不起,我的头被整天看着电脑屏幕烧坏了!这很好,非常感谢你!现在我可以摆脱这些邪恶的循环!它只需要0.0117s!非常感谢!! – RR1 2013-05-04 19:01:37

0

ë你在Python 2.x(2.6或2.7)。在python 2中,每当你打电话给range时,你都会创建一个包含很多元素的列表。 (在这种情况下,你要创建width - 1长度的1名列表,然后的height - 1长度。一种方法width - 1列表加快这是使每提前一个列表,并使用该列表中的每个时间。

例如

height_indices = range(0, height - 1) 
for i in range(0, width - 1): 
    for j in height_indices: 
     # etc 

为了防止不必创建任一列表,你可以使用xrange返回发电机,这将节省内存和时间,如蟒蛇,

for i in xrange(0, width - 1): 
    for j in xrange(0, height - 1): 
     # etc. 

你也应该使用filter函数来研究一个函数并执行它。它将返回函数返回的项目列表,但如果您所做的只是递增全局计数器并修改全局数组,则不必返回任何内容或关注返回的列表。

+0

嗨,那里,谢谢你的回应,我忘了提及我使用2.7版本的python树莓派。我已经尝试过提前制作清单的方法,这样可以节约大约0.2秒,但仍然让我的执行时间大约为5秒。你会有任何其他想法检查图像(黑色与白色像素一团),并确定这些像素和存储它们? – RR1 2013-05-04 18:41:00