両眼視差マップによって3次元ポイントクラウドの復元[Win10 + OpenCV3.4.1 + PCL1.8]

免責事項:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/YunLaowang/article/details/86644361

三次元ポイントクラウドWin10 + OpenCV3.4.1 + PCL1.8環境の再構成、図3に基づいて両眼ステレオ視差を用いました。

原則

3Dポイントクラウドの両眼視差マップ再構成の原理を使用して(3次元点群のRGB-Dカメラプロセス及び再構成の使用は大きな違いはないで、メインオブジェクトが両眼視することにより、深さ情報を得ることで、非常に簡単です Z c Z_c )、を算出 X c Y c X_C、Y_c 元のRGB情報を三次元ポイントクラウド(PointXYZRGB)を構成するために提供されると、座標値。

コード

/*
相机参数:
	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;
}

もう一つ注意すべきは、その計算であります ( X c , Y c ) (X_C、Y_c) を計算した場合、次のように:
{ X c = ( u u 0 ) Z c / f x Y c = ( v v 0 ) Z c / f y \開始{ケース} X_C =(U - U_0)* Z_c / F_X \\ Y_c =(V - v_0)* Z_c / f_y \\ \端{ケース}

得られた座標: x バツ 、右へ-axis y 下軸正方向、以下に示すように。

画像間の関係は、座標系とカメラ座標系

したがって、適切な結果を表示するために約する必要があります x バツ 180°(三次元の回転)の回転をγ軸。そして周り x バツ 以下のように三次元変換行列のγ軸回転です。

取ります Θ = 180 ° \シータ= 180° 、周囲に見 x バツ に相当する180°の回転を、γ軸:
{ y = y z = z \ {ケース}を開始し、^ \プライム= -y \\ Z ^ \プライム= -z \\ \端{ケース}

結果が示されています。

材料と処理

以下からのブロガーが使用する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;
}

备注:

おすすめ

転載: blog.csdn.net/YunLaowang/article/details/86644361