9

这个问题有点语言不可知,但我选择的工具恰好是一个numpy数组。查找图像中的空白区域

什么我做的是通过PIL拍摄两幅图像的差异:

img = ImageChops.difference(img1, img2) 

而且我想找到包含从一个画面到另一个变化的矩形区域。当然,内置的.getbbox()方法,但如果有两个区域进行更改,它将从一个区域返回到另一个区域,如果每个角落只有1个像素更改,它将返回整个图像。

例如考虑以下地方o是一个非零像素:

______________________ 
|o   ooo | 
|  oooo ooo | 
|  o    | 
|  o o   | 
|     | 
|  oo  o  | 
| o o  ooo | 
|  oo  ooooo | 
|    ooo | 
|    o  | 
|____________________| 

我想获得包含每个非零区域的边框4×4元组。对于

oooo 
o 
o o 

结构的边缘的情况下,我并不十分担心,这让您处理 - 要么获得两部分单独或一起,因为倒L形的边界将完全重叠单一的边界像素。

所以我希望得到一些输入之前,我真的写东西我从来没有做过任何这种先进与图像处理(如果有在我已经使用的内存模块预先存在的方法,我欢迎他们!) 。

我的伪代码十岁上下的版本是这样的:

for line in image: 
    started = False 
    for pixel in line: 
     if pixel and not started: 
     started = True 
     save start coords 
     elif started and not pixel: 
     started = False 
     save end coords (x - 1 of course) 

这应该给我的坐标表,但后来我不得不确定的区域是连续的。我可以用图形类型的搜索来做到这一点? (我们在上个学期的算法中做了大量的DFS和BFS)当然,我想我可以做到这一点,而不是结合我以前的循环?

我不会在“大”上的图像会做这一点 - 他们是从一个摄像头拉到和最好的一个我现在有做640×480。至多我会做720p或1080p,但这对未来来说已经足够了,所以这不是一个真正的问题。

所以我的问题(S):我在正确的道路上领导,还是我的方法了吗?更重要的是,是否有内置的功能阻止我重新发明车轮?最后,有没有什么好的资源可以帮助我们看看(教程,论文等)?

谢谢!

回答

17

我相信scipy's ndimage module有你需要的一切......

这里有一个简单的例子

import numpy as np 
import scipy as sp 
import scipy.ndimage.morphology 

# The array you gave above 
data = np.array( 
     [ 
      [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
     ]) 


# Fill holes to make sure we get nice clusters 
filled = sp.ndimage.morphology.binary_fill_holes(data) 

# Now seperate each group of contigous ones into a distinct value 
# This will be an array of values from 1 - num_objects, with zeros 
# outside of any contigous object 
objects, num_objects = sp.ndimage.label(filled) 

# Now return a list of slices around each object 
# (This is effectively the tuple that you wanted) 
object_slices = sp.ndimage.find_objects(objects) 

# Just to illustrate using the object_slices 
for obj_slice in object_slices: 
    print data[obj_slice] 

此输出:

[[1]] 
[[1 1 1] 
[1 1 1]] 
[[1 1 1 1] 
[1 0 0 0] 
[1 0 0 1]] 
[[1]] 
[[0 1 1 0] 
[1 0 0 1] 
[0 1 1 0]] 
[[0 0 1 0 0] 
[0 1 1 1 0] 
[1 1 1 1 1] 
[0 1 1 1 0] 
[0 0 1 0 0]] 

注意 “object_slices” 基本上什么您最初要求,如果你需要的实际indicies。

编辑:只是想指出的是,尽管它看似妥善处理

[[1 1 1 1] 
[1 0 0 0] 
[1 0 0 1]] 

边缘的情况下,它实际上并没有(因此额外的唯一的[[1]])。你可以看到这一点,如果你打印出来的“对象”阵列和看一看的对象3 & 4.

[[1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0] 
[0 0 0 0 0 0 3 3 3 3 0 0 0 2 2 2 0 0 0 0] 
[0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 5 5 0 0 0 0 0 0 0 6 0 0 0 0 0] 
[0 0 0 0 5 5 5 5 0 0 0 0 0 6 6 6 0 0 0 0] 
[0 0 0 0 0 5 5 0 0 0 0 0 6 6 6 6 6 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 0 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0]] 

希望帮助!

[1]

+0

神圣烟雾,这是完美的!这正是我想要的 - 我想我实际上更喜欢它以这种方式处理边缘情况 - 这样它会真正获得所有像素的框。我希望我能不止一次地投票! – 2010-07-22 20:49:02

+0

@Wayne - 很高兴帮助!一旦你学会了如何将不同的操作符串在一起,scipy.ndimage中有相当不错的一批函数。祝你好运! – 2010-07-22 21:03:19

+0

@JoeKington是最有帮助的程序员之一 – chimpsarehungry 2013-03-02 22:03:00

1

你可以寻找图像中的连接组件,然后确定这些组件的边框。

+0

我糊涂了 - 这怎么比我说我在做不同? – 2010-07-22 19:14:35

1

聚类包(ie this)应能大部分工作(寻找连接像素)。那么寻找一个簇的边界框是微不足道的。

+0

群集如何帮助(特别是这个包)?从我收集的文档中收集到的信息来看,它只能找到X距离的数据,而且不会(看起来)存储任何X-Y数据。我错过了什么吗? – 2010-07-22 19:11:06