一、整体方案(推荐工程路线)
OpenCV + OpenGL + Win32 / MFC / Qt
双目定位 → 3D 点云 → 贴图 → 显示
VC++(VS2015--VS2022 都行)
┌─────────────┐
│ 双目相机采集 │
└──────┬──────┘
↓
┌────────────────┐
│ 相机标定 & 校正 │
└──────┬─────────┘
↓
┌────────────────┐
│ 立体匹配(视差)│
└──────┬─────────┘
↓
┌────────────────┐
│ 3D 坐标计算 │
└──────┬─────────┘
↓
┌────────────────┐
│ 贴图 / 纹理映射 │
└──────┬─────────┘
↓
┌────────────────┐
│ OpenGL 显示 Demo│
└────────────────┘
二、开发环境准备(VC++)
1、软件环境
| 项目 | 建议 |
|---|---|
| IDE | Visual Studio 2019 / 2022 |
| OpenCV | OpenCV 4.x(x64) |
| OpenGL | GLFW + GLAD 或 MFC |
| 语言 | C++ |
| 架构 | x64 Release |
2、OpenCV 配置(关键)
- 下载 OpenCV Windows 版
- 设置环境变量:
text
OPENCV_DIR = D:\opencv\build\x64\vc16
Path += %OPENCV_DIR%\bin
- VS 项目属性:
text
C/C++ → 附加包含目录:
D:\opencv\build\include
链接器 → 附加库目录:
D:\opencv\build\x64\vc16\lib
链接器 → 输入:
opencv_world480.lib
三、双目定位核心流程(代码级)
1、双目标定(一次离线完成)
cpp
// 角点检测
findChessboardCorners(imgL, boardSize, cornersL);
cornerSubPix(imgL, cornersL, Size(11,11), Size(-1,-1), criteria);
// 双目标定
stereoCalibrate(
objectPoints,
imagePointsL,
imagePointsR,
cameraMatrixL, distCoeffsL,
cameraMatrixR, distCoeffsR,
imageSize,
R, T, E, F,
CALIB_FIX_INTRINSIC
);
输出:
- 左右相机内参
- 旋转矩阵
R - 平移向量
T
2、立体校正(非常重要)
cpp
stereoRectify(
cameraMatrixL, distCoeffsL,
cameraMatrixR, distCoeffsR,
imageSize, R, T,
R1, R2, P1, P2, Q
);
initUndistortRectifyMap(...);
remap(imgL, imgL_rect, mapLx, mapLy, INTER_LINEAR);
remap(imgR, imgR_rect, mapRx, mapRy, INTER_LINEAR);
校正后:极线完全水平
3、立体匹配(视差 → 深度)
推荐:BM(快) / SGBM(准)
cpp
cv::Ptr<cv::StereoSGBM> sgbm =
cv::StereoSGBM::create(0, 128, 5);
sgbm->setP1(8 * 3 * 5 * 5);
sgbm->setP2(32 * 3 * 5 * 5);
sgbm->setDisp12MaxDiff(1);
sgbm->setPreFilterCap(63);
sgbm->setUniquenessRatio(10);
sgbm->compute(imgL_gray, imgR_gray, disp);
4、3D 坐标计算(定位)
cpp
cv::reprojectImageTo3D(disp, points3D, Q);
points3D(x,y) 就是 世界坐标系下的 (X,Y,Z)
四、贴图(Texture Mapping)Demo
1、 取左图作为纹理
cpp
cv::Mat texture = imgL.clone();
2、OpenGL 贴图到 3D 点
cpp
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID);
glBegin(GL_POINTS);
for (auto& p : points3D) {
glTexCoord2f(u, v);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
实际工程里更常见的是:
- 三角剖分(Delaunay)
- Mesh + UV 映射
参考代码 双目视觉定位和贴图demo,vc环境开发测试 www.youwenfan.com/contentcsv/101699.html
五、VC 项目结构示例
BinocularDemo/
├── main.cpp
├── stereo_calib.cpp
├── stereo_match.cpp
├── pointcloud_render.cpp
├── shader/
│ ├── vert.glsl
│ └── frag.glsl
├── data/
│ ├── left/
│ └── right/
六、测试建议
测试顺序
- 单目标定(左右分别)
- 双目标定
- 校正对齐效果
- 视差图质量
- 3D 点云可视化
- 贴图效果
常见问题
| 问题 | 原因 |
|---|---|
| 深度抖动 | 基线太短 / 光照不均 |
| 空洞太多 | 纹理缺失 |
| 贴图扭曲 | UV 没对齐 |
| 帧率低 | SGBM 参数过重 |