Я бы решил это с помощью алгоритма стиля водораздела. Я описал метод ниже, однако он создан для работы только с одной (многосегментной) линией, поэтому вам нужно разделить изображение на отдельные строки.
Пример игрушки:
0000000
0111110
0111110
0110000
0110000
0000000
Где 0
обозначает черный, а 1
обозначает белый.
Теперь моя реализация решения:
import numpy as np
img = np.array([[0,0,0,0,0,0,0],
[0,255,255,255,255,255,0],
[0,255,255,255,255,255,0],
[0,255,255,0,0,0,0],
[0,0,0,0,0,0,0]],dtype='uint8')
def flood(arr,value):
flooded = arr.copy()
for y in range(1,arr.shape[0]-1):
for x in range(1,arr.shape[1]-1):
if arr[y][x]==255:
if arr[y-1][x]==value:
flooded[y][x] = value
elif arr[y+1][x]==value:
flooded[y][x] = value
elif arr[y][x-1]==value:
flooded[y][x] = value
elif arr[y][x+1]==value:
flooded[y][x] = value
return flooded
ends = np.zeros(img.shape,dtype='uint64')
for y in range(1,img.shape[0]-1):
for x in range(1,img.shape[1]-1):
if img[y][x]==255:
temp = img.copy()
temp[y][x] = 127
count = 0
while 255 in temp:
temp = flood(temp,127)
count += 1
ends[y][x] = count
print(ends)
Выход:
[[0 0 0 0 0 0 0]
[0 5 4 4 5 6 0]
[0 5 4 3 4 5 0]
[0 6 5 0 0 0 0]
[0 0 0 0 0 0 0]]
Теперь концы обозначаются позициями максимальных значений в указанном массиве (6
в данном случае).
Объяснение : Я проверяю все белые пиксели как возможные концы. Для каждого такого пикселя я «заливаю» изображение - я помещаю специальное значение (127
- отличное от 0
и отличное от 255
), а затем распространяю его - на каждом шаге все 255
, которые являются соседями (в фоновом режиме) Чувство Неймана) особой ценности сами становятся особыми ценностями. Я считаю шаги, необходимые для удаления всех 255
. Потому что если вы начнете (постоянную скорость) затопление с конца, это займет больше времени, чем если бы у вас был источник в каком-либо другом месте, тогда максимальное время затопления - это конец вашей линии.
Я должен признать, что я не проверял это глубоко, поэтому я не могу гарантировать правильную работу в особом случае, например, в случае самопересекающейся линии. Я также осознаю грубость моего решения, особенно в области обнаружения соседей и распространения специальных значений, поэтому не стесняйтесь улучшать его. Я предположил, что все пиксели границы являются черными (никакая линия не касается "рамки" вашего изображения).