一笔画-获取图像轮廓坐标点


构图

首先是制作合适的图像,尽量是黑色背景,白色的图像。
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)

一笔画轮廓

可视化采集到的坐标集合
在这里插入图片描述

坐标点

得到的坐标点结果如下,坐标是按照一笔画方式排序的。
在这里插入图片描述


—————— 但行好事莫问前程,你若盛开蝴蝶自来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值