当前位置: 首页 > news >正文

高端网站建设公司哪家公司好海外营销

高端网站建设公司哪家公司好,海外营销,广州网站建设哪家技术好,军工企业专业网站建设方案转载自个人博客:Open3D实现点云数据的序列化与网络传输 在处理点云数据的时候,有时候需要实现点云数据的远程传输。当然可以利用传输文件的方法直接把点云数据序列化成数据流进行传输,但Open3D源码在实现RPC功能时就提供了一套序列化及传输的…

转载自个人博客:Open3D实现点云数据的序列化与网络传输

在处理点云数据的时候,有时候需要实现点云数据的远程传输。当然可以利用传输文件的方法直接把点云数据序列化成数据流进行传输,但Open3D源码在实现RPC功能时就提供了一套序列化及传输的方法及思路,那我们就可以搬过来化为己用。

其中利用Open3D方法序列化点云最为重要,总的流程为根据需要进行有损压缩、序列化、根据需要进行无损压缩、网络传输,即:根据需要使用2.1、1.1、根据需要使用2.2、3.1。

本文全文使用C++实现,另外,本文参考的Open3D源码是V0.18.0版本,若想查看完整Open3D源码,请自行Down\Clone:Open3D Github

1. 序列化(重点)

1.1 实现

Open3D在实现其RPC功能时提供了标准类型open3d::io::rpc::messages::SetMeshData,至于为什么要标准类型,是方便msgpack进行序列化。

那么流程即为:先将点云数据open3d::geometry::PointCloud转化为这个类型,再使用msgpack进行序列化。

将PointCloud转化为标准数据类型SetMeshData是需要逐步转化的,我在这里用一个函数封装,具体代码见下:

#include "open3d/geometry/PointCloud.h"
#include "open3d/io/rpc/Messages.h"/// 将需要序列化的目标点云数据pcd设定为:
/// std::shared_ptr<open3d::geometry::PointCloud> pcd;/// 定义的结构体,用于使用msgpack对其进行序列化
/// 可以添加其他需要一起发送的标准数据,一起序列化
struct PACK{/// Point cloud dataopen3d::io::rpc::messages::SetMeshData pcdMesh;/// Text datastd::vector<std::string> text;/// 用于msgpack序列化,只支持标准数据(std)MSGPACK_DEFINE_ARRAY(pcdMesh, text);
};PACK serialization(std::shared_ptr<open3d::geometry::PointCloud> pcd)
{PACK pack = {{}, {}};if(pcd == nullptr) return pack;pack.pcdMesh.path = "";pack.pcdMesh.time = 0;pack.pcdMesh.layer = "";/// pcd->points_pack.pcdMesh.data.vertices = open3d::io::rpc::messages::Array::FromPtr((double*)pcd->points_.data(), {int64_t(pcd->points_.size()), 3});/// pcd->normals_if(pcd->HasNormals()){pack.pcdMesh.data.vertex_attributes["normals"] =open3d::io::rpc::messages::Array::FromPtr((double*)pcd->normals_.data(), {int64_t(pcd->normals_.size()), 3});}/// pcd->colors_if(pcd->HasColors()){pack.pcdMesh.data.vertex_attributes["colors"] =open3d::io::rpc::messages::Array::FromPtr((double*)pcd->colors_.data(), {int64_t(pcd->colors_.size()), 3});}return pack;
}void main(){// std::shared_ptr<open3d::geometry::PointCloud> pcd;.../// 1.将PointCloud转化为标准数据类型SetMeshDataPACK pack = serialization(pcd);/// 2.将SetMeshData所在结构体用msgpack序列化msgpack::sbuffer sbuf;msgpack::pack(sbuf, pack); /// 得到序列化后的数据sbuf...
}

1.2 源码参考(可跳过)

Open3D源码中对处理点云数据的声明定义:

using namespace open3d::utility;namespace open3d {
namespace io {
namespace rpc {bool SetPointCloud(const geometry::PointCloud& pcd,const std::string& path,int time,const std::string& layer,std::shared_ptr<ConnectionBase> connection) {// TODO use SetMeshData here after switching to the new PointCloud class.if (!pcd.HasPoints()) {LogInfo("SetMeshData: point cloud is empty");return false;}messages::SetMeshData msg;msg.path = path;msg.time = time;msg.layer = layer;msg.data.vertices = messages::Array::FromPtr((double*)pcd.points_.data(), {int64_t(pcd.points_.size()), 3});if (pcd.HasNormals()) {msg.data.vertex_attributes["normals"] =messages::Array::FromPtr((double*)pcd.normals_.data(),{int64_t(pcd.normals_.size()), 3});}if (pcd.HasColors()) {msg.data.vertex_attributes["colors"] = messages::Array::FromPtr((double*)pcd.colors_.data(), {int64_t(pcd.colors_.size()), 3});}msgpack::sbuffer sbuf;messages::Request request{msg.MsgId()};msgpack::pack(sbuf, request);msgpack::pack(sbuf, msg);/// 得到序列化后的数据sbuf/// 之后是网络传输的部分zmq::message_t send_msg(sbuf.data(), sbuf.size());if (!connection) {connection = std::shared_ptr<Connection>(new Connection());}auto reply = connection->Send(send_msg);return ReplyIsOKStatus(*reply);
}}

那么使用即为:

/// 网络传输Connection的申明定义见3
auto connection = std::make_shared<Connection>("tcp://127.0.0.1:51454", 500, 500);
ASSERT_TRUE(SetPointCloud(pcd, "", 0, "", connection));

2. 压缩

一般,需要显示完全场景的点云数据都占用较大内存,如果像我这样需要实时传输点云数据以实时更新场景的情况,那对点云数据进行压缩处理就有利于应对更多的网络场景。

Open3D自身实现的下采样(有损压缩)和第三方实现的无损压缩可以同时使用。

2.1 下采样(有损压缩)

Open3D本身就提供了多种下采样方法,通过对原生点云数据再采样,减少点的个数,即减小点云数据的大小。

详细的各种下采样方法见我另一篇文章:点云下采样有损压缩

这里以体素下采样为例:

int voxelSize = 0.002; // 设置体素的尺寸大小
pcd = pcd->VoxelDownSample(voxelSize);

2.2 无损压缩

既然前面已经实现数据的序列化了,那就可以用其他常用的压缩库进行压缩,比如zlib。

要注意的是,这种压缩会消耗一定的CPU资源,占用一定时间。

zlib官方文档:zlib 1.3.1 Manual

其提供了几种压缩等级(level):

#define Z_NO_COMPRESSION         0
#define Z_BEST_SPEED             1
#define Z_BEST_COMPRESSION       9
#define Z_DEFAULT_COMPRESSION  (-1)

完整代码如下:

#include "zlib.h"/// 序列化内容见上一节,这里略
/int compress(const std::string &input, std::string &output, int level)
{/// Estimate the maximum value of the compressed size and allocate spaceuLongf compressedMaxSize = compressBound(input.size());output.resize(compressedMaxSize);/// Compress and get the real sizeint result = compress2((Bytef *)output.data(), &compressedMaxSize,(const Bytef *)input.data(), input.size(),level);if (result != Z_OK) return result;/// Reallocate the real spaceoutput.resize(compressedMaxSize);return Z_OK;
}void main(){// std::shared_ptr<open3d::geometry::PointCloud> pcd;.../// 1.对原点云数据进行下采样(有损压缩)pcd = pcd->VoxelDownSample(0.002);/// 2.将PointCloud转化为标准数据类型SetMeshDataPACK pack = serialization(pcd);/// 3.将SetMeshData所在结构体用msgpack序列化msgpack::sbuffer sbuf;msgpack::pack(sbuf, pack); /// 得到序列化后的数据sbuf/// 4.对数据进行压缩QByteArray byteArray(sbuf.data(), static_cast<int>(sbuf.size()));std::string originalData(byteArray.data(), byteArray.size());std::string compressedData;if(compress(originalData, compressedData, 1) != Z_OK){std::cerr << "Compression failed." << std::endl;}/// 得到压缩后的数据compressedData
}

解压类似:

#include "zlib.h"int decompress(const std::string &input, std::string &output)
{/// Allocate an estimated spacestd::string data(input.size() * 10, '\0');uLongf size = data.size();int result = uncompress((Bytef *)data.data(), &size, (const Bytef *)input.data(), input.size());if (result != Z_OK) return result;output.assign(data.data(), size);return Z_OK;
}

3. 网络传输

我使用的是nanomsg,比源码中使用的ZeroMQ好用,当然,对数据流的传输可以使用其他的各种方法。

3.1 本人使用的传输方法

我使用的是nanomsg进行网络传输,nanomsg的使用参考我其他的文章。

这里的代码如下:

#include <nanomsg/nn.h>
#include <nanomsg/bus.h>/// 序列化内容和压缩内容见上两节,这里略
/
void main(){// std::shared_ptr<open3d::geometry::PointCloud> pcd;.../// 1.对原点云数据进行下采样(有损压缩)pcd = pcd->VoxelDownSample(0.002);/// 2.将PointCloud转化为标准数据类型SetMeshDataPACK pack = serialization(pcd);/// 3.将SetMeshData所在结构体用msgpack序列化msgpack::sbuffer sbuf;msgpack::pack(sbuf, pack); /// 得到序列化后的数据sbuf/// 4.对数据进行压缩QByteArray byteArray(sbuf.data(), static_cast<int>(sbuf.size()));std::string originalData(byteArray.data(), byteArray.size());std::string compressedData;if(compress(originalData, compressedData, 1) != Z_OK){std::cerr << "Compression failed." << std::endl;}/// 得到压缩后的数据compressedData/// 5.将压缩后的数据发送int socket = nn_socket(AF_SP, NN_BUS);nn_bind(socket, "ws://127.0.0.1:55555");if(nn_send(socket, compressedData.data(), compressedData.size(),0) < 0){std::cerr << "Send error" << std::endl;}/// 5.如果不需要压缩,直接发送序列化的数据if(nn_send(socket, sbuf.data(), sbuf.size(),0) < 0){std::cerr << "Send error" << std::endl;}
}

3.2 源码中的方法

Open3D使用ZeroMQ库进行网络传输

Open3D源码中对网络传输的声明定义:

using namespace open3d::utility;namespace open3d {
namespace io {
namespace rpc {Connection::Connection(): Connection(defaults.address, defaults.connect_timeout, defaults.timeout) {
}Connection::Connection(const std::string& address,int connect_timeout,int timeout): context_(GetZMQContext()), // GetZMQContext()在别处定义、实现socket_(new zmq::socket_t(*GetZMQContext(), ZMQ_REQ)),address_(address),connect_timeout_(connect_timeout),timeout_(timeout) {socket_->set(zmq::sockopt::linger, timeout_);socket_->set(zmq::sockopt::connect_timeout, connect_timeout_);socket_->set(zmq::sockopt::rcvtimeo, timeout_);socket_->set(zmq::sockopt::sndtimeo, timeout_);socket_->connect(address_.c_str());
}Connection::~Connection() { socket_->close(); }std::shared_ptr<zmq::message_t> Connection::Send(zmq::message_t& send_msg) {if (!socket_->send(send_msg, zmq::send_flags::none)) {zmq::error_t err;if (err.num()) {LogInfo("Connection::send() send failed with: {}", err.what());}}std::shared_ptr<zmq::message_t> msg(new zmq::message_t());if (socket_->recv(*msg)) {LogDebug("Connection::send() received answer with {} bytes",msg->size());} else {zmq::error_t err;if (err.num()) {LogInfo("Connection::send() recv failed with: {}", err.what());}}return msg;
}std::shared_ptr<zmq::message_t> Connection::Send(const void* data,size_t size) {zmq::message_t send_msg(data, size);return Send(send_msg);
}
}

那么使用即为:

auto connection = std::make_shared<Connection>("tcp://127.0.0.1:51454", 500, 500);/// 序列化内容见1
/// 得到序列化后的数据sbufzmq::message_t send_msg(sbuf.data(), sbuf.size());
auto reply = connection->Send(send_msg);
http://www.shuangfujiaoyu.com/news/36798.html

相关文章:

  • 企业型网站怎么做我想做电商怎么加入
  • 杭州酒店网站设计公司推荐潍坊seo教程
  • 幼儿园微信公众号如何做微网站广西seo公司
  • ui毕业设计代做网站百度市场应用官方app
  • 网络营销公司排名榜seo营销排名
  • 创新驱动发展战略内容seo 技术优化
  • 网站添加视频代码网站建站设计
  • 可以免费做会计题的网站百度代发排名
  • 知名企业网站建设市场营销推广方案
  • 计算机专业网站开发开题报告网络销售公司怎么运作
  • 一流的福州网站建设seo优化培训课程
  • 怎样建立自己的销售网站seo推广外包报价表
  • 深圳网站建设培训哪家好宁波seo智能优化
  • 网站音乐播放器插件电商的推广方式有哪些
  • 吉林省建设信息网官网seo分析是什么意思
  • wordpress数据库改变后台账号seo网站优化价格
  • 企业网站内容运营每日舆情信息报送
  • 天津企业网站制作关键词优化网站排名
  • 如果做动态网站的开发设计网站的软件
  • 北京seo收费网络优化工程师骗局
  • 山东建设部网站英文网站seo发展前景
  • 做网站用什么语言好互联网营销培训
  • 长春做商业平台网站网页推广怎么做
  • 怎么推广自己做的网站吗值得收藏的五个搜索引擎
  • 福州网站建设专业公司公司网站与推广
  • 谷歌自建站和优化重庆企业站seo
  • 优速网站建设国内建站平台
  • 网站费计入什么科目全网推广
  • 公司门户网站是什么网络营销模式包括哪些
  • 做网站页面多少钱品牌推广策划书范文案例