[C++&OpenCv] 两点距离、三点角度的计算

#include <opencv/cv.h>  
#include <opencv/highgui.h>  
#include <stdio.h>  
//#include <atlstr.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>  //opencv申明
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2/opencv.hpp>
#include < iostream>
#include <stdio.h>
#include "cstring"

using namespace cv;
using namespace std;

vector<Point> points;

IplImage* src = 0;   
IplImage* dst = 0; 
int i = 0 ,j=0;

//两点间距离公式
float getDistance(CvPoint pointO, CvPoint pointA)
{
    float distance;
    distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
    distance = sqrtf(distance);
	//屏幕分辨率为1366*768,一个像素约为0.214mm,所以这里乘以0.214转化为实际尺寸,当然分辨率不同,一个像素表示的实际长度也不同
    return distance;
}

//两条直线间的夹角
float angle(Point pt1, Point pt0, Point pt2)
{
double dx1 = (pt1.x - pt0.x);
double dy1 = (pt1.y - pt0.y);
double dx2 = (pt2.x - pt0.x);
double dy2 = (pt2.y - pt0.y);
double angle_line = (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10);
double a = acos(angle_line) * 180 / 3.141592653;
return a;
}


void on_mouse( int event, int x, int y, int flags, void* ustc)  
{  
	static CvPoint pre_pt = (-1,-1);  
	static CvPoint cur_pt = (-1,-1);  
	CvFont font;  
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);  
	char temp[16];  
	if( event == CV_EVENT_LBUTTONDOWN )  
	{  
	    cvCopy(dst,src);  
	    sprintf(temp,"(%d,%d)",x,y);  
	    pre_pt = cvPoint(x,y);  
		points.push_back(pre_pt);
	    //cvPutText(src,temp, pre_pt, &font, cvScalar(0,0,255));  
	    cvCircle( src, pre_pt,3,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 ); 
		int k = points.size();
		if(k>1)
		{
		cvLine(src,points.at(i),points.at(i+1),cvScalar(0,255,60),1,8,0);
		float Dis = getDistance(points.at(i),points.at(i+1));
		//转换字节数组到float数据		
		char m_Dis[50]; 
		sprintf(m_Dis,"%.2f",Dis);//如果用sprintf函数小数点后会有6位
		cvPutText(src,m_Dis,(points.at(i)+points.at(i+1))/2, &font, cvScalar(0,0,255)); 
		i++;
		}
		if(k>2)
		{
		 float  m_angle = angle(points.at(j), points.at(j+1), points.at(j+2));
		 char m_angle1[50]; 
		 sprintf(m_angle1,"%.2f",m_angle);//如果用sprintf函数小数点后会有6位
		 //将角度保留两位小数
		// double aaa = floor(m_angle * 100.000f + 0.5) / 100.000f;
		 cvPutText(src,m_angle1,points.at(j+1), &font, cvScalar(255,0,255));
		 j++;
		}
	    cvShowImage( "src", src );  
	    cvCopy(src,dst);  
	}  
	else if( event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))  
	{  
	    cvCopy(dst,src);  
	    sprintf(temp,"(%d,%d)",x,y);  
	    cur_pt = cvPoint(x,y);        
	    cvPutText(src,temp, cur_pt, &font, cvScalar(255,0,255));  
	    cvShowImage( "src", src );  
	}  

}  
int main()  
{  
	src=cvLoadImage("D:\\Data\\1.jpg",1);  
	dst=cvCloneImage(src);  
	cvNamedWindow("src",1);  
	cvSetMouseCallback( "src", on_mouse, 0 );    
	cvShowImage("src",src);  
	cvWaitKey(0);   
	cvDestroyAllWindows();  
	cvReleaseImage(&src);  
	cvReleaseImage(&dst);  
	return 0;  
}

在这里插入图片描述

OpenCVC++版)中,可以使用`findHomography()`函数结合`fitEllipse()`来从三个点拟合一个圆。这里是一个基本的步骤说明: 1. 首先,确保你已包含了所需的OpenCV头文件,并导入相应的模块: ```cpp #include <opencv2/opencv.hpp> #include <opencv2/calib3d/calib3d.hpp> #include <opencv2/core.hpp> using namespace cv; using namespace std; ``` 2. 定义三个点作为输入: ```cpp Point2f points[3]; points[0].x = x1; // 第一点的x,y坐标 points[0].y = y1; // 同理设置其余两点 ``` 3. 创建一个`Mat`对象来存放点的坐标矩阵,通常是一个3行3列的矩阵: ```cpp Mat pointsMatrix(3, 3, CV_32FC1, points); ``` 4. 使用`findHomography()`找到将原点到这三点的变换矩阵: ```cpp Mat H, mask; vector<Point2f> corners; perspectiveTransform(Point2f::zeros(1, 3), H, pointsMatrix); H.convertTo(H, CV_32F); // 将矩阵转换为浮点类型以便后续处理 // 接下来,由于我们只需要旋转和平移,所以找到中心点(假设为原点) Mat translation = (-H.colPivots()[0]).t(); // 对应于逆旋转矩阵,得到平移向量 ``` 5. 使用`fitEllipse()`从中心点和旋转角度找到拟合的椭圆参数,实际上OpenCV会返回最接近圆形的椭圆: ```cpp RotatedRect ellipse = fitEllipse(corners); // 棱镜法近似,corners可能为空,仅用于示例 double center_x = ellipse.center.x; double center_y = ellipse.center.y; double radius = ellipse.size.width / 2; // 半径近似为长轴的一半 ``` 6. 结果保存: ```cpp std::cout << "Center of the fitted circle: (" << center_x << ", " << center_y << ")\n"; ``` 注意:这种方法可能会得到椭圆而不是严格的圆,因为它依赖的是透视变换的简化模型。如果需要更精确的结果,可以考虑使用其他算法如RANSAC(RANdom SAmple Consensus)进行圆的拟合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶布布

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值