#include <iostream>
#include <opencv2/opencv_modules.hpp>
#ifdef HAVE_OPENCV_VIZ
#endif
static const char* keys =
{ "{@images_list | | 图像列表,已保存捕获的模式图像}"
"{@calib_param_path | | 校准参数 }"
"{@proj_width | | 用来获取模式的投影仪宽度 }"
"{@proj_height | | 用来获取模式的投影仪高度}"
"{@white_thresh | | 白色阈值高度(可选)}"
"{@black_thresh | | 黑色阈值(可选)}" };
static void help()
{
cout << "\n此示例显示如何使用“Structured Light 模块”解码先前获取的格雷码模式,生成点云"
"\n调用:\n"
"./example_structured_light_pointcloud <images_list> <calib_param_path> <proj_width> <proj_height> <white_thresh> <black_thresh>\n"
<< endl;
}
static bool readStringList( const string& filename, vector<string>& l )
{
l.resize( 0 );
如果( !fs.isOpened() )
{
cerr << "打开 " << filename << endl 失败;
返回 false;
}
如果( n.
type() != FileNode::SEQ )
{
cerr << "cam 1 图像不是一个序列!失败" << endl;
返回 false;
}
对于( ; it != it_end; ++it )
{
l.push_back( ( string ) *it );
}
n = fs["cam2"];
如果( n.
type() != FileNode::SEQ )
{
cerr << "cam 2 图像不是一个序列!失败" << endl;
返回 false;
}
对于( ; it != it_end; ++it )
{
l.push_back( ( string ) *it );
}
如果( l.size() % 2 != 0 )
{
cout << "错误: 图像列表包含奇数个(偶数个)元素\n";
返回 false;
}
返回 true;
}
int main(
int argc,
char** argv )
{
params.width = parser.get<
int>( 2 );
params.height = parser.get<
int>( 3 );
如果( images_file.empty() 或calib_file.empty() 或
params.width < 1 或
params.height < 1 或 argc < 5 或 argc > 7 )
{
帮助();
返回 -1;
}
size_t white_thresh = 0;
size_t black_thresh = 0;
如果( argc == 7 )
{
white_thresh = parser.get<unsigned>( 4 );
black_thresh = parser.get<unsigned>( 5 );
graycode->setWhiteThreshold( white_thresh );
graycode->setBlackThreshold( black_thresh );
}
vector<string> imagelist;
bool ok = readStringList( images_file, imagelist );
如果( !ok 或 imagelist.empty() )
{
cout << "不能打开 " << images_file << " 或字符串列表为空" << endl;
帮助();
返回 -1;
}
如果( !fs.isOpened() )
{
cout << "打开校准数据文件失败。" << endl;
帮助();
返回 -1;
}
Mat cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, R, T;
fs["cam1_intrinsics"] >> cam1intrinsics;
fs["cam2_intrinsics"] >> cam2intrinsics;
fs["cam1_distorsion"] >> cam1distCoeffs;
fs["cam2_distorsion"] >> cam2distCoeffs;
fs["R"] >> R;
fs["T"] >> T;
cout << "cam1intrinsics" << endl << cam1intrinsics << endl;
cout << "cam1distCoeffs" << endl << cam1distCoeffs << endl;
cout << "cam2intrinsics" << endl << cam2intrinsics << endl;
cout << "cam2distCoeffs" << endl << cam2distCoeffs << endl;
cout << "T" << endl << T << endl << "R" << endl << R << endl;
如果( (!R.
data) || (!T.
data) || (!cam1intrinsics.
data) || (!cam2intrinsics.
data) || (!cam1distCoeffs.
data) || (!cam2distCoeffs.
data) )
{
cout << "加载相机校准参数失败" << endl;
帮助();
返回 -1;
}
size_t numberOfPatternImages = graycode->getNumberOfPatternImages();
vector<vector<Mat> > captured_pattern;
captured_pattern.resize( 2 );
captured_pattern[0].resize( numberOfPatternImages );
captured_pattern[1].resize( numberOfPatternImages );
Mat color =
imread( imagelist[numberOfPatternImages], IMREAD_COLOR );
cout << "校正图像..." << endl;
stereoRectify( cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q, 0,
-1, imagesSize, &validRoi[0], &validRoi[1] );
Mat map1x, map1y, map2x, map2y;
对于( size_t i = 0; i < numberOfPatternImages; i++ )
{
captured_pattern[0][i] =
imread( imagelist[i], IMREAD_GRAYSCALE );
captured_pattern[1][i] =
imread( imagelist[i + numberOfPatternImages + 2], IMREAD_GRAYSCALE );
如果( (!captured_pattern[0][i].data) || (!captured_pattern[1][i].data) )
{
cout << "图像为空" << endl;
帮助();
返回 -1;
}
remap( captured_pattern[1][i], captured_pattern[1][i], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( captured_pattern[0][i], captured_pattern[0][i], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
}
cout << "完成" << endl;
vector<Mat> blackImages;
vector<Mat> whiteImages;
blackImages.resize( 2 );
whiteImages.resize( 2 );
cvtColor( color, whiteImages[0], COLOR_RGB2GRAY );
whiteImages[1] =
imread( imagelist[2 * numberOfPatternImages + 2], IMREAD_GRAYSCALE );
blackImages[0] =
imread( imagelist[numberOfPatternImages + 1], IMREAD_GRAYSCALE );
blackImages[1] =
imread( imagelist[2 * numberOfPatternImages + 2 + 1], IMREAD_GRAYSCALE );
remap( color, color, map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( whiteImages[0], whiteImages[0], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( whiteImages[1], whiteImages[1], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( blackImages[0], blackImages[0], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( blackImages[1], blackImages[1], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
cout << endl << "解码图案 ..." << endl;
bool decoded = 灰度码->解码( 捕获模式, 视差图像, 黑图像, 白图像,
结构光::解码_3D_地下世界 );
if( decoded )
{
cout << endl << "模式解码" << endl;
Mat cm_disp, scaledDisparityMap;
cout <<
"disp min " <<
min << endl <<
"disp max " <<
max << endl;
resize( cm_disp, cm_disp,
Size( 640, 480 ), 0, 0, INTER_LINEAR_EXACT );
imshow(
"cm disparity m", cm_disp );
Mat dst, thresholded_disp;
threshold( scaledDisparityMap, thresholded_disp, 0, 255, THRESH_OTSU + THRESH_BINARY );
resize( thresholded_disp, dst,
Size( 640, 480 ), 0, 0, INTER_LINEAR_EXACT );
imshow(
"threshold disp otsu", dst );
#ifdef HAVE_OPENCV_VIZ
Mat pointcloud_tresh, color_tresh;
pointcloud.
copyTo( pointcloud_tresh, thresholded_disp );
color.
copyTo( color_tresh, thresholded_disp );
myWindow.setBackgroundMeshLab();
myWindow.showWidget(
"pointcloud",
viz::WCloud( pointcloud_tresh, color_tresh ) );
myWindow.showWidget(
"text2d",
viz::WText(
"点云",
Point(20, 20), 20, viz::Color::green() ) );
myWindow.spin();
#endif
}
返回 0;
}
设计用于命令行解析。
定义 utility.hpp:820
用于遍历序列和映射。
定义 persistence.hpp:634
文件存储结点类。
定义 persistence.hpp:482
FileNodeIterator begin() const
返回指向第一个结点元素的迭代器
FileNodeIterator end() const
返回指向最后一个结点元素之后的元素的迭代器
XML/YAML/JSON 文件存储类,封装了所有必要的写入或读取信息...
定义 persistence.hpp:304
MatSize size
定义 mat.hpp:2160
void copyTo(OutputArray m) const
将矩阵复制到其他阵列。
uchar * data
指向数据的指针
定义 mat.hpp:2140
void convertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const
将阵列转换为另一种数据类型,并可以进行缩放。
用于 2D 矩形的模板类。
定义 types.hpp:444
用于指定图像或矩形的尺寸的模板类。
定义 types.hpp:335
Viz3d 类表示 3D 可视化窗口。此类是隐式共享的。
定义 viz3d.hpp:68
文本和小部件图像。
定义 widgets.hpp:408
void reprojectImageTo3D(InputArray disparity, OutputArray _3dImage, InputArray Q, bool handleMissingValues=false, int ddepth=-1)
将差异图像重新投影到 3D 空间。
void stereoRectify(InputArray cameraMatrix1, InputArray distCoeffs1, InputArray cameraMatrix2, InputArray distCoeffs2, Size imageSize, InputArray R, InputArray T, OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags=CALIB_ZERO_DISPARITY, double alpha=-1, Size newImageSize=Size(), Rect *validPixROI1=0, Rect *validPixROI2=0)
计算校准立体摄像机的每个头部的校正变换。
void initUndistortRectifyMap(InputArray cameraMatrix, InputArray distCoeffs, InputArray R, InputArray newCameraMatrix, Size size, int m1type, OutputArray map1, OutputArray map2)
计算无畸变和校正变换映射。
void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)
缩放,计算绝对值,并将结果转换为 8 位。
void minMaxIdx(InputArray src, double *minVal, double *maxVal=0, int *minIdx=0, int *maxIdx=0, InputArray mask=noArray())
在一个数组中查找全局最小值和最大值。
void min(InputArray src1, InputArray src2, OutputArray dst)
计算两个数组或一个数组和标量的每个元素的最小值。
void max(InputArray src1, InputArray src2, OutputArray dst)
计算两个数组或一个数组和标量的每个元素的最大值。
std::string String
定义 cvstd.hpp:151
std::shared_ptr< _Tp > Ptr
定义 cvstd_wrapper.hpp:23
#define CV_32FC1
定义 interface.h:118
void imshow(const String &winname, InputArray mat)
在指定的窗口中显示图像。
int waitKey(int delay=0)
等待按下某个键。
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR)
从文件中加载图像。
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
将图像从一种颜色空间转换为另一种颜色空间。
void applyColorMap(InputArray src, OutputArray dst, int colormap)
在给定的图像上应用 GNU Octave/MATLAB 等效的 colormap。
double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)
对每个数组元素应用固定级别的阈值。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
PyParams params(const std::string &tag, const std::string &model, const std::string &weights, const std::string &device)
磁盘上文件关联的文件存储的“黑盒”表示。
定义 core.hpp:102
StructuredLightPattern 构造函数的参数。
定义 graycodepattern.hpp:77
例如,本教程中使用的数据集使用投影仪捕获,分辨率为 1280x800,因此两个摄像机分别捕获了 42 幅模式图像(从编号 1 到 42)+ 1 幅白色(编号 43)和 1 幅黑色(编号 44)。
cout << "校正图像..." << endl;
stereoRectify( cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q, 0,
-1, imagesSize, &validRoi[0], &validRoi[1] );
Mat map1x, map1y, map2x, map2y;
initUndistortRectifyMap( cam1intrinsics, cam1distCoeffs, R1, P1, imagesSize,
CV_32FC1, map1x, map1y );
initUndistortRectifyMap( cam2intrinsics, cam2distCoeffs, R2, P2, imagesSize,
CV_32FC1, map2x, map2y );
........
对于( size_t i = 0; i < numberOfPatternImages; i++ )
{
........
remap( captured_pattern[1][i], captured_pattern[1][i], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( captured_pattern[0][i], captured_pattern[0][i], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
}
........
remap( color, color, map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( whiteImages[0], whiteImages[0], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( whiteImages[1], whiteImages[1], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( blackImages[0], blackImages[0], map2x, map2y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );
remap( blackImages[1], blackImages[1], map1x, map1y, INTER_NEAREST, BORDER_CONSTANT,
Scalar() );