2012-03-01 20 views
6

私はいくつかの奇妙な形のオブジェクトを含む単色の画像(白黒のグレースケールではありません)をいくつか持っています。私はpython27、PIL、scipyのダウンロード& numpyの、以下の方法で使用して各オブジェクトを抽出しようとしている:Pythonを使用して白黒画像内のブロブを囲む四角形の境界ボックス

  1. を配列として各オブジェクトを「抽出」各参加アップオブジェクト
  2. の周りにバウンディングボックスをフィット - のために各オブジェクト/バウンディングボックス

は私がhttp://www.scipy.org/Cookbook/Watershedhttp://scikits-image.org/docs/dev/auto_examples/plot_contours.htmlを見て持っていたし、これらの作業を行うが、私はどんな「やや切断」のビットを得ることを確認するために長方形でバウンディングボックスを持っていることは特に夢中ですバウンディングボックスに含まれています。理想的には、分離されたビット(例えば、左下のブロブ)を処理するためには、ある種の閾値制御があるだろう。これに最も適したツールボックスは何ですか?

unbounded image example of image bounds

+2

はscipy.ndimage' 'を見てください。それはあなたが必要とするすべてを持っています。 (特に 'label'と' find_objects'と 'fill_holes'と組み合わせて、あなたの"あいまいな "寛容のためのぼかしとスレッシュホールド)少し時間がたっていますので、他の誰かが完全な例を投稿します:) –

答えて

14

これは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() 

利回り enter image description here

+0

こんにちはそこにunutbu、この答えはありがとう、ありがとう!その足のチュートリアルは良い発見だった、私はそれを以前見たことがない。重なり合うスライスは、いくつかの画像(例えば、例1)では機能するが、他の画像では機能しない。私がしているようにしてください、私はこれの理由を理解することはできません。何か案は? – user714852

+0

これは本当に元の人とは別の質問ですので、私はそれを開いたことを尋ねました:http://stackoverflow.com/questions/9548758/how-can-i-find-and-delete-overlapped-slices-of-リストからのイメージ – user714852

+1

このコードでは、KDTreeを使用して重複する長方形を検索します。それをテストしてください。私はまだ私のアドホックなアルゴリズムについて多くの不安を持っています。重複する四角形を見つける問題は、「古典的な問題」のように見え、古典的な答えが必要です。私が一日で夢を見ていることは、多くの賢い人々がおそらく何年もの間人工的に考案してきたように、近くにいることはまずありません。 – unutbu

関連する問題