使用 numpy/scipy 进行形状识别(可能是分水岭) [英] Shape recognition with numpy/scipy (perhaps watershed)

查看:42
本文介绍了使用 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.

让我们把事情分解一下.

Let's break things down a bit.

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:
ymin:{0.start}, ymax:{0.stop}
xmin:{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天全站免登陆