5.1-2D图像与3D点云融合

返回 >>>>>> PCL-3D点云总目录

概述

截止目前为止,我们学习了机器人学,学习了2D和3D视觉算法。我们也学习了2D相机(图像数据的来源)和3D相机(点云数据的来源)工作原理。

实际上,我们最终要做的,是一个手眼机器人系统。在这个系统里,相机与机器人构成了两个非常关键的部分,它们之间需要密切配合,因此,它们之间的关系,也就非常重要。确定相机与机器人之间的关系,这是手眼标定要解决的问题。

另一方面,在很多场合,为了增强算法的鲁棒性,我们通常同时使用图像数据与点云数据,这又涉及到2D与3D配准的问题。

相机配准

由之前学习的相机内参相关知识:
在这里插入图片描述

将彩色图和深度图合并成点云

方式一:
通过双重循环遍历

/**
     * 将彩色图和深度图合并成点云
     * @param matrix 相机内参矩阵3x3
     * @param rgb    彩色图
     * @param depth  深度图
     * @param cloud  输出点云
     */
static void convert(Mat &matrix, Mat &rgb, Mat &depth, PointCloud::Ptr &cloud) {
    double camera_fx = matrix.at<double>(0, 0);
    double camera_fy = matrix.at<double>(1, 1);
    double camera_cx = matrix.at<double>(0, 2);
    double camera_cy = matrix.at<double>(1, 2);

    cout << "fx: " << camera_fx << endl;
    cout << "fy: " << camera_fy << endl;
    cout << "cx: " << camera_cx << endl;
    cout << "cy: " << camera_cy << endl;

    // 遍历深度图
    for (int v = 0; v < depth.rows; v++)
        for (int u = 0; u < depth.cols; u++) {
            // 获取深度图中(m,n)处的值
            ushort d = depth.ptr<ushort>(v)[u];
            // d 可能没有值,若如此,跳过此点
            if (isnan(d) && abs(d) < 0.0001)
                continue;
            // d 存在值,则向点云增加一个点
            PointT p;

            // 计算这个点的空间坐标
            p.z = double(d) / 1000; //单位是米
            p.x = (u - camera_cx) * p.z / camera_fx;
            p.y = (v - camera_cy) * p.z / camera_fy;

            // 从rgb图像中获取它的颜色
            // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色
            Vec3b bgr = rgb.at<Vec3b>(v, u);
            p.b = bgr[0];
            p.g = bgr[1];
            p.r = bgr[2];

            // 把p加入到点云中
            cloud->points.push_back(p);
            //cout << cloud->points.size() << endl;
        }


    // 设置并保存点云
    cloud->height = 1;
    cloud->width = cloud->points.size();
    cout << "point cloud size = " << cloud->points.size() << endl;
    cloud->is_dense = false;
}
int main(){
    cv::Mat cameraMatrix; // 从文件加载相机内参
    cv::Mat rgb;         // 从相机得到RGB彩色图
    cv::Mat depth;       // 从相机得到depth深度图
    PointCloud::Ptr pCloud = PointCloud::Ptr(new PointCloud);
    convert(cameraMatrix, rgb, depth, pCloud);
}

方式二:
通过指针遍历,并提前准备好计算矩阵

#include <iostream>
#include <opencv2/opencv.hpp>
#include <sstream>
#include <cstdlib>
#include <pcl/io/io.h>

using namespace std;
using namespace cv;

float qnan_ = std::numeric_limits<float>::quiet_NaN();
const char *cameraInCailFile = "./assets/3DCameraInCailResult.xml";

Eigen::Matrix<float, 1920, 1> colmap;
Eigen::Matrix<float, 1080, 1> rowmap;
//const short w = 512, h = 424;
const short w = 1920, h = 1080;

void prepareMake3D(const double cx, const double cy,
                   const double fx, const double fy) {
    float *pm1 = colmap.data();
    float *pm2 = rowmap.data();
    for (int i = 0; i < w; i++) {
        *pm1++ = (i - cx + 0.5) / fx;
    }
    for (int i = 0; i < h; i++) {
        *pm2++ = (i - cy + 0.5) / fy;
    }
}
/**
 * 根据内参,合并RGB彩色图和深度图到点云
 * @param cloud
 * @param depthMat
 * @param rgbMat
 */
void getCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud, Mat &depthMat, Mat &rgbMat) {
    const float *itD0 = (float *) depthMat.ptr();
    const char *itRGB0 = (char *) rgbMat.ptr();

    if (cloud->size() != w * h)
        cloud->resize(w * h);


    pcl::PointXYZRGB *itP = &cloud->points[0];
    bool is_dense = true;

    for (size_t y = 0; y < h; ++y) {

        const unsigned int offset = y * w;
        const float *itD = itD0 + offset;
        const char *itRGB = itRGB0 + offset * 4;
        const float dy = rowmap(y);

        for (size_t x = 0; x < w; ++x, ++itP, ++itD, itRGB += 4) {
            const float depth_value = *itD / 1000.0f;

            if (!isnan(depth_value) && abs(depth_value) >= 0.0001) {

                const float rx = colmap(x) * depth_value;
                const float ry = dy * depth_value;
                itP->z = depth_value;
                itP->x = rx;
                itP->y = ry;

                itP->b = itRGB[0];
                itP->g = itRGB[1];
                itP->r = itRGB[2];
            } else {
                itP->z = qnan_;
                itP->x = qnan_;
                itP->y = qnan_;

                itP->b = qnan_;
                itP->g = qnan_;
                itP->r = qnan_;
                is_dense = false;
            }
        }
    }
    cloud->is_dense = is_dense;
}

int main(){
    Mat cameraMatrix = cv::Mat_<double>(3, 3);
    FileStorage paramFs(cameraInCailFile, FileStorage::READ);
    paramFs["cameraMatrix"] >> cameraMatrix;
    // 内参数据
    double fx = cameraMatrix.at<double>(0, 0);
    double fy = cameraMatrix.at<double>(1, 1);
    double cx = cameraMatrix.at<double>(0, 2);
    double cy = cameraMatrix.at<double>(1, 2);
    // 提前准备计算所需参数
    prepareMake3D(cx, cy, fx, fy);

    cv::Mat rgbMat;      // 从相机得到RGB彩色图
    cv::Mat depthMat;        // 从相机得到depth深度图
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    getCloud(cloud, depthMat, rgbMat)
}

注:以上文字和图片均来源于链接,若有侵权请联系转载方删除。

返回 >>>>>> PCL-3D点云总目录

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Understand是一种功能强大的软件开发工具,它提供了多种语言和平台的静态代码分析功能,用于帮助开发人员理解和改进他们的代码质量。 5.1是Understand的一个特定版本号,它表示 Understad软件的第5个大版本的一个小更新。 Windows64表示这个Understand版本适用于运行在Windows操作系统的64位机器上。 通过使用Understand 5.1-windows64,开发人员可以对代码进行全面的分析和评估,以确保代码的质量和可维护性。它可以帮助开发人员识别潜在的代码缺陷、冗余代码和性能问题,并提供解决方案来改善代码质量。 该版本还具备了适用于Windows 64位机器的优化和兼容性,以确保在这样的机器上能够运行和运行分析任务的平稳性。 总之,Understand 5.1-windows64是一款适用于在Windows 64位操作系统上运行的强大的软件开发工具,它为开发人员提供了全面的代码分析功能,帮助他们提高代码质量和可维护性。 ### 回答2: understand 5.1-windows64 指的是一个软件的版本和系统要求。Understand 是一款用于源代码分析的软件工具,用于帮助开发人员理解和浏览复杂的代码。5.1 是这个软件的版本号,表示该软件经过一系列的更新和改进。windows64 表示该软件支持 64 位的 Windows 操作系统。 对于开发人员来说,使用 Understand 5.1-windows64 有几个优势。首先,它可以帮助他们更好地理解和分析源代码。该软件提供了多种功能,如交互式图表、图形视图和搜索功能,可以帮助开发人员深入了解代码的结构和关系,从而更高效地调试和优化代码。 其次,Understand 5.1-windows64 具有良好的兼容性,可以在 Windows 64 位系统上正常运行。64 位操作系统相比于32位操作系统具有更大的内存容量和更快的处理速度,这对于处理大型代码库和复杂的分析任务非常重要。使用 64 位系统可以提高软件工具的性能和效率。 此外,Understand 5.1-windows64 的更新版本可能还会解决了一些 bug,增加了新功能或提高了软件的稳定性。开发人员可以从该软件的版本迭代获益。 总之,Understand 5.1-windows64 是一款功能强大的源代码分析工具,适用于 Windows 64 位系统。它可以帮助开发人员更好地理解和分析源代码,提高开发效率,并且与 64 位操作系统相对应,能够更好地支持大型代码库和复杂的分析任务。 ### 回答3: understand5.1-windows64是一款用于软件开发的工具,它是在Windows操作系统下工作的64位版本。Understand是一个功能强大的代码理解工具,它可以帮助程序员对代码进行深入的分析和理解。 使用understand5.1-windows64,程序员可以对源代码进行静态分析,了解代码的结构、功能和相互关系。它支持多种编程语言,包括C、C++、C#、Java等。程序员可以快速地浏览代码,并通过各种视图和图表来可视化分析结果。 此外,understand5.1-windows64还提供了全面的代码检查和度量功能,帮助程序员评估代码的质量和健壮性。它可以检测潜在的错误、重复的代码和性能问题,并生成报告供程序员参考和改进。 另外,understand5.1-windows64还支持代码重构和搜索功能。程序员可以通过重构工具对代码进行重构,提高代码的可读性和可维护性。搜索功能可以帮助程序员快速定位特定的代码片段,提高开发效率。 总而言之,understand5.1-windows64是一款功能强大且易于使用的代码理解工具。它提供了丰富的分析和度量功能,帮助程序员更好地理解和改进源代码。无论是初学者还是经验丰富的开发人员,都可以从受益并提高代码开发的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值