单目摄像头光学图像测距_单目相机测距(2)

      本篇文章为单目相机测距的姊妹篇,上一篇文章只考虑了摄像头平行于地面的情况,而本篇文章讨论了摄像头存在角度即悬挂的情况。

       其实本来不打算更新这篇文章,因为里面有些地方在我看来存在争议,但是刚巧我做报告要讲这一部分,因此顺便更新一下。存在争议的地方我会在文章中指出。

       本篇文章内容参考自:

       https://blog.csdn.net/mao_hui_fei/article/details/80822339

正文:

      目标输入一个像素坐标点,然后计算出该像素点实际位置距离摄像头水平距离和垂直距离,即实现了单目摄像头测距

      限制:摄像头固定角度,倾斜照射到地面,不考虑镜头畸变(选用无畸变相机)

5fd2a22b72308721b6b579201ca9dfcd.png

d0f309bff64b9dc78ae507df22d0a461.png

需要提前测得的量:

H:摄像头高度

Dmin:图像底边距摄像头实际距离

Dmax:图像顶边距摄像头实际距离

β:水平视场角

height:图像像素高度

width:图像像素宽度

输入:

X0:要测量的点的像素X坐标

Y0:要测量的点的像素Y坐标

输出:

X1:该点距摄像头的水平距离

Y1:该点距摄像头的垂直距离

       下面是具体计算过程,我是从ppt中直接截的图,如果给读者带来不便,在此表示歉意。

       在图中我标明了坐标轴,对于一些距离我也是采用的箭头标注,因为qq截图好像没有其他工具,可能有些混乱。

d0e506b3e673696bdaf615bbd517f03f.png

1478a6c3ebc07065157b13c8b892e8b6.png

b770a99846165a7fa9ca3fdab6e85b52.png

1c78399b7360ba3be5bc57353270e757.png

6190aab819cb4c358f55b25b86cf6d50.png

3a3aec4dea4f0c79e2cdfdca21ec95f8.png

       这里就是有争议的地方,在原文中,作者用了一个D1变量,但是并没有说明D1究竟代表什么,他最终推导出来的结果为B1=(Y1+D1)*tan(β/2)。这也是该篇博客评论区讨论最多的地方,由于联系不上作者,我就采用了评论区中大多数人的看法:D1=Dmax-Y1,但是,问题来了,如果D1=Dmax-Y1,那么Y1+D1=Dmax,那么D1就是一个无用变量 ,这本身就不合理了。而且,该作者还提供了c++代码,在他的源码中(我后面会附上),指定了D1的值,而且我将Dmax-Y1的值输出,发现Dmax-Y1根本不等于D1

      所以我就混乱了,为此我还特意咨询了一位评论区大神,他很坚定的告诉我D1就是Dmax-Y1,引入D1只是起了误导作用,完全没用,但是当我问他关于源码的问题,他说不要看源码。。。

      这也是为什么我本来不打算更新这篇文章的原因,因为D1究竟是什么,怎么确定的,我现在仍然不知道。

      以下为C++源码:

#include #include #include #include #include #include "windows.h"  #include "fstream" //opencv相关#include #include #include #include #include #include #include #include #include   //hog特征的c文件//自己编写的文件//#include "UART.h"//#include "findline.h"//#include "DrawImage.h"//绘制图形using namespace std;using namespace cv;using namespace cv::ml;RNG rng(12345);int main(){  float Alpha;//俯仰角Αα:阿尔法 Alpha  float Theta;//垂直视场角  西塔 Theta  float Beta;//水平视场角Ββ:贝塔 Beta,可以求  //测量出的参数,摄像头俯仰角一变,就会变化  float H1 = 44.0;//摄像头高度  float Dmin = 19.2;//最短距离  float Dmax = 187.1;//最长距离  //float D1 = 29.8;//摄像头坐标与水平面线交点差值  float X0 = 0;//像素坐标值  float Y0 = 0;//像素坐标值  float X1 = 0;//实际距离摄像头水平距离,左负右正  float Y1 = 0;//实际距离摄像头垂直距离  float width = 0;  float height = 0;  //中间变量  float d0 = 0;//步进视场角,用来计算离摄像头垂直距离,d(theta)  float B1 = 0;//每个Y1实际水平距离  //画圈半径,便于显示  int radius = 40;  //参数计算  Beta = atan(40.5 / 22.5);//水平视场角β  Alpha = atan(Dmin / H1);//俯仰角  //H2 = Dmin*H1 / Dmin1; //摄像头理论高度  Theta = atan(Dmax / H1) - Alpha;//垂直视场角  cout << "水平视场角β为:" << Beta * 180.0 / 3.1415926 << " 度" << endl;  cout << "垂直视场角θ为:" << Theta * 180.0 / 3.1415926 << " 度" << endl;  cout << "俯仰角α为:" << Alpha * 180.0 / 3.1415926 << " 度" << endl;  cout << "摄像头实际高度H1为:   " << H1 << " 厘米" << endl;  cout << "最短距离Dmin为:   " << Dmin << " 厘米" << endl;  cout << "最长距离Dmax为:   " << Dmax << " 厘米" << endl;  /*Mat srcImage = imread("1.jpg");*/  long int iiii = 1000;  Mat frame;  //【1】从摄像头读入视频  VideoCapture capture(0);  //该参数为0,则打开计算机自带摄像头,如果为1则打开外置USB摄像头  while (1)  {    iiii++;    //隔一段时间保存一张图片    if (iiii >= 100)//通过改变i后面的值来刷新图片界面    {      iiii = 0;      capture >> frame;// //读取当前帧,capture >> frame与capture.read(frame)功能一样,      if (frame.empty())      {        return 0;      }      width = frame.cols;      height = frame.rows;      cout << "图像宽度" << width << endl;      cout << "图像高度" << height << endl;      //视场中央线      line(frame, Point(width / 2, 0), Point(width / 2, height), Scalar(6, 88, 255), 3, LINE_AA);      line(frame, Point(0, height / 2), Point(width, height / 2), Scalar(6, 88, 255), 3, LINE_AA);      cout << "请输入像素坐标值X0(以回车结束):" << endl;      cin >> X0;      cout << "请输入像素坐标值Y0(以回车结束):" << endl;      cin >> Y0;      cout << "输入的结果为" << endl;      cout << "当前像素坐标值X0为:" << X0 << endl;      cout << "当前像素坐标值Y0为   " << Y0 << endl;      Point center(X0, Y0);      //绘制圆心        circle(frame, center, 3, Scalar(0, 255, 0), -1, 8, 0);      //绘制圆轮廓        circle(frame, center, radius, Scalar(155, 50, 255), 3, 8, 0);      namedWindow("原图", 0);      imshow("原图", frame);      waitKey(2);      waitKey(200);      waitKey(200);      waitKey(200);      d0 = (height - Y0) * Theta / height; //步进小角度      Y1 = H1 * tan(Alpha + d0); //垂直距离      //B1 = (Y1 + D1) * tan(Beta / 2.0);      B1 = (Dmax) * tan(Beta / 2.0);      X1 = 2.0 * B1 * (X0 - width / 2.0) / width;      cout << "距离摄像头水平距离X1为:" << X1 << " 厘米" << endl;      cout << "距离摄像头垂直距离Y1为:" << Y1 << " 厘米" << endl;    }  }  waitKey(0);}

       第138行被我改为了第139行,输出结果是不一样的,很恼火。

       由于测试不是很容易操作,因此后续看情况再决定增不增加测试部分,先这样吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值