一笔画-获取图像轮廓坐标点
文章目录
- 构图
- K邻近算法
- 代码
- 一笔画轮廓
- 坐标点
构图
首先是制作合适的图像,尽量是黑色背景,白色的图像。
SL3.jpg
K邻近算法
使用 python
from sklearn.neighbors import NearestNeighbors
代码
完整代码
import cv2
import numpy as np
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt
# 获取图片一笔画的轮廓点
def sort_contour_points(points):
"""按照最近邻算法排序轮廓点"""
if len(points) == 0:
return points # 如果点集为空,直接返回
ordered_points = []
current_point = points[0]
ordered_points.append(current_point)
remaining_points = np.delete(points, 0, axis=0) # 移除当前点
while len(remaining_points) > 0:
nbrs = NearestNeighbors(n_neighbors=1, algorithm='auto').fit(remaining_points)
_, indices = nbrs.kneighbors([current_point])
next_point_idx = indices[0][0]
# 检查索引是否超出范围
if next_point_idx >= len(remaining_points):
break # 如果超出范围,退出循环
current_point = remaining_points[next_point_idx]
ordered_points.append(current_point)
remaining_points = np.delete(remaining_points, next_point_idx, axis=0)
return np.array(ordered_points)
def sample_points(points, num_samples):
"""对轮廓点进行采样"""
if len(points) == 0:
return points # 如果点集为空,直接返回
indices = np.linspace(0, len(points) - 1, num_samples).astype(int)
return points[indices]
def get_contour_points(image_path, num_samples=1000):
"""从图像中提取轮廓并采样到指定数量的点"""
# 读取图像
image = cv2.imread(image_path)
if image is None:
raise ValueError("图像路径错误或图像无法读取")
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 轮廓检测
contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 合并所有轮廓点
contour_points = np.vstack(contours).squeeze()
# 按照一笔画方式排序轮廓点
sorted_points = sort_contour_points(contour_points)
# 采样到指定数量的点
sampled_points = sample_points(sorted_points, num_samples)
return sampled_points
def plot_contour_points(points):
"""可视化轮廓点"""
if len(points) == 0:
print("没有可用的轮廓点")
return
plt.plot(points[:, 0], points[:, 1], '-o', markersize=2)
plt.gca().invert_yaxis() # 反转Y轴以匹配图像坐标系
plt.title("Sampled Contour Points")
plt.xlabel("X")
plt.ylabel("Y")
plt.show()
# 示例使用
if __name__ == "__main__":
# 图像路径
image_path = "SL3.jpg" # 替换为你的图像路径
# 获取自定义数量个轮廓点, num_samples 自定义数量
sampled_points = get_contour_points(image_path, num_samples=100)
# 输出结果
print("Sampled Points Shape:", sampled_points.shape)
# sum_array = sampled_points.sum(axis=1)[:, np.newaxis]
first = sampled_points[:, 0]
second = sampled_points[:, 1]
print("first min max:", np.min(first), np.max(first)) # 找到0维最大最小的元素
print("second min max:", np.min(second), np.max(second)) # 找到1维最大最小的元素
print("First 10 Points:\n", sampled_points[:10])
with open('output.txt', 'w') as file:
# 将列表转换为用逗号分隔的字符串,并写入文件
# 默认的坐标轴0点是图像的左下角, 通过0/1维最大最小的元素 求平均平移,使坐标原点在图像中间,方便个性化使用
file.write(','.join(map(str, (sampled_points-np.array([(57+525)/2, (18+508)/2])).tolist())))
# 可视化
plot_contour_points(sampled_points)
一笔画轮廓
可视化采集到的坐标集合
坐标点
得到的坐标点结果如下,坐标是按照一笔画方式排序的。
—————— 但行好事莫问前程,你若盛开蝴蝶自来