15

私の目標は、多くの個別の形状を含む図面をトレースし、これらの形状を個々の画像に分割することです. 白地に黒です。私は numpy、opencv&co にはまったく慣れていませんが、現在の考えは次のとおりです。

  • 黒いピクセルをスキャンする
  • 黒いピクセルが見つかりました -> 分水界
  • 分水界の境界を見つける (ポリゴン パスとして)
  • 検索を続行しますが、既に見つかった境界内の点は無視します

こういうのが苦手なのですが、何か良い方法はありませんか?

最初に、流域の結果の長方形の境界ボックスを見つけようとしました (これは多かれ少なかれ例のコラージュです)。

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) を使用すると、argwhere は機能しているように見えますが、流域 (res) の後、完全な配列が再び出力されるだけです。

次のステップは、シェイプの周りのポリゴン パスを見つけることかもしれませんが、今のところバウンディング ボックスで十分です。

助けてください!

4

2 に答える 2

16

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

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

scipy.ndimage.labelブール配列内の個別のオブジェクトを区別しscipy.ndimage.find_objects、各オブジェクトのバウンディングボックスを見つけるために使用します。

少し分解してみましょう。

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()

ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください

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

于 2012-03-13T21:14:55.757 に答える
6

ndimagescipyのライブラリを使用します。この関数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()

ここに画像の説明を入力してください

于 2012-03-13T21:03:35.070 に答える