Подтвердить что ты не робот

Распознавание формы с помощью numpy/scipy (возможно, водораздела)

Моя цель - проследить чертежи, в которых есть много отдельных фигур, и разделить эти фигуры на отдельные изображения. Он черный на белом. Я совершенно новичок в numpy, opencv и amo; 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) он просто выводит полный массив снова.

Следующим шагом может быть поиск пути многоугольника вокруг фигуры, но ограничивающая рамка будет великолепна на данный момент!

Пожалуйста, помогите!

4b9b3361

Ответ 1

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

enter image description hereenter image description hereenter image description here

Надеюсь, это немного упростит, как найти ограничивающие прямоугольники объектов.

Ответ 2

Используйте библиотеку ndimage из scipy. Функция 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