2012-03-01 37 views
6

Tôi có một vài ảnh đơn sắc (đen trắng không xám) với một vài đối tượng hình kỳ lạ. Tôi đang cố gắng để giải nén từng đối tượng sử dụng python27, PIL, scipy & NumPy và phương pháp sau:Hộp giới hạn hình chữ nhật xung quanh các đốm màu trong ảnh đơn sắc bằng cách sử dụng python

  1. Fit một hộp bounding xung quanh từng đối tượng tham gia lên
  2. "Extract" từng đối tượng như là một mảng - cho từng đối tượng/bounding hộp

tôi đã có một cái nhìn tại http://www.scipy.org/Cookbook/Watershedhttp://scikits-image.org/docs/dev/auto_examples/plot_contours.html và những công việc làm, nhưng tôi đặc biệt quan tâm để có hộp bounding là hình chữ nhật để đảm bảo rằng bất kỳ bit "hơi bị ngắt kết nối" được được bao gồm trong hộp giới hạn. Lý tưởng nhất là xử lý các bit bị ngắt kết nối (ví dụ: các đốm màu dưới cùng bên trái) Tôi có một số loại kiểm soát ngưỡng. Bất kỳ ý tưởng nào về hộp công cụ nào phù hợp nhất với điều này?

unbounded image example of image bounds

+2

Hãy nhìn vào 'scipy.ndimage'. Nó có mọi thứ bạn cần. (đặc biệt là 'label' và' find_objects', kết hợp với 'fill_holes' và một chút blurring và thresholding cho dung sai" fuzzy "của bạn) Tôi đang chạy một chút ngắn về thời gian, vì vậy hy vọng ai đó sẽ đăng một ví dụ đầy đủ :) –

Trả lời

14

này sử dụng 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() 

mang enter image description here

+0

Xin chào unutbu, cảm ơn câu trả lời này thật tuyệt vời! Đó là hướng dẫn bàn chân là một tìm kiếm tốt, tôi đã không nhìn thấy nó trước đây. Các lát chồng chéo hoạt động đối với một số hình ảnh (ví dụ: một hình ảnh), nhưng không hoạt động với các hình ảnh khác. Hãy thử như tôi có thể, tôi không thể tìm ra lý do cho việc này. Bất kỳ ý tưởng? – user714852

+0

Vì đây thực sự là một câu hỏi riêng đối với câu hỏi ban đầu, tôi đã mở nó tại: http://stackoverflow.com/questions/9548758/how-can-i-find-and-delete-overlapped-slices-of- an-image-from-a-list – user714852

+1

Mã bây giờ sử dụng một KDTree để tìm hình chữ nhật chồng lên nhau. Hãy kiểm tra nó. Tôi vẫn còn có nhiều hiểu lầm về thuật toán đặc biệt của tôi. Vấn đề tìm hình chữ nhật chồng chéo có vẻ như là một "vấn đề kinh điển" và nên có một câu trả lời cổ điển. Những gì tôi mơ ước trong một ngày không thể ở bất cứ nơi nào gần như tốt như những gì nhiều người thông minh có lẽ đã nghĩ ra trong nhiều năm. – unutbu

Các vấn đề liên quan