Как найти конкретную точку на контуре в opencv / python - PullRequest
3 голосов
/ 20 мая 2019

Я использовал opencv для создания некоторых контуров, и мне нужно определить конкретную точку на контуре, которая обычно является самой внутренней точкой V-образной формы.На прикрепленном изображении точка, которую я хочу определить, показана зелеными стрелками.

Example

Слева - простой случай, в котором идентификацию можно выполнить (например, путем вычисления выпуклой оболочки контура, а затем найти точку, наиболее удаленную от корпуса)..

Однако справа от прикрепленного изображения гораздо более сложный случай, когда вместо 1 контура я получаю несколько, а красивой формы «V» нет, что делает невозможным идентификациювнутренняя точка V.Как показано красной пунктирной линией, одним из решений может быть экстраполяция верхнего контура, пока он не пересекается с нижним.Кто-нибудь знает, как я могу пойти по этому поводу?Или есть лучшее решение?

Для записи, которую я пробовал:

  • расширение / эрозия (работает, когда несколько контуров близко друг к другу, в противном случае нет)

  • хотя преобразование p (имеет тенденцию неправильно перемещать целевую точку)

Любые указатели будут чрезвычайно полезны.

1 Ответ

1 голос
/ 21 мая 2019

Это решение будет работать для двух предоставленных вами изображений.Это также должно быть хорошим решением для всех других изображений, которые имеют аналогичную окраску и имеют форму v (или, по крайней мере, частичную форму v), которая указывает вправо.

Давайте посмотрим насначала легче изображениеЯ начал с сегментирования изображения с использованием цветовых пространств.

# Convert frame to hsv color space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Define range of pink color in HSV
(b,r,g,b1,r1,g1) = 0,0,0,110,255,255
lower = np.array([b,r,g])
upper = np.array([b1,r1,g1])
# Threshold the HSV image to get only pink colors
mask = cv2.inRange(hsv, lower, upper)

color spaces

Затем я нашел mid_point, где было одинаковое количество белоговыше и ниже этой строки.

# Calculate the mid point
mid_point = 1
top, bottom = 0, 1
while top < bottom:
    top = sum(sum(mask[:mid_point, :]))
    bottom = sum(sum(mask[mid_point:, :]))
    mid_point += 1

Затем я заполнил изображение, начиная с середины: bg = np.zeros ((h + 2, w + 2), np.uint8)

kernel = np.ones((k_size, k_size),np.uint8)  
cv2.floodFill(mask, bg, (0, mid_point), 123)

floodfilled

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

# Find the gray pixel that is furthest to the right
idx = 0
while True:
    column = mask_temp[:,idx:idx+1]
    element_id, gray_px, found = 0, [], False
    for element in column:
        if element == 123:
            v_point = idx, element_id
            found = True
        element_id += 1
    # If no gray pixel is found, break out of the loop
    if not found: break
    idx += 1

Результат:

result1

Теперь для более жесткого изображения.На изображении справа 'v' не полностью соединяется:

does not connect

Чтобы закрыть 'v', я итеративно расширил проверенную маскуесли он подключен:

# Flood fill and dilate loop
k_size, iters = 1, 1
while True:
    bg = np.zeros((h+2, w+2), np.uint8)
    mask_temp = mask.copy()    
    kernel = np.ones((k_size, k_size),np.uint8)    
    mask_temp = cv2.dilate(mask_temp,kernel,iterations = iters)
    cv2.floodFill(mask_temp, bg, (0, mid_point), 123)
    cv2.imshow('mask', mask_temp)
    cv2.waitKey()
    k_size += 1
    iters += 1
    # Break out of the loop of the right side of the image is black
    if mask_temp[h-1,w-1]==0 and mask_temp[1, w-1]==0: break

dilation

В результате получается:

output2

...