文章目录
- 前言
- 1.PercipioViewer软件操作步骤
-
- [1.1 加载录制的bag文件](#1.1 加载录制的bag文件)
- [1.2 设置视频播放速度](#1.2 设置视频播放速度)
- 2.C++代码解析bag文件
-
- [2.1 运行编译后的Demo](#2.1 运行编译后的Demo)
- 3.常见问题FAQ
-
- [3.1 编译过程中报错](#3.1 编译过程中报错)
- [3.2 保持的是否是ROS中的Rosbag包?](#3.2 保持的是否是ROS中的Rosbag包?)
前言
Percipio Viewer 软件支持录制相机采集图像时的视频。录制视频过程中,支持调整部分参数,不支持关闭/开启数据流。
前提条件 :
根据录制内容,开启对应数据流。
1.PercipioViewer软件操作步骤

1.1 加载录制的bag文件

1.2 设置视频播放速度

主要有0.2X,0.5X,1X,1.5X和2X五种速度可以设置。
2.C++代码解析bag文件
具体解析bag文件的代码,可从如下链接下载:
cpp
git clone git@gitee.com:jet_zou/percipio_viewer_stream_decode.git
详细的代码如下:
cpp
/*
* @Description:
* @Author: zxy
* @Date: 2023-09-08 09:07:05
* @LastEditors: zxy
* @LastEditTime: 2024-04-16 18:27:04
*/
#include "utils.hpp"
#define PERCIPIO_DPETH_RENDER_ENABLE
#ifdef PERCIPIO_DPETH_RENDER_ENABLE
#include "DepthRender.hpp"
#endif
#pragma pack(1)
struct StreamSize
{
int32_t m_width;
int32_t m_height;
};
struct StreamInfo {
float f_sacle_unit;
StreamSize depthSize;
StreamSize colorSize;
StreamSize irLeftSize;
StreamSize irRightSize;
int32_t Reserved[10];
};
struct RecordInfo {
uint32_t record_info_version;
TY_DEVICE_BASE_INFO dev_info;
int32_t depthStreaming;
int32_t colorStreaming;
int32_t lIrStreaming;
int32_t rIrStreaming;
int32_t allComps;
//
TY_CAMERA_CALIB_INFO depth_calib_info;
TY_CAMERA_CALIB_INFO color_calib_info;
char tycam_version[32];
uint64_t record_duration_start;
uint64_t record_duration_stop;
};
#pragma pack()
#define IMAGE_HEADER_SIZE (4096)
static int GetFileSize(const char *file_name, uint64_t *file_byte_size)
{
FILE * fp;
if (!(fp = fopen(file_name, "rb")))
{
return (-1);
}
#if defined(_WIN32) || defined(_WIN64)
#if _MSC_VER >= 1400
if (_fseeki64(fp, (uint64_t)(0), SEEK_END))
{
fclose(fp);
return (-1);
}
*file_byte_size = _ftelli64(fp);
#else
#error Visual Studio version is less than 8.0(VS 2005) !
#endif
#else
if (fseeko(fp, (uint64_t)(0), SEEK_END))
{
fclose(fp);
return (-1);
}
*file_byte_size = ftello(fp);
#endif
fclose(fp);
return 0;
}
static inline int parseImage(const TY_IMAGE_DATA& image, cv::Mat* pDepth
, cv::Mat* pLeftIR, cv::Mat* pRightIR
, cv::Mat* pColor)
{
if (pDepth && image.componentID == TY_COMPONENT_DEPTH_CAM){
if (image.pixelFormat == TY_PIXEL_FORMAT_XYZ48)
*pDepth = cv::Mat(image.height, image.width, CV_16SC3, image.buffer).clone();
else
*pDepth = cv::Mat(image.height, image.width, CV_16U, image.buffer).clone();
}
else if (pLeftIR && image.componentID == TY_COMPONENT_IR_CAM_LEFT)
parseIrFrame(&image, pLeftIR);
else if (pRightIR && image.componentID == TY_COMPONENT_IR_CAM_RIGHT)
parseIrFrame(&image, pRightIR);
else if (pColor && image.componentID == TY_COMPONENT_RGB_CAM)
parseColorFrame(&image, pColor);
else
return -1;
return 0;
}
int main(int argc, char* argv[])
{
if(argc != 2) {
printf("Need to specify a file!\n");
return -1;
}
uint64_t file_length;
int error_code = GetFileSize(argv[1], &file_length);
if(error_code < 0) {
printf("Could not get file size!\n");
return -1;
}
FILE* fp = fopen(argv[1], "rb");
if(fp == NULL) {
printf("Failed to open file!\n");
return -1;
}
std::vector<char> header_buffer(IMAGE_HEADER_SIZE);
size_t cnt = fread(&header_buffer[0], 1, IMAGE_HEADER_SIZE, fp);
if(cnt < IMAGE_HEADER_SIZE) {
printf("File format error!\n");
fclose(fp);
return -1;
}
RecordInfo* pBagInfo = (RecordInfo*)&header_buffer[0];
StreamInfo* pStreamInfo = (StreamInfo*)(&header_buffer[0] + sizeof(RecordInfo));
printf("tycam version : %s\n", pBagInfo->tycam_version);
printf("deice sn : %s\n", pBagInfo->dev_info.id);
bool depthStreaming = pBagInfo->depthStreaming;
bool colorStreaming = pBagInfo->colorStreaming;
bool lIrStreaming = pBagInfo->lIrStreaming;
bool rIrStreaming = pBagInfo->rIrStreaming;
bool component = pBagInfo->allComps;
int32_t stream_cnt_per_frame = 0; //stream_size
if (depthStreaming) stream_cnt_per_frame++;
if (colorStreaming) stream_cnt_per_frame++;
if (lIrStreaming) stream_cnt_per_frame++;
if (rIrStreaming) stream_cnt_per_frame++;
uint64_t record_duration = pBagInfo->record_duration_stop - pBagInfo->record_duration_start;
std::vector<char> stream_header(sizeof(int32_t) * 5);
uint64_t stream_length = file_length - IMAGE_HEADER_SIZE;
uint32_t frame_size = 0;
for (int32_t i = 0; i < stream_cnt_per_frame; i++) {
cnt = fread(&stream_header[0], sizeof(int32_t) * 5, 1, fp);
frame_size += ((int32_t*)(&stream_header[0]))[4];
fseek(fp, ((int32_t*)(&stream_header[0]))[4], SEEK_CUR);
}
uint32_t playback_frame_rate, playback_total_frames;
uint64_t playback_duration = record_duration*1000*1000;
if (record_duration > 1000) {
playback_frame_rate = static_cast<uint32_t>((stream_length/(frame_size + sizeof(int32_t)*5*stream_cnt_per_frame))/(record_duration/1000));
playback_total_frames = static_cast<uint32_t>(stream_length/(frame_size + sizeof(int32_t)*5*stream_cnt_per_frame));
} else {
playback_frame_rate = 1;
playback_total_frames = 1;
}
fseek(fp, IMAGE_HEADER_SIZE, SEEK_SET);
#ifdef PERCIPIO_DPETH_RENDER_ENABLE
DepthRender depthViewer;
#endif
uint64_t start_time = 0;
uint64_t end_time = 0;
TY_IMAGE_DATA image;
std::vector<char> framebuffer[4];
while (true) {
start_time = getSystemTime();
if (feof(fp)) {
printf("Repeat!\n");
fseek(fp, IMAGE_HEADER_SIZE, SEEK_SET);
}
fread(&stream_header[0], sizeof(int32_t) * 5, 1, fp);
image.componentID = ((int32_t*)(&stream_header[0]))[0];
image.width = ((int32_t*)(&stream_header[0]))[1];
image.height = ((int32_t*)(&stream_header[0]))[2];
image.pixelFormat = ((int32_t*)(&stream_header[0]))[3];
image.size = ((int32_t*)(&stream_header[0]))[4];
if (image.componentID == TY_COMPONENT_DEPTH_CAM) {
if(framebuffer[0].size() < image.size) framebuffer[0].resize(image.size);
fread(&framebuffer[0][0], image.size, 1, fp);
image.buffer = &framebuffer[0][0];
} else if (image.componentID == TY_COMPONENT_RGB_CAM) {
if(framebuffer[1].size() < image.size) framebuffer[1].resize(image.size);
fread(&framebuffer[1][0], image.size, 1, fp);
image.buffer = &framebuffer[1][0];
} else if (image.componentID == TY_COMPONENT_IR_CAM_LEFT) {
if(framebuffer[2].size() < image.size) framebuffer[2].resize(image.size);
fread(&framebuffer[2][0], image.size, 1, fp);
image.buffer = &framebuffer[2][0];
} else if (image.componentID == TY_COMPONENT_IR_CAM_RIGHT) {
if(framebuffer[3].size() < image.size) framebuffer[3].resize(image.size);
fread(&framebuffer[3][0], image.size, 1, fp);
image.buffer = &framebuffer[3][0];
} else {
printf("Invalid component id!\n");
exit(-1);
}
cv::Mat depth, leftIR, rightIR, color;
parseImage(image, &depth, &leftIR, &rightIR, &color);
if(!depth.empty()) {
#ifdef PERCIPIO_DPETH_RENDER_ENABLE
cv::Mat dep_render = depthViewer.Compute(depth);
if(!dep_render.empty()) cv::imshow("depth", dep_render);
#else
cv::imshow("depth", depth * 15);
#endif
}
if(!leftIR.empty()) cv::imshow("leftIR", leftIR);
if(!rightIR.empty()) cv::imshow("rightIR", rightIR);
if(!color.empty()) cv::imshow("color", color);
int key = cv::waitKey(1);
if((key & 0xff) == 'q')
break;
end_time = getSystemTime();
float delt = ((playback_duration/(uint64_t)playback_total_frames)/(1000*1000) - (end_time - start_time)) / (stream_cnt_per_frame);
if(delt > 0) MSleep(static_cast<uint32_t>(delt));
}
fclose(fp);
printf("Main done!\n");
return 0;
}
2.1 运行编译后的Demo
使用Cmake-gui界面,编译完成后,使用VisualStudio软件生成解决方案后,生成对应的.exe文件,之后使用如下命令,即可解析.bag文件。
cpp
.\ decode test.exe .\bag名字

3.常见问题FAQ
3.1 编译过程中报错
在使用Cmake进行编译时,需要引入Opencv路径
3.2 保持的是否是ROS中的Rosbag包?
不是哦,历史原因,起的名字是Rosbag,非ROS中的Rosbag包。