在使用Python的单色图像中的blob周围的矩形边界框 [英] Rectangular bounding box around blobs in a monochrome image using python

查看:480
本文介绍了在使用Python的单色图像中的blob周围的矩形边界框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些单色图像(黑色和白色不是灰度),带有一些奇形怪状的物体。我正在尝试使用python27,PIL,scipy&提取每个对象。 numpy和以下方法:


  1. 在每个联合对象周围安装一个边界框

  2. 提取每个对象作为数组 - 为每个对象/边界框

我已经看过。

  import numpy as np 
将scipy.ndimage导入为ndimage
导入scipy.spatial为空
导入scipy.misc为misc
导入matplotlib.pyplot为plt
导入matplotlib.patches为补丁

类BBox(对象):
def __init __(self,x1,y1,x2,y2):
'''
(x1,y1)是左上角,
(x2,y2)是右下角,
,(0,0)位于左上角。
'''
如果x1> x2:x1,x2 = x2,x1
如果y1> y2:y1,y2 = y2,y1
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
def taxicab_diagonal(self):
'''
将出租车距离从(x1,y1)返回到(x2,y2)
'''
返回self.x2 - self。 x1 + self.y2 - self.y1
def重叠(self,other):
'''
返回True iff self和其他重叠。
'''
不返回((self.x1> other.x2)
或(self.x2< other.x1)
或(self.y1> other.y2)
或(self.y2< other.y1))
def __eq __(self,other):
return(self.x1 == other.x1
和self.y1 == other.y1
和self.x2 == other.x2
和self.y2 == other.y2)

def find_paws(data,smooth_radius) = 5,阈值= 0.0001):
#https://stackoverflow.com/questions/4087919/how-can-i-improve-my-paw-detection
检测并隔离连续区域在输入数组中
#稍微模糊输入数据,这样爪子就有了连续的足迹
data = ndimage.uniform_filter(data,smooth_radius)
#阈值模糊数据(这个由于模糊,需要有点> 0)
thresh = data>阈值
#填充爪子中的任何内部孔以获得更清洁的区域...
filled = ndimage.morphology.binary_fill_holes(thresh)
#标记每个连续爪子
coded_pa​​ws,num_paws = ndimage.label(已填充)
#隔离每个爪子的范围
#find_objects返回一个2元组列表:( slice(...),slice(...))
#表示对象周围的矩形框
data_slices = ndimage.find_objects(coded_pa​​ws)
返回data_slices

def slice_to_bbox(切片):
表示切片中的s :
dy,dx = s [:2]
收益率BBox(dx.start,dy.start,dx.stop + 1,dy.stop + 1)

def remove_overlaps(bboxes):
'''
返回一组包含给定BBox的BBox。
当两个BBox重叠时,用两个包含两者的最小BBox替换两者。
'''
#列出Bbox的左上角和右下角
corner = []

#list Bbox的左上角
ulcorners = []

#dict将角落映射到Bboxes。
bbox_map = {}

bbox中的bbox:
ul =(bbox.x1,bbox.y1)
lr =(bbox.x2,bbox.y2 )
bbox_map [ul] = bbox
bbox_map [lr] = bbox
ulcorners.append(ul)
corner.append(ul)
corner.append(lr) )

#使用KDTree,我们可以有效地找到附近的角落。
tree = spatial.KDTree(角落)
new_corners = []
用于ulcorners中的角落:
bbox = bbox_map [corner]
#查找所有内点角落的出租车距离
indices = tree.query_ball_point(
corner,bbox_map [corner] .taxicab_diagonal(),p = 1)
for tree中的near_corner [indices]:
near_bbox = bbox_map [tuple(near_corner)]
if bbox!= near_bbox and bbox.overlaps(near_bbox):
#展开两个bbox。
#由于我们改变了bbox,因此
#bbox_map中对此bbox的所有引用都会同时更新。
bbox.x1 = near_bbox.x1 = min(bbox.x1,near_bbox.x1)
bbox.y1 = near_bbox.y1 = min(bbox.y1,near_bbox.y1)
bbox。 x2 = near_bbox.x2 = max(bbox.x2,near_bbox.x2)
bbox.y2 = near_bbox.y2 = max(bbox.y2,near_bbox.y2)
return set(bbox_map.values() )

如果__name__ =='__ main__':
fig = plt.figure()
ax = fig.add_subplot(111)

data = misc.imread('image.png')
im = ax.imshow(data)
data_slices = find_paws(255-data,smooth_radius = 20,threshold = 22)

bboxes = remove_overlaps(slice_to_bbox(data_slices))
for bbox in bboxes:
xwidth = bbox.x2 - bbox.x1
ywidth = bbox.y2 - bbox.y1
p = patches .Rectangle((bbox.x1,bbox.y1),xwidth,ywidth,
fc ='none',ec ='red')
ax.add_patch(p)

plt.show()

产生


I have a few monochrome images (black and white not greyscale) with a few weirdly shaped objects. I'm trying to extract each object using python27, PIL, scipy & numpy and the following method:

  1. Fit a bounding box around each joined-up object
  2. "Extract" each object as an array - for each object / bounding box

I've had a look at http://www.scipy.org/Cookbook/Watershed and http://scikits-image.org/docs/dev/auto_examples/plot_contours.html and these do work, but I'm particularly keen to have the bounding box be rectangular to make sure that any "slightly disconnected" bits get included in the bounding box. Ideally to deal with the disconnected bits (e.g. bottom left blobs) I'd have some kind of threshold control. Any ideas on what toolbox would best suit this?

解决方案

This uses Joe Kington's find_paws function.

import numpy as np
import scipy.ndimage as ndimage
import scipy.spatial as spatial
import scipy.misc as misc
import matplotlib.pyplot as plt
import matplotlib.patches as patches

class BBox(object):
    def __init__(self, x1, y1, x2, y2):
        '''
        (x1, y1) is the upper left corner,
        (x2, y2) is the lower right corner,
        with (0, 0) being in the upper left corner.
        '''
        if x1 > x2: x1, x2 = x2, x1
        if y1 > y2: y1, y2 = y2, y1
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2
    def taxicab_diagonal(self):
        '''
        Return the taxicab distance from (x1,y1) to (x2,y2)
        '''
        return self.x2 - self.x1 + self.y2 - self.y1
    def overlaps(self, other):
        '''
        Return True iff self and other overlap.
        '''
        return not ((self.x1 > other.x2)
                    or (self.x2 < other.x1)
                    or (self.y1 > other.y2)
                    or (self.y2 < other.y1))
    def __eq__(self, other):
        return (self.x1 == other.x1
                and self.y1 == other.y1
                and self.x2 == other.x2
                and self.y2 == other.y2)

def find_paws(data, smooth_radius = 5, threshold = 0.0001):
    # https://stackoverflow.com/questions/4087919/how-can-i-improve-my-paw-detection
    """Detects and isolates contiguous regions in the input array"""
    # Blur the input data a bit so the paws have a continous footprint 
    data = ndimage.uniform_filter(data, smooth_radius)
    # Threshold the blurred data (this needs to be a bit > 0 due to the blur)
    thresh = data > threshold
    # Fill any interior holes in the paws to get cleaner regions...
    filled = ndimage.morphology.binary_fill_holes(thresh)
    # Label each contiguous paw
    coded_paws, num_paws = ndimage.label(filled)
    # Isolate the extent of each paw
    # find_objects returns a list of 2-tuples: (slice(...), slice(...))
    # which represents a rectangular box around the object
    data_slices = ndimage.find_objects(coded_paws)
    return data_slices

def slice_to_bbox(slices):
    for s in slices:
        dy, dx = s[:2]
        yield BBox(dx.start, dy.start, dx.stop+1, dy.stop+1)

def remove_overlaps(bboxes):
    '''
    Return a set of BBoxes which contain the given BBoxes.
    When two BBoxes overlap, replace both with the minimal BBox that contains both.
    '''
    # list upper left and lower right corners of the Bboxes
    corners = []

    # list upper left corners of the Bboxes
    ulcorners = []

    # dict mapping corners to Bboxes.
    bbox_map = {}

    for bbox in bboxes:
        ul = (bbox.x1, bbox.y1)
        lr = (bbox.x2, bbox.y2)
        bbox_map[ul] = bbox
        bbox_map[lr] = bbox
        ulcorners.append(ul)
        corners.append(ul)
        corners.append(lr)        

    # Use a KDTree so we can find corners that are nearby efficiently.
    tree = spatial.KDTree(corners)
    new_corners = []
    for corner in ulcorners:
        bbox = bbox_map[corner]
        # Find all points which are within a taxicab distance of corner
        indices = tree.query_ball_point(
            corner, bbox_map[corner].taxicab_diagonal(), p = 1)
        for near_corner in tree.data[indices]:
            near_bbox = bbox_map[tuple(near_corner)]
            if bbox != near_bbox and bbox.overlaps(near_bbox):
                # Expand both bboxes.
                # Since we mutate the bbox, all references to this bbox in
                # bbox_map are updated simultaneously.
                bbox.x1 = near_bbox.x1 = min(bbox.x1, near_bbox.x1)
                bbox.y1 = near_bbox.y1 = min(bbox.y1, near_bbox.y1) 
                bbox.x2 = near_bbox.x2 = max(bbox.x2, near_bbox.x2)
                bbox.y2 = near_bbox.y2 = max(bbox.y2, near_bbox.y2) 
    return set(bbox_map.values())

if __name__ == '__main__':
    fig = plt.figure()
    ax = fig.add_subplot(111)

    data = misc.imread('image.png')
    im = ax.imshow(data)    
    data_slices = find_paws(255-data, smooth_radius = 20, threshold = 22)

    bboxes = remove_overlaps(slice_to_bbox(data_slices))
    for bbox in bboxes:
        xwidth = bbox.x2 - bbox.x1
        ywidth = bbox.y2 - bbox.y1
        p = patches.Rectangle((bbox.x1, bbox.y1), xwidth, ywidth,
                              fc = 'none', ec = 'red')
        ax.add_patch(p)

    plt.show()

yields

这篇关于在使用Python的单色图像中的blob周围的矩形边界框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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