Python:轮廓点序列转换

  • 图像的封闭外轮廓,将其转换为从右上边开始顺时针的点序列。
  • 确定右上角的起点,以及确保点按顺时针顺序排列。

一、如何确定右上角的起点

  • 图像坐标系的原点通常在左上角,y轴向下,所以右上角的点应该是x最大的,而y最小的点。

二、但如何确定轮廓的原始方向是顺时针还是逆时针?

  • 可以通过计算轮廓的面积的符号来判断。
    例如,使用cv2.contourArea(contour, oriented=True),如果返回的值为正,则是逆时针,否则顺时针。或者反过来?需要测试。

三、如何将轮廓点旋转到起点?

  • 假设轮廓是一个循环的列表,例如,轮廓中的点按顺序排列,可以找到起点的索引,然后将该点作为起始点,后面的点依次跟随,保持顺序。例如,如果轮廓的点列表是 [A, B, C, D, A],找到C是起点,则新的顺序是 [C, D, A, B, C]

四、如何旋转数组?

  • 旋转数组的方法是找到起点的索引,然后将数组分为两部分:从索引到末尾,再加上从开头到索引的部分。
    例如,contour是一个numpy数组,假设contour的索引为i,则新的轮廓是 np.concatenate([contour[i:], contour[:i]])

五、步骤:

    1. 确定轮廓是否为顺时针,如果不是,反转。
    1. 找到右上角的起点。
    1. 找到该起点在轮廓中的索引。
    1. 将数组旋转,使得起点成为第一个点。
    1. 输出新的点序列。

六、程序

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 30 09:04:57 2025

轮廓点序列转换程序ds010.py
"""

import cv2
import numpy as np

# 读取图像并二值化处理
image = cv2.imread('d:/imgs/bak01/my_img01-B2.jpg', cv2.IMREAD_GRAYSCALE)
_, thresh = cv2.threshold(image, 50, 255, cv2.THRESH_BINARY)

# 查找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for contour in contours:
    # 确保轮廓为顺时针方向
    area = cv2.contourArea(contour, oriented=True)
    if area > 0:  # 如果面积为正表示逆时针,需要反转
        contour = contour[::-1]

    # 找到右上角的起点(x最大,y最小)
    x_coords = contour[:, 0, 0]
    max_x = x_coords.max()
    mask = (x_coords == max_x)
    candidates = contour[mask]
    y_coords = candidates[:, 0, 1]
    min_y_idx = np.argmin(y_coords)
    start_pt = candidates[min_y_idx]

    # 找到起点在轮廓中的索引
    idx = np.where((contour[:, 0, 0] == start_pt[0, 0]) & 
                  (contour[:, 0, 1] == start_pt[0, 1]))[0][0]

    # 旋转轮廓点数组,使起点位于开头
    rotated_contour = np.roll(contour, -idx, axis=0)

    # 转换为二维坐标列表
    point_sequence = rotated_contour.squeeze(axis=1).tolist()

    # 输出结果
    print("顺时针点序列(从右上角开始):")
    for point in point_sequence:
        print(f"({point[0]}, {point[1]})")

# 可选:可视化结果(需要OpenCV)
canvas = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.drawContours(canvas, [rotated_contour], -1, (0,255,255), 8)

zoom_xs=0.2
new_img2 = cv2.resize(canvas, None, fx=zoom_xs, fy=zoom_xs)
cv2.imshow('Result', new_img2)


cv2.waitKey(0)
cv2.destroyAllWindows()

六、运行结果

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容