OpenCV学习笔记(5)_ ellipse绘制函数浅析
文章目录
1. ellipse第一种重载——绘制椭圆弧
1.1 函数原型
void cv::ellipse( InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar & color, int thickness = 1, int lineType = LINE_8, int shift = 0 )
从这个函数原型中我们可以看出,第一种重载方式,可以由椭圆的中心点坐标center,椭圆的长短轴axes,起始的角度angle,弧段的起讫角度startangle和endangle,以及绘制相关的颜色、线宽、线型、坐标偏移参数来进行椭圆的绘制。
1.2 参数解析
在OpenCV的文档中,为了说明具体的角方向定义、轴方向定义等,还给出了如下的示意图:
但笔者认为这个示意图有些不太清楚的地方,于是补充并修正了一些内容,给出如下示意图:
这两张图是第一种重载方式的参数重点,下面来重点讲述一下:
- 对于第一种情况,椭圆的axes.width > axes.height;
- 注意对照示意图,axes.width表示的是椭圆的主轴,即FIRST AXIS,axes.height表示的是椭圆的副轴,即SECOND AXIS,主轴的方向沿图像坐标轴X轴顺时针偏移的方向即为angle;
- 以主轴axes.width为半径虚拟一个圆,以主轴为基准,顺时针方向偏移start angle角度,得到起始弧段点,由这个点向椭圆主轴做投影,在椭圆弧上的投影点作为椭圆弧段的真正起始点;
- 椭圆弧段的真正结束点也是采取相同的方式获得;
- 沿顺时针方向,将椭圆弧段的起始点和结束点之间的椭圆弧段绘制出来,即为图中的深蓝色弧,为该模式下绘制出的椭圆弧段;
- 注意在这种绘制模式下,axes.width和awes.height均表示的是椭圆的半轴长度,这和下一种模式会有区别;
- 对于第二种情况,即椭圆的axes.width < axes.height时,仍将axes.width所在的轴作为主轴,和第一种情况类似,也仍是以axes.width作为半径虚拟一个圆,各种偏移角、起始角、结束角均与第一种情况类似。
1.3 绘制示例
下面就来实践一把,看一看绘制的实际情况:
#define _CRT_SECURE_NO_WARNINGS #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) {
// ellipse 第一种重载的绘制 Point ecenter; Size ax1, ax2; double angle; double startangle; double endangle; Mat pic1 = Mat::zeros(Size(512, 512), CV_8UC3); Mat pic2 = Mat::zeros(Size(512, 512), CV_8UC3); ecenter.x = 256; ecenter.y = 256; ax1.width = 200; ax1.height = 100; angle = 30; startangle = 20; endangle = 150; ellipse(pic1, ecenter, ax1, angle, 0, 360, Scalar(0, 255, 0), 1, LINE_AA, 0); ellipse(pic1, ecenter, ax1, angle, startangle, endangle, Scalar(0, 0, 255), 2, LINE_AA, 0); putText(pic1, "AXES.WIDTH > AXES.HEIGHT", Point(25, 25), FONT_HERSHEY_PLAIN, 1, Scalar(0, 255, 0)); imshow("ellipseExample1", pic1); ax2.width = 100; ax2.height = 200; ellipse(pic2, ecenter, ax2, angle, 0, 360, Scalar(0, 255, 0), 1, LINE_AA, 0); ellipse(pic2, ecenter, ax2, angle, startangle, endangle, Scalar(0, 0, 255), 2, LINE_AA, 0); putText(pic2, "AXES.WIDTH < AXES.HEIGHT", Point(25, 25), FONT_HERSHEY_PLAIN, 1, Scalar(0, 255, 0)); imshow("ellipseExample2", pic2); waitKey(0); return EXIT_SUCCESS; }
注意其中的参数:
- 椭圆中心点坐标为(256,256);
- 椭圆的长轴半径为200,短轴半径为100;
- 第一种设置下长轴为主轴,第二种设置下短轴为主轴;
- 当startangle和endangle分别设置为0和360时,可以把整个椭圆完整绘制出来,即为结果图中的绿色椭圆;
- 红色弧段为绘制出来的椭圆弧段:
2. ellipse第二种重载——RotatedRect方式绘制椭圆
接下来这种方式,OpenCV给出了一种数据结构 RotatedRect 来存储椭圆的相关信息。
2.1 ellipse函数原型
void cv::ellipse( InputOutputArray img, const RotatedRect & box, const Scalar & color, int thickness = 1, int lineType = LINE_8 )
相较于第一种重载方式,这种方式将椭圆的形状参数全部归并到一个RotatedRect对象即box中。
RotatedRect共有三个属性:
分别是angle center size
这个数据结构的理解很容易:center表示矩形的中心点;angle表示矩形顺时针偏转的角度;size中分别表示矩形的width和height。
注意RotatedRect中,size.width也是作为主轴存在的。
2.2 ellipse绘制示例
#define _CRT_SECURE_NO_WARNINGS #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char* argv[]) {
// ellipse 第一种重载的绘制 Point ecenter; Size ax1, ax2; double angle; double startangle; double endangle; ecenter.x = 256; ecenter.y = 256; angle = 30; startangle = 20; endangle = 150; // ellipse 第二种重载的绘制 RotatedRect e1; Mat pic3 = Mat::zeros(Size(512, 512), CV_8UC3); e1.center = ecenter; e1.size.width = 400; e1.size.height = 200; e1.angle = angle; ellipse(pic3, e1, Scalar(255, 0, 0), 1, LINE_AA); imshow("ellipseExample3", pic3); waitKey(0); return EXIT_SUCCESS; }
这里注意,size.width和size.height和第一种重载模式中不同,分别对应椭圆的主轴长和副轴长,而不是半轴长。所以我们从代码中能看到, e1.size.width
设置为400, e1.size.height
设置为200。如此绘制出来的椭圆才和第一种重载模式中的完整椭圆大小一致。
【创作不易,水平有限,如有错漏,轻喷勿骂】
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/102191.html