CINE文件读取-Phantom高速摄像机

2023-05-16

CINE文件是由Phantom数码高速摄像机录制的视频格式,使用Phantom公司配套的软件Phantom CV可直接读取CINE文件并展示流场图像。

前段时间尝试直接读取CINE文件,找遍国内平台没有发现关于CINE文档结构的中文手册。结合github与CINE官方文档读取成功后,尝试做一个汉化版本,仅供参考。


1. CINE文件结构解析

1.1. CINE文件头 (CINEFILEHEADER structure)

1.2. 位图信息头(BITMAPINFOHEADER)

1.3. 相机设置信息Camera setup information

1.4. 标记的信息块(The tagged information blocks)

1.5. 图像数据(The image object)

1.5.1. 图像注释数据(The Annotation data)

1.5.2. 图像像素数据(Pixel array)

2. Python读取

2.1. 读取颜色过滤器阵列(CFA)

2.2. 10色深图像读取规则


1. CINE文件结构解析

官方文档链接:

The Cine File Format (force.com)

CINE文件分为四大部分:CINE文件头、位图信息头、相机设置信息、标记的信息块。

1.1. CINE文件头 (CINEFILEHEADER structure)

Camera setup information:包含版本信息、图像范围、绝对触发时间和文件中其他部分的偏移量。此文件头也包含在同步保存的.chd文件中,.chd文件是在Phantom软件将图像保存为CINE以外的文件格式时创建的。

1.2. 位图信息头(BITMAPINFOHEADER)

Windows structure for the image header:包含有关像素的图像尺寸和位深度的信息。与Windows系统下的BMP图像的结构类似,但某些字段的含义已扩展为支持每个颜色分量超过 8 位的图像。

1.3. 相机设置信息Camera setup information

包含在CINE录制过程中使用的采集参数。包含了图像的保存方式,要根据此部分设计读取功能。

SETUP结构包含采集参数、图像处理设置以及在CINE录制期间收集或使用的所有其他元数据。

相机、软件或其他外部设备会收集大量与图像采集同步的数据,例如:图像时间、曝光、模拟和二进制信号以及距离数据。范围数据包含诸如相机方向、到对象的距离等信息。

1.4. 标记的信息块(The tagged information blocks)

固定结构可以直接访问整个结构,使用起来非常简单快捷。为了允许未来的扩展或可选数据,我们将该模块添加到CINE格式中。

1.5. 图像数据(The image object)

包含两种类型的信息:图像注释数据和图像像素数据。

1.5.1. 图像注释数据(The Annotation data)

注释仅包括图像大小。如果图像未压缩,则可以从之前的信息中估计得到其大小,但如果图像被压缩,则无法计算大小,因此具有图像大小信息的注释块对于解析图像大小非常有用。

这里的压缩并不是传统意义上的图像压缩,而是储存方式的压缩,CINE存储时为了节省空间,会采用特殊的存储方式,因此无法从字节数估计。

1.5.2. 图像像素数据(Pixel array)

Phantom相机生成的图像的宽度倍数为16像素。在16位存储格式情况下,可能会根据不同录制需求有10、12、14位的实际深度和相应的值范围:[0,1023]、[0,4095]、[0,16383]。

下面这句很重要:

The values stored in the cine files are not left aligned, they are integer values stored as read from the sensor.

存储在电影文件中的值不是左对齐的,它们是存储为从传感器读取的整数值。这句话在读取图像像素数据的时候非常重要,如果不按照对应位处存储的方式去读取的话,则会导致什么都读不出,甚至出现读取错误!

2. Python读取

本文所有程序来自OTTOMATIC的GitHub主页:

GitHub - ottomatic-io/pycine: Reading Vision Research .cine files with python

在调试时遇到了两个问题,其他部分读取很顺利,参考CINE的官方文档都可以很顺利调试,整个过程需要两三天。下面具体说遇到的两个问题。

2.1. 读取颜色过滤器阵列(CFA)

第一个问题是源程序没有提供CFA=0的程序,恰巧我的文件就是灰度的,因此读起来会报错。

 考虑到我仅用于该任务,CFA与其他信息用不到,因此我读取header之后直接跳至pImage部分的第frame_index张图像进行处理。

frame_index = start_frame - 1
count_temp = count - frame_index
while count_temp:
    breakf.seek(header["pImage"][frame_index])

2.2. 10色深图像读取规则

 CINE的图像数据存储方式有非压缩压缩两种:

  1. 非压缩:如果位深度大于8,(10、12或14位),则值将作为16bits或者uint16_t、小端字节(little endian)存储在文件中,并用0填充到左侧(最高有效位)。 
  2. 压缩:在标准方法中,位深度大于8的任何像素都存储在单独的16位字中。在10位像素的情况下,通过将填充改为16位并在5个字节中存储4个像素,可以更有效地存储信息。 

上图展示的10bit图像压缩方式。四个压缩像素P0、P1、P2和P3存储在5个字节中:字节0、字节1、字节2、字节3和字节4(字节0位于最低内存地址,P0.9为像素0的第10位,即像素0的最高有效位)。这种压缩方式占用的空间是非压缩方式的80%,通常用在需要快速实时数据传输的场合中,当电影存储在CineMag中或通过10g以太网适配器读取图像时。

该段代码演示的是读取图像数据(The image object):其中packed就是上图的Byte0~5,unpacked就是上图中的P0~P3:

# 创建空二维数组储存图像像素
P = np.zeros([height, width], dtype="uint16")
# 读取图像长度
image_size = struct.unpack("I", f.read(4))[0]
data = f.read(image_size)
# 以数据流的方式读入
Byte = np.frombuffer(data, dtype="uint8",).astype(np.uint16)
P.flat[0::4] = ((Byte[0::5] & 0b11111111) << 2) | (Byte[1::5] >> 6)
P.flat[1::4] = ((Byte[1::5] & 0b00111111) << 4) | (Byte[2::5] >> 4)
P.flat[2::4] = ((Byte[2::5] & 0b00001111) << 6) | (Byte[3::5] >> 2)
P.flat[3::4] = ((Byte[3::5] & 0b00000011) << 8) | Byte[4::5]

f.read(4)读取图像注释数据,长度为4个字节。我读取的文件宽1280×高800,4个字节unpack之后image_size=1280000。这一步也可以看出压缩规则:每个像素是10bit,一共有1280×800=1024000个像素,因此共占用:1280×800×10bit=1280000(image_size)×8bit=10240000bit。

Byte = f.read(image_size),读取对应长度的1280000个字节。此时的Byte为二进制格式。

 将Byte以frombuffer数据流的方式、uint8的格式读入P,并转为uint16的格式,把1280000(image_size)×8bit看作1280000个0~255的数字。

以第一行为例:

  1. P.flat[0::4]:代表解压缩后的图像像素数据从第0位开始每隔4个像素存储在P中;
  2. Byte[0::5]和Byte[1::5]:代表第1个字节和第2个字节分别从从0位和从1位每隔5位读取,以8位的二进制形式(只有0和1);
  3. (Byte[0::5] & 0b11111111):“&”符号表示的是二进制中的位运算:按位与。0b表示二进制,与0b11111111进行按位与运算表明截取1位置的状态,截去0位置的状态。这是最简单的位运算,如果不理解的话就去看二进制位运算。举个例子:0b11001100& 0b11111111=0b11001100。该步运算的目的是从第0位开始取每隔5个字节Byte的全部位。
  4. ((Byte[0::5] & 0b11111111) << 2):“<<”符号表示的是二进制中的移位操作,“<<”是左移两位,右侧补0,若当前数据类型长度不足且不变,高位丢弃;“>>”是右移两位,高位补0,低位丢弃。该步运算的目的是将当前Byte(第0位开始每隔5个字节)读到的8bit左移2位,为该像素的前2位(在下一个)腾出空间。由于在读取data后已转换为uint16,左侧全部补0,因此在左移操作时高位会保留下来,不会被丢弃。
  5. (Byte[1::5] >> 6):该步运算的目的是将当前Byte(第1位开始每隔5个字节)读到的2bit右移6位,做好移至上个Byte左移2位腾出来的空位上的准备。
  6. ((packed[0::5] & 0b11111111) << 2) | (packed[1::5] >> 6):“|”是或操作,当两个位都为0时,结果才为0。该步运算的目的是拼接上两步操作得到的8bit与2bit,得到10bit的数据。

以上就是四行代码中第一行的解读,另三行同理,照着压缩结构图与步骤慢慢理解。

uint8类型读取uint16类型转换非常关键,缺一不可:

  1. 只以uint8的方式读不转为uint16的话,会导致左移操作时高位丢失,无法正确读取数据。
  2. 直接以uint16的类型读取也可以,但压缩示意图就变了,需要重新设计解压缩程序。理论上可行,但没有试过。既然官方文档是10bit压缩至1字节中的压缩结构,就不推荐用其他的数据类型读取了。

其他部分配合官方文档和程序都可以慢慢调试出来,在此不再详细分析。

如果文中有任何错误欢迎评论区和私信指出,有问题欢迎友好交流。

位运算(&、|、^、~、>>、 | 菜鸟教程 (runoob.com)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CINE文件读取-Phantom高速摄像机 的相关文章

  • 【自学Docker 】Docker port命令

    Docker port命令 概述 docker port命令教程 docker port 命令可以用于列出指定的 Docker容器 的端口映射 xff0c 或者将容器里的端口映射到宿主机 该命令后面的 CONTAINER 可以是容器Id x
  • 【自学Docker】Docker pull命令

    大纲 Docker pull命令 docker pull命令教程 docker pull 命令用于从镜像仓库中拉取或者更新指定镜像 docker pull 命令中的 name 即镜像名称后面可以跟上镜像标签或者镜像摘要 docker pul
  • 【自学Docker】Docker push命令

    大纲 Docker push命令 docker push命令教程 docker push 命令用于将本地的 Docker镜像 上传到 Docker镜像仓库 docker push命令使用之前需要要先登陆到镜像仓库 docker push命令
  • 【自学Linux】Linux运行级别

    Linux运行级别 Linux运行级别教程 Linux 可以支持运行级别的设置 xff0c 运行级别就是操作系统当前正在运行的功能级别 xff0c 级别是从 0 到 6 Centos7 系统之前的版本是通过 etc inittab 文件来定
  • 【自学Linux】 Linux文件目录结构

    Linux文件目录结构 Linux文件目录结构教程 在 Linux 中 xff0c 有一个很经典的说法 xff0c 叫做一切皆文件 xff0c 因此 xff0c 我们在系统学习 Linux 之前 xff0c 首先要了解 Linux 的文件目
  • 【自学Linux】Linux一切皆文件

    Linux一切皆文件 Linux一切皆文件教程 Linux 中所有内容都是以文件的形式保存和管理的 xff0c 即一切皆文件 xff0c 普通文件是文件 xff0c 目录是文件 xff0c 硬件设备 xff08 键盘 监视器 硬盘 打印机
  • 链路聚合--Eth-Trunk

    链路聚合技术是解决二层交换机多条链路产生环路的问题 xff0c 不仅避免了环路问题 xff0c 还提高了数据的传输效率 链路聚合分为两种模式 xff1a 手动模式和LACP模式 手动模式 手动模式就是人工的方式去创建Eth Trunk和成员

随机推荐

  • 块元素和内联元素的特点和区别

    lt css基础之块级元素和内联元素 块级元素的特点 xff1a 1 占一整行 2 是一个矩形 3 可定义宽度和高度 xff0c 内边距 xff0c 外边距等 4 其display属性默认为block 内联元素的特点 xff1a 1 并不占
  • 在vs code中使用git

    在vs code使用git 1 下载安装git 下载地址 xff1a Git Downloads 下载后安装选择默认选项即可 2 安装完成后 xff0c 设置git的环境变量 xff1a 在系统的path环境变量中添加git exe的安装目
  • Ubuntu下压缩与解压缩

    一 linux下常用的压缩格式 linux下常用的压缩扩展名有 xff1a tar tar bz2 tar gz 二 Windows下7ZIP软件的安装 因为Linux下很多文件是bz2 gz结尾的文件 xff0c 因此需要在windows
  • VIO的图优化模型

    因子图结构 VIO在纯视觉的基础上添加了IMU约束 xff0c 因子图如下 xff1a 状态变量 VIO中 xff0c 待估计的状态变量为 i 61 R
  • CMakeLists写法总结

    个人最近学习了一些关于常见的CMakeLists的一些写法格式 xff0c 分享给大家 CMAKE MINIMUM REQUIRED VERSION xxx 该项表示要求CMAKE的最低版本号 PROJECT aim1 此项表示所建立的工程
  • Qt两种传参形式(信号槽传参、界面传参)

    一 UI界面传参 在Qt中传输数据通常有两种形式 xff0c 一种是把待传输的数据先保存到UI界面的控件中 xff0c 然后子类从界面中读取数据 使用该控件作为参数传递承载 1 首先将计算出的数值传到控件中 ui span class to
  • Intel RealSense T265 Windows10 环境下运行

    Intel RealSense T265 Windows10 环境下运行 最近从某宝上买了个T265 体验了下 intel的硬件开发 卖家怕我不会用还专门问了我会不会用 intel的包装里面不带那个很酷炫的三脚架 xff01 xff01 x
  • TB6612FNG电机驱动替代方案

    最近东芝的一个很常用的电机驱动芯片TB6612FNG停产 xff0c 这是一个全桥驱动芯片 xff0c 经过测试 xff0c 两款比较好的替代芯片有ST公司的L298系列 xff0c L293D系列和VNH5019系列的全桥驱动器 这里的完
  • 关于链表中头指针和头结点的理解

    线性表使用顺序 xff08 数组 xff09 存储时有个弊端 xff0c 那就是在插入和删除时需要大量的移动数据 xff0c 这显示是非常消耗时间的 xff0c 所以可以采用链式存储 xff0c 即有一个指针域 xff08 单链表 xff0
  • 相对深度与绝对深度,深度图与真实距离

    刚开始看单目深度估计 xff0c 好多概念都不清楚 xff0c 下面是我的理解 xff0c 有不对之处希望大佬指出 首先是相对深度和绝对深度的概念 绝对深度就是利用激光雷达等设备获取的相机与物体之间的距离 xff0c 比如KITTI数据集就
  • Gazebo和ROS通信实现发球

    ROS版本 xff1a ROS Kinetic 操作系统 xff1a Ubuntu16 04 LTS YouTube上有一个视频 xff0c 是一个乒乓球机器人在gazebo里面的方针 https www youtube com watch
  • apt: 如何通过apt-get 来安装自己的程序-----apt本地源的学习

    本文档介绍使用apt mirror软件搭建apt本地源 需求 xff1a 内网开发环境由于其特定原因不能上外网 xff0c 所以需要本地环境下的内网源来方便开发人员下载安装软件 建议 xff1a 单独使用一块磁盘来存放源文件或者单独一个目录
  • Gazebo中加入一个双目相机及相机参数设置

    ROS版本 xff1a ROS Kinetic 操作系统 xff1a Ubuntu16 04 LTS kinect 为了在gazebo中观察并利用利用视觉进行小球的定位并与ros通信 xff0c 我们需要一个深度相机 xff0c 这时可以直
  • 树莓派4B开机运行自己的QT5程序,不进入图形化界面。

    最近做项目 xff0c 遇到一个需求 xff0c 使用树莓派连接显示屏 xff0c 但是为了保密性 xff0c 不能进入桌面 xff0c 直接运行自己的图形化界面 刚开始翻阅了很多网友大神写的教程 xff0c 但是在树莓派方面 xff0c
  • 详解Python中def __init__(self)与def __init__(self.参数1、参数2······)的区别

    两者的主要区别 1 初始化参数为空的表述方式不同 2 初始化附参数的表达方式不同 结构2的self name一定要指向上面的参数 3 实例化时的方法不同 def init xff08 self xff09 与def init xff08 s
  • Threat of Adversarial Attacks on Deep Learning in Computer Vision A Survey

    Attacks for classification Box constrained L BFGS Fast Gradient Sign Method FGSM Basic amp Least Likely Class Iterative
  • ssh端口映射-访问本地映射的目标主机映射的Docker容器中的jupyter

    背景 xff1a 我的电脑是本地主机 xff0c 同事的电脑 xff08 3080TI xff09 是目标主机 xff0c 系统中有容器 xff0c 我需要连接目标主机中的容器 xff0c 需要图形界面或文件夹目录 只使用vscode或SF
  • Anaconda虚拟环境下Pytorch CPU GPU版本安装

    目录 1 python安装 xff1a Anaconda 1 1 Anaconda与Python 1 2 下载anaconda 1 3 conda与pip的区别 1 4 虚拟环境 1 4 1 虚拟环境的作用 1 4 2 创建虚拟环境 1 4
  • Zerotier+Microsoft远程桌面 实现内网穿透搭建异地局域网内远程连接控制桌面

    目录 1 Zerotier配置 1 1 安装Zerotier 1 2 创建网络 1 3 远程设备与被控制主机加入网络 2 Microsoft 远程桌面配置 2 1 软件安装 2 2 被控制主机开启远程桌面服务 2 3 添加被控制主机IP 2
  • CINE文件读取-Phantom高速摄像机

    CINE文件是由Phantom数码高速摄像机录制的视频格式 xff0c 使用Phantom公司配套的软件Phantom CV可直接读取CINE文件并展示流场图像 前段时间尝试直接读取CINE文件 xff0c 找遍国内平台没有发现关于CINE