Нахождение расстояния между скелетом и границей с использованием openCV python


person Eshant    schedule 17.12.2018    source источник
comment
Для каждого красного пикселя найдите ближайший белый пиксель (который должен быть соединен искомой ортогональной линией) и рассчитайте расстояние, используя евклидово расстояние. Затем вы можете либо взять среднее значение всех расстояний, либо минимальное / максимальное значение в зависимости от желаемых результатов.   -  person T A    schedule 17.12.2018
comment
imho в вашем случае нет проблем с преобразованием расстояния. За исключением того, что расстояния могут быть ошибочными с ошибкой, зависящей от максимального размера зазоров в контуре.   -  person Micka    schedule 17.12.2018
comment
@TA, как мне найти ближайший белый пиксель для каждого красного пикселя? Можете ли вы объяснить логику? Я думаю, это может сработать!   -  person Eshant    schedule 17.12.2018
comment
@Eshant В качестве простого подхода: выполните поиск в 8-окрестности вашего пикселя, затем последовательно увеличивайте размер вашей поисковой среды, пока не получите результат.   -  person T A    schedule 17.12.2018


Ответы (1)


Максимальная ширина — это максимальное расстояние от любой точки на границе до средней линии (возможно, умноженное на два).

Чтобы определить это значение, вы можете использовать distance_transform следующим образом:

import numpy as np
import matplotlib.pyplot as plt
import cv2

# Generate test image
size = (100, 100)

mid_line = np.zeros(size, dtype='uint8')
mid_line[(range(10, 40), range(10, 40))] = 1
mid_line[(range(40, 80), np.linspace(40, 70, 40).astype(int))] = 1

outline = np.zeros(size, dtype='uint8')
outline[(np.linspace(5, 33, 30).astype(int),
         np.linspace(16, 47, 30).astype(int))] = 1

outline[(np.linspace(14, 47, 30).astype(int),
         np.linspace(5, 35, 30).astype(int))] = 1

outline[(np.linspace(36, 72, 40).astype(int),
         np.linspace(50, 77, 40).astype(int))] = 1

outline[(np.linspace(47, 88, 40).astype(int),
         np.linspace(35, 65, 40).astype(int))] = 1

dist = cv2.distanceTransform(255 - (255*mid_line), cv2.DIST_L2, 3)

# Visualize
plt.figure("Mid line plus edges over the distance transform")
plt.imshow(dist, cmap='gray')
overlay = mid_line + 2 * outline
plt.imshow(np.ma.masked_where(overlay == 0, overlay), cmap='jet', alpha=0.6)

# Get the maximum width
max_width = np.max(dist[outline > 0])
print("Maximum width:", max_width)


plt.show()

который генерирует изображение:

введите здесь описание изображения

И выводит:

Maximum width: 10.954346

к терминалу.

person jmetz    schedule 17.12.2018
comment
отлично работает для тестового изображения. Но когда я использую его для своего собственного изображения, я получаю сообщение об ошибке: слишком большая последовательность; не может быть больше 32. Вы знаете, что может быть не так? - person Eshant; 19.12.2018
comment
Не могли бы вы обновить свой вопрос, показав код, который вы пробовали? - person jmetz; 19.12.2018