最近要做一个小项目,要完成相机的测距实现,最先考虑的是三角激光测距,但是实现起来太麻烦了,基本要搭一个简易的激光测距雷达...然后是双目测距,然而一个便宜的双目工业相机也要四五百,而且以前也没接触过双目测距...

于是就想试试单目测距的效果怎么样,通过参考网络上的各种资料,加上以前玩过三角激光测距,所以也算比较顺利的写出来个简易实现单目测距的代码,精度还算差强人意。

原理大概是这样的 :

这是三维情况下的小孔成像模型 :                             

我们把它简化成更为直观的二维平面模型(渣画勿喷...):

这里要说明下,这是一个典型的小孔成像模型,与单目相机的成像原理类似。

中间通过红蓝的垂线是相机的主光轴,d是被测物体至镜头的距离,f为相机镜头的焦距,w为被测物体的实际宽度(高度),w'为物体在成像平面(感光元件)上的宽度(高度)。

根据相似三角形公式可得:f / d = w' / w

由于f(相机镜头焦距)一般都是已知参数(买相机的时候总要选镜头焦距吧...),即使不清楚也可以通过计算得出,这里就不具体说了,w(实际物体宽或高)则是可以实际测得的常量。

重点说下怎么通过计算得出w'(物像宽或高)。举个栗子,假设你手上的相机是200w像素捕获画面尺寸为1920*1080,感光元件尺寸为1/2.7'',宽高分别为5.3mm和4mm(估值),被测物体在画面上的像素宽高都为600 pixel,那么w'(x) = (5.3 / 1920 * 600)(mm),同样的,w'(y) = (4 / 1080 * 600)(mm)。关于感光元件尺寸和画面尺寸可以通过查看相机参数手册获得,而感光元件的宽和高可以通过其尺寸计算出来,这里直接扔张感光元件靶面尺寸表作为参考,图来源自网络:

这样,得知了 f,w,w' ,就可以根据上文提到的相似三角形公式计算得出d啦。

不过以上考虑的的是理想情况,前提是保证物像光线通过主光轴,相机是完全无畸变的,且被测物体平面要与相机成像平面保持平行状态。在这里我使用的相机是无畸变工业相机(低程度畸变,完全没畸变的相机是不存在的...),如果是较为廉价的相机或者是广角镜头相机都会存在较大程度的画面畸变,可以通过软件进行校正。准确来说这些情况都属于无法完全消除的偏差,只能通过后期软件来尽量减少这种偏差。

以上也就是为什么单目测距的精度要比双目测距差的多的原因,但是在所需测量精度不需要很精确的情况(偏差 < 10% ~ 15%),以及成本受限的情况下,单目测距依然是首选方案,何况其实现起来也十分简单。

如果想了解更加复杂的情况和更详细的原理可以参考这篇文章:https://blog.csdn.net/qiushui3103800391/article/details/79162938

以下是代码实现部分,使用 OpenCV 3.4.0

// 单目测距.cpp: 定义控制台应用程序的入口点。//#include "stdafx.h"#include "opencv2/opencv.hpp"#include #include #include // 单位像素宽/高(cm/pixel)#define UNIT_PIXEL_W 0.0008234375#define UNIT_PIXEL_H 0.000825using namespace std;int main(void){cv::Mat frame;cv::VideoCapture capture(0);const double f = 0.35;  // 焦距const double w = 8.5;   // 被测物体宽度const double h = 5.6;   // 被测物体高度if (!capture.isOpened()) {printf("The camera is not opened.\n");return EXIT_FAILURE;}for (;;) {capture >> frame;if (frame.empty()) {printf("The frame is empty.\n");break;}cv::medianBlur(frame, frame, 3);cv::Mat grayImage;cv::cvtColor(frame, grayImage, cv::COLOR_BGR2GRAY);// otsu 可以换用动态阈值cv::threshold(grayImage, grayImage, NULL, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);vector<vector<:point>> contours;vector<:point> maxAreaContour;cv::findContours(grayImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//cv::drawContours(frame, contours, -1, cv::Scalar(0, 0, 255), 2, 8);// 提取面积最大轮廓double maxArea = 0;for (size_t i = 0; i < contours.size(); i++) {double area = fabs(cv::contourArea(contours[i]));if (area > maxArea) {maxArea = area;maxAreaContour = contours[i];}}// 轮廓外包正矩形cv::Rect rect = cv::boundingRect(maxAreaContour);cv::rectangle(frame, cv::Point(rect.x, rect.y), cv::Point(rect.x + rect.width, rect.y + rect.height), cv::Scalar(255, 0, 0), 2, 8);// 计算成像宽/高double width = rect.width * UNIT_PIXEL_W;double height = rect.height * UNIT_PIXEL_H;// 分别以宽/高为标准计算距离double distanceW = w * f / width;double distanceH = h * f / height;char disW[50], disH[50];sprintf_s(disW, "DistanceW : %.2fcm", distanceW);sprintf_s(disH, "DistanceH : %.2fcm", distanceH);cv::putText(frame, disW, cv::Point(5, 20), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(0, 255, 0), 1, 8);cv::putText(frame, disH, cv::Point(5, 40), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(0, 255, 0), 1, 8);cv::imshow("Frame", frame);cv::imshow("Gray", grayImage);if ((cv::waitKey(10) & 0XFF) == 27) break;}cv::destroyAllWindows();capture.release();return EXIT_SUCCESS;}

这里使用的相机感光元件尺寸 CMOS 1/2.7'',捕获画面尺寸设置为640 * 480。

代码分别使用了w'(x)和w'(y)作为参数进行测距。

实际测试结果:

实际距离15cm,计算距离14.40 ~ 14.57cm,偏差量0.43 ~ 0.60cm

实际距离7cm,计算距离6.83 ~ 6.85cm,偏差量0.15 ~ -0.17cm

实际距离20cm,计算距离18.86 ~ 19.12cm,偏差量0.88 ~ 1.14cm

可以看出,测距精度和实际距离呈反比,这里的测试结果跟其他博主写两篇文章测出的结果情况一样,都是偏小。另外,测量精度与画面尺寸(相机像素值)呈正比,如果用更高像素的相机来测量会跟精确。

 End 

声明:部分内容来源于网络,仅供读者学习、交流之目的。文章版权归原作者所有。如有不妥,请联系删除。

opencv手册_OpenCV之单目测距实现相关推荐

  1. OpenCV 单目测距实现

    最近要做一个小项目,要完成相机的测距实现,最先考虑的是三角激光测距,但是实现起来太麻烦了,基本要搭一个简易的激光测距雷达...然后是双目测距,然而一个便宜的双目工业相机也要四五百,而且以前也没接触过双 ...

  2. python opencv单目测距 小孔成像原理

    python opencv单目测距 小孔成像原理 小孔成像原理 代码 opencv>3.x 小孔成像原理 一 用相似三角形计算物体或者目标到相机的距离 我们将使用相似三角形来计算相机到一个已知的 ...

  3. python手机摄像头投测距_python opencv单目测距 小孔成像原理

    python opencv单目测距 小孔成像原理 小孔成像原理 一 用相似三角形计算物体或者目标到相机的距离 我们将使用相似三角形来计算相机到一个已知的物体或者目标的距离. 相似三角形就是这么一回事: ...

  4. 【自动驾驶】摄像头单目测距原理及实现

    原文链接:摄像头单目测距原理及实现 可以观看这个视频,了解针孔相机和透镜. 摄像头单目测距原理及实现 一.测距原理 空间的深度或距离等数据的摄像头. 人的眼睛长在头部的前方,两只眼的视野范围重叠,两眼 ...

  5. python测量镜头到目标距离_摄像头单目测距原理及实现

    摄像头单目测距原理及实现 一.测距原理 空间的深度或距离等数据的摄像头. 人的眼睛长在头部的前方,两只眼的视野范围重叠,两眼同时看某一物体时,产生的视觉称为双眼视觉. 双眼视觉的优点是可以弥补单眼视野 ...

  6. 单目测距原理与实现(代码可运行)

    Opencv3实现单目视觉测距 一.前言 单目视觉测距:网上有很多关于单目测距的文章,主要借鉴的是OpenCV学习笔记(二十一)--简单的单目视觉测距尝试和单目摄像机测距(python+opencv) ...

  7. python 人脸检测、单目测距以及人脸打码

    最近想写博客但是下班后完全提不起兴趣,今天周末刚好闲下心来,想了想把在github发现的一个人脸检测项目调试了下,发现挺不错的,准确率跟速度都挺适合低配版设备使用,所以过几天想自己训练一下检测车牌,试 ...

  8. 相机模型、相机标定及基于yolov5的单目测距实现

    相机模型.相机标定及基于yolov5的单目测距实现 1 前言 2 相机模型及单目测距原理 3 相机参数标定 3.1 内参矩阵 3.2 内参标定 3.3 外参矩阵 4 基于yolov5的单目测距实现 1 ...

  9. yolo 车辆测距+车辆识别+单目测距(双目测距)

    基于yolo目标检测算法实现的车前道路中的车辆和行人检测,并且可以估测出目标与本车之间的距离 一.视频展示 yolo车距1 订阅专栏获得源码(提供完整代码,无需看下文) 二.单目测距原理 图中有一个车 ...

最新文章

  1. java数据结构堆_Java 数据结构-堆实现
  2. k8s使用glusterfs存储报错type 'features/utime'
  3. codeforces193B
  4. 阿里云专属数据库,重新定义云数据库新形态
  5. 【VBS】总结 Visual Basic 的分支结构和循环结构
  6. 记一次MongoDB故障排查的过程
  7. c++ string split_闲话Python之砍瓜切菜split()
  8. 使c语言程序变成流程图的软件6,下载_AutoFlowchart(C语言流程图生成器) V3.5.3 英文版_6z6z下载站...
  9. “隐身侠”轻松破解,忽略开关机保护
  10. 在CSDN的博文中如何添加博主名片
  11. 工商银行网银支付问题 有网站想要安装以下加载项 来自Industrial and Commercial Bank of China Limited‘ 第三方支付机构上送网联跳转报文请求参数错误
  12. 从7654浏览器卸载到安装360安全卫士
  13. 龙卷风收音机android安卓版,龙卷风收音机
  14. 修改服务器网卡速率,linux查看网卡速率命令(linux如何改网卡速率命令)
  15. android热修复原理总结
  16. 如何查看远程端口是否打开
  17. PD充电调试问题解析(一)
  18. 它来了,任务调度框架 Quartz保姆级教程奉上
  19. 阿里云视觉AI训练营_Class3_文字识别项目讲解及使用说明
  20. Thinking in Java读书笔记-第二章

热门文章

  1. MultiByteToWideChar和WideCharToMultiByte的正确使用方法及参数详解
  2. MySQL一次查几万条数据,【mysql】一次插入几万条数据应该怎么做优化
  3. mysql注释符号_MySQL基础知识(2021最新版教程)
  4. 运动会计算机系,秋季运动会计算机系总结计划 (12页)-原创力文档
  5. java 试卷自动生成_基于JAVA的试题自动生成系统 - WEB源码|JSP源码/Java|源代码 - 源码中国...
  6. python数据获取及预处理_python数据预处理(入门)
  7. 监管码服务器维修,云风的 BLOG
  8. 数据库设计的三大范式[学习笔记]
  9. java 二叉树_拼多多Java开发1234面:二叉树+负载均衡+MySQL+Redis+高并发
  10. 一个“想忘带东西都难”的出行指南