免責事項:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/YunLaowang/article/details/86644361
三次元ポイントクラウドWin10 + OpenCV3.4.1 + PCL1.8環境の再構成、図3に基づいて両眼ステレオ視差を用いました。
原則
3Dポイントクラウドの両眼視差マップ再構成の原理を使用して(3次元点群のRGB-Dカメラプロセス及び再構成の使用は大きな違いはないで、メインオブジェクトが両眼視することにより、深さ情報を得ることで、非常に簡単です )、を算出 元のRGB情報を三次元ポイントクラウド(PointXYZRGB)を構成するために提供されると、座標値。
- :視差画像がキャプチャされている両眼立体視と深さマップは、原則を参照することが原則の範囲両眼の深さプロファイリング:見落とさ小さな問題
- :復興プロセスに関連する3次元点群を参照することができ、三次元再構成技術概要
コード
/*
相机参数:
cam0 = [4152.073 0 1288.147; 0 4152.073 973.571; 0 0 1]
cam1 = [4152.073 0 1501.231; 0 4152.073 973.571; 0 0 1]
doffs = 213.084
baseline = 176.252
width = 2872
height = 1984
相机内参数矩阵:
K=[fx 0 u0; 0 fy v0; 0 0 1]
*/
#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
using namespace pcl;
int user_data;
// 相机内参
const double u0 = 1288.147;
const double v0 = 973.571;
const double fx = 4152.073;
const double fy = 4152.073;
const double baseline = 176.252;
const double doffs = 213.084;// 两个相机主点在x方向上的差距, doffs = cx1 - cx0
void viewerOneOff(visualization::PCLVisualizer& viewer)
{
viewer.setBackgroundColor(0.0, 0.0, 0.0);
}
int main()
{
// 读入数据
Mat color = imread("im0.png"); // RGB
Mat depth = imread("disp0.png",IMREAD_UNCHANGED);// depth
if (color.empty() || depth.empty())
{
cout << "The image is empty, please check it!" << endl;
return -1;
}
// 相机坐标系下的点云
PointCloud<PointXYZRGB>::Ptr cloud(new PointCloud<PointXYZRGB>);
for (int row = 0; row < depth.rows; row++)
{
for (int col = 0; col < depth.cols; col++)
{
ushort d = depth.ptr<ushort>(row)[col];
if (d==0)
continue;
PointXYZRGB p;
// depth
p.z = fx * baseline / (d + doffs); // Zc = baseline * f / (d + doffs)
p.x = (col - u0) * p.z / fx; // Xc向右,Yc向下为正
p.y = (row - v0) * p.z / fy;
p.y = -p.y; // 为便于显示,绕x轴三维旋转180°
p.z = -p.z;
// RGB
p.b = color.ptr<uchar>(row)[col * 3];
p.g = color.ptr<uchar>(row)[col * 3 + 1];
p.r = color.ptr<uchar>(row)[col * 3 + 2];
cloud->points.push_back(p);
}
}
cloud->height = depth.rows;
cloud->width = depth.cols;
cloud->points.resize(cloud->height * cloud->width);
visualization::CloudViewer viewer("Cloud Viewer");
viewer.showCloud(cloud);
viewer.runOnVisualizationThreadOnce(viewerOneOff);
while (!viewer.wasStopped())
{
user_data = 9;
}
return 0;
}
もう一つ注意すべきは、その計算であります
を計算した場合、次のように:
得られた座標: 、右へ-axis 下軸正方向、以下に示すように。
画像間の関係は、座標系とカメラ座標系
したがって、適切な結果を表示するために約する必要があります 180°(三次元の回転)の回転をγ軸。そして周り 以下のように三次元変換行列のγ軸回転です。
取ります
、周囲に見
に相当する180°の回転を、γ軸:
結果が示されています。
材料と処理
以下からのブロガーが使用するRGBと深チャート:ビジョンmiddlebury_Adirondack、ダウンロードして自由です。
- 問題の
ミドルは、グランドトゥルースを提供するため.PFMフォーマットであり、OpenCVのは、.PFM形式のファイル操作をサポートしていないので、あなたはあなた自身の「ホイール」を構築したり、OpenCVのでサポートされている形式に有効にする必要があります。 - 解决方法
这里使用的是图片格式在线转换工具,将.pfm格式图片转成.png格式:多种格式在线互转网站,亲测好用。
当然,github上大神也提供了开源的“轮子”,可直接读入.pfm文件并转成Mat格式:点击此处链接,操作十分简单,如下是作者给出的例子。
/**
* Example of how to read and save PFM files.
*/
#include <iostream>
#include <string>
#include "PFMReadWrite.h"
using namespace std;
using namespace cv;
int main(void)
{
//Example that loads an image and stores it under another name
Mat image = loadPFM(string("image.pfm"));
//Display the image
imshow("Image", image);
waitKey(0);
savePFM(image, "image_saved.pfm");
return 0;
}
备注:
- 上述代码同样支持其他图片,只要修改对应的相机内参即可。
- 所有相关文件下载【CSDN】:双目立体视差图进行三维点云重建【OpenCV3.4.1+PCL1.8】
- 参考:用VS+Opencv3.1从双目立体视差图中重建三维点云