2012-03-13 16 views
12

私の目標は、それらの中に別々の形をしている図面をトレースし、これらの形を個々の画像に分割することです。それは白い黒です。私はnumpyの、OpenCVの&コに非常に新しいです - しかし、ここで私の現在の考えです:黒画素のためのnumpy/scipy(多分流域)の形状認識

  • スキャン
  • た黒画素 - >流域
  • は(ポリゴンパスなど)流域の境界を見つける
  • は、検索を続けますが、すでに見つかっ境界私は物事のこれらの種類で非常によくないよ

内の点を無視し、より良い方法はありますか?

まずI(これは例の多かれ少なかれコラージュである)流域結果の矩形のバウンディングボックスを見つけることを試みた:

どういうわけ
from numpy import * 
import numpy as np 
from scipy import ndimage 

np.set_printoptions(threshold=np.nan) 

a = np.zeros((512, 512)).astype(np.uint8) #unsigned integer type needed by watershed 
y, x = np.ogrid[0:512, 0:512] 
m1 = ((y-200)**2 + (x-100)**2 < 30**2) 
m2 = ((y-350)**2 + (x-400)**2 < 20**2) 
m3 = ((y-260)**2 + (x-200)**2 < 20**2) 
a[m1+m2+m3]=1 

markers = np.zeros_like(a).astype(int16) 
markers[0, 0] = 1 
markers[200, 100] = 2 
markers[350, 400] = 3 
markers[260, 200] = 4 

res = ndimage.watershed_ift(a.astype(uint8), markers) 
unique(res) 

B = argwhere(res.astype(uint8)) 
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1 
tr = a[ystart:ystop, xstart:xstop] 

print tr 

、私は元の配列(A)を使用しargはうまくいくように見えますが、流域(res)の後では完全な配列を出力します。

次のステップでは、図形の周りのポリゴンパスを見つけることができますが、境界ボックスは今のところ素晴らしいでしょう!

助けてください!

答えて

14

@Hookedは、すでにあなたの質問のほとんどに答えたが、彼は答えたとき、私はこれを書いている途中にあったので、私はそれを投稿しますそれはまだ役に立つと期待しています...

あなたはいくつかのあまりに多くのフープを飛び越そうとしています。 watershed_iftは必要ありません。

scipy.ndimage.labelを使用してブール値配列内の別々のオブジェクトを区別し、scipy.ndimage.find_objectsを使用して各オブジェクトのバウンディングボックスを検索します。

少し分けてみましょう。

enter image description here enter image description here

import numpy as np 
from scipy import ndimage 
import matplotlib.pyplot as plt 

def draw_circle(grid, x0, y0, radius): 
    ny, nx = grid.shape 
    y, x = np.ogrid[:ny, :nx] 
    dist = np.hypot(x - x0, y - y0) 
    grid[dist < radius] = True 
    return grid 

# Generate 3 circles... 
a = np.zeros((512, 512), dtype=np.bool) 
draw_circle(a, 100, 200, 30) 
draw_circle(a, 400, 350, 20) 
draw_circle(a, 200, 260, 20) 

# Label the objects in the array. 
labels, numobjects = ndimage.label(a) 

# Now find their bounding boxes (This will be a tuple of slice objects) 
# You can use each one to directly index your data. 
# E.g. a[slices[0]] gives you the original data within the bounding box of the 
# first object. 
slices = ndimage.find_objects(labels) 

#-- Plotting... ------------------------------------- 
fig, ax = plt.subplots() 
ax.imshow(a) 
ax.set_title('Original Data') 

fig, ax = plt.subplots() 
ax.imshow(labels) 
ax.set_title('Labeled objects') 

fig, axes = plt.subplots(ncols=numobjects) 
for ax, sli in zip(axes.flat, slices): 
    ax.imshow(labels[sli], vmin=0, vmax=numobjects) 
    tpl = 'BBox:\nymin:{0.start}, ymax:{0.stop}\nxmin:{1.start}, xmax:{1.stop}' 
    ax.set_title(tpl.format(*sli)) 
fig.suptitle('Individual Objects') 

plt.show() 

enter image description here

それは少し明確にするオブジェクトのバウンディングボックスを見つける方法になりうまくいけば。

+0

お返事ありがとうございました。私はこれがそれだと思います。なぜなら、私は、境界矩形の領域を節約することはできません。他の図形が「覗き見」されるためです。だから私の計画は、反転されたラベル配列(現在の形状の外のすべてが黒になる)で画像領域を掛け、次にndimageで画像領域を保存することです。あなたはこれをどうやって正しい方向に向けるのでしょうか?私は時間があるとすぐに、私は慎重にrtfmを知っていることを知っている! – user978250

+1

私は 'label == num'を' num'が 'label'の中のオブジェクトの番号であるところ(ラベル付き配列)としたいと思います。このような操作は、数値配列でベクトル化されるため、文字通り上の文です。 "オブジェクト"の内側に真の真偽の配列を、外側には "False"の配列を取得します。 –

5

scipyのndimageライブラリを使用してください。関数labelは、しきい値内にあるピクセルの各ブロックに固有のタグを配置します。これにより、固有のクラスタ(図形)が識別されます。 aのあなたの定義を皮切り:

from scipy import ndimage 

image_threshold = .5 
label_array, n_features = ndimage.label(a>image_threshold) 

# Plot the resulting shapes 
import pylab as plt 
plt.subplot(121) 
plt.imshow(a) 
plt.subplot(122) 
plt.imshow(label_array) 
plt.show() 

enter image description here

関連する問題