#python #contour #area
#python #контур #область
Вопрос:
У меня есть один контур, в котором я хотел бы найти область (изображение в конце post- contour является линией подсказки и описывается синим набором точек). Я пытался использовать alphashape для этого (см. Ниже), но это работает недостаточно хорошо для моих целей (аппроксимация контура alphashape зеленым цветом на изображении). Существуют ли другие методы, которые я могу использовать, чтобы получить область внутри этого контура?
Спасибо!
Вот мой код на данный момент. точки — это список всех отдельных контуров, с которыми я хочу это сделать.
for cnum in np.arange(0,(len(points))):
cpoints_nan=points[cnum]
cpoints=[]
for i in np.arange(0, len(cpoints_nan)): #Get rid of nan pairs
if np.isnan(cpoints_nan[i][0]): #If current pair of points is [nan, nan]
continue
else: #If current pair of points is not nan, add to cpoints
cpoints.append([cpoints_nan[i][0][np.logical_not(np.isnan(cpoints_nan[i][0]))][0], cpoints_nan[i][1][np.logical_not(np.isnan(cpoints_nan[i][1]))][0]])
if len(cpoints)>3: #Need more than two points to use alphashape. Greater than 3 because for closed "loops" the last point is the first and so this will still just form a line rather than a polygon
alpha=alphashape.optimizealpha(cpoints)
hull = alphashape.alphashape(cpoints, alpha)
contour_areas.append(hull.area) #Get area inside contour
РЕДАКТИРОВАТЬ: многие из контуров, на которые я смотрю, самопересекаются, так что это дополнительный уровень сложности
Контурное изображение: https://i.stack.imgur.com/qBnmv.png
Комментарии:
1. используйте формулу shoelance: en.wikipedia.org/wiki/Shoelace_formula … или преобразуйте точки контура в фигурный многоугольник, который имеет атрибут area
Ответ №1:
Предполагая, что точки расположены в правильном порядке, что линия не пересекается сама с собой и что линия образует законченную фигуру (после точек [-1] идет точка [1]), вы можете вычислить are путем суммирования отдельных частичных подписанных областей:
# p = cpoints
area = 0
for i in range(len(p) -1):
area = (p[i][0] - p[i 1][0]) * (p[i][1] p[i 1][1]) / 2
area = (p[i][0] - p[-1][0]) * (p[i][1] p[-1][1]) / 2
Для каждого сегмента линии вы вычисляете площадь между ним и осью x. Если линия идет влево, область добавляется, если линия идет вправо, область вычитается. Это дает вам правильную область, потому что вы добавляете для части контура, которая обращена вверх, и вычитаете для части, которая обращена вниз.
Это зависит от порядка точек (они должны быть в тригонометрическом смысле, чтобы дать положительную область). Если ваши точки идут по часовой стрелке, умножьте на -1. Если вам все равно, возьмите абсолютное значение в конце.
Это должно дать вам хороший результат, но будьте осторожны с числовой нестабильностью, если у вас экстремальные значения или много точек.
Комментарии:
1. Спасибо, об этом полезно знать! К сожалению, многие контуры, с которыми мне приходится иметь дело, самопересекаются, и это аспект, который мне нужно учитывать при поиске области, учитывая характер проблемы, которую я исследую. Есть ли хорошие способы справиться с такой ситуацией?
2. Если у вас есть самопересечения, приведенный выше алгоритм будет считать одну часть положительной и одну часть отрицательной, чтобы вы получили разницу между двумя областями. Если вы знаете, что у вас есть простые ситуации, такие как одно пересечение, вы можете попытаться найти пересекающиеся сегменты и разделить фигуру на 2, вычислить площади для каждого и суммировать их. Если это сложнее, я бы поискал что-нибудь другое.