opencv判断 线夹角_学习OpenCV3:画出代表夹角的圆弧

一、问题

已知3个点 g_center、g_p1和g_p2。其中g_center是夹角的中心点,g_center和g_p1组成夹角的起始边

,g_center和g_p2组成夹角的结束边

,现希望画出从

的夹角。

二、分析

OpenCV中cv::ellipse()不止可以画椭圆,还可以画圆弧。

bool ellipse(

cv::Mat& img, // 画图的图片

cv::Point center, // 椭圆的中心位置

cv::Size axes, // 椭圆长轴和短轴的长度

double angle, // 椭圆主轴的角度

double startAngle, // 圆弧起始的角度

double endAngle, // 圆弧结束的角度

const cv::Scalar& color, // 圆弧的颜色

int thickness=1, // 圆弧的厚度

int lineTyppe=8, // 连通性,可以为4、8

int shift=0 // 作为分数处理的半径位

);

数学上常用的坐标系是以右上角作为正坐标,而OpenCV的图片是以右下角作为正坐标。

三、实现

#include

#include

#include

#include

using namespace std;

using namespace cv;

Point2d g_center(400, 300), g_p1(400, 100), g_p2(600, 300);

// 画夹角

void draw_angle(Mat img, Point2d p0, Point2d p1, Point2d p2, double radius)

{

// 计算直线的角度

double angle1 = atan2(-(p1.y - p0.y), (p1.x - p0.x)) * 180 / CV_PI;

double angle2 = atan2(-(p2.y - p0.y), (p2.x - p0.x)) * 180 / CV_PI;

// 计算主轴的角度

double angle = angle1 <= 0 ? -angle1 : 360 - angle1;

// 计算圆弧的结束角度

double end_angle = (angle2 < angle1) ? (angle1 - angle2) : (360 - (angle2 - angle1));

// 画圆弧

ellipse(img, p0, Size(radius, radius), angle, 0, end_angle, Scalar(0, 0, 255), 2);

}

// 鼠标回调函数

void mouse_callback(int event, int x, int y, int flags, void *param)

{

static Point2d p(0, 0), p1(0, 0), p2(0, 0);

static int n = -1;

switch (event)

{

case cv::EVENT_LBUTTONDOWN: // 鼠标左键点击

{

p1 = Point2d(x, y);

int w = 15, h = 15;

Rect r0(g_center.x - w, g_center.y - h, 2 * w, 2 * h);

Rect r1(g_p1.x - w, g_p1.y - h, 2 * w, 2 * h);

Rect r2(g_p2.x - w, g_p2.y - h, 2 * w, 2 * h);

if (r0.contains(p1)) // 鼠标落在中心点g_center

{

n = 0;

p = g_center;

}

else if (r1.contains(p1)) // 鼠标落在g_p1

{

n = 1;

p = g_p1;

}

else if (r2.contains(p1)) // 鼠标落在g_p2

{

n = 2;

p = g_p2;

}

break;

}

case cv::EVENT_MOUSEMOVE: // 鼠标移动

p2 = Point2d(x, y);

if (n == 0)

{

g_center = p + p2 - p1;

}

else if (n == 1)

{

g_p1 = p + p2 - p1;

}

else if (n == 2)

{

g_p2 = p + p2 - p1;

}

break;

case cv::EVENT_LBUTTONUP: // 鼠标左键释放

p1 = Point2d(0, 0);

p2 = Point2d(0, 0);

n = -1;

break;

default:

break;

}

}

// 主函数

int main()

{

string window_name = "image";

namedWindow(window_name, WINDOW_AUTOSIZE);

int w = 800, h = 600;

Mat image_original = Mat(h, w, CV_8UC3, Scalar(255, 255, 255));

cv::setMouseCallback(window_name, mouse_callback); // 调用鼠标回调函数

while (true)

{

Mat img = image_original.clone(); // 拷贝空白图片,方便重复画图

line(img, g_center, g_p1, Scalar(0, 255, 0), 2); // 画绿线l1

line(img, g_center, g_p2, Scalar(255, 0, 0), 2); // 画蓝线l2

draw_angle(img, g_center, g_p1, g_p2, 15); // 画红色夹角

imshow(window_name, img);

if (waitKey(3) > 0)

break;

}

return 0;

}

操作方法:

鼠标左键点击直线的起点或终点并按住移动,由此可以修改直线。夹角是从绿线顺时针到蓝线。在键盘输入任意的键,可退出程序。

运行结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值