- 圖像的封閉外輪廓,將其轉(zhuǎn)換為從右上邊開始順時(shí)針的點(diǎn)序列。
- 確定右上角的起點(diǎn),以及確保點(diǎn)按順時(shí)針順序排列。
一、如何確定右上角的起點(diǎn)
- 圖像坐標(biāo)系的原點(diǎn)通常在左上角,y軸向下,所以右上角的點(diǎn)應(yīng)該是x最大的,而y最小的點(diǎn)。
二、但如何確定輪廓的原始方向是順時(shí)針還是逆時(shí)針?
- 可以通過計(jì)算輪廓的面積的符號(hào)來判斷。
例如,使用cv2.contourArea(contour, oriented=True),如果返回的值為正,則是逆時(shí)針,否則順時(shí)針?;蛘叻催^來?需要測(cè)試。
三、如何將輪廓點(diǎn)旋轉(zhuǎn)到起點(diǎn)?
- 假設(shè)輪廓是一個(gè)循環(huán)的列表,例如,輪廓中的點(diǎn)按順序排列,可以找到起點(diǎn)的索引,然后將該點(diǎn)作為起始點(diǎn),后面的點(diǎn)依次跟隨,保持順序。例如,如果輪廓的點(diǎn)列表是 [A, B, C, D, A],找到C是起點(diǎn),則新的順序是 [C, D, A, B, C]
四、如何旋轉(zhuǎn)數(shù)組?
- 旋轉(zhuǎn)數(shù)組的方法是找到起點(diǎn)的索引,然后將數(shù)組分為兩部分:從索引到末尾,再加上從開頭到索引的部分。
例如,contour是一個(gè)numpy數(shù)組,假設(shè)contour的索引為i,則新的輪廓是 np.concatenate([contour[i:], contour[:i]])
五、步驟:
- 確定輪廓是否為順時(shí)針,如果不是,反轉(zhuǎn)。
- 找到右上角的起點(diǎn)。
- 找到該起點(diǎn)在輪廓中的索引。
- 將數(shù)組旋轉(zhuǎn),使得起點(diǎn)成為第一個(gè)點(diǎn)。
- 輸出新的點(diǎn)序列。
六、程序
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 30 09:04:57 2025
輪廓點(diǎn)序列轉(zhuǎn)換程序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:
# 確保輪廓為順時(shí)針方向
area = cv2.contourArea(contour, oriented=True)
if area > 0: # 如果面積為正表示逆時(shí)針,需要反轉(zhuǎn)
contour = contour[::-1]
# 找到右上角的起點(diǎn)(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]
# 找到起點(diǎn)在輪廓中的索引
idx = np.where((contour[:, 0, 0] == start_pt[0, 0]) &
(contour[:, 0, 1] == start_pt[0, 1]))[0][0]
# 旋轉(zhuǎn)輪廓點(diǎn)數(shù)組,使起點(diǎn)位于開頭
rotated_contour = np.roll(contour, -idx, axis=0)
# 轉(zhuǎn)換為二維坐標(biāo)列表
point_sequence = rotated_contour.squeeze(axis=1).tolist()
# 輸出結(jié)果
print("順時(shí)針點(diǎn)序列(從右上角開始):")
for point in point_sequence:
print(f"({point[0]}, {point[1]})")
# 可選:可視化結(jié)果(需要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()
六、運(yùn)行結(jié)果
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。