6

몇 가지 이상한 모양의 개체가있는 흑백 이미지 (흑백이 아니라 회색조)가 있습니다. 내가 python27, PIL을 사용하여 각 객체를 추출하기 위해 노력하고있어, & NumPy와 다음과 같은 방법 scipy :파이썬을 사용하여 단색 이미지의 얼룩 (blob) 주위 사각형 경계 상자

  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'와 결합하여 약간의 블러 링과 thresholding을 당신의 "퍼지 (fuzzy)"관용을 위해) 저는 약간 시간이 부족합니다. 그래서 다른 누군가가 전체 예제를 게시 할 것입니다 :) –

답변

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,이 답변을 주셔서 감사합니다. 그 발 튜토리얼은 좋은 발견이었고, 나는 전에 그것을 보지 못했습니다. 겹치는 조각은 일부 이미지 (예 : 예)에서는 작동하지만 다른 이미지에서는 작동하지 않습니다. 시도해 볼 수도 있지만 그 이유를 알 수는 없습니다. 어떤 아이디어? – user714852

+0

이것은 원래 하나의 질문과는 별도로 내가 열어 본 질문과 같습니다 : http://stackoverflow.com/questions/9548758/how-can-i-find-and-delete-overlapped-slices-of- an-image-from-a-list – user714852

+1

코드는 이제 KDTree를 사용하여 겹치는 사각형을 찾습니다. 시험해보십시오. Ad-hoc 알고리즘에 대해 아직도 많은 불안감이 있습니다. 겹치는 사각형을 찾는 문제는 "고전적인 문제"처럼 보입니다. 고전적인 대답이 있어야합니다. 하루에 꿈꾸는 것은 많은 똑똑한 사람들이 아마도 많은 인력으로 고안 한 것만큼이나 좋은 것 같지는 않습니다. – unutbu