Eine Möglichkeit, dies zu nähern ist Ihren eigenen (naiven) Algorithmus zu implementieren, die meine erste Idee war. Auf der anderen Seite, warum das Rad neu erfinden:
Man kann leicht sehen, dass das Problem als ein Schwarzweiß (Raster/Pixel) Bild interpretiert werden kann. Dann bilden der äußere und innere Bereich den Hintergrund (schwarz), während der Rand eine geschlossene (weiße) Schleife ist. (Natürlich könnten die Farben auch umgeschaltet werden, aber ich werde jetzt Weiß auf Schwarz verwenden.) Es gibt einige ziemlich anspruchsvolle Bildverarbeitungsbibliotheken für Python, nämlich skimage, ndimage und mahotas.
Ich bin kein Experte, aber ich denke skimage.draw.polygon
, skimage.draw.polygon_perimiter
sind der einfachste Weg, um Ihr Problem zu lösen.
Meine Experimente ergaben folgendes:
import matplotlib.pyplot as plt
import numpy as np
from skimage.draw import polygon, polygon_perimeter
from skimage.measure import label, regionprops
# some test data
# I used the format that your input data is in
# These are 4+99*4 points describing the border of a 99*99 square
border_points = (
[[100,100]] +
[[100,100+i] for i in range(1,100)] +
[[100,200]] +
[[100+i,200] for i in range(1,100)] +
[[200,200]] +
[[200,200-i] for i in range(1,100)] +
[[200,100]] +
[[200-i,100] for i in range(1,100)]
)
# convert to numpy arrays which hold the x/y coords for all points
# repeat first point at the end to close polygon.
border_points_x = np.array([p[0] for p in border_points] + [border_points[0][0]])
border_points_y = np.array([p[1] for p in border_points] + [border_points[0][1]])
# empty (=black) 300x300 black-and-white image
image = np.zeros((300, 300))
# polygon() calculates the indices of a filled polygon
# one would expect this to be inner+border but apparently it is inner+border/2
# probably some kind of "include only the left/top half"
filled_rr, filled_cc = polygon(border_points_y, border_points_x)
# set the image to white at these points
image[filled_rr, filled_cc] = 1
# polygon_perimeter() calculates the indices of a polygon perimiter (i.e. border)
border_rr, border_cc = polygon_perimeter(border_points_y, border_points_x)
# exclude border, by setting it to black
image[border_rr, border_cc] = 0
# label() detects connected patches of the same color and enumerates them
# the resulting image has each of those regions filled with its index
label_img, num_regions = label(image, background=0, return_num=True)
# regionprops() takes a labeled image and computes some measures for each region
regions = regionprops(label_img)
inner_region = regions[0]
print("area", inner_region.area)
# expecting 9801 = 99*99 for inner
# this is what you want, the coords of all inner points
inner_region.coords
# print it
fig, ax = plt.subplots()
ax.imshow(image, cmap=plt.cm.gray)
Sind Sie sicher, dass Sie alle inneren Punkte (das heißt Zellen innerhalb der Grenze) auflisten möchten? Aus den in Ihrem ersten Bild angegebenen Indizes scheint es, als könnte das eine ziemlich große Menge sein, vielleicht zu groß, um effizient gehandhabt zu werden. Wenn alles, was Sie (später) brauchen, eine Möglichkeit ist, die Mitgliedschaft zu testen, wäre es wahrscheinlich besser, das einzeln zu testen. – PeterE