直线骨架化python
时间: 2023-07-14 11:59:53 浏览: 96
直线骨架化(Straight Line Skeletonization)是一种图像处理技术,用于将图像中的曲线或多边形转换为其骨架或中轴线。在Python中,您可以使用一些库来实现直线骨架化,其中一种常用的库是scikit-image。
以下是一个简单的示例代码,演示了如何使用scikit-image库进行直线骨架化:
```python
import numpy as np
from skimage import morphology
# 生成一个二值图像作为输入
image = np.zeros((10, 10), dtype=np.uint8)
image[2:8, 4:6] = 1
# 进行骨架化
skeleton = morphology.skeletonize(image)
# 打印结果
print(skeleton.astype(np.uint8))
```
在上面的代码中,我们首先创建了一个10x10的空白图像,并在其中绘制了一个矩形。然后,我们使用`skeletonize`函数对图像进行骨架化处理,并将结果打印出来。
请注意,这只是一个简单的示例,实际应用中可能需要更复杂的图像处理步骤和参数调整,以获得更好的结果。您可以根据实际需求对代码进行修改和优化。另外,还有其他一些库和算法可用于直线骨架化,您可以根据自己的需求选择合适的方法。
相关问题
用python实现 将输入的骨架化的图像进行曲线拟合 批量图片输入和批量图片保
存
实现步骤:
1. 导入必要的库,包括opencv、numpy、os等
2. 定义函数,读取文件夹中的所有图片并进行骨架化处理
3. 定义函数,将骨架化图像进行曲线拟合,并输出拟合后的图像
4. 定义函数,将拟合后的图像保存到指定文件夹中
5. 调用函数,实现批量处理图片
代码如下:
```python
import cv2
import numpy as np
import os
# 读取文件夹中的所有图片并进行骨架化处理
def skel_batch(folder_path):
# 获取文件夹中的所有图片路径
file_list = os.listdir(folder_path)
for file in file_list:
# 判断是否为图片文件
if file.endswith('.jpg') or file.endswith('.png'):
# 读取图片
img = cv2.imread(os.path.join(folder_path, file))
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 骨架化
size = np.size(thresh)
skel = np.zeros(thresh.shape, np.uint8)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
done = False
while not done:
eroded = cv2.erode(thresh, element)
temp = cv2.dilate(eroded, element)
temp = cv2.subtract(thresh, temp)
skel = cv2.bitwise_or(skel, temp)
thresh = eroded.copy()
zeros = size - cv2.countNonZero(thresh)
if zeros == size:
done = True
# 显示骨架化图像
cv2.imshow('Skeleton', skel)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 将骨架化图像进行曲线拟合,并输出拟合后的图像
def curve_fitting(skel):
# 轮廓检测
contours, hierarchy = cv2.findContours(skel, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# 提取轮廓
cnt = contours[0]
# 进行曲线拟合
rows, cols = skel.shape
[vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
# 绘制直线
line = cv2.line(skel,(cols-1,righty),(0,lefty),(255,255,255),1)
# 显示拟合后的图像
cv2.imshow('Fitting', line)
cv2.waitKey(0)
cv2.destroyAllWindows()
return line
# 将拟合后的图像保存到指定文件夹中
def save_batch(folder_path, save_path):
# 获取文件夹中的所有图片路径
file_list = os.listdir(folder_path)
for file in file_list:
# 判断是否为图片文件
if file.endswith('.jpg') or file.endswith('.png'):
# 读取图片
img = cv2.imread(os.path.join(folder_path, file))
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 骨架化
size = np.size(thresh)
skel = np.zeros(thresh.shape, np.uint8)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
done = False
while not done:
eroded = cv2.erode(thresh, element)
temp = cv2.dilate(eroded, element)
temp = cv2.subtract(thresh, temp)
skel = cv2.bitwise_or(skel, temp)
thresh = eroded.copy()
zeros = size - cv2.countNonZero(thresh)
if zeros == size:
done = True
# 进行曲线拟合
line = curve_fitting(skel)
# 保存拟合后的图像
cv2.imwrite(os.path.join(save_path, file), line)
# 批量处理图片
folder_path = './images' # 输入文件夹
save_path = './result' # 输出文件夹
skel_batch(folder_path) # 骨架化处理
save_batch(folder_path, save_path) # 曲线拟合并输出
```
注意事项:
1. 需要提前创建好输入文件夹和输出文件夹
2. 输入文件夹中的图片必须为jpg或png格式的
3. 输出文件夹中的图片格式与输入文件夹中的图片格式相同
骨架快速提取的算法python
常用的骨架快速提取算法有多种,其中一种是基于中轴线的细化算法,可以用Python实现。
1. 首先,将二值化的图像进行细化(或称为骨架化),得到中轴线。
2. 对中轴线进行拓扑分析,找到所有端点和交叉点。
3. 从任意一个端点出发,沿着中轴线向交叉点方向搜索,直到找到另一个端点为止。这一过程中,记录下搜索路径上的所有交叉点和端点,这些点就是骨架的分支点。
4. 对于每个分支点,将其周围的中轴线分成若干条子骨架,这些子骨架之间没有交叉点或端点,每个子骨架的起点是该分支点,终点是其周围的交叉点或端点。
5. 对于每个子骨架,用最小二乘法拟合一条直线,得到该子骨架的方向和长度。将所有子骨架的方向和长度记录下来,得到整个骨架的形状。
以下是一个基于OpenCV的Python代码示例,实现了基于中轴线的骨架快速提取算法:
```python
import cv2
import numpy as np
# 读入二值化图像
img = cv2.imread("binary_image.png", cv2.IMREAD_GRAYSCALE)
# 细化图像,得到中轴线
skel = cv2.ximgproc.thinning(img)
# 找到所有端点和交叉点
keypoints = cv2.xfeatures2d.StarDetector_create().detect(skel)
# 遍历所有端点,提取骨架
skeleton = []
for kp in keypoints:
if kp.response < 100: # 筛选出较长的端点
continue
path = [kp.pt] # 记录搜索路径
while True:
neighbors = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
neighbors[1, 1] = 0
neighbor_kps = [kp for kp in cv2.KeyPoint_convert(cv2.KeyPointsFilter.filter(keypoints, neighbors))]
if len(neighbor_kps) == 1: # 到达另一个端点
path.append(neighbor_kps[0])
break
elif len(neighbor_kps) == 2: # 继续搜索
path.append(neighbor_kps[0])
path.append(neighbor_kps[1])
skel[int(path[-1][1]), int(path[-1][0])] = 0 # 避免重复搜索
kp = neighbor_kps[1] # 选取下一个邻居
else: # 遇到分叉点或环
break
if len(path) > 2: # 筛选出较长的骨架
skeleton.append(path)
# 提取骨架方向和长度
shapes = []
for path in skeleton:
coords = np.array(path, np.float32)
direction = cv2.fitLine(coords, cv2.DIST_L2, 0, 0.01, 0.01)
length = np.linalg.norm(coords[-1] - coords[0])
shapes.append((direction, length))
# 显示骨架
display_img = cv2.cvtColor(skel, cv2.COLOR_GRAY2BGR)
for shape in shapes:
pt1 = tuple(np.round(shape[0][:2] - shape[0][2:] * shape[1]).astype(int))
pt2 = tuple(np.round(shape[0][:2] + shape[0][2:] * shape[1]).astype(int))
cv2.line(display_img, pt1, pt2, (0, 0, 255), 2)
cv2.imshow("skeleton", display_img)
cv2.waitKey()
```
其中,使用了OpenCV的细化函数(`cv2.ximgproc.thinning`)和拟合直线函数(`cv2.fitLine`),以及Star特征检测器(`cv2.xfeatures2d.StarDetector_create`)。通过遍历所有端点,沿着中轴线搜索骨架并拟合直线,最终得到了骨架的形状。
阅读全文