├── Dataset └── dataset ├── example ├── result1.png └── result2.png ├── CMakeLists.txt ├── include ├── matcher.hpp ├── registration.hpp ├── neighborhood.hpp ├── toolfile.hpp └── pointCloudMapping.hpp ├── LICENSE ├── README.md └── src ├── main.cpp ├── neighborhood.cpp ├── matcher.cpp ├── registration.cpp ├── toolfile.cpp └── pointCloudMapping.cpp /Dataset/dataset: -------------------------------------------------------------------------------- 1 | download the dataset and save the files here 2 | -------------------------------------------------------------------------------- /example/result1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeformRobotics/semantic-histogram-based-global-localization/HEAD/example/result1.png -------------------------------------------------------------------------------- /example/result2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeformRobotics/semantic-histogram-based-global-localization/HEAD/example/result2.png -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(CMAKE_BUILD_TYPE Release) 4 | set(DCMAKE_BUILD_TYPE Release) 5 | 6 | project(mapAlignment) 7 | 8 | find_package(PCL REQUIRED) 9 | include_directories(${PCL_INCLUDE_DIRS}) 10 | add_definitions(${PCL_DEFINITIONS}) 11 | 12 | find_package(OpenCV REQUIRED) 13 | include_directories(${OpenCV_INCLUDE_DIRS}) 14 | 15 | find_package(Eigen3 REQUIRED) 16 | include_directories(${EIGEN3_INCLUDE_DIRS}) 17 | 18 | find_package(Pangolin REQUIRED) 19 | include_directories(${Pangolin_INCLUDE_DIRS}) 20 | 21 | include_directories(${PROJECT_SOURCE_DIR}/include) 22 | 23 | FILE(GLOB SRC_FILES "src/*.cpp") 24 | 25 | 26 | add_executable(mapAlignment ${SRC_FILES}) 27 | 28 | target_link_libraries(mapAlignment ${PCL_LIBRARIES} ${Pangolin_LIBRARIES} ${OpenCV_LIBS} ${EIGEN3_LIBRARIES}) 29 | 30 | -------------------------------------------------------------------------------- /include/matcher.hpp: -------------------------------------------------------------------------------- 1 | #ifndef matcher_hpp 2 | #define matcher_hpp 3 | 4 | #include "opencv2/opencv.hpp" 5 | #include "opencv2/core.hpp" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include "neighborhood.hpp" 13 | 14 | 15 | using namespace cv; 16 | using namespace std; 17 | using namespace Eigen; 18 | 19 | class matcher 20 | { 21 | public: 22 | matcher(Descriptor Ds1, Descriptor Ds2); 23 | matcher(Descriptor Ds1, Descriptor Ds2, int type); 24 | ~matcher(); 25 | MatrixXf scoreMatrix; 26 | MatrixXi getMatcherID(); 27 | MatrixXi getGoodMatcher(); 28 | 29 | private: 30 | int size1; 31 | int size2; 32 | VectorXf noNei; 33 | }; 34 | 35 | #endif /* pointCloudMapping */ 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Freeform Robotics 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # semantic-histogram-based-global-localization 2 | The global localization system based on semantic information 3 | 4 | paper link: https://arxiv.org/abs/2010.09297 or https://ieeexplore.ieee.org/document/9353207/ 5 | 6 | Results 7 | - 8 | ![](https://github.com/gxytcrc/Semantic-Graph-based--global-Localization/blob/main/example/result1.png) 9 | ![](https://github.com/gxytcrc/Semantic-Graph-based--global-Localization/blob/main/example/result2.png) 10 | 11 | # 1. Prerequisites # 12 | * Ubuntu 13 | * CMake 14 | * Eigen 15 | * Pangolin 16 | * OpenCV 17 | * PCL 18 | 19 | # 2. Running # 20 | Clone the repository and catkin_make: 21 | ``` 22 | git clone https://https://github.com/FreeformRobotics/Semantic-Graph-based--global-Localization.git 23 | mkdir build 24 | cd build 25 | cmake .. 26 | catkin_make 27 | ``` 28 | Download the dataset that is created from Airsim, and save them into the Datset . Download link: https://drive.google.com/file/d/1PIuRyah6lKDTe_YJ6HSVRX4l7MQLwKq5/view?usp=sharing. 29 | 30 | Launch it as follows: 31 | ``` 32 | ./mapAlignment robot1-foldername startFrameNumber endFrameNumber robot2-foldername startFrameNumber endFrameNumber 33 | ``` 34 | -------------------------------------------------------------------------------- /include/registration.hpp: -------------------------------------------------------------------------------- 1 | #ifndef registration_hpp 2 | #define registration_hpp 3 | 4 | 5 | #include "opencv2/opencv.hpp" 6 | #include "opencv2/core.hpp" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace cv; 17 | using namespace std; 18 | using namespace Eigen; 19 | 20 | class registration 21 | { 22 | public: 23 | registration(vector > centerpoint1, vector > centerpoint2, MatrixXi matcherID); 24 | ~registration(); 25 | void matcherRANSAC(float Td); 26 | void Alignment(); 27 | MatrixXi inlierID; 28 | MatrixXf Rotation, Translation; 29 | 30 | private: 31 | MatrixXf sourcePoints; 32 | MatrixXf targetPoints; 33 | MatrixXf sourceInliers; 34 | MatrixXf targetInliers; 35 | MatrixXi totalID; 36 | VectorXi inlierTotalID; 37 | VectorXi labelVector; 38 | 39 | }; 40 | 41 | void getTransform(MatrixXf source, MatrixXf target); 42 | #endif /* pointCloudMapping */ 43 | -------------------------------------------------------------------------------- /include/neighborhood.hpp: -------------------------------------------------------------------------------- 1 | #ifndef neighborhood_hpp 2 | #define neighborhood_hpp 3 | 4 | #include "opencv2/opencv.hpp" 5 | #include "opencv2/core.hpp" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | 18 | using namespace cv; 19 | using namespace std; 20 | using namespace Eigen; 21 | 22 | class Neighborhood 23 | { 24 | public: 25 | Neighborhood(vector > Cpoint); 26 | ~Neighborhood(); 27 | MatrixXf getNeighbor(); 28 | VectorXf label; 29 | private: 30 | vector > centerpoint; 31 | 32 | }; 33 | 34 | class Descriptor 35 | { 36 | public: 37 | Descriptor(Neighborhood Nei, int stepNumber, int stepLengh); 38 | Descriptor(Neighborhood Nei); 39 | Descriptor(Neighborhood Nei, int Histogram); 40 | ~Descriptor(); 41 | MatrixXf getDescriptor(int DesID); 42 | void draw(int DesID, Mat lab); 43 | int size(); 44 | int SL; 45 | int SN; 46 | VectorXf noNeighbor; 47 | VectorXf labelVector; 48 | 49 | 50 | private: 51 | MatrixXf neighbor; 52 | vector DescriptorVector; 53 | }; 54 | 55 | 56 | 57 | #endif /* pointCloudMapping */ 58 | -------------------------------------------------------------------------------- /include/toolfile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef vo_hpp 2 | #define vo_hpp 3 | 4 | #include "opencv2/video/tracking.hpp" 5 | #include "opencv2/imgproc/imgproc.hpp" 6 | #include "opencv2/highgui/highgui.hpp" 7 | #include "opencv2/features2d/features2d.hpp" 8 | #include "opencv2/calib3d/calib3d.hpp" 9 | #include 10 | #include 11 | 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "pointCloudMapping.hpp" 26 | 27 | 28 | using namespace cv; 29 | using namespace std; 30 | using namespace Eigen; 31 | 32 | void insertPose(string&dir, Mat &pose, int number); 33 | void insertSYNTIAPose(string&dir, Mat&pose, int number); 34 | 35 | cv::Mat Quaternion2Matrix (cv::Mat q); 36 | 37 | void gatherPointCloudData(pcl::PointCloud::Ptr& cloud, vector >& centerpoint, Mat pose, Mat Label, vector label_gray, vector camera, float scale, string dir, int fileNumber, int startpoint); 38 | void gatherDenseMap(pcl::PointCloud::Ptr& cloud, vector >& centerpoint, Mat pose, Mat Label, vector camera, float scale, string dir, int fileNumber, int type); 39 | void calculateGroundTruth(Mat pose1, Mat pose2, MatrixXf Rotation, MatrixXf translation, Matrix4f& T); 40 | void matchingEvaluation(vector > Cpoint1, vector > Cpoint2, MatrixXi matcherID, MatrixXi InlierID, float& Pvalue, float& Rvalue, float& Pcount1); 41 | void outputCenterpoint(vector >& centerpoint, string txtname); 42 | void inputCenterpoint(vector >& centerpoint, int number, string txtname); 43 | 44 | 45 | #endif /* pointCloudMapping */ 46 | -------------------------------------------------------------------------------- /include/pointCloudMapping.hpp: -------------------------------------------------------------------------------- 1 | #ifndef pointCloudMapping_hpp 2 | #define pointCloudMapping_hpp 3 | 4 | #include "opencv2/opencv.hpp" 5 | #include "opencv2/core.hpp" 6 | #include "opencv2/flann.hpp" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "toolfile.hpp" 24 | 25 | 26 | 27 | using namespace cv; 28 | using namespace std; 29 | using namespace pcl; 30 | using namespace Eigen; 31 | 32 | struct pointCloudMapping 33 | { 34 | public: 35 | 36 | void insertValue(pcl::PointCloud::Ptr&insertCloud, Mat&depthmap, Mat&image1, Matrix4f&TransformsValue, vector&camera, float scale, vector > Centerpoint, Mat Labels); 37 | void initialize3Dmap(int type); 38 | void pointCloudFilter(); 39 | void pointExtraction(vector label); 40 | void pointExtraction(vector label, Mat labelimag); 41 | void pointVisuallize(pcl::PointCloud::Ptr&insertCloud1, pcl::PointCloud::Ptr&insertCloud2, MatrixXi matcherID, MatrixXf R, MatrixXf T); 42 | vector > Cpoint; 43 | pcl::PointCloud::Ptr outputPointCloud(); 44 | 45 | private: 46 | pcl::PointCloud::Ptr Cloud; 47 | pcl::PointCloud::Ptr GlobalCloud; 48 | Matrix4f T = Matrix4f::Identity(); 49 | Mat depth; 50 | Mat image; 51 | Mat LabelValue; 52 | float fx; 53 | float fy; 54 | float cx; 55 | float cy; 56 | float baseline; 57 | float s; 58 | }; 59 | 60 | #endif /* pointCloudMapping */ 61 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "pointCloudMapping.hpp" 2 | #include "neighborhood.hpp" 3 | #include "toolfile.hpp" 4 | #include 5 | #include 6 | #include "matcher.hpp" 7 | #include "registration.hpp" 8 | 9 | 10 | using namespace cv; 11 | using namespace std; 12 | using namespace Eigen; 13 | 14 | 15 | int main(int argc, const char * argv[]) 16 | { 17 | if(argc!=7) 18 | { 19 | cout << "usage: ./SLAM_Project address frameCount" << endl; 20 | return 1; 21 | } 22 | 23 | char file_name1[1024]; 24 | char fullpath1[1024]; 25 | char file_name2[1024]; 26 | char fullpath2[1024]; 27 | 28 | sprintf(file_name1, "%s/", argv[1]); 29 | sprintf(fullpath1,"../Dataset/%s",file_name1); 30 | int startPoint1 = atoi(argv[2]); 31 | int fileNumber1 = atoi(argv[3]); 32 | cout<<"file number is: "< camera(4); 42 | float scale = 1; 43 | camera[0] = 512; //fx 44 | camera[1] = 512; //fy 45 | camera[2] = 512; //cx 46 | camera[3] = 288;//cy 47 | 48 | //iniltialize the R and T 49 | MatrixXf R, T; 50 | R.setIdentity(); 51 | T.setZero(); 52 | 53 | //create the value for visual odometry 54 | Mat frame_pose = cv::Mat::eye(4, 4, CV_64F); 55 | pcl::PointCloud::Ptr cloud2(new pcl::PointCloud); 56 | pcl::PointCloud::Ptr cloud1(new pcl::PointCloud); 57 | 58 | Mat pose1 = cv::Mat::zeros(1000, 7, CV_64FC1); 59 | Mat pose2 = cv::Mat::zeros(1000, 7, CV_64FC1); 60 | 61 | //generate the correspondent rgb value of all labels in the segmentation image 62 | Mat Label = (cv::Mat_(11, 3)<< 175, 6, 140, 63 | 65, 54, 217, 64 | 156, 198, 23, 65 | 184, 145, 182, 66 | 211, 80, 208, 67 | 232, 250, 80, 68 | 234, 20, 250, 69 | 99, 242, 104, 70 | 142, 1, 246, 71 | 81, 13, 36, 72 | 112, 105, 191); 73 | 74 | //Obtain the label number 75 | vector label_gray(11); 76 | label_gray[0] = 72; label_gray[1] = 76; label_gray[2] = 165; label_gray[3] = 161; label_gray[4] = 134; 77 | label_gray[5] = 225; label_gray[6] = 110; label_gray[7] = 184; label_gray[8] = 71; label_gray[9] = 36; 78 | label_gray[10] = 117; 79 | 80 | //insert the odeometry value 81 | insertPose(dir1,pose1, 1000); 82 | insertPose(dir2,pose2, 1000); 83 | 84 | //initiallize the intial value of the keypoint; 85 | vector > centerpoint2; 86 | vector > centerpoint1; 87 | 88 | gatherPointCloudData(cloud1, centerpoint1, pose1, Label, label_gray, camera, scale, dir1, fileNumber1, startPoint1); 89 | gatherPointCloudData(cloud2, centerpoint2, pose2, Label, label_gray, camera, scale, dir2, fileNumber2, startPoint2); 90 | 91 | //add the edge between the neighborhood 92 | Neighborhood Nei1(centerpoint1); 93 | 94 | //MatrixXf neighbor; 95 | Neighborhood Nei2(centerpoint2); 96 | //neighbor = Nei2.getNeighbor(); 97 | //cout< > Cpoint){ 4 | cout<<"Neighborhood construct"< cp(4); 9 | cp[0] = Cpoint[i][0]; cp[1] = Cpoint[i][1]; cp[2] = Cpoint[i][2]; cp[3] = Cpoint[i][3]; 10 | label(i) = cp[3]; 11 | centerpoint.push_back(cp); 12 | } 13 | } 14 | 15 | Neighborhood::~Neighborhood(){ 16 | cout<<"The Neighborhood object destroyed"< neighborID; 84 | for(int IDnum = 0; IDnum neighborID; 121 | for(int NeiNum = 0; NeiNum neighborID; 155 | for(int NeiNum = 0; NeiNum(label, 0); 222 | int G = lab.at(label, 1); 223 | int B = lab.at(label, 2); 224 | for(int pointi = startPointi; pointi(pointi, pointj)[0] = B; 227 | DescriptorPlot.at(pointi, pointj)[1] = G; 228 | DescriptorPlot.at(pointi, pointj)[2] = R; 229 | } 230 | } 231 | } 232 | } 233 | imshow("descriptor", DescriptorPlot); 234 | waitKey(1000000); 235 | } 236 | 237 | int Descriptor::size(){ 238 | int des_size = DescriptorVector.size(); 239 | return des_size; 240 | } 241 | -------------------------------------------------------------------------------- /src/matcher.cpp: -------------------------------------------------------------------------------- 1 | #include "matcher.hpp" 2 | #include "neighborhood.hpp" 3 | 4 | //Random walk decriptor matching 5 | matcher::matcher(Descriptor Ds1, Descriptor Ds2){ 6 | cout<<"matcher constructed"<maxScore){ 219 | maxScore = scoreMatrix(i, j); 220 | ID = j; 221 | } 222 | } 223 | matcherID(i, 1) = ID; 224 | } 225 | return matcherID; 226 | } 227 | 228 | MatrixXi matcher::getGoodMatcher(){ 229 | MatrixXi matcherID(size1, 3); 230 | MatrixXi goodMatcherId; 231 | matcherID.setZero(); 232 | int count = 0; 233 | for(int i =0; imaxScore){ 243 | secondMaxScore = maxScore; 244 | maxScore = scoreMatrix(i, j); 245 | ID = j; 246 | } 247 | 248 | } 249 | if(maxScore<0.5){ 250 | //cout<<"no good score"<InverseScore){ 263 | InverseScore = scoreMatrix(IDi, ID); 264 | InverseID = IDi; 265 | //cout<<"maxmum score: "< > centerpoint1, vector > centerpoint2, MatrixXi matcherID){ 4 | int size = matcherID.rows(); 5 | sourcePoints.resize(size, 3); 6 | targetPoints.resize(size, 3); 7 | labelVector.resize(size, 1); 8 | totalID.resize(size, 2); 9 | totalID = matcherID; 10 | //generate the source cloud and target cloud 11 | for(int i=0; i svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV); 90 | Eigen::Matrix3f V = svd.matrixV(), U = svd.matrixU(); 91 | R0 = V * U.transpose(); 92 | T0 = avergae_target.transpose() - R0 * (avergae_source.transpose()); 93 | 94 | for (int i = 0; i < source.rows(); i++) { 95 | source.row(i) = (R0*source.row(i).transpose() + T0).transpose(); 96 | } 97 | R = R0 * R; 98 | T = T0 + T; 99 | 100 | } 101 | 102 | } 103 | 104 | void getWeightedTransform(MatrixXf source, MatrixXf target, MatrixXf& R, MatrixXf& T, VectorXf labelVector, int iteNum){ 105 | 106 | int size = source.rows(); 107 | MatrixXf avergae_source(1, 3); 108 | MatrixXf avergae_target(1, 3); 109 | MatrixXf A(3, 3); 110 | 111 | MatrixXf R0(3, 3); 112 | MatrixXf T0(3, 1); 113 | 114 | R.resize(3, 3); 115 | T.resize(3, 1); 116 | 117 | R.setIdentity(); 118 | T.setZero(); 119 | 120 | int count = 0; 121 | for(int i =0; i svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV); 211 | Eigen::Matrix3f V = svd.matrixV(), U = svd.matrixU(); 212 | R0 = V * U.transpose(); 213 | T0 = avergae_target.transpose() - R0 * (avergae_source.transpose()); 214 | 215 | for (int i = 0; i < new_source.rows(); i++) { 216 | new_source.row(i) = (R0*new_source.row(i).transpose() + T0).transpose(); 217 | } 218 | R = R0 * R; 219 | T = T0 + T; 220 | 221 | } 222 | 223 | } 224 | 225 | void registration::matcherRANSAC(float Td){ 226 | //generate the random points for Ransac processing 227 | MatrixXf sourceRandom(4, 3); 228 | MatrixXf targetRandom(4, 3); 229 | //get the time value for obtaining the random points 230 | clock_t startTime,endTime; 231 | startTime = clock(); 232 | 233 | int totalNum = sourcePoints.rows(); 234 | int maxCount = 0; 235 | 236 | //initialize the inlier ID 237 | inlierID.resize(1,2); 238 | inlierID.setZero(); 239 | for(int iter=0; iter<1000; iter++){ 240 | endTime = clock(); 241 | int timedifference = (int)((endTime - startTime)*10000); 242 | srand((int)time(0)+timedifference); 243 | 244 | //obtain the random points 245 | int Count = sourcePoints.rows(); 246 | for(int i=0; i<4; i++){ 247 | int randomNum = rand()%Count; 248 | sourceRandom.row(i) = sourcePoints.row(randomNum); 249 | targetRandom.row(i) = targetPoints.row(randomNum); 250 | } 251 | 252 | //calculate the R and T 253 | MatrixXf R, T; 254 | getTransform(sourceRandom, targetRandom, R, T, 1); 255 | // cout<<"R:"< inliers; 263 | for(int i=0; i>N; 17 | int count = 0; 18 | for(int i=0;i>a[i]>>b[i]>>c[i]>>d[i]>>e[i]>>f[i]>>g[i]; 21 | //cout<(i, 0) = a[i]; 24 | pose.at(i, 1) = b[i]; 25 | pose.at(i, 2) = c[i]; 26 | pose.at(i, 3) = d[i]; 27 | pose.at(i, 4) = e[i]; 28 | pose.at(i, 5) = f[i]; 29 | pose.at(i, 6) = g[i]; 30 | 31 | 32 | } 33 | myfile.close(); 34 | } 35 | 36 | void insertSYNTIAPose(string&dir, Mat&pose, int number){ 37 | 38 | double a[number]; 39 | double b[number]; 40 | double c[number]; 41 | double d[number]; 42 | double e[number]; 43 | double f[number]; 44 | double g[number]; 45 | double h[number]; 46 | double i1[number]; 47 | double j[number]; 48 | double k[number]; 49 | double l[number]; 50 | double m[number]; 51 | double n[number]; 52 | double o[number]; 53 | double p[number]; 54 | 55 | string txtname = dir+"synthia.txt"; 56 | ifstream myfile(txtname); 57 | int N; 58 | myfile>>N; 59 | int count = 0; 60 | for(int i=0;i>a[i]>>b[i]>>c[i]>>d[i]>>e[i]>>f[i]>>g[i]>>h[i]>>i1[i]>>j[i]>>k[i]>>l[i]>>m[i]>>n[i]>>o[i]>>p[i]; 63 | //cout<(i, 0) = a[i]; 66 | pose.at(i, 1) = b[i]; 67 | pose.at(i, 2) = c[i]; 68 | pose.at(i, 3) = d[i]; 69 | pose.at(i, 4) = e[i]; 70 | pose.at(i, 5) = f[i]; 71 | pose.at(i, 6) = g[i]; 72 | pose.at(i, 7) = h[i]; 73 | pose.at(i, 8) = i1[i]; 74 | pose.at(i, 9) = j[i]; 75 | pose.at(i, 10) = k[i]; 76 | pose.at(i, 11) = l[i]; 77 | pose.at(i, 12) = m[i]; 78 | pose.at(i, 13) = n[i]; 79 | pose.at(i, 14) = o[i]; 80 | pose.at(i, 15) = p[i]; 81 | 82 | 83 | 84 | } 85 | myfile.close(); 86 | } 87 | 88 | void outputCenterpoint(vector >& centerpoint, string txtname){ 89 | ofstream outfile; 90 | outfile.open(txtname); 91 | int size = centerpoint.size(); 92 | for(int i =0; i >& centerpoint, int number, string txtname){ 103 | ifstream myfile(txtname); 104 | int N; 105 | myfile>>N; 106 | int count = 0; 107 | for(int i=0;i>x>>y>>z>>l; 111 | vector cp(4); 112 | cp[0] = x; cp[1] = y; cp[2] = z; cp[3] = l; 113 | cout<(0); 125 | double x = q.at(1); 126 | double y = q.at(2); 127 | double z = q.at(3); 128 | 129 | double xx = x*x; 130 | double yy = y*y; 131 | double zz = z*z; 132 | double xy = x*y; 133 | double wz = w*z; 134 | double wy = w*y; 135 | double xz = x*z; 136 | double yz = y*z; 137 | double wx = w*x; 138 | 139 | double ret[4][4]; 140 | ret[0][0] = 1.0f-2*(yy+zz); 141 | ret[0][1] = 2*(xy-wz); 142 | ret[0][2] = 2*(wy+xz); 143 | ret[0][3] = 0.0f; 144 | 145 | ret[1][0] = 2*(xy+wz); 146 | ret[1][1] = 1.0f-2*(xx+zz); 147 | ret[1][2] = 2*(yz-wx); 148 | ret[1][3] = 0.0f; 149 | 150 | ret[2][0] = 2*(xz-wy); 151 | ret[2][1] = 2*(yz+wx); 152 | ret[2][2] = 1.0f-2*(xx+yy); 153 | ret[2][3] = 0.0f; 154 | 155 | ret[3][0] = 0.0f; 156 | ret[3][1] = 0.0f; 157 | ret[3][2] = 0.0f; 158 | ret[3][3] = 1.0f; 159 | 160 | return cv::Mat(4,4,CV_64FC1,ret).clone(); 161 | } 162 | 163 | Matrix4f obtainTransformMatrix(Mat pose, int i, int type){ 164 | Matrix4f frame_pose = Matrix4f::Identity(); 165 | if(type == 1){ 166 | Mat q = cv::Mat::zeros(4, 1, CV_64FC1); 167 | q.at(0,0) = pose.at(i, 3); 168 | q.at(0,1) = pose.at(i, 4); 169 | q.at(0,2) = pose.at(i, 5); 170 | q.at(0,3) = pose.at(i, 6); 171 | Mat rotation = cv::Mat::zeros(4, 4, CV_64FC1); 172 | rotation = Quaternion2Matrix (q); 173 | for(int row = 0; row<3; row++){ 174 | for(int col=0; col<3; col++){ 175 | frame_pose(row, col) = rotation.at(row, col); 176 | } 177 | } 178 | frame_pose(0,3) = pose.at(i, 0); 179 | frame_pose(1,3) = pose.at(i, 1); 180 | frame_pose(2,3) = pose.at(i, 2); 181 | } 182 | else{ 183 | 184 | int count = 0; 185 | for(int col = 0; col<4; col++){ 186 | for(int row=0; row<4; row++){ 187 | frame_pose(row, col) = pose.at(i, count); 188 | count = count + 1; 189 | } 190 | } 191 | 192 | } 193 | return frame_pose; 194 | } 195 | 196 | void gatherPointCloudData(pcl::PointCloud::Ptr& cloud, vector >& centerpoint, Mat pose, Mat Label, vector label_gray, vector camera, float scale, string dir, int fileNumber, int startpoint){ 197 | //init the pointcloud mapping structure 198 | pointCloudMapping pointCloudMapping; 199 | //initiallize the frame pose 200 | Matrix4f frame_pose = Matrix4f::Identity(); 201 | Matrix4f frame_pose0 = Matrix4f::Identity(); 202 | Matrix4f camera_pose = Matrix4f::Identity(); 203 | 204 | for(int i =startpoint; i::Ptr& cloud, vector >& centerpoint, Mat pose, Mat Label, vector camera, float scale, string dir, int fileNumber, int type){ 243 | //init the pointcloud mapping structure 244 | pointCloudMapping pointCloudMapping; 245 | //initiallize the frame pose 246 | Matrix4f frame_pose = Matrix4f::Identity(); 247 | Matrix4f frame_pose0 = Matrix4f::Identity(); 248 | Matrix4f camera_pose = Matrix4f::Identity(); 249 | pcl::visualization::CloudViewer viewer("viewer"); 250 | 251 | for(int i =0; i > Cpoint1, vector > Cpoint2, MatrixXi matcherID, MatrixXi InlierID, float& Pvalue, float& Rvalue, float& Pcount1){ 281 | int size0 = matcherID.rows(); 282 | float Pcount0 = 0; float Ncount0 = 0; 283 | for(int i = 0; i=10){ 295 | Ncount0 = Ncount0 + 1; 296 | } 297 | } 298 | int size1 = InlierID.rows(); 299 | Pcount1 = 0; float Ncount1 = 0; 300 | for(int i = 0; i=10){ 312 | Ncount1 = Ncount1 + 1; 313 | } 314 | } 315 | Pvalue = Pcount1/(Pcount1 + Ncount1); 316 | Rvalue = Pcount1/(Pcount0); 317 | float rate = Pcount1/(Pcount0+Ncount0); 318 | cout<<"Pvalue: "<(0, 0); 332 | frame_pose1(1,3) = pose1.at(0, 1); 333 | frame_pose1(2,3) = pose1.at(0, 2); 334 | Mat q1 = cv::Mat::zeros(4, 1, CV_64FC1); 335 | q1.at(0,0) = pose1.at(0, 3); 336 | q1.at(0,1) = pose1.at(0, 4); 337 | q1.at(0,2) = pose1.at(0, 5); 338 | q1.at(0,3) = pose1.at(0, 6); 339 | 340 | Mat rotation1 = cv::Mat::zeros(4, 4, CV_64FC1); 341 | rotation1 = Quaternion2Matrix (q1); 342 | for(int row = 0; row<3; row++){ 343 | for(int col=0; col<3; col++){ 344 | frame_pose1(row, col) = rotation1.at(row, col); 345 | } 346 | } 347 | 348 | frame_pose2(0,3) = pose2.at(0, 0); 349 | frame_pose2(1,3) = pose2.at(0, 1); 350 | frame_pose2(2,3) = pose2.at(0, 2); 351 | Mat q2 = cv::Mat::zeros(4, 1, CV_64FC1); 352 | q2.at(0,0) = pose2.at(0, 3); 353 | q2.at(0,1) = pose2.at(0, 4); 354 | q2.at(0,2) = pose2.at(0, 5); 355 | q2.at(0,3) = pose2.at(0, 6); 356 | 357 | Mat rotation2 = cv::Mat::zeros(4, 4, CV_64FC1); 358 | rotation2 = Quaternion2Matrix (q2); 359 | for(int row = 0; row<3; row++){ 360 | for(int col=0; col<3; col++){ 361 | frame_pose2(row, col) = rotation2.at(row, col); 362 | } 363 | } 364 | 365 | GT = frame_pose1.inverse()*frame_pose2; 366 | 367 | for(int row = 0; row<3; row++){ 368 | for(int col=0; col<3; col++){ 369 | ownPose(row, col) = Rotation(row, col); 370 | } 371 | } 372 | ownPose(0, 3) = translation(0, 0); 373 | ownPose(1, 3) = translation(1, 0); 374 | ownPose(2, 3) = translation(2, 0); 375 | 376 | T = GT * ownPose.inverse(); 377 | 378 | } 379 | 380 | -------------------------------------------------------------------------------- /src/pointCloudMapping.cpp: -------------------------------------------------------------------------------- 1 | #include "pointCloudMapping.hpp" 2 | 3 | void showPointCloud( 4 | const vector> &pointcloud); 5 | 6 | 7 | void pointCloudMapping::insertValue(pcl::PointCloud::Ptr&insertCloud, Mat&depthmap, Mat&image1, Matrix4f&TransformsValue, vector&camera, float scale, vector > Centerpoint, Mat Labels){ 8 | //cout<<"received the depth map, start generate the point cloud"<>( ); 23 | GlobalCloud = pcl::make_shared>( ); 24 | *GlobalCloud = *insertCloud; 25 | //cout<<"global size: "<points.size()<width = depth.cols*depth.rows; 32 | // cloud->height = 1; 33 | // cloud->points.resize (cloud->width * cloud->height); 34 | pcl::PointCloud::Ptr temp(new pcl::PointCloud); 35 | cout<<"type: "<(i, j))/255)*100; 57 | if(Dep > 50){ 58 | continue; 59 | } 60 | 61 | //cout<(i, j)[0]; 73 | g= image.at(i, j)[1]; 74 | r = image.at(i, j)[2]; 75 | 76 | 77 | unsigned char R= r; 78 | unsigned char G= g; 79 | unsigned char B= b; 80 | 81 | uint8_t rp = r; 82 | uint8_t gp = g; 83 | uint8_t bp = b; 84 | uint32_t rgb = ((uint32_t )rp<<16 | (uint32_t )gp<<8 | (uint32_t )bp); 85 | point.rgb = *reinterpret_cast(&rgb); 86 | 87 | temp->push_back(point); 88 | } 89 | } 90 | transformPointCloud (*temp, *temp, T); 91 | //cout<points.size()<<" points"<& centerX, vector& centerY, 111 | pcl::PointCloud::Ptr temp, vector >& Cpoint, int lab, Mat LabelValue, Matrix4f T) 112 | { 113 | 114 | 115 | if (binImg.empty() || 116 | binImg.type() != CV_8UC1) 117 | { 118 | return; 119 | } 120 | 121 | lableImg.release(); 122 | binImg.convertTo(lableImg, CV_32SC1); 123 | 124 | //cout<(i); 138 | for (int j = 1; j < cols-1; j++) 139 | { 140 | if (data[j] == 255) 141 | { 142 | std::stack> neighborPixels; 143 | neighborPixels.push(std::pair(i,j)); 144 | label = label + 1; 145 | if(label == 255){ 146 | label = label+1; 147 | } 148 | int count = 0; 149 | float sumX = 0; 150 | float sumY = 0; 151 | float sum3dX = 0; 152 | float sum3dY = 0; 153 | float sum3dZ = 0; 154 | // cout<<"j: "< curPixel = neighborPixels.top(); 158 | int curX = curPixel.first; 159 | int curY = curPixel.second; 160 | imgClone.at(curX, curY) = label; 161 | 162 | neighborPixels.pop(); 163 | float Dep0, Dep1, Dep2, Dep3, Dep4; 164 | Dep0 = (float(depthClone.at(curX, curY))/255)*100; 165 | Dep1 = (float(depthClone.at(curX, curY-1))/255)*100; 166 | Dep2 = (float(depthClone.at(curX, curY+1))/255)*100; 167 | Dep3 = (float(depthClone.at(curX-1, curY))/255)*100; 168 | Dep4 = (float(depthClone.at(curX+1, curY))/255)*100; 169 | 170 | if (imgClone.at(curX, curY-1) == 255 && abs(Dep0 - Dep1)<1) 171 | { 172 | neighborPixels.push(std::pair(curX, curY-1)); 173 | } 174 | if (imgClone.at(curX, curY+1) == 255 && abs(Dep0 - Dep2)<1) 175 | { 176 | neighborPixels.push(std::pair(curX, curY+1)); 177 | } 178 | if (imgClone.at(curX-1, curY) == 255 && abs(Dep0 - Dep3)<1) 179 | { 180 | neighborPixels.push(std::pair(curX-1, curY)); 181 | } 182 | if (imgClone.at(curX+1, curY) == 255 && abs(Dep0 - Dep4)<1) 183 | { 184 | neighborPixels.push(std::pair(curX+1, curY)); 185 | } 186 | // if (imgClone.at(curX+1, curY+1) == 255) 187 | // { 188 | // neighborPixels.push(std::pair(curX+1, curY+1)); 189 | // } 190 | // if (imgClone.at(curX+1, curY-1) == 255) 191 | // { 192 | // neighborPixels.push(std::pair(curX+1, curY-1)); 193 | // } 194 | // if (imgClone.at(curX-1, curY-1) == 255) 195 | // { 196 | // neighborPixels.push(std::pair(curX-1, curY-1)); 197 | // } 198 | // if (imgClone.at(curX-1, curY+1) == 255) 199 | // { 200 | // neighborPixels.push(std::pair(curX-1, curY+1)); 201 | // } 202 | 203 | //generate 2D center 204 | float u0 = (float)curY; 205 | float v0 = (float)curX; 206 | u0 = u0-1; 207 | v0 = v0-1; 208 | sumX = sumX + u0; 209 | sumY = sumY + v0; 210 | // if(count >8070 && count<8100){ 211 | // cout<<"count: "<(curX, curY))/255)*100; 222 | if(Dep > 30){ 223 | continue; 224 | } 225 | count = count + 1; 226 | //cout<5000){ 236 | float averageXf = sumX / count; 237 | float averageYf = sumY / count; 238 | int aveX = (int)averageXf; 239 | int aveY = (int)averageYf; 240 | //cout<<"aveX: "<(lab, 2); 254 | int g= LabelValue.at(lab, 1); 255 | int r = LabelValue.at(lab, 0); 256 | 257 | unsigned char R= r; 258 | unsigned char G= g; 259 | unsigned char B= b; 260 | 261 | uint8_t rp = r; 262 | uint8_t gp = g; 263 | uint8_t bp = b; 264 | uint32_t rgb = ((uint32_t )rp<<16 | (uint32_t )gp<<8 | (uint32_t )bp); 265 | point.rgb = *reinterpret_cast(&rgb); 266 | 267 | vector cp(4); 268 | Transformation(averageX3, averageY3, averageZ3, T); 269 | cp[0] = averageX3; cp[1] = averageY3; cp[2] = averageZ3; cp[3] = (float)lab; 270 | int CSzie = Cpoint.size(); 271 | //cout<<"Cpoint size: "<0){ 273 | bool fuse = false; 274 | float Distance = 10000; 275 | for(int sizeI = 0; sizeI7){ 281 | // cout<push_back(point); 300 | Cpoint.push_back(cp); 301 | 302 | } 303 | } 304 | } 305 | } 306 | 307 | } 308 | 309 | void pointCloudMapping::pointExtraction(vector label){ 310 | 311 | Mat image_gray; 312 | vector centerX; 313 | vector centerY; 314 | cvtColor(image, image_gray, CV_BGR2GRAY); 315 | int imgRow = image.rows; int imgCol = image.cols; 316 | //cout<::Ptr temp(new pcl::PointCloud); 318 | for(int lab = 0; lab<11; lab++){ 319 | Mat image_bw = cv::Mat::zeros(imgRow, imgCol, CV_8UC1); 320 | for(int row = 0; row(row, col) == label[lab]){ 323 | image_bw.at(row, col) = 255; 324 | } 325 | else{ 326 | image_bw.at(row, col) = 0; 327 | } 328 | 329 | } 330 | } 331 | cv::Mat labelImg; 332 | // /cout<<"label: "<points.size()<<" points"< label, Mat labelimag){ 352 | cout< centerX; 354 | vector centerY; 355 | int imgRow = image.rows; int imgCol = image.cols; 356 | 357 | pcl::PointCloud::Ptr temp(new pcl::PointCloud); 358 | for(int lab = 0; lab<9; lab++){ 359 | Mat image_bw = cv::Mat::zeros(imgRow, imgCol, CV_8UC1); 360 | for(int row = 0; row(row, col) == label[lab]){ 363 | image_bw.at(row, col) = 255; 364 | } 365 | else{ 366 | image_bw.at(row, col) = 0; 367 | } 368 | } 369 | } 370 | cv::Mat labelImg; 371 | // /cout<<"label: "<points.size()<<" points"< downSampled; 393 | downSampled.setInputCloud (Cloud); 394 | downSampled.setLeafSize (1.8f, 1.8f, 1.8f); 395 | downSampled.setDownsampleAllData(true); 396 | downSampled.filter (*Cloud); 397 | 398 | // pcl::RadiusOutlierRemoval pcFilter; 399 | // pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud); 400 | // pcFilter.setInputCloud(Cloud); 401 | // pcFilter.setRadiusSearch(200); 402 | // pcFilter.setMinNeighborsInRadius(4); 403 | // pcFilter.filter(*Cloud); 404 | 405 | cout<<"The filtered point cloud has: "<points.size()<<" points"<::Ptr pointCloudMapping::outputPointCloud() 410 | { 411 | pcl::PointCloud::Ptr temp(new pcl::PointCloud); 412 | *temp = *GlobalCloud+*Cloud; 413 | return temp; 414 | } 415 | 416 | void showPointCloud(const vector> &pointcloud) { 417 | 418 | if (pointcloud.empty()) { 419 | cerr << "Point cloud is empty!" << endl; 420 | return; 421 | } 422 | //创建一个窗口 423 | pangolin::CreateWindowAndBind("Point Cloud Viewer_1", 1024, 768); 424 | //启动深度测试 425 | glEnable(GL_DEPTH_TEST); 426 | glEnable(GL_BLEND); 427 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 428 | pangolin::DataLog log; 429 | std::vector labels; 430 | labels.push_back(std::string("sin(t)")); 431 | log.SetLabels(labels); 432 | // Define Projection and initial ModelView matrix 433 | pangolin::OpenGlRenderState s_cam( 434 | pangolin::ProjectionMatrix(1024, 768, 500, 500, 512, 389, 0.1, 1000), 435 | pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0) 436 | ); 437 | 438 | pangolin::View &d_cam = pangolin::CreateDisplay() 439 | .SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -1024.0f / 768.0f) 440 | .SetHandler(new pangolin::Handler3D(s_cam)); 441 | 442 | while (pangolin::ShouldQuit() == false) { 443 | // Clear screen and active view to render into 444 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 445 | pangolin::glDrawAxis(3); 446 | d_cam.Activate(s_cam); 447 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 448 | 449 | glPointSize(20); 450 | glBegin(GL_POINTS); 451 | for (auto &p: pointcloud) { 452 | glColor3f(p[3], p[4], p[5]); 453 | glVertex3d(p[0], p[1], p[2]); 454 | } 455 | glEnd(); 456 | // Swap frames and Process Events 457 | pangolin::FinishFrame(); 458 | usleep(5000); // sleep 5 ms 459 | } 460 | return; 461 | } 462 | 463 | void pointCloudMapping::pointVisuallize(pcl::PointCloud::Ptr&insertCloud1, pcl::PointCloud::Ptr&insertCloud2, MatrixXi matcherID, MatrixXf R, MatrixXf T){ 464 | pcl::PointCloud::Ptr temp(new pcl::PointCloud); 465 | pcl::PointCloud::Ptr temp1(new pcl::PointCloud); 466 | pcl::PointCloud::Ptr temp2(new pcl::PointCloud); 467 | //obtain the clouds. 468 | Matrix4f TransforMatrix = Matrix4f::Identity(); 469 | // for(int row = 0; row<3; row++){ 470 | // for(int col=0; col<3; col++){ 471 | // TransforMatrix(row, col) = R(row, col); 472 | // } 473 | // } 474 | // TransforMatrix(0, 3) = T(0, 0); 475 | // TransforMatrix(1, 3) = T(1, 0); 476 | // TransforMatrix(2, 3) = T(2, 0); 477 | 478 | TransforMatrix(2, 3) = TransforMatrix(2, 3)+80; 479 | *temp1 = *insertCloud1; 480 | *temp2 = *insertCloud2; 481 | transformPointCloud (*temp1, *temp1, TransforMatrix); 482 | *temp = *temp1 + *temp2; 483 | //obtain the line information 484 | int size = matcherID.rows(); 485 | 486 | //cout<<" has: "<points.size()<<" points"< viewer(new pcl::visualization::PCLVisualizer("point cloud")); 488 | viewer->setBackgroundColor(0, 0, 0); 489 | pcl::visualization::PointCloudColorHandlerRGBField rgb(temp); 490 | viewer->addPointCloud(temp, rgb, "Point cloud"); 491 | viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 25, "Point cloud"); 492 | viewer->addCoordinateSystem(1.0); 493 | viewer->initCameraParameters(); 494 | viewer->setCameraPosition(0, 0, 0, 0, 0, 1, 0, -1, 0); 495 | 496 | int count = 0; 497 | int line_numeber = 0; 498 | char str[25];// 499 | while(!viewer->wasStopped()){ 500 | viewer->spinOnce(1000); 501 | line_numeber++; 502 | sprintf(str, "%d", line_numeber); 503 | if(count < size){ 504 | viewer->addLine (temp1->points[matcherID(count, 0)], temp2->points[matcherID(count, 1)], str); 505 | } 506 | count++; 507 | 508 | } 509 | 510 | // vector> pointcloud; 511 | // cout<<"global size: "<points.size()<points.size(); i++){ 513 | // int r = insertCloud->points[i].r; 514 | // int g = insertCloud->points[i].g; 515 | // int b = insertCloud->points[i].b; 516 | // Eigen::VectorXd point1(6); 517 | // point1<< 0, 0, 0, r/ 255.0, g/255.0, b/255.0; 518 | // point1[0] = double(insertCloud->points[i].x); 519 | // //cout << "X" << " " << point1[0] << endl; 520 | // point1[1] = double(insertCloud->points[i].y); 521 | // //cout << "Y" << " " << point1[1] << endl; 522 | // point1[2] = double(insertCloud->points[i].z); 523 | // //cout << "Z" << " " << point1[2] << endl; 524 | // pointcloud.push_back(point1); 525 | // } 526 | // showPointCloud(pointcloud); 527 | } --------------------------------------------------------------------------------