背景
最近在做云平台的数据回放功能,在数据传输解析渲染上遇到比较棘手的问题,主要如下:
- 一帧pcd格式的点云后端处理后发给前端有4M左右大小,前端解析渲染三个点云数据需要5s
- 一张图片也有3M左右大小,解析渲染也很耗时,想要做到10fps播放基本不可能
解决办法
- 数据压缩
- 优化传输形式,如proto
- 图像降低分辨率
数据压缩
- 前后端通信采用gzip格式压缩,三帧点云数据量从15M减少为5M
- (已弃用)将点云数据从float变为int,然后3个点云int数据合并为一个long类型,从12字节变为8字节,体积减少三分之一。但是前端需要反过来解析为float,耗时700ms左右,得不偿失
proto
采用proto传输形式,其中点云类型测试了三种:float,int32,sint32,由于点云数据存在大量负数,float每个数字都是固定的4字节存储,int32和sint32是可变字节数,sint32对负数存储更加友好,故最终对比选择sint32进行点云数据传输,详细对比信息如下:
| 解析时间 | 解析前大小 | 解析后大小 | |
|---|---|---|---|
| float | 47ms | 3.1M | 3.5M |
| int32 | 50ms | 1.3M | 4.1M |
| sint32 | 36ms | 1.2M | 1.6M |
图像最初使用string,但是前端proto解析耗时久,网上资料显示proto处理string类型优势并不大,三个点云解析时间20ms左右,四个图像解析时间要200ms以上,故用bytes替换string,修改后图像解析时间大幅缩短,只需要1ms左右,但是额外多出byte转base64的时间,一个图像大约需要40ms,这样总体三点云四图像的总体解析渲染耗时较之前节省了140ms,目前只需要120ms左右
图像降低分辨率
为了进一步减少byte转base64的耗时,后端在发送图像数据前进行分辨率降低,长宽都减少为原来的一半,观察单个数据渲染效果尚可,7个数据一同显示便没有太大区别,基于此测试得到如下结果:
| 数据大小 | 总耗时 | 后端耗时 | byte转string | 渲染耗时 |
|---|---|---|---|---|
| 一张图片压缩 40kb | 830ms | 513ms | 2ms | 1ms |
| 四张图片压缩 186kb | 1640ms | 1319ms | 7ms | 2ms |
| 一张图片未压缩 707kb | 627ms | 380ms | 27ms | 4ms |
| 四张图片未压缩 4M | 1250ms | 716ms | 210ms | 21ms |
经过上述改进,目前在数据已经在本机内存情况下解析渲染一帧三点云+四图像数据的总体时间为20ms左右,能够满足10fps的需求,为了做到流畅播放,还需要解决数据传输问题,如何更快的把数据缓存到用户本机还在解决,欢迎大家提出好的建议,一起讨论进步!