Как получить область внутри контура?

#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, вычислить площади для каждого и суммировать их. Если это сложнее, я бы поискал что-нибудь другое.