如何在OpenCV中通过两个端点、半径和圆心绘制圆弧
基于已知圆心、半径、端点用OpenCV绘制彩色分段圆弧
直接调用OpenCV原生ellipse接口即可实现,圆是长短轴相等的特殊椭圆,不需要手动逐点计算圆弧像素,渲染效率和边缘平滑度都有保证。
预期实现效果参考:
实现步骤
- 计算端点对应圆周角度
OpenCV绘制圆弧需要传入起始角度、终止角度,角度规则为:以圆心为原点,x轴正方向(向右)为0度,沿顺时针方向角度递增,单位为角度(非弧度)。
对任意端点(x,y),计算其相对于圆心(cx, cy)的角度公式:
注意dx = x - cx dy = y - cy 弧度值 = atan2(dy, dx) 角度值 = 弧度值 * 180 / πatan2参数顺序:第一个参数传y方向差值,第二个传x方向差值,顺序写反会导致角度计算完全错误。 - 确定圆弧绘制范围
两个端点会把整圆切为两段弧,ellipse的绘制逻辑是始终从startAngle顺时针绘制到endAngle,扫过的角度为endAngle - startAngle:- 画较短的劣弧时,保证
endAngle - startAngle的绝对值小于180即可 - 画较长的优弧时,可以给终止角度加360,保证扫过的角度大于180
- 画多段不同颜色的圆弧,只需要依次算出每段弧的起止角度,分别调用
ellipse传入对应颜色即可
- 画较短的劣弧时,保证
- 调用接口绘制
绘制圆对应的圆弧时,ellipse的椭圆旋转角度参数传0,长短轴参数都传已知半径即可。
代码示例
Python 版本
import cv2 import math import numpy as np # 已知参数:圆心坐标、半径、两个圆弧端点 cx, cy = 200, 200 radius = 100 p1 = (300, 200) p2 = (200, 300) # 新建空白画布 canvas = np.zeros((400, 400, 3), dtype=np.uint8) # 角度计算函数 def get_point_angle(pt, center_x, center_y): dx = pt[0] - center_x dy = pt[1] - center_y return math.atan2(dy, dx) * 180 / math.pi angle1 = get_point_angle(p1, cx, cy) angle2 = get_point_angle(p2, cx, cy) # 绘制p1到p2的红色劣弧(90度) cv2.ellipse( canvas, center=(cx, cy), axes=(radius, radius), angle=0, startAngle=angle1, endAngle=angle2, color=(0, 0, 255), # OpenCV为BGR通道顺序,此处为红色 thickness=2, lineType=cv2.LINE_AA # 抗锯齿 ) # 绘制剩余的蓝色优弧(270度) cv2.ellipse( canvas, center=(cx, cy), axes=(radius, radius), angle=0, startAngle=angle2, endAngle=angle1 + 360, color=(255, 0, 0), # 蓝色 thickness=2, lineType=cv2.LINE_AA ) # 展示结果 cv2.imshow("arc_draw_demo", canvas) cv2.waitKey(0) cv2.destroyAllWindows()
C++ 版本
#include <opencv2/opencv.hpp> #include <cmath> using namespace cv; double calcPointAngle(Point2f pt, float cx, float cy) { float dx = pt.x - cx; float dy = pt.y - cy; return atan2(dy, dx) * 180 / CV_PI; } int main() { // 已知参数 float cx = 200, cy = 200, r = 100; Point2f p1(300, 200), p2(200, 300); Mat canvas = Mat::zeros(400, 400, CV_8UC3); double a1 = calcPointAngle(p1, cx, cy); double a2 = calcPointAngle(p2, cx, cy); // 画红色劣弧 ellipse(canvas, Point(cx, cy), Size(r, r), 0, a1, a2, Scalar(0,0,255), 2, LINE_AA); // 画蓝色优弧 ellipse(canvas, Point(cx, cy), Size(r, r), 0, a2, a1 + 360, Scalar(255,0,0), 2, LINE_AA); imshow("arc_draw_demo", canvas); waitKey(0); return 0; }
注意事项
- 不要通过手动计算圆弧散点再连线的方式绘制,原生接口做了亚像素优化,抗锯齿效果更好,运行速度也更快
- 颜色参数注意OpenCV默认是BGR通道顺序,和常规RGB顺序相反,不要传错
- 如果绘制的弧和端点没有对齐,优先检查角度计算时dx、dy的顺序和符号,以及角度单位是否误传了弧度
- 多段彩色圆弧不需要做蒙版或者位运算,按顺序分段绘制即可,后绘制的内容会覆盖在之前的内容上方
内容的提问来源于stack exchange,提问作者Ali Rafay
相关产品推荐
相关产品推荐

