如何用cv2.ellipse基于两点坐标绘制圆弧?
问题:基于两点坐标绘制肘部圆弧(OpenCV实现)
我有图像中两个点的x、y坐标,想要绘制一条连接这两点的圆弧。目前使用OpenCV的cv2.ellipse函数,但该函数需要起始角度和终止角度,而非点坐标。当前代码如下:
# eclipse start_angle = 180 * np.arctan2(coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1])/ np.pi end_angle = 180 * np.arctan2(coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1])/ np.pi # Calculate center of the ellipse center = (coordinates[2][0], coordinates[2][1]) # Draw the ellipse cv2.ellipse(frame, (int(center[0] * frame.shape[1]), int(center[1] * frame.shape[0])), (100, 100), start_angle, end_angle, 2, (0, 255, 0), -1) # -1 for filled ellipse
我希望基于两点而非角度绘制圆弧,具体是要绘制表示肘部角度的圆弧(类似肘部关节处的弧形标注)。
解决方案
要实现肘部圆弧标注,核心是围绕肘部中心点,计算上臂、前臂两个方向的角度,再用cv2.ellipse绘制对应弧段,以下是修正后的实现:
关键逻辑
- 确定三个核心点:
coordinates[1](上臂端点)、coordinates[2](肘部中心)、coordinates[3](前臂端点) - 转换角度体系:OpenCV的角度是顺时针计算(0°对应x轴正方向),而
np.arctan2是逆时针角度,需要做转换 - 选择正确弧段:判断两个角度的差值,确保绘制的是肘部弯曲内侧的短弧
修正代码
import numpy as np import cv2 # 假设coordinates为归一化坐标(取值0-1) vec_upper = np.array([coordinates[1][0] - coordinates[2][0], coordinates[1][1] - coordinates[2][1]]) vec_forearm = np.array([coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1]]) # 将向量转换为OpenCV体系的角度(顺时针0-360°) def vec_to_opencv_angle(vec): rad = np.arctan2(vec[1], vec[0]) deg = np.degrees(rad) return (360 - deg) % 360 angle_upper = vec_to_opencv_angle(vec_upper) angle_forearm = vec_to_opencv_angle(vec_forearm) # 确保绘制的是肘部弯曲内侧的短弧 angle_diff = (angle_forearm - angle_upper) % 360 if angle_diff > 180: angle_upper, angle_forearm = angle_forearm, angle_upper # 转换肘部中心为图像像素坐标 center_pixel = (int(coordinates[2][0] * frame.shape[1]), int(coordinates[2][1] * frame.shape[0])) # 圆弧尺寸,等长轴为圆形弧,可根据需求调整 arc_axes = (60, 60) # 绘制圆弧(线宽2,绿色;若要填充将最后参数改为-1) cv2.ellipse(frame, center_pixel, arc_axes, 0, angle_upper, angle_forearm, (0, 255, 0), 2)
替代方案(手动生成圆弧点)
如果不想用cv2.ellipse,可以手动计算圆弧上的采样点,再用cv2.polylines连接:
def get_arc_points(center, radius, start_angle, end_angle, num_points=50): # 转换为弧度 start_rad = np.radians(start_angle) end_rad = np.radians(end_angle) # 生成角度序列 angles = np.linspace(start_rad, end_rad, num_points) # 计算每个点的坐标 points = np.array([ [center[0] + radius * np.cos(angle), center[1] + radius * np.sin(angle)] for angle in angles ], dtype=np.int32) return points.reshape((-1, 1, 2)) # 使用示例 arc_points = get_arc_points(center_pixel, 60, angle_upper, angle_forearm) cv2.polylines(frame, [arc_points], isClosed=False, color=(0,255,0), thickness=2)
内容的提问来源于stack exchange,提问作者Arsh Guleria
相关产品推荐
相关产品推荐

