带有numpy/scipy的形状识别(也许是分水岭) [英] Shape recognition with numpy/scipy (perhaps watershed)

查看:360
本文介绍了带有numpy/scipy的形状识别(也许是分水岭)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是追踪其中包含许多单独形状的图形,并将这些形状分成单独的图像.它是白色的黑色.我对numpy,opencv& co很陌生-但这是我目前的想法:

My goal is to trace drawings that have a lot of separate shapes in them and to split these shapes into individual images. It is black on white. I'm quite new to numpy,opencv&co - but here is my current thought:

  • 扫描黑色像素
  • 发现黑色像素->分水岭
  • 找到流域边界(作为多边形路径)
  • 继续搜索,但忽略已经找到的边界内的点

我对这些事情不太擅长,有没有更好的方法?

I'm not very good at these kind of things, is there a better way?

首先,我试图找到分水岭结果的矩形边界框(这或多或少是示例拼贴):

First I tried to find the rectangular bounding box of the watershed results (this is more or less a collage of examples):

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)之后,它只是再次输出了完整的数组.


Somehow, when I use the original array (a) then argwhere seems to work, but after the watershed (res) it just outputs the complete array again.

下一步可能是找到形状周围的多边形路径,但现在的边框非常棒!

The next step could be to find the polygon path around the shape, but the bounding box would be great for now!

请帮助!

推荐答案

@Hooked已经回答了您的大部分问题,但是当他回答时我正在撰写本文,因此我希望将其发布仍然有用...

@Hooked has already answered most of your question, but I was in the middle of writing this up when he answered, so I'll post it in the hopes that it's still useful...

您正试图跳过太多圈.您不需要watershed_ift.

You're trying to jump through a few too many hoops. You don't need watershed_ift.

您可以使用scipy.ndimage.label区分布尔数组中的各个对象,并使用scipy.ndimage.find_objects查找每个对象的边界框.

You use scipy.ndimage.label to differentiate separate objects in a boolean array and scipy.ndimage.find_objects to find the bounding box of each object.

让我们分解一下.

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

希望这使如何找到对象的边界框更加清晰.

Hopefully that makes it a bit clearer how to find the bounding boxes of the objects.

这篇关于带有numpy/scipy的形状识别(也许是分水岭)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆