简体   繁体   中英

Get pixel boundary coordinates from binary image in Python (not edges)

I have a binary image containing a single contiguous blob, with no holes. I would like create a polygon object based on the exterior edges of the edge pixels. I know how to get the edge pixels themselves, but I want the actual coordinates of the pixel boundaries, sorted clockwise or counter-clockwise. All of the pixels have integer coordinates.

For example, say I have a single pixel at (2,2). The vertices of the polygon would be: (2.5, 2.5) (2.5, 1.5) (1.5, 1.5) (1.5, 2.5) (2.5, 2.5)

Is there an exact, non-approximate way to do this? Preferably in Python?

See example:

from PIL import Image, ImageFilter, ImageChops
import math

a = [['.','.','.','.','.','.','.'],
      ['.','.','.','.','.','.','.'],
      ['.','.','.','.','.','.','.'],
      ['.','#','#','#','.','.','.'],
      ['.','#','#','#','.','.','.'],
      ['.','.','.','.','.','.','.']]      

sz=(len(a[0]), len(a))
flat_list = [j=='.' for i in a for j in i]
image=Image.new('1', sz)
image.putdata(flat_list)
contour=ImageChops.difference(image, image.filter(ImageFilter.MinFilter(3)))
contour_list=list(contour.getdata())
points=[divmod(i,sz[0]) for i in range(len(contour_list)) if contour_list[i]]
points_x,points_y=zip(*points)
avg=lambda x: sum(x)/len(x)
mean_x=avg(points_x)
mean_y=avg(points_y)
phase=[(math.atan2(points_y[i]-mean_y, points_x[i]-mean_x),i) \
       for i in range(len(points))] 
phase.sort()
for i in range(len(points)):
    print(*points[phase[i][1]])

Based on the comments, here is the approach that I implemented:

  1. multiply all pixel coordinates by 10, so that we'll only deal with integers.

  2. For each pixel, generate the 4 corners by adding +/- 5. For example, for (20,20), the corners are (25, 25) (25, 15) (15, 15) (15, 25) (25, 25). And store all the corners in a list.

  3. Count the occurrences of each corner. If the count is odd, it is a corner to the blob. Making the coordinates integers makes this step easy. Counting floats has issues.

  4. Divide the blob corner coordinates by 10, getting back the original resolution.

  5. Sort the corners clockwise using a standard algorithm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM