Изображение Python - Нахождение самой большой ветви из скелета изображения

У меня есть скелетонированное изображение в следующей форме: введите описание изображения здесь

И я хочу извлечь "самую большую ветку" из скелета: введите описание изображения здесь

Я знаю, что, возможно, мне нужно извлечь точку соединения и разделить линии де из этой точки (?), Но я понятия не имею, как это сделать.

Есть ли способ сделать это с помощью Python Scikit Image или OpenCV?

1 ответ

Решение

Я считаю, что вы можете использовать OpenCV, чтобы сделать следующее:

  1. Используйте HarrisCorner, чтобы обнаружить все углы на изображении. Это даст вам три показанные зеленые точки (я нарисовал целый круг, чтобы выделить местоположение).

  1. Добавить черный пиксель на всех углах

  2. Получить все ветви на картинке, используя findContours. Затем проверьте длину каждого контура с помощью arcLength и получите самый длинный.

Есть замечательный пакет python для анализа скелетов с помощью python под названием FilFinder ($pip install fil_finder), который элегантно решает эту проблему. Ниже приведен код, взятый из их учебника.

Создайте скелет:

import numpy as np
import cv2
import matplotlib.pyplot as plt
from fil_finder import FilFinder2D
import astropy.units as u

skeleton = cv2.imread("./data/XmviQ.png", 0) #in numpy array format

fil = FilFinder2D(skeleton, distance=250 * u.pc, mask=skeleton)
fil.preprocess_image(flatten_percent=85)
fil.create_mask(border_masking=True, verbose=False,
use_existing_mask=True)
fil.medskel(verbose=False)
fil.analyze_skeletons(branch_thresh=40* u.pix, skel_thresh=10 * u.pix, prune_criteria='length')

# Show the longest path
plt.imshow(fil.skeleton, cmap='gray')
plt.contour(fil.skeleton_longpath, colors='r')
plt.axis('off')
plt.show()

Выход:

В вашей задаче вас интересует не самый длинный путь по графу, соответствующий скелету, а путь самой длинной ветви. Продолжая приведенный выше блок кода, следующий сценарий сделает свое дело. Я добавил фреймы данных, чтобы наглядно показать, что FilFinder автоматически генерирует много интересной информации о скелете.

import pandas as pd
plt.imshow(fil.skeleton, cmap='gray')

# this also works for multiple filaments/skeletons in the image: here only one
for idx, filament in enumerate(fil.filaments): 

    data = filament.branch_properties.copy()
    data_df = pd.DataFrame(data)
    data_df['offset_pixels'] = data_df['pixels'].apply(lambda x: x+filament.pixel_extents[0])

    print(f"Filament: {idx}")
    display(data_df.head())

    longest_branch_idx = data_df.length.idxmax()
    longest_branch_pix = data_df.offset_pixels.iloc[longest_branch_idx]

    y,x = longest_branch_pix[:,0],longest_branch_pix[:,1]

    plt.scatter(x,y , color='r')

plt.axis('off')
plt.show()

Выход:

Другие вопросы по тегам