Opencv - определение контура сосуда после обнаружения края - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть изображение судна.После обнаружения острых краев и другой обработки мне удалось получить это изображение .Судно хорошо видно, но я бы хотел получить контур этого судна.Как мне это сделать?

1 Ответ

0 голосов
/ 03 декабря 2018

Причина, по которой вы получаете два отдельных контура, заключается в том, что вы применяете детектор краев Canny к изображению в градациях серого.Это дает результат «белых линий» - краев на чистом изображении.cv2.findContours() в терминах непрофессионалов ищет подключенные белые пиксели на двоичном изображении.Таким образом, поскольку у вас есть две отдельные линии, он находит два контура.cv2.findContours() возвращает массив точек контуров, поэтому, прежде чем искать интересующую вас область, вы должны сначала соединить эти две линии, чтобы получить только один контур.Это можно сделать, перебирая точки и добавляя точки со значениями 0 для x или y и / или значениями высоты или ширины изображений.Это даст вам 4 очка - начальную и конечную точку первого контура плюс начало и конец второго.Затем вы можете измерить расстояние между этими точками, чтобы определить, какой из них подходит.Насколько я помню, формула для расстояния между двумя точками равна sqrt((x2-x1)^2+(y2-y1)^2).Таким образом, если вы вычислите расстояние от одной точки до оставшихся 3, самое короткое расстояние означает, что эти две точки соответствуют тогетру (как и две точки, которые соответствуют тогетеру, который находится дальше).Теперь у вас есть начальная и конечная точки обеих линий, и вы можете соединить их.Конечно, вы можете сделать другой критерий, например, если первая точка имеет x==0 и y>0, затем проведите линию к точке (0,0) и оттуда другую линию до второй точки, чтобы вы не вырезали частьобласть интересов.Я сделал простой пример, чтобы показать вам логику достижения этого.Обратите внимание, что это не рабочее решение для автоматизации - для достижения этого вам придется многократно обновлять его.

Пример кода:

import cv2
import numpy as np

img = cv2.imread('vessel.png')
h, w, ch = img.shape
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(img,100,200)
_, contours, hierarchy = cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
points = []

cv2.imshow('edges', edges)

for cnt in contours:
    for i in cnt[:,0]:
        x = int(i[0])
        y = int(i[1])
        if x == 0:
            points.append((x,y))
        elif y == 0:
            points.append((x,y))
        elif w-1<= x <= w+1:
            points.append((x,y))
        elif h-1<= y <= h+1:
            points.append((x,y))

if len(points) == 4:
    x1, y1 = points[0]
    x2, y2 = points[1]
    x3, y3 = points[2]
    x4, y4 = points[3]

dist1 = np.sqrt((x2-x1)**2 + (y2-y1)**2)
dist2 = np.sqrt((x3-x1)**2 + (y3-y1)**2)    
dist3 = np.sqrt((x4-x1)**2 + (y4-y1)**2)

if dist2 < dist1 and dist2 < dist3:
    cv2.line(edges, (x3,y3), (x1,y1), 255, 1)
    cv2.line(edges, (x2,y2), (x4,y4), 255, 1)

_, contours, hierarchy = cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, 0, (0,255,0), 2)

cv2.imshow('img', img)
cv2.imshow('edges+lines', edges)

cv2.waitKey(0)
cv2.destroyAllWindows()

Исходное изображение:

enter image description here

Края:

enter image description here

Края + линии:

enter image description here

Контуры:

enter image description here

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

Пример кода:

import cv2
import numpy as np

img = cv2.imread('vessel.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, 0, (0,255,0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Изображение с порогом:

enter image description here

Контуры:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...