zoukankan      html  css  js  c++  java
  • 激光相机数据融合(5)--Gazebo仿真数据融合

    这一节将用ROS+Gazebo 环境获取激光获取点云,并用PCL和OPENCV处理,源代码在:https://github.com/ZouCheng321/5_laser_camera_sim

     由于激光的视角远大于相机,所以我们使用了5个相机来获取图像,这类似于Ladybug相机:

    相机获取的五张图像:

     

    接下来我们用来构建彩色点云:

    相机与激光的位置变换,由于是正五边形分别,这很容易求得:

      Eigen::Matrix4f rt0,rt1,rt2,rt3,rt4;
        rt0<< 0,0,-1,0,  0,1,0,0,  1,0,0,0, 0,0,0,1;
        rt1<< 0,0,-1,0,  -0.95105651629,0.30901699437,0,0,  0.30901699437,0.95105651629,0,0, 0,0,0,1;
        rt2 << 0,0,-1,0,  -0.58778525229,-0.80901699437,0,0,  -0.80901699437,0.58778525229,0,0, 0,0,0,1;
        rt3 << 0,0,-1,0,  0.58778525229,-0.80901699437,0,0,  -0.80901699437,-0.58778525229,0,0, 0,0,0,1;
        rt4 << 0,0,-1,0,  0.95105651629,0.30901699437,0,0,  0.30901699437,-0.95105651629,0,0, 0,0,0,1;
        Eigen::Matrix4f inv0,inv1,inv2,inv3,inv4;
        inv0=rt0.inverse();
        inv1=rt1.inverse();
        inv2=rt2.inverse();
        inv3=rt3.inverse();
        inv4=rt4.inverse();
    
        RT.push_back(rt0);
        RT.push_back(rt1);
        RT.push_back(rt2);
        RT.push_back(rt3);
        RT.push_back(rt4);
    
        INV.push_back(inv0);
        INV.push_back(inv1);
        INV.push_back(inv2);
        INV.push_back(inv3);
        INV.push_back(inv4);

    相机的内参,已经在仿真软件中设定:

     std::vector<cv::Point2d> imagePoints;
    
        cv::Mat intrisicMat(3, 3, cv::DataType<double>::type); // Intrisic matrix
        intrisicMat.at<double>(0, 0) = 476.715669286;
        intrisicMat.at<double>(1, 0) = 0;
        intrisicMat.at<double>(2, 0) = 0;
    
        intrisicMat.at<double>(0, 1) = 0;
        intrisicMat.at<double>(1, 1) = 476.715669286;
        intrisicMat.at<double>(2, 1) = 0;
    
        intrisicMat.at<double>(0, 2) = 400;
        intrisicMat.at<double>(1, 2) = 400;
        intrisicMat.at<double>(2, 2) = 1;
    
    
    
        cv::Mat rVec(3, 1, cv::DataType<double>::type); // Rotation vector
        rVec.at<double>(0) = 0;
        rVec.at<double>(1) = 0;
        rVec.at<double>(2) = 0;
    
        cv::Mat tVec(3, 1, cv::DataType<double>::type); // Translation vector
        tVec.at<double>(0) = 0.4;
        tVec.at<double>(1) = 0;
        tVec.at<double>(2) = -0.1;
    
        cv::Mat distCoeffs(5, 1, cv::DataType<double>::type);   // Distortion vector
        distCoeffs.at<double>(0) = 0;
        distCoeffs.at<double>(1) = 0;
        distCoeffs.at<double>(2) = 0;
        distCoeffs.at<double>(3) = 0;
        distCoeffs.at<double>(4) = 0;

    去除相机后方的点云:

    std::vector<cv::Point3d> Generate3DPoints(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,int num)
    {
        std::vector<cv::Point3d> points;
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
    
        Eigen::Matrix4f TR;
        TR << 0,0,-1,0,  0,1,0,0,  1,0,0,0, 0,0,0,1;
        pcl::transformPointCloud (*cloud, *cloud_f, RT[num]);
    
        pcl::PassThrough<pcl::PointXYZ> pass;
        pass.setInputCloud (cloud_f);
        pass.setFilterFieldName ("z");
        pass.setFilterLimits (0.0, 10);
        //pass.setFilterLimitsNegative (true);
        pass.filter (*cloud);
        cout<<"size:"<<cloud->size()<<endl;
    
    
    
        for(int i=0;i<=cloud->points.size();i++)
        {
            points.push_back(cv::Point3d(cloud->points[i].x, cloud->points[i].y, cloud->points[i].z));
        }
    
        return points;
    }

    将前方的点云投影到相机平面,这里直接用opencv自带的projectPoints函数:

            cv::projectPoints(objectPoints, rVec, tVec, intrisicMat, distCoeffs, imagePoints);

    保留图像内的点云:

     for(int i=0;i<imagePoints.size();i++)
            {
                if(imagePoints[i].x>=0&&imagePoints[i].x<800&&imagePoints[i].y>=0&&imagePoints[i].y<800)
                {
    
                    pcl::PointXYZRGB point;
                    point.x = cloud->points[i].x;
                    point.y = cloud->points[i].y;
                    point.z = cloud->points[i].z;
                    point.r = _I(round(imagePoints[i].x),round(imagePoints[i].y))[2];
                    point.g = _I(round(imagePoints[i].x),round(imagePoints[i].y))[1];
                    point.b = _I(round(imagePoints[i].x),round(imagePoints[i].y))[0];
    
                    colored_cloud->points.push_back (point);
                }
            }

    最后显示所有点云:

      pcl::visualization::PCLVisualizer viewer("Cloud viewer");
        viewer.addPointCloud(colored_cloud_sum, "sample cloud");
        viewer.setBackgroundColor(0,0,0);
    
        while(!viewer.wasStopped())
            //while (!viewer->wasStopped ())
            viewer.spinOnce(100);

    要构建这个项目:

    cd 5_laser_camera_sim
    mkdir build
    cd build
    cmake ..
    make
    ./color

    将看到如下显示:

  • 相关阅读:
    Jquery才可以使用 this 指定当前DOM
    微擎使用腾讯地图拾取坐标
    使用 MUI 自制 弹出层
    mui 底部导航栏
    PHP 向数组头部插入数据
    a 标签添加 onclick 事件
    # & 等特殊字符会导致传参失败
    HTML 颜色输入框修改事件的触发,以及获取修改后的颜色
    C++ malloc()函数的注意点及使用示例
    C++ malloc函数
  • 原文地址:https://www.cnblogs.com/zoucheng/p/7867986.html
Copyright © 2011-2022 走看看