Как найти определенную точку на контуре в opencv/python

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

Пример

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

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

Для записи я пробовал:

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

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

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


person ennjaycee    schedule 20.05.2019    source источник


Ответы (1)


Это решение будет работать для двух изображений, которые вы предоставили. Это также должно быть хорошим решением для всех других изображений, которые имеют аналогичную окраску и форму «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)

цветовые пространства

Затем я нашел 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)

затопленный

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

# 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

Результат:

результат1

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

не подключается

Чтобы закрыть «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

расширение

Это результат:

выход2

person Stephen Meschke    schedule 20.05.2019
comment
Большое спасибо! Для более сложного изображения эффект расширения заключается в том, что целевая точка смещается немного дальше влево, чем она должна быть на самом деле, но я думаю, что могу легко компенсировать это в зависимости от количества итераций расширения. Еще раз спасибо за вашу усердную работу и отличное решение. - person ennjaycee; 21.05.2019