解析图漾相机录制的bag视频文件

文章目录

  • 前言
  • 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包。

相关推荐
爱凤的小光7 个月前
图漾相机错误码解析
数码相机·图漾相机
爱凤的小光7 个月前
图漾相机——Sample_V2示例程序(待补充)
3d·图漾相机
爱凤的小光9 个月前
图漾PercipioIPTool软件使用
图漾相机
爱凤的小光1 年前
图漾相机基础操作
图漾相机