OpenCV C++双目三维重建:双目摄像头实现双目测距

目录

OpenCV C++双目三维重建:双目摄像头实现双目测距

1.目录结构

2.依赖库

3.双目相机标定

(1)双目相机标定-Python版

(2)双目相机标定-Matlab版

4.相机参数配置

5. 双目测距

6. 运行Demo

7. 效果图

8. 源码下载

9.参考资料


本篇博文是《双目摄像头实现双目测距(Python)》的续作,我们将搭建一个OpenCV C++版本的双目三维重建系统。由于我们只考虑三维重建实现双目测距效果,因而去除了PCL和Open3d库三维显示效果,但依然保留了视差图,深度图等可视化效果,用户可以通过鼠标点击图像,即可获得对应的世界坐标以及深度距离信息。

从效果来看,C++版本的双目测距和Python版本的效果几乎一致,性能更优,速度更快,基本可以达到工业级别测距精度,可在Linux开发板运行,非常适合应用于无人机,智能小车测距避障等场景。​

来~先看一下Demo的效果图(鼠标点击,终端会打印对应距离信息):

OpenCV C++双目摄像头实现双目测距主要支持:

  • 支持双USB连接线的双目摄像头
  • 支持使用WLS滤波器对视差图进行滤波
  • 支持双目测距(鼠标点击图像即可获得其深度距离)
  • 提供配套的opencv-4.3.0和opencv_contrib-4.3.0源码 (需要自己编译)
  • 相比Python版本,C++版本性能更优,速度更快,可在Linux开发板运行,非常适合应用于无人机,智能小车测距避障等场景。
  • 简单运行,项目源码只在Ubuntu 18.04系统进行了验证;第三方依赖库只有opencv和opencv_contrib,如果你在Windows系统开发,请在Windows平台配置好opencv和opencv_contrib开发环境;

诚然,网上有很多C++版本双测距的代码,但项目都不是十分完整,而且恢复视差图效果也一般,难以达到商业实际应用,究其原因,主要有下面几个:

  • 双目摄像头质量问题,
  • 双目标定存在问题,导致校准误差较大
  • 没有使用WLS滤波器对视差图进行滤波,该方法可以极大提高视差图的效果

双目测距Demo视频

如果你需要Python版本的双目测距, 请查看鄙人另一篇博客《双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python》

本篇将着重介绍OpenCV C++项目实现双目测距的过程,关于双目相机标定+双目校正+双目匹配等内容,请查看鄙人另一篇博客《双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python》

【项目源码下载地址】OpenCV C++双目摄像头实现双目测距

【尊重原则,转载请注明出处】https://panjinquan.blog.csdn.net/article/details/127446435


1.目录结构

.
├── configs          # 相机参数文件
├── data             # 相机采集的数据
├── docs             # 一些文档图片
├── src              # C++源码
├── build.sh         # 构建build脚本
├── main.cpp         # 主程序
├── CMakeLists.txt   # CMake文件
└── README.md        # 说明文档

2.依赖库

  • 系统平台:Ubuntu 18.04
  • opencv-4.3.0 (opencv-3.4.0以上亦可)
  • opencv_contrib-4.3.0 (opencv_contrib-3.4.0以上亦可),WLS滤波器需要用到opencv_contrib库

opencv安装教程,请参考文章:Ubuntu18.04安装opencv和opencv_contrib

PS: 需确保opencv和opencv_contrib的版本号一致,避免版本差异导致编译错误。

项目源码只在Ubuntu 18.04系统进行了验证;第三方依赖库只有opencv和opencv_contrib,如果你在Windows系统开发,请在Windows平台配置好opencv和opencv_contrib开发环境;


3.双目相机标定

(1)双目相机标定-Python版

请参考鄙人另一篇博客,无需Matlab,即可进行相机标定:双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python

该方法双目标定完成后,会得到一个双目相机内外参数信息(stereo_cam.yml)文件:

%YAML:1.0
---
size: !!opencv-matrixrows: 2cols: 1dt: ddata: [ 640., 480. ]
K1: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 7.6159209686584518e+02, 0., 3.2031427422505453e+02, 0.,7.6167321445963728e+02, 2.2467546927337131e+02, 0., 0., 1. ]
D1: !!opencv-matrixrows: 1cols: 5dt: ddata: [ 3.4834574885170888e-02, -5.5261651661983137e-02,5.7491952731614823e-04, -4.2764224824172658e-05,1.8477350140315381e-02 ]
K2: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 7.6327773941976670e+02, 0., 2.8768149948082271e+02, 0.,7.6350419442870850e+02, 2.1897333598636970e+02, 0., 0., 1. ]
D2: !!opencv-matrixrows: 1cols: 5dt: ddata: [ 3.5020972475517692e-02, -4.0770660841280497e-02,-4.4231087565750534e-04, -1.0552562170995372e-03,-9.7749906830348537e-02 ]
R: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9999370552351063e-01, 7.8563885326366346e-04,3.4600122760633780e-03, -7.9503151737356746e-04,9.9999600079883766e-01, 2.7140949167922721e-03,-3.4578661403601796e-03, -2.7168286517956050e-03,9.9999033095517087e-01 ]
T: !!opencv-matrixrows: 3cols: 1dt: ddata: [ -6.0005833133148414e+01, 1.7047017063672587e-01,6.0300223404957642e-01 ]
E: !!opencv-matrixrows: 3cols: 3dt: ddata: [ -1.1005724987007073e-04, -6.0346296076620343e-01,1.6883191705475561e-01, 3.9550629985097430e-01,-1.6255182474732952e-01, 6.0007339329190145e+01,-1.2276256904913259e-01, -6.0005727085740176e+01,-1.6345135556766910e-01 ]
F: !!opencv-matrixrows: 3cols: 3dt: ddata: [ -6.7250769136371160e-10, -3.6870834234286016e-06,1.6143104894409041e-03, 2.4160347372858321e-06,-9.9287680075344234e-07, 2.7862421257891157e-01,-1.1014218394645766e-03, -2.7856049650040260e-01, 1. ]
R1: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9997618806974742e-01, -2.0278309638726887e-03,-6.5963016213173775e-03, 2.0367881225372914e-03,9.9999701250432615e-01, 1.3514719999064883e-03,6.5935413581266105e-03, -1.3648750875444691e-03,9.9997733090723306e-01 ]
R2: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9994547731576255e-01, -2.8407384289991728e-03,-1.0048512373976153e-02, 2.8270879178959596e-03,9.9999506202764499e-01, -1.3724045434755307e-03,1.0052361397026631e-02, 1.3439216883706559e-03,9.9994857062992937e-01 ]
P1: !!opencv-matrixrows: 3cols: 4dt: ddata: [ 7.3741438842621210e+02, 0., 3.1126281356811523e+02, 0., 0.,7.3741438842621210e+02, 2.2189782714843750e+02, 0., 0., 0., 1.,0. ]
P2: !!opencv-matrixrows: 3cols: 4dt: ddata: [ 7.3741438842621210e+02, 0., 3.1126281356811523e+02,-4.4251577456670653e+04, 0., 7.3741438842621210e+02,2.2189782714843750e+02, 0., 0., 0., 1., 0. ]
Q: !!opencv-matrixrows: 4cols: 4dt: ddata: [ 1., 0., 0., -3.1126281356811523e+02, 0., 1., 0.,-2.2189782714843750e+02, 0., 0., 0., 7.3741438842621210e+02, 0.,0., 1.6664137886344466e-02, 0. ]

参数说明:

  • 参数size,对应图像宽高(width,height)
  • 参数K1,对应左目相机内参矩阵(3×3)
  • 参数D1,对应左目相机畸变系数矩阵(5×1)
  • 参数K2,对应右目相机内参矩阵(3×3)
  • 参数D2,对应右目相机畸变系数矩阵(5×1)
  • 参数T,对应双目相机平移向量T(3×1)
  • 参数R,对应双目相机旋转矩阵R(3×3)
  • 至于配置文件中的参数,如R1, R2, P1, P2, Q这些重投影矩阵,可默写即可,不用修改,这些在运行时,会重新计算。

(2)双目相机标定-Matlab版

网上已经存在很多Matlab双目相机标定的教程,请自行百度哈 ;使用Matlab工具箱进行双目相机标定后,请对应参数进行修改

需要注意的是:旋转矩阵R是(3×3)二维矩阵,而Matlab给出的是旋转向量om(1×3),请使用cv2.Rodrigues()将旋转向量转为旋转矩阵,参考下面的代码进行转换

    import cv2import numpy as np# 定义旋转矩阵R,旋转向量omR = [[9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03],[-7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03],[-3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01]]R = np.asarray(R)print(f"旋转矩阵R:\n {R}")# 把旋转矩阵R转化为旋转向量omom, _ = cv2.Rodrigues(R)print(f"旋转向量om:\n {om}")# 把旋转向量om转换为旋转矩阵RR1, _ = cv2.Rodrigues(om)print(f"旋转矩阵R1:\n {R1}")

4.相机参数配置

  • 双目相机标定完成后,得到了相机内外参数信息
  • 根据自己相机参数定义C++的CameraParam即可
  • 下面C++代码中,定义了双目相机CameraParam变量camera1,用户需要根据自己的双目相机,修改对应的相机内外参数。

/*** 双目摄像头的相机参数*/
struct CameraParam {
int width;           //图像的宽度width
int height;          //图像的高度height
Mat cameraMatrixL;   //左相机内参K1(3×3)
Mat distCoeffL;      //左相机畸变系数D1(5×1)
Mat cameraMatrixR;   //右相机内参K2(3×3)
Mat distCoeffR;      //右相机畸变系数D2(5×1)
Mat T;               //平移向量T(3×1)
Mat R;               //旋转矩阵R(3×3),如果是(3×1)旋转向量,请使用cv::Rodrigues()进行变换转为(3×3)旋转矩阵R
};/**** 设置摄像头参数,需要根据双目摄像头标定结果进行填写*/
static CameraParam camera1 = {
640,//width
480,//height
(Mat_<double>(3, 3)
<< 7.6159209686633153e+02, 0., 3.2031427422691633e+02, 0., 7.6167321446015626e+02, 2.2467546926913309e+02, 0., 0., 1.),//cameraMatrixL
(Mat_<double>(5, 1)
<< 3.4834574887256914e-02, -5.5261651680159028e-02, 5.7491952534806736e-04, -4.2764223950233445e-05, 1.8477350164208820e-02),//distCoeffL
(Mat_<double>(3, 3)
<< 7.6327773983796783e+02, 0., 2.8768149776326379e+02, 0., 7.6350419482215057e+02, 2.1897333669573928e+02, 0., 0., 1.),
(Mat_<double>(5, 1)
<< 3.5020967512300320e-02, -4.0770565902033332e-02, -4.4231049297594003e-04, -1.0552565496142535e-03, -9.7750314807571667e-02),
(Mat_<double>(3, 1)
<< -6.0005833075452117e+01, 1.7047023105446815e-01, 6.0300273851103448e-01),
(Mat_<double>(3, 3)
<< 9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03, -7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03, -3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01),
};

5. 双目测距

OpenCV C++版本的双目测距与Python版本双目测距的效果几乎一致,且性能更优,速度更快,基本可以达到工业级别测距精度。由于我们只考虑三维重建实现双目测距效果,因而去除了PCL和Open3d库三维显示效果,但依然保留了视差图,深度图等可视化效果,用户可以通过鼠标点击图像,即可获得对应的世界坐标以及深度距离信息。

函数接口声明,都已经给出了详细的参数说明,为了方便大家学习,函数命名和实现逻辑与Python版本的几乎一致:

Python版本 C++版本
//
// Created by pan_jinquan@163.com on 2022/10/6.
//#ifndef CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H
#define CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;cv::Mat xyz_coord;                                   //用于存放每个像素点距离相机镜头的三维坐标
cv::Point start;                                     //鼠标按下的起始点
cv::Rect buttonRect;                                 //定义矩形选框
bool buttonStatus = false;                           //是否选择对象/*** 双目摄像头的相机参数*/
struct CameraParam {int width;           //图像的宽度widthint height;          //图像的高度heightMat cameraMatrixL;   //左相机内参K1(3×3)Mat distCoeffL;      //左相机畸变系数D1(5×1)Mat cameraMatrixR;   //右相机内参K2(3×3)Mat distCoeffR;      //右相机畸变系数D2(5×1)Mat T;               //平移向量T(3×1)Mat R;               //旋转矩阵R(3×3),如果是(3×1)旋转向量,请使用cv::Rodrigues()进行变换转为(3×3)旋转矩阵R
};/**** 设置摄像头参数,需要根据双目摄像头标定结果进行填写*/
static CameraParam camera1 = {640,//width480,//height(Mat_<double>(3, 3)<< 7.6159209686633153e+02, 0., 3.2031427422691633e+02, 0., 7.6167321446015626e+02, 2.2467546926913309e+02, 0., 0., 1.),//cameraMatrixL(Mat_<double>(5, 1)<< 3.4834574887256914e-02, -5.5261651680159028e-02, 5.7491952534806736e-04, -4.2764223950233445e-05, 1.8477350164208820e-02),//distCoeffL(Mat_<double>(3, 3)<< 7.6327773983796783e+02, 0., 2.8768149776326379e+02, 0., 7.6350419482215057e+02, 2.1897333669573928e+02, 0., 0., 1.),(Mat_<double>(5, 1)<< 3.5020967512300320e-02, -4.0770565902033332e-02, -4.4231049297594003e-04, -1.0552565496142535e-03, -9.7750314807571667e-02),(Mat_<double>(3, 1)<< -6.0005833075452117e+01, 1.7047023105446815e-01, 6.0300273851103448e-01),(Mat_<double>(3, 3)<< 9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03, -7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03, -3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01),
};/**** 鼠标响应回调函数* @param event* @param x* @param y*/
static void onMouse(int event, int x, int y, int, void *) {if (buttonStatus) {buttonRect.x = MIN(x, start.x);buttonRect.y = MIN(y, start.y);buttonRect.width = std::abs(x - start.x);buttonRect.height = std::abs(y - start.y);}switch (event) {case EVENT_LBUTTONDOWN:             //鼠标左按钮按下的事件start = Point(x, y);buttonRect = Rect(x, y, 0, 0);buttonStatus = true;cout << "image(x,y)=" << start;cout << " world coords=(x,y,depth)=" << xyz_coord.at<Vec3f>(start) << endl;break;case EVENT_LBUTTONUP:               //鼠标左按钮释放的事件buttonStatus = false;if (buttonRect.width > 0 && buttonRect.height > 0)break;}
}/**** 显示图像* @param winname 窗口名称* @param image 图像* @param delay 显示延迟,0表示阻塞显示* @param flags 显示方式*/
static void show_image(const string &winname, cv::Mat &image, int delay = 0, int flags = cv::WINDOW_AUTOSIZE) {cv::namedWindow(winname, flags);cv::imshow(winname, image);cv::waitKey(delay);
}/**** 读取视频文件* @param video_file 视频文件* @param cap 视频流对象* @param width 设置图像的宽度* @param height 设置图像的高度* @param fps 设置视频播放频率* @return*/
bool get_video_capture(string video_file, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {//VideoCapture video_cap;cap.open(video_file);if (width > 0 && height > 0) {cap.set(cv::CAP_PROP_FRAME_WIDTH, width); //设置图像的宽度cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); //设置图像的高度}if (fps > 0) {cap.set(cv::CAP_PROP_FPS, fps);}if (!cap.isOpened())//判断是否读取成功{return false;}return true;
}/**** 读取摄像头* @param camera_id 摄像头ID号,默认从0开始* @param cap 视频流对象* @param width 设置图像的宽度* @param height 设置图像的高度* @param fps 设置视频播放频率* @return*/
bool get_video_capture(int camera_id, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {//VideoCapture video_cap;cap.open(camera_id);    //摄像头ID号,默认从0开始if (width > 0 && height > 0) {cap.set(cv::CAP_PROP_FRAME_WIDTH, width); //设置捕获图像的宽度cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);  //设置捕获图像的高度}if (fps > 0) {cap.set(cv::CAP_PROP_FPS, fps);}if (!cap.isOpened()) //判断是否成功打开相机{return false;}return true;
}class StereoReconstruct {
public:/**** 构造函数,初始化StereoReconstruct* @param camera 双目相机参数* @param use_wls 是否使用WLS滤波器对视差图进行滤波*/StereoReconstruct(CameraParam camera, bool use_wls = true);/**** release*/~StereoReconstruct();/**** 开始双目测距任务* @param frameL* @param frameR*/void task(Mat frameL, Mat frameR, int delay = 0);/**** 畸变校正和立体校正* @param imgL 左视图* @param imgR 右视图* @param rectifiedL 校正后左视图* @param rectifiedR 校正后右视图*/void get_rectify_image(Mat &imgL, Mat &imgR, Mat &rectifiedL, Mat &rectifiedR);/**** 获得视差图* @param imgL 畸变校正和立体校正后的左视图* @param imgR 畸变校正和立体校正后的右视图* @param dispL 返回视差图* @param use_wls 是否使用WLS滤波器对视差图进行滤波*/void get_disparity(Mat &imgL, Mat &imgR, Mat &dispL, bool use_wls = true);//SGBM匹配算法/**** 计算像素点的3D坐标(左相机坐标系下)* @param disp 视差图* @param points_3d 返回三维坐标points_3d,三个通道分布表示(X,Y,Z),其中Z是深度图depth, 即距离,单位是毫米(mm)* @param scale 单位变换尺度,默认scale=1.0,单位为毫米*/void get_3dpoints(Mat &disp, Mat &points_3d, float scale = 1.0);/**** 将输入深度图转换为伪彩色图,方面可视化* @param depth* @param colormap*/void get_visual_depth(cv::Mat &depth, cv::Mat &colormap, float clip_max = 6000.0);/**** 显示矫正效果* @param rectifiedL* @param rectifiedR*/void show_rectify_result(cv::Mat rectifiedL, cv::Mat rectifiedR);/**** 可视化视差图和深度图* @param frameL* @param frameR* @param points_3d* @param disp* @param delay*/void show_2dimage(Mat &frameL, Mat &frameR, Mat &points_3d, Mat &disp, int delay);/**** 显示Mat的最大最小值* @param src* @param vmin 最小值下限* @param vmax 最大值下限*/void clip(cv::Mat &src, float vmin, float vmax);/**** 显示Mat的最大最小值* @param src* @param th* @param vmin*/void clip_min(cv::Mat &src, float th, float vmin);public:string depth_windows = "depth-color";             // 深度图的窗口名称int use_wls;                                      // 是否使用WLS滤波器对视差图进行滤波Size image_size;                                  // 图像宽高(width,height)Rect validROIL;                                   // 图像校正之后,会对图像进行裁剪,这里的左视图裁剪之后的区域Rect validROIR;                                   // 图像校正之后,会对图像进行裁剪,这里的右视图裁剪之后的区域Mat mapLx, mapLy, mapRx, mapRy;                   // 映射表Mat Rl, Rr, Pl, Pr, Q;                            // 校正后的旋转矩阵R,投影矩阵P, 重投影矩阵Qcv::Ptr<cv::StereoSGBM> sgbm;
};#endif //CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H

6. 运行Demo

  • 主程序main.cpp实现了三个Demo
  1. 测试demo视频文件: 这是使用摄像头录制的双目视频文件,用于测试效果双目测距的效果
  2. 测试双目摄像头(双USB连接线的双目摄像头):用于测试双目摄像头,需要根据自己的摄像头修改ID号
  3. 测试一对左右相机图像效果
//
// 双目测距Demo
// Created by pan_jinquan@163.com on 2022/10/6.
//
#include <opencv2/opencv.hpp>
#include <iostream>
#include "stereo_reconstruct.h"/**** 测试demo视频文件* @return*/
int test_video_file() {CameraParam camera = camera1;//双目相机参数bool use_wls = true;         //是否使用WLS滤波器对视差图进行滤波StereoReconstruct *detector = new StereoReconstruct(camera, use_wls);int imageWidth = camera1.width;      //单目图像的宽度int imageHeight = camera1.height;    //单目图像的高度string left_video = "../data/lenacv-video/left_video.avi";string right_video = "../data/lenacv-video/right_video.avi";VideoCapture capL, capR;bool retL = get_video_capture(left_video, capL, imageWidth, imageHeight);bool retR = get_video_capture(right_video, capR, imageWidth, imageHeight);Mat frameL, frameR;while (retL && retR) {capL >> frameL;capR >> frameR;if (frameL.empty() or frameR.empty()) break;detector->task(frameL, frameR, 20);}capL.release();         //释放对相机的控制capR.release();         //释放对相机的控制delete detector;return 0;}/**** 测试双目摄像头(双USB连接线的双目摄像头)* @return*/
int test_camera() {CameraParam camera = camera1;//双目相机参数bool use_wls = true;         //是否使用WLS滤波器对视差图进行滤波StereoReconstruct *detector = new StereoReconstruct(camera, use_wls);int imageWidth = camera1.width;       //单目图像的宽度int imageHeight = camera1.height;     //单目图像的高度int camera1 = 0;                      //左摄像头ID号(请修改成自己左摄像头ID号)int camera2 = 1;                      //右摄像头ID号(请修改成自己右摄像头ID号)VideoCapture capL, capR;bool retL = get_video_capture(camera1, capL, imageWidth, imageHeight);bool retR = get_video_capture(camera2, capR, imageWidth, imageHeight);Mat frameL, frameR;while (retL && retR) {capL >> frameL;capR >> frameR;if (frameL.empty() or frameR.empty()) break;detector->task(frameL, frameR, 20);}capL.release();         //释放对相机的控制capR.release();         //释放对相机的控制delete detector;return 0;
}/**** 测试一对左右图像* @return*/
int test_pair_image_file() {CameraParam camera = camera1;//双目相机参数bool use_wls = true;         //是否使用WLS滤波器对视差图进行滤波StereoReconstruct *detector = new StereoReconstruct(camera, use_wls);Mat frameL = imread("../data/left.png", IMREAD_COLOR);Mat frameR = imread("../data/right.png", IMREAD_COLOR);detector->task(frameL, frameR, 0);delete detector;return 0;
}int main() {//测试一对左右图像test_pair_image_file();//测试demo视频文件test_video_file();//测试双目摄像头(双USB连接线的双目摄像头)test_camera();return 0;
}
  • 终端运行脚本:bash build.sh
#!/usr/bin/env bash
if [ ! -d "build/" ];thenmkdir "build"
elseecho "exist build"
fi
cd build
cmake ..
make -j4
sleep 1
./Demo

7. 效果图

C++版本的双目测距与Python版本的效果几乎一致。从重建效果来看,未使用WLS滤波,其视差图出现了很多空洞,存在很多误匹配点;但使用WLS滤波后,视差图变得比较平滑,整体效果都有明显改善。

左视图 右视图
视差图(未滤波) 深度图(未滤波)
视差图(滤波后) 深度图(滤波后)
  • 运行主程序后,鼠标点击depth-color窗口的图像任意区域,终端会打印对应距离信息


8. 源码下载

OpenCV C++版本双目测距项目代码包含:OpenCV C++双目摄像头实现双目测距

【项目源码下载地址】OpenCV C++双目摄像头实现双目测距

  • 支持双USB连接线的双目摄像头
  • 支持使用WLS滤波器对视差图进行滤波
  • 支持双目测距(鼠标点击图像即可获得其深度距离)
  • 提供配套的opencv-4.3.0和opencv_contrib-4.3.0源码 (需要自己编译)
  • 相比Python版本,C++版本性能更优,速度更快,可在Linux开发板运行,非常适合应用于无人机,智能小车测距避障等场景。
  • 简单运行,项目源码只在Ubuntu 18.04系统进行了验证;第三方依赖库只有opencv和opencv_contrib,如果你在Windows系统开发,请在Windows平台配置好opencv和opencv_contrib开发环境;

如果你需要Python版本的双目测距, 请查看鄙人另一篇博客《双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python》

双目测距Demo视频


9.参考资料

  1. 双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python
  2. 双目摄像头实现双目测距(Python)
  3. 结构光三维重建-3D Scanning Software实现三维重建
  4. Ubuntu18.04安装opencv和opencv_contrib

OpenCV C++双目三维重建:双目摄像头实现双目测距相关推荐

  1. Android双目三维重建:Android双目摄像头实现双目测距

    Android双目三维重建:Android双目摄像头实现双目测距 目录 Android双目三维重建:Android双目摄像头实现双目测距 1.开发版本 2.Android双目摄像头 3.双目相机标定 ...

  2. 双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python

    双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python 目录 双目三维重建系统(双目标定+立体校正+双目测距+点云显示)Python 1.项目结构 2. Environment 3.双 ...

  3. 三维重建(单目、双目、多目、点云、SFM、SLAM)

    1 相机几何与标定 1.1 相机模型中的坐标系 1.2 四种坐标系之间的转换 1.3 相机内参 1.4 相机标定 2 传统三维重建 2.1 RGBD三维重建 2.1.1 KinectFusion 2. ...

  4. ROS+Opencv的双目相机标定和orbslam双目参数匹配

    本文承接ROS调用USB双目摄像头模组 目录 先完成单目标定 双目标定 生成可用于ORB-SLAM2的yaml文件 生成可用于ORB-SLAM3的yaml文件 参考 按照上面链接配置好后,执行 ros ...

  5. 双目三维重建_【光电视界】简单介绍双目视觉三维重构

    今日光电        有人说,20世纪是电的世纪,21世纪是光的世纪:知光解电,再小的个体都可以被赋能.欢迎来到今日光电! ----与智者为伍 为创新赋能---- 1.三维重构 1.1.三维重构到底 ...

  6. opencv读取MATLAB双目标定的结果进行双目校正

    概述: opencv内部也有双目标定的函数,但是结果有时候会飘,所以想先用MATLAB标定工具箱试试看.使用MATLAB先队两个相机进行单目标定,然后进行双目标定,将结果保存在xml文件中.xml文件 ...

  7. ORB-SLAM2:一个支持单目、双目和RGB-D摄像头(相机)的开源SLAM系统(翻译)

    书读百遍其义自见,为了日后能方便快速回顾ORB-SLAM2的原理和思想,这里本人将论文翻译成中文母语,网上也有其他的翻译版本,诸君也可参照.本文不求诸君全信,但求无误导之嫌疑.小经验:研究源码以及修改 ...

  8. MatLab的双目相机标定和orbslam双目参数匹配

    本文承接ROS调用USB双目摄像头模组 目录 相机标定 导出为YAML文件(也可以手动粘贴) 生成可用于ORB-SLAM2的yaml文件 生成可用于ORB-SLAM3的yaml文件 2022.5.6补 ...

  9. python opencv以MJPG读取usb摄像头

    python下使用opencv以MJPG读取usb摄像头 修改格式的原因 用 cap = cv2.VideoCapture(1)打开usb双目摄像头时发现帧率很低,使用cap.set(cv2.CAP_ ...

  10. python+opencv用电脑调用手机摄像头或其他网路摄像头

    python+opencv用电脑调用手机摄像头或其他网路摄像头 文章目录: 1 获取手机摄像头或网络摄像头的ip 1.1 获取手机摄像头的ip 1.2 获取网络摄像头的IP 1.3 关于RTSP协议 ...

最新文章

  1. 简单易上手编译FFmpeg
  2. 展开被 SpringBoot 玩的日子 《 二 》 WEB 开发
  3. VC使用CRT调试功能检测内存泄漏(转载)
  4. 爬虫笔记:Requests库详解
  5. Oracle10g下载地址
  6. Incompatible JavaHL library loaded. Subversion 1.8.x required.
  7. html 表格 左侧表头,左侧是表头的JS表格控件(自写,网上没有的)
  8. android 删除文件 代码_代码审计之某系统后台存在任意删除文件
  9. jpa 连接多个mysql 数据库_SpringBoot 连接多个数据库
  10. 大学python笔记整理_python 笔记整理
  11. 计算机网络ping用法,新手入门:ping命令的用法解释
  12. 【数字电子技术基础】数字电子钟设计
  13. std::numeric_limits的使用
  14. layui 数字步进器_vue mand-mobile ui Stepper步进器默认值传字符串进去不起作用
  15. word突然不能保存只能另存为
  16. php短网址生成代码,一个php短网址的生成代码(仿微博短网址)
  17. matlab 画 带虚部,MATLAB1:求实部、虚部、模和幅角的运算
  18. uniapp下载图片
  19. 物联网产业规模已达万亿,目前的主要应用领域有哪些?
  20. 网络编程(wireshare抓数据包及分析、三次握手与四次挥手、数据库sqlite3及操作)笔记-day15

热门文章

  1. 架构图、用例图、流程图、时序图、类图
  2. 教育行业 服务器虚拟化,教育行业桌面虚拟化方案
  3. 通过2048学习自定义view(一)
  4. 组态王如何让计算机关机,组态王软件系统登陆与退出.doc
  5. 程序猿DD元旦送书:第二弹!
  6. 未来新一代计算机发展趋势有,未来新一代计算机的代表有()。
  7. 基于springboot老年人健康体检系统(带论文)
  8. python爬取五百丁word模板(有图+有代码)
  9. 短信发送接口超详细短信接口使用教程
  10. Verilog Language--Modules:Hierachy--Module add