Python 图像 - 从图像骨架中寻找最大的分支
Python Image - Finding largest branch from image skeleton
我有一张骨架化的图像,形状如下:
我想从骨架中提取 "largest branch":
我知道也许我需要提取连接点并从该点划分线(?),但我不知道该怎么做。
有什么方法可以用 Python Scikit Image 或 OpenCV 做到这一点吗?
我相信您可以使用 OpenCV 执行以下操作:
- 使用HarrisCorner检测图像中的所有角点。这将为您提供显示的三个绿色点(我画了一个完整的圆圈以突出显示该位置)。
在所有角落添加一个黑色像素
使用findContours. Then check the length of each contour using arcLength获取图片中的所有分支,取最长的
有一个很棒的 python 包,用于使用 python 分析骨架,称为 FilFinder ($pip install fil_finder
),它优雅地解决了这个问题。下面是从他们的 tutorial.
中采用的代码
生成骨架:
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()
输出:
我有一张骨架化的图像,形状如下:
我想从骨架中提取 "largest branch":
我知道也许我需要提取连接点并从该点划分线(?),但我不知道该怎么做。
有什么方法可以用 Python Scikit Image 或 OpenCV 做到这一点吗?
我相信您可以使用 OpenCV 执行以下操作:
- 使用HarrisCorner检测图像中的所有角点。这将为您提供显示的三个绿色点(我画了一个完整的圆圈以突出显示该位置)。
在所有角落添加一个黑色像素
使用findContours. Then check the length of each contour using arcLength获取图片中的所有分支,取最长的
有一个很棒的 python 包,用于使用 python 分析骨架,称为 FilFinder ($pip install fil_finder
),它优雅地解决了这个问题。下面是从他们的 tutorial.
生成骨架:
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()
输出: