本周主要任务02:Fusion 使用ICP进行逐帧融合
任务时间: 2014年9月8日-2014年9月14日
任务完成情况:
已实现将各帧融合到统一的第一帧所定义的摄像机坐标系下,但是由于部分帧之间的ICP融合结果 不佳,导致所有帧融合在统一坐标系下结果不好。
任务涉及基本方法:
1.exe文件当前目录搜索文件
程序文件:
fusion.cpp
1 //fusion.cpp 2 //函数:main() 3 //功能: 4 //输入: 5 //创建时间:2014/09/10 6 //最近更新时间:2014/09/16 7 //创建者:肖泽东 8 9 #include <iostream> 10 #include <fstream> 11 12 #include <pcl/io/pcd_io.h> 13 #include <pcl/io/io.h> 14 #include <pcl/point_cloud.h> 15 #include <pcl/console/parse.h> 16 #include <pcl/visualization/pcl_visualizer.h> 17 #include <pcl/registration/icp.h> 18 int state = 0; 19 bool next_flag = false; 20 21 //显示帮助 22 void showHelp(char* program_name) 23 { 24 std::cout << std::endl; 25 std::cout << "Usage: " << program_name << " sourcefile.pcd targetfile.pcd" << std::endl; 26 std::cout << "-h: Show this help." << std::endl; 27 } 28 29 //按键触发 30 void keyboardEventOccurred (const pcl::visualization::KeyboardEvent& event, 31 void* nothing) 32 { 33 if (event.getKeySym () == "space" && event.keyDown ()) //空格按键触发 34 { 35 state++; //状态标志 36 state = state % 4; //四种状态依次交替 37 next_flag = true; //允许变换到下一状态 38 } 39 } 40 41 int main(int argc, char** argv) 42 { 43 // 显示帮助文档 44 if(pcl::console::find_switch (argc,argv,"-h") || pcl::console::find_switch(argc,argv,"--help")) 45 { 46 showHelp(argv[0]); 47 return 0; 48 } 49 //搜索.xml文件名 50 fstream outFile; 51 char buffer[256]; 52 //std::string dir = "C:\Users\xzd\Documents\KinectFile\2014-09-07\Select\mengyue\"; 53 std::string dir = ".\pcdFiles\"; //在exe当前目录搜索文件夹(.\...) 54 std::string source_filename, target_filename; //定义ICP融合源文件和目标文件 55 outFile.open("pcdFileList.txt",ios::in); //打开保存各帧pcd文件的文件列表txt 56 57 Eigen::Matrix4f RT[100]; //定义矩阵数组保存各帧之间的坐标系变换矩阵 58 Eigen::Matrix4f RT2First[100]; //定义矩阵数组保存各帧到起始帧之间的坐标系变换矩阵 59 int index = 0; //定义帧索引 60 61 //定义配准源点云和目标点云 62 pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZ> ()); //源点云 63 pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZ> ()); //目标点云 64 pcl::PointCloud<pcl::PointXYZ>::Ptr aligned_cloud(new pcl::PointCloud<pcl::PointXYZ> ()); //配准对齐后点云 65 66 //ICP 配准定义 67 pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; //定义ICP类型实例icp 68 //设置ICP基本参数 69 icp.setMaxCorrespondenceDistance(100); //设置对应点容忍最大距离 70 icp.setMaximumIterations(20); //设置最大迭代次数 71 icp.setRANSACIterations(0); //不进行RANSAC迭代 72 73 outFile.getline(buffer,256,' '); //读取第一行,将该行数据存到buffer 74 target_filename = dir + buffer; //目标点云位置,第一帧点云为最初的目标点云 75 std::cout << target_filename << std::endl; 76 if(pcl::io::loadPCDFile(target_filename,*target_cloud) < 0) //导入目标点云 77 { 78 std::cout << "Error loading point cloud " << target_filename << std::endl; 79 showHelp(argv[0]); 80 return -1; 81 } 82 83 while(index < 20) //加入计算的帧数 84 { 85 outFile.getline(buffer,256,' '); //从第二行起,依次获取每行数据 86 source_filename = dir + buffer; //源点云位置,除第一帧点云外,其他帧依次作为其前一帧的ICP源点云 87 std::cout << source_filename << std::endl; // 88 89 if(pcl::io::loadPCDFile(source_filename,*source_cloud) < 0) //导入源点云 90 { 91 std::cout << "Error loading point cloud " << source_filename << std::endl; 92 showHelp(argv[0]); 93 return -1; 94 } 95 96 icp.setInputCloud(source_cloud); //初始化源点云 97 icp.setInputTarget(target_cloud); //初始化目标点云 98 99 icp.align(*aligned_cloud); //配准后点云 100 std::cout << "has converged:" << icp.hasConverged() << " score: " << 101 icp.getFitnessScore() << std::endl; //配准结果 102 103 RT[index] = icp.getFinalTransformation(); //将得到的ICP变换矩阵赋值给RT矩阵数组, 104 //由index索引,RT[0]表示第二帧点云向第一帧点云的变换矩阵 105 106 //计算所有点云向第一帧点云的变换,计算方法是相邻帧点云变换矩阵的累乘 107 if(index == 0) //如果第一个变换 108 RT2First[index] = RT[index]; //第二帧先第一帧的变换 109 else 110 RT2First[index] = RT[index] * RT2First[index-1]; //其他帧向第一帧的变换 111 112 index++; //转向下一变换 113 114 std::cout << icp.getFinalTransformation() << std::endl; //输出变换矩阵 115 *target_cloud = *source_cloud; //当前帧作为目标点云,下一次循环将使下一帧点云作为源点云 116 } 117 outFile.close(); //结束关闭pcd文件列表txt 118 std::cout << "Computer transform matrix completed" << std::endl; //提示变换矩阵计算完成信息 119 120 //测试各帧到第一帧的变换是否准确 121 target_filename = dir + "Depth0070.xml.pcd"; //目标帧:第一帧 122 source_filename = dir + "Depth0071.xml.pcd"; //源帧:可以是已计算的系列帧中任意一帧 123 124 if(pcl::io::loadPCDFile(source_filename,*source_cloud) < 0) //导入源点云 125 { 126 std::cout << "Error loading point cloud " << source_filename << std::endl; 127 showHelp(argv[0]); 128 return -1; 129 } 130 131 if(pcl::io::loadPCDFile(target_filename,*target_cloud) < 0) //导入目标点云 132 { 133 std::cout << "Error loading point cloud " << target_filename << std::endl; 134 showHelp(argv[0]); 135 return -1; 136 } 137 138 //执行变换 139 pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZ> ()); //定义变换后点云 140 pcl::PointCloud<pcl::PointXYZ>& Transform_cloud = *transformed_cloud; //点云 141 142 pcl::transformPointCloud (*source_cloud, *transformed_cloud,RT2First[0]); //执行变换 143 icp.setInputCloud(transformed_cloud); //初始化源点云 144 icp.setInputTarget(target_cloud); //初始化目标点云 145 //icp.align(*aligned_cloud); //执行融合,ICP 146 147 pcl::visualization::PCLVisualizer viewer ("ICP transform"); //定义显示对象实例 148 149 int v1 (0); //显示窗口分隔 150 int v2 (1); 151 viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1); //窗口分隔位置 creatViewPort(x_min,y_min,x_max,y_max,int &viewport) 152 viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2); 153 154 // Define R,G,B colors for the point cloud 155 pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source_cloud_color_handler (source_cloud, 255, 255, 255);//White 156 // We add the point cloud to the viewer and pass the color handler 157 viewer.addPointCloud (source_cloud, source_cloud_color_handler, "source_cloud_v1", v1); 158 159 pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> target_cloud_color_handler (target_cloud, 230, 20, 20); // Red 160 viewer.addPointCloud (target_cloud, target_cloud_color_handler, "target_cloud_v1", v1); 161 162 //viewer.addCoordinateSystem (1.0, "cloud", 0); 163 //viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey 164 viewer.setBackgroundColor(0.05, 0.05, 0.05, v1); 165 viewer.setBackgroundColor(0.05, 0.05, 0.05, v2); 166 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "source_cloud_v1"); 167 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "target_cloud_v1"); 168 //viewer.setPosition(800, 400); // Setting visualiser window position 169 170 // Define R,G,B colors for the point cloud 171 pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> transformed_cloud_color_handler (transformed_cloud, 255, 255, 255); //White 172 // We add the point cloud to the viewer and pass the color handler 173 viewer.addPointCloud (transformed_cloud, transformed_cloud_color_handler, "transformed_cloud_v2", v2); 174 viewer.addPointCloud (target_cloud, target_cloud_color_handler, "target_cloud_v2", v2); 175 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud_v2"); 176 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "target_cloud_v2"); 177 178 viewer.registerKeyboardCallback (&keyboardEventOccurred, (void*) NULL); //触发回调函数,查询按键 179 180 while(!viewer.wasStopped()) 181 { 182 viewer.spinOnce(); //窗口刷新 183 if(next_flag) 184 { 185 //std::cout << state << std::endl; 186 switch(state) 187 { 188 case 1: //状态1:只显示目标点云 189 viewer.removePointCloud("transformed_cloud_v2",v2); 190 std::cout << "Target Point Cloud" << std::endl; 191 break; 192 case 2: //状态2:将变换后点云加入到目标点云坐标系 193 viewer.addPointCloud (transformed_cloud, transformed_cloud_color_handler, "transformed_cloud_v2", v2); 194 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud_v2"); 195 std::cout << "All Point Cloud" << std::endl; 196 break; 197 case 3: //状态3:移除目标点云,只显示变换后点云 198 viewer.removePointCloud("target_cloud_v2",v2); 199 std::cout << "Transformed Point Cloud" << std::endl; 200 break; 201 case 0: //状态0:全部显示 202 viewer.addPointCloud (target_cloud, target_cloud_color_handler, "target_cloud_v2", v2); 203 viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "target_cloud_v2"); 204 std::cout << "All Point Cloud" << std::endl; 205 break; 206 default: 207 break; 208 } 209 next_flag = false; //禁止进行下一次变换 210 } 211 } 212 return 0; 213 }
CMakeLists.txt
1 cmake_minimum_required(VERSION 2.6 FATAL_ERROR) 2 3 project(Fusion_Project) 4 5 find_package(PCL 1.6 REQUIRED) 6 7 include_directories(${PCL_INCLUDE_DIRS}) 8 link_directories(${PCL_LIBRARY_DIRS}) 9 add_definitions(${PCL_DEFINITIONS}) 10 11 add_executable (fusion fusion.cpp) 12 target_link_libraries (fusion ${PCL_LIBRARIES})