ifm3d和c++来实现点云图像的保存和显示(o3d303)

1.起因

导师要求用ifm的o3d303这款摄像头来实现点云图像的捕捉,ifm官方是提供了一个软件,叫做“视觉助手”,这个软件能够以一种很简单的方式就能够查看相机捕获的点云图,并且可以通过这个软件来查看和修改相机的一些出厂信息,例如ip(这个特别重要!!)。但是这个软件并不能将你捕获的点云图以.pcd的格式保存下来,只能把捕获的点云图以.h5的格式保存下来,很难进行二次开发,所以,为了满足老师的要求,就要通过ifm官方提供的ifm3d库来进行对相机的连接和点云图的获取

2.环境搭建

1.ifm3d 1.4.2

2.pcl 1.2.1

3.改ip

2.1下载ifm3d库

先挑个你喜欢版本下载(我一般都是下载最新版)

发布 ·ifm/ifm3d (github.com)这个网站下载

下载这个文件后,就按照官网的教程进行ifm3d库的环境搭建使用 ifm3d 安装程序安装 — ifm3d v1.4.3 文档(就是安装好把所有bin文件的路径库库向path中一顿放,然后在window命令行验证)

到这里,ifm3d库的环境就算搭好了。

2.2pcl库的环境搭建

这里就不细说了,百度一下一抓一大把,注意要选择对应的版本攻略。

2.3ip更改

这点非常重要!!像我这种小白第一次接触这种程序与相机的通信,对于相机ip这个概念特别模糊最开始接触o3d303这款相机的ip是在ifm提供的官方sdk中。

打开start的那个ppt后,细读了一下

发现这段话,大概的意思就是想要打开sdk里的这个“Lighvis”这个可视化插件,相机的ip必须为192.168.0.69

包括后面的很多插件都有提及到ip,我就对相机的ip产生了兴趣,在起因中我讲过,ifm官方提供的那个视觉助手中提供了查看ip和修改ip的功能。

这里我用红框框柱的就是相机的ip,这里我们需要把这串ip复制,然后在上方的方框里粘贴(这操作看起来怪怪的,实际上真的很奇怪,ip那栏明明写着192.168.0.69,但是我当我选择通过手动输入ip连接的时候,输入192.168.0.69,却显示连不上,当我输入169.254.50.239后就能连接上了,这就证明这个相机的ip是169.254.50.239。真的很想骂娘,ifm这么搞是吧,好好好,后面还有更离谱的操作)

ip改好后,就要填写ipv4协议了

找到相机的网络

进入属性后,双击ipv4协议

这些在视觉助手里都有的看。

3.代码展示

在展示代码前我还想吐槽一下ifm,ifm的帮助文档只写了o3r这一个型号的示例代码,所以让我写o3d型号的代码变得异常的艰难

o3r型号的函数和o3d的完全不一样。所以这个“基本库的用法”这章就显的特别鸡肋!!

在我四处溜达的时候,发现ifm的手册里有这句话

我研究了一下,结果发现这是一份大概是17年的代码,老的掉牙,现在ifm自己都不用camera这个类和头文件了!!还不更新,真的想把ifm打一顿。

诶,这条路走不通那还是会ifm官网看有没有相关的示例代码吧

我就又溜达溜达

其中看到了这位大哥用Python实现我的目的

ifm3dlib+Python实现摄像头点云数据保存_ifm相机sdk_okfang616的博客-CSDN博客

我又同时在ifm官网那位大哥的Python代码有少许和这章的c++类似,我就开始重点研究这章

很幸运,这章并没有用到o3r的专属函数,看起来是所有型号相机通用的,那就开始试着写一下,这里就直接给最后的代码吧

#include <iostream>
#include <ifm3d/fg.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <ifm3d/device/device.h>
#include <chrono>
#include <ifm3d/fg/buffer.h>
#include <ifm3d/device/o3d.h>

using namespace std::chrono_literals;
using namespace ifm3d::literals;

void Callback(ifm3d::Frame::Ptr frame) {
    auto dist = frame->GetBuffer(ifm3d::buffer_id::RADIAL_DISTANCE_IMAGE);
    std::cout << dist.height() << " " << dist.width() << std::endl;
}

int main(int argc, const char** argv) {

    // 填写相机的 IP 地址和端口号
    std::string camera_ip = "169.254.50.239";
    int camera_port = 80;  // 假设相机的端口号是80

    // 创建相机对象
    auto cam = ifm3d::Device::MakeShared(camera_ip, camera_port); // 实例化相机
    auto fg = std::make_shared<ifm3d::FrameGrabber>(cam, 50010);

    // 启动数据流
    fg->Start({ ifm3d::buffer_id::AMPLITUDE_IMAGE, ifm3d::buffer_id::RADIAL_DISTANCE_IMAGE, ifm3d::buffer_id::XYZ });

    pcl::visualization::CloudViewer viewer("Real-time Point Cloud Viewer");

    while (!viewer.wasStopped()) {
        auto frame = fg->WaitForFrame().get();
        ifm3d::Buffer xyz = frame->GetBuffer(ifm3d::buffer_id::XYZ);

        // ifm3d库从相机缓冲器获取的XYZ数据!!!!!
        ifm3d::Buffer_<ifm3d::Point3D_16S>  xyz_data = xyz;

        // Create a Point Cloud object
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

        // Populate the Point Cloud with XYZ data
        for (const auto& point : xyz_data)
        {
            pcl::PointXYZ pcl_point;
            pcl_point.x = point.val[1];
            pcl_point.y = point.val[2];
            pcl_point.z = point.val[0];
            cloud->push_back(pcl_point);
        }

        pcl::io::savePCDFileASCII("point_cloud.pcd", *cloud);

        // 点云的来源就是通过ifm3d库从相机获取的XYZ数据,然后将其转换为PCL点云,并使用PCL的CloudViewer进行实时可视化。
        viewer.showCloud(cloud);
    }

    return 0;
}

下面顺便展示一下代码运行效果

4.总结

总结一下,最重要的一点就是先让程序与相机完成通信,只要他们完成了通信,后面的操作都简单了

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值