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