基于C++ OpenCV实现从鼠标指定点绘制圆切线的开发需求
实现OpenCV中基于鼠标点绘制圆的切线(C++)
核心流程
要完成从鼠标点击点向半径为4的圆绘制切线的功能,分两步实现:
- 通过OpenCV鼠标回调获取屏幕鼠标坐标
- 基于几何计算求出切线切点,再绘制切线
1. 鼠标坐标获取
把你已有的坐标提取逻辑整合到标准OpenCV鼠标回调函数中:
#include <opencv2/opencv.hpp> using namespace cv; // 全局变量:存储圆心、鼠标点、是否触发绘制 Point2f circle_center(300, 300); // 示例圆心,可按需调整 Point2f mouse_point; bool has_mouse_click = false; void mouseCallback(int event, int x, int y, int flags, void* userdata) { if (event == EVENT_LBUTTONDOWN) { mouse_point.x = x; mouse_point.y = y; has_mouse_click = true; } }
2. 切线计算与绘制函数
根据几何推导,实现计算切点并绘制切线的函数:
void drawTangents(Mat& img, const Point2f& center, float radius, const Point2f& outer_point) { float dx = outer_point.x - center.x; float dy = outer_point.y - center.y; float dist_sq = dx*dx + dy*dy; float radius_sq = radius*radius; // 点在圆内/圆上时无切线 if (dist_sq <= radius_sq + 1e-6) { return; } float dist = sqrt(dist_sq); float cos_theta = sqrt(dist_sq - radius_sq) / dist; float sin_theta = radius / dist; // 计算两个切点坐标 Point2f t1, t2; t1.x = center.x + dx*cos_theta - dy*sin_theta; t1.y = center.y + dy*cos_theta + dx*sin_theta; t2.x = center.x + dx*cos_theta + dy*sin_theta; t2.y = center.y + dy*cos_theta - dx*sin_theta; // 绘制切线与切点 line(img, outer_point, t1, Scalar(0, 255, 0), 2); // 绿色切线1 line(img, outer_point, t2, Scalar(0, 255, 0), 2); // 绿色切线2 circle(img, t1, 2, Scalar(0, 0, 255), -1); // 红色切点1 circle(img, t2, 2, Scalar(0, 0, 255), -1); // 红色切点2 }
3. 主函数整合
将各部分整合,实现实时交互效果:
int main() { Mat img = Mat::zeros(600, 600, CV_8UC3); namedWindow("Tangent Demo"); setMouseCallback("Tangent Demo", mouseCallback); while (true) { Mat frame = img.clone(); // 绘制半径为4的目标圆 circle(frame, circle_center, 4, Scalar(255, 0, 0), -1); if (has_mouse_click) { drawTangents(frame, circle_center, 4, mouse_point); } imshow("Tangent Demo", frame); if (waitKey(1) == 27) { // 按ESC退出 break; } } destroyAllWindows(); return 0; }
补充说明
- 示例中圆的圆心固定为(300,300),可根据需求修改
circle_center的坐标 - 点击鼠标左键后,程序自动计算并绘制从点击点到圆的两条切线
- 代码加入浮点误差容忍值(1e-6),避免精度问题导致的逻辑错误
内容的提问来源于stack exchange,提问作者m baku
相关产品推荐
相关产品推荐

