OpenCV Периметр и площадь заданной точки в подключенном компоненте

Предположим, у меня есть бинарное изображение, и я хочу сделать в OpenCV следующее: учитывая точку, измерьте площадь и периметр связанного компонента, которому принадлежит эта точка.

def areaAndPerimeter(point):
   ...do some stuff...
   return area, perimeter

Я знаю, что могу использовать cv2.findContours(), чтобы найти периметр и площадь каждого связанного компонента, но я не знаю, как связать эту информацию с точкой ввода. Какой периметр и площадь соответствуют компоненту связности point


person mv3    schedule 23.01.2017    source источник
comment
Я думаю, что вы делаете connectedComponentsWithStats(), и он помечает все точки в каждой капле одним цветом. Таким образом, вы найдете цвет (т.е. метку), соответствующий вашей точке, чтобы определить, к какой капле она принадлежит. Я могу безнадежно ошибаться! Насколько я знаю, в Matlab он называется bwlabel().   -  person Mark Setchell    schedule 24.01.2017
comment
Да, я начал работать над решением, в котором я использую просто старый добрый connectedComponents(), а затем извлекаю каждый компонент 1 на 1 и запускаю findContours() отдельно для каждого, но это кажется такой тратой времени, когда я могу запустить findContours() один раз для всего изображения и пропустить подключенное компоненты все вместе.   -  person mv3    schedule 24.01.2017


Ответы (1)


Для этой функции я бы просто увеличил регион, начиная с точки. Ниже приведен псевдокод:

 - Define a point queue Q
 - Define a foreground point vector F
 - Define a boundary point vector B
 - Put starting point in Q
 - While Q is not empty
      - p = Q.top
      - if p is foreground
          - F.push(p)
          - Q.push(neighbors of p)
      - else 
          - B.push(p)
- Return size(F), size(B)

В конце F содержит пиксели переднего плана, а B содержит граничные пиксели (черные сразу за белыми). Таким образом, size(F) дает площадь, а size(B) — периметр.

person ilke444    schedule 24.01.2017
comment
Это хорошие меры периметра и площади? Я предполагаю, что их можно было бы принять как определения, но когда я пытаюсь это сделать, они не соответствуют результатам функций opencv cv2.arcLength() и cv2.contourArea(). Размер самого контура соответствует вашему определению периметра, но функция cv2.arclength() не равна этому и дает результаты, более близкие к тому, что я ожидал. - person mv3; 24.01.2017
comment
Поскольку существуют разные меры расстояния (например, евклидово или манхэттенское расстояние), площадь и длина дуги также зависят от вашего приближения, поскольку область изображения является дискретной. Приведенный выше код показывает, сколько пикселей находится на переднем плане? и сколько пикселей на границе?. Если вы хотите использовать приближение OpenCV, используйте все точки в B и запустите cv2.contourArea(B) и cv2.arcLength(B). - person ilke444; 24.01.2017
comment
Ясно, я собираюсь попытаться синхронизировать это с тем, что я сейчас делаю, то есть использую cv2.connectedComponents() для поиска связанных компонентов, извлекая компонент моей точки, затем используя cv2.findContours() и впоследствии cv2.contourArea() и cv2.arcLenth(). - person mv3; 26.01.2017