TianMouCV 算法库

TianMouCV是一个专门为Tianmouc传感器(混合时空差分-帧的互补视觉传感器)设计的高性能计算机视觉库。 它结合了传统基于帧(Frame-based)的视觉算法和新兴的基于时空差分数据(TSD-based)的视觉处理技术 旨在提供高动态范围(HDR)、高帧率重建,支持低延迟追踪、检测、交互和稳健的光流估计等功能。

目前文档基于 Tianmoucv-0.4.2.0 版本

安装指南

Unix 系统安装

  1. 安装基本的编译工具:

sudo apt-get update
sudo apt-get install make cmake build-essential

注:macOS 使用 brew 安装 gcc/g++,install 默认使用 g++。

brew install make cmake gcc
  1. 安装 Python 和 PyTorch(推荐使用 CUDA 版本与 Anaconda):

conda create -n tianmoucv --python=3.10
conda activate tianmoucv
conda install pytorch torchvision torchaudio pytorch-cuda=12.0 -c pytorch -c nvidia
  1. 执行自动安装脚本:

pip install tianmoucv -i https://pypi.tuna.tsinghua.edu.cn/simple

或者从源码安装:

git clone https://github.com/Tianmouc/tianmoucv.git
cd tianmoucv
sh install.sh

Windows 系统安装

  1. 安装基本的编译工具(MinGW, Make, CMake, Git):

注意:将 MinGW 的 bin 文件夹路径添加到系统环境变量 PATH 中。

  1. 安装 Python 和 PyTorch:

conda create -n tianmoucv --python=3.10
conda activate tianmoucv
conda install pytorch torchvision torchaudio pytorch-cuda=12.0 -c pytorch -c nvidia
  1. 执行自动安装脚本:

git clone git@github.com:Tianmouc/tianmoucv.git
cd tianmoucv
./install.bat

软件包结构与功能概览

TianMouCV 核心包分为以下几个主要模块:

  • tianmoucv.camera: 相机 SDK 与实时流接口,支持多目相机同时使用及自动曝光控制。

  • tianmoucv.data: 灵活的数据读取器,支持多种格式(.tmdat, PCIe 二进制数据)和数据集管理。

  • tianmoucv.isp: 图像信号处理,包含 RAW 到 RGB 处理、高动态范围(HDR)融合、去马赛克及可视化工具。

  • tianmoucv.proc: 核心算法库,分为特征提取、光流估计、图像重建和目标追踪等子模块。

  • tianmoucv.sim: 传感器软件仿真器,能够模拟真实硬件的 2x2 ROD 分簇结构、多种噪声模型(泊松噪声、读出噪声、固定模式噪声等)以及稀疏编码逻辑。

  • tianmoucv.rdp: 数据解码与协议处理模块。

数据格式说明 (TMDAT)

TMDAT 是 Tianmouc 传感器记录数据的标准格式。一个典型的数据集结构如下:

├── dataset_root/
│   ├── sample_name (matchkey)/
│   │   ├── cone/
│   │       ├── info.txt
│   │       ├── xxx.tmdat  (存储 RGB/RAW 数据,低帧率)
│   │   ├── rod/
│   │       ├── info.txt
│   │       ├── xxx.tmdat  (存储 TD, SDL, SDR 数据,高帧率)
  • CONE (RGB): 对应低帧率高分辨率的图像流(30.3 fps)。

  • ROD (TSD): 对应高帧率(最高 10000 fps)的差分数据流。

  • matchkey: 数据集索引中的唯一标识。

调用示例说明

tianmoucv_example 目录下提供了丰富的示例程序,涵盖了从基础控制到高级算法的应用:

基础控制与数据处理

  • 相机操作: camera/open_camera.py (开启相机流), camera/TMC_GUI_controller.py (图形界面控制器)。

  • 数据管理: introduction_to_tianmouc_data.ipynb (详细讲解 TMDAT 格式与读取方式)。

  • 格式转换: data/convert_pcie_bin_to_tmdat.py (将 PCIe 二进制数据转换为标准 TMDAT 格式)。

传感器仿真 (Simulator)

核心算法应用 (Proc)

  • 光流估计 (Optical Flow):
    • proc/optical_flow/opticalflow_HS_method.ipynb (传统 Horn-Schunck 方法)。

    • proc/optical_flow/opticalflow_LK_method.ipynb (传统 Lucas-Kanade 方法)。

    • proc/optical_flow/opticalflow_spynet.ipynb (深度学习 SpyNet 模型)。

  • 图像重建 (Reconstruction):
    • proc/reconstructor/reconstruct_gray.ipynb (基础灰度重建)。

    • proc/reconstructor/reconstruct_tiny_unet.ipynb (轻量级 UNet 重建)。

    • proc/reconstructor/SLIM/ (自监督运动图像学习算法实现)。

  • 目标追踪 (Tracking):
    • proc/feature_tracking_sd.ipynb (基于 SD 数据的特征点提取与追踪)。

  • 图像增强:
    • proc/denoise/denoise_tmdat_lvatf.ipynb (低照度降噪算法)。

    • proc/deblur/deblur_stgdnet.ipynb (基于时空梯度的去模糊算法)。

API 接口详细说明

相机接口 (tianmoucv.camera)

主要提供相机连接、流媒体读取和自动曝光等功能。

class tianmoucv.camera.sdk_utils.TMstreamingDataReader(cfg_path=None, lib_path=None, device_id=0)[源代码]

这段代码实现了一个名为TMstreamingDataReader的类,作为数据读取器。 类的初始化方法(init)中,加载了SDK库文件,并初始化了相机。

@parameter cfg_path: csv格式的配置文件 @parameter lib_path: 预编译的sdk动态链接库,ubuntu为.so,windows为.dll,macOS为,dylib @parameter device_id: 相机的id,支持多目相机同时使用

主要函数说明:

  • __init__方法:加载SDK库文件,初始化相机,准备数据包。

  • setExposure方法:设置相机的曝光时间。

  • __enter__方法:开始读取数据。

  • __exit__方法:处理异常并停止相机。

  • __call__方法:读取数据帧并返回。

这段代码的功能是通过SDK库读取相机的数据帧并进行处理,提供了读取数据和设置曝光时间的接口。 在使用该类时,可以通过with语句自动调用__enter__和__exit__方法,确保资源的正确释放。

数据读取 (tianmoucv.data)

支持从本地存储读取 Tianmouc 原始数据并进行预处理。

class tianmoucv.data.tianmoucData.TianmoucDataReader(path, N=1, camera_idx=0, aop_denoise=False, aop_denoise_args=None, showList=True, MAXLEN=-1, uniformSampler=False, matchkey=None, cachePath=None, ifcache=False, print_info=True, training=True, strict=False, use_data_parser=False, _correct_sd_upsampler=False, dark_level=0)[源代码]
  • TianmoucDataReader(version 0.3.7.4 in dev)
    • Data structure

      ├── dataset │ ├── matchkey(sample name) │ │ ├── cone │ │ ├── info.txt │ │ ├── xxx.tmdat │ │ ├── rod │ │ ├── info.txt │ │ ├── xxx.tmdat │ │ ├── cone1 │ │ ├── info.txt │ │ ├── xxx.tmdat │ │ ├── rod1 │ │ ├── info.txt │ │ ├── xxx.tmdat

    • @dataPath:
      • a path to a sample/dataset: string

      • a list of dataset path/sample: [string1, string2]

      • if the path is belong to a dataset/datasets or a list of samples, please use matchkey to index a certain sample, or set matchkey = None

      • if you use multiple camera, set camera_idx

    • @matchkey:
      • matchkey should be unified, is the only key to select data sample

      • matchkey is the folder name containing the cop/aop data folder

    • @N: number of continous samples, N=1 as default
      • the returned sample will contain (N+1) COP,and N*M+1 AOP

      • for example N=1, in 750@8bit, M=750/30=25, M = 25, a sample contain 2 COP and 26 AOP

    • @camera_idx:
      • camera_idx = 0 as default

      • in multi-camera system, use camera_idx to create a dataset fot certain camera

    • @MAXLEN:
      • the maximum read data length, set -1 to read all data, used only in training task

    [Output] create a dataset, the containings please refer to TianmoucDataReader.__getitem__()

packRead(idx, key, ifSync=True, needPreProcess=True)[源代码]

use the decoder and isp preprocess to generate a paired (RGB,n*TSD) sample dict:

  • COP
    • COP is stored seprately as F0,F1,F2 … FN+1, use string key to get them

    • COP’s framerate is 30.3fps

    • i = 0~N

    • sample[‘Fi_without_isp’] = only demosaced frame data, without addtional isp 3*320*640, t=t_0+i*T

    • sample[‘Fi_HDR’]: RGB+SD Blended HDR frame data, 3*320*640, t=t_0+i*T ms

    • sample[‘Fi’]: preprocessed frame data, 3*320*640, t=t_0+i*T ms

  • AOP
    • AOP data is stored in a large tensor, [T,C,H,W]

    • channel 0 is TD, channel 1 is SDL, channel 2 is SDR

    • sample[‘tsdiff’] = TSD data upsample to (N+1)*3*320*640, from t=t_0 to t=t+ N*T ms (eg. T=33 in 757 @ 8 bit mode)

    • sample[‘rawDiff’]: raw TSD data, (N+1)*3*160*160, from t=t_0 to t=t+ N*T ms (eg. T=33 in 757 @ 8 bit mode)

    • all tianmoucv API use sample[‘rawDiff’] for input, sample[‘tsdiff’] is used by some NN-based method

  • sample[‘meta’]:
    • a dict

    • file path infomation

    • camera timestamps for each data

    • more other details

  • sample[‘labels’]:
    • list of labels, if you have one

  • sample[‘sysTimeStamp’]: unix system time stamp in us, use for multi-sensor sync, -1 if not supported
    • you can calculate Δt = sysTimeStamp1-sysTimeStamp2, unit is ‘us’

get_dark_noise()[源代码]

inspect dark noise or calibrate dark noise data

choose_correct_fpn(thr_fpn=1, idx=0)[源代码]

空间噪声

get_raw_tsdiff_(index)[源代码]

只拿原始rod数据和其绝对id,提升效率

td_fpn_calibration_(Num=20)[源代码]

计算奇数帧和偶数帧TD空间噪声,Num为标定所用的index数量

sd_fpn_calibration_(Num=20)[源代码]

计算奇数index帧和偶数index帧TD空间噪声,Num为标定所用的index数量 返回标定的SD_mean_left, SD_mean_right

图像处理 (tianmoucv.isp)

提供 RAW 图像到 RGB 图像的转换,以及差分数据的可视化。

tianmoucv.isp.isp_basic.default_rgb_isp(raw, blc=0, gamma=0.9, raw_input=True)[源代码]

默认的RGB RAW数据处理流程

  • 空洞填补

  • 去马赛克

  • 白平衡

  • 自适应降噪

  • 自动饱和度

  • 自动曲线

  • 自动归一化

注意: 速度非常慢,仅供参考

tianmoucv.isp.isp_basic.ACESToneMapping(color, adapted_lum=1)[源代码]

https://zhuanlan.zhihu.com/p/21983679

tianmoucv.isp.isp_basic.Scurve(Y, curve_factor)[源代码]

曲线调整 :param img: cv2.imread读取的图片数据 :curve_factor: 增加对比度,值越大对比度越大 :return: 返回的白平衡结果图片数据

tianmoucv.isp.isp_basic.adjust_curve(image, curve_factor=0.02)[源代码]

曲线调整

tianmoucv.isp.isp_basic.adjust_saturation(image, saturation_factor=(128, 256))[源代码]

饱和度调整

参数:

img – cv2.imread读取的图片数据

Saturation_factor:

增加饱和度,saturation_factor越大饱和度越大

返回:

返回的饱和度结果图片数据

tianmoucv.isp.isp_basic.lyncam_raw_comp(raw)[源代码]

Tianmouc Bayer 填充

Author: Taoyi Wang

tianmoucv.isp.isp_basic.exp_bayer_to_rgb_conv(bayer_image)[源代码]

# Define convolution kernels for each color channel # These kernels are designed to average the surrounding pixels # Kernel for Red and Blue channels (they are at the corners of the Bayer pattern) lyh testing

tianmoucv.isp.isp_basic.demosaicing_npy(bayer=None, bayer_pattern='bggr', level=0, bitdepth=8)[源代码]

Call this function to load raw bayer image :param bayer: input bayer image :param level: demosaicing level. 0: bilinear linear; 1: gradient :param bayer_type: bayer_type: : 0–RGrRGr…GbBGbB, 1–GrRGrR…BGbBGb… Author: Taoyi Wang

传感器仿真器 (tianmoucv.sim)

模拟传感器硬件逻辑,生成合成数据。

  • run_sim: 高级接口,处理图像序列文件夹,输出完整的数据集结构。

  • run_sim_singleimg: 简单接口,处理单张图像,输出仿真的差分张量。

tianmoucv.sim.simple_tmc_sim_advance.push_to_fifo(tensor, x)[源代码]

push to fifo, depth = self defined

参数:
  • tensor (torch.tensor) – fifo tensor

  • x (torch.tensor) – new data

返回:

new fifo tensor

返回类型:

torch.tensor

tianmoucv.sim.simple_tmc_sim_advance.visualize_diff(diff_out, vis_gain, color='rg')[源代码]

diff data visualization

参数:
  • diff_out (_type_) – _description_

  • vis_gain (_type_) – _description_

  • color (str, optional) – _description_. Defaults to ‘rg’.

返回:

_description_

返回类型:

_type_

tianmoucv.sim.simple_tmc_sim_advance.diff_response(pix_v_out, threshold, sim_cnt, device, fpn=None, xy=False)[源代码]
参数:
  • float (pix_v_out, original input, please convert to) – 3D tensor, [2, H, W]

  • threshold – dict, {‘td’: float, ‘sd’: float}

  • sim_cnt – int, simulation counter, the number of frames simulated

  • device – torch.device, cuda or cpu

  • fpn – dict, optional fixed pattern noise

  • xy – bool, whether to return SDX and SDY

返回:

td_quantized, sdl_quant, sdr_quant (or sdx, sdy if xy=True)

tianmoucv.sim.simple_tmc_sim_advance.get_fpn_from_stat(rod_height, rod_width, device)[源代码]

Generate Fixed Pattern Noise (FPN) from dark_fpn_stat.

算法库 (tianmoucv.proc)

特征库 (features)

tianmoucv.proc.features.diff.gaussain_kernel(size=5, sigma=2)[源代码]

generate Gaussain blur kernel

parameter:
param size:

特征的数量,int

param sigma:

高斯标准差,int

tianmoucv.proc.features.diff.gaussian_smooth(inputTensor: Tensor, kernel: Tensor) Tensor[源代码]

用现有高斯核做高斯模糊

parameter:
param inputTensor:

待处理矩阵,torch.Tensor

param kernel:

高斯模糊核,torch.Tensor

return:

处理后同尺寸模糊图,torch.Tensor

tianmoucv.proc.features.diff.HarrisCorner(Ix: Tensor, Iy: Tensor, thresh=0.1, k=0.1, size=5, sigma=1, nmsSize=11)[源代码]

Harris 角点检测

\[R=det(H)−ktrace(H)\]
\[\lambda1 + \lambda2 = \sum I_x^2 * \sum I_y^2 - \sum I_{xy} ^ 2\]
\[\lambda1 * \lambda2 = \sum I_{xy} ^ 2\]
\[R = det H - k trace H ^2= \lambda_1*\lambda_2 - k(\lambda_1 + \lambda_2)^ 2\]
\[= (\sum I_{X^2} * \sum I_{y^2} - \sum I_{xy} ^ 2) - k (\sum I_x^2 + \sum I_y^2)^2\]
parameter:
param Ix:

x方向梯度,[h,w],torch.Tensor

param Iy:

y方向梯度,[h,w],torch.Tensor

param size:

高斯核尺寸,int

param th:

控制阈值,范围是0-1,对梯度来说应该设小一点,float

param nmsSize:

最大值筛选的范围

param k:

是一个经验参数,0-1,float

tianmoucv.proc.features.diff.TomasiCorner(Ix: Tensor, Iy: Tensor, index=1000, size=5, sigma=2, nmsSize=11)[源代码]

Shi-Tomasi 角点检测 在Harris角点检测的基础上,Shi和Tomasi 在1993的一篇论文《Good Features to track》中提出了基于Harris角点检测的Shi-Tomasi方法。 经验参数需求更少,更快,但效果变差

parameter:
param Ix:

x方向梯度,[h,w],torch.Tensor

param Iy:

y方向梯度,[h,w],torch.Tensor

param size:

高斯核尺寸,int

param index:

前N个点,int

param nmsSize:

最大值筛选的范围

tianmoucv.proc.features.diff.hog(Ix: Tensor, Iy: Tensor, kplist: list)[源代码]

hog 特征描述

parameter:
param Ix:

x方向梯度,[h,w],torch.Tensor

param Iy:

y方向梯度,[h,w],torch.Tensor

param kplist:

list of [x,y] 需要hog的坐标list, list

tianmoucv.proc.features.diff.compute_multiscale_sift_descriptor(Ix: Tensor, Iy: Tensor, kp_list: list, num_levels=6)[源代码]

计算 Harris 角点的 SIFT 特征描述子

参数:
  • Ix (Tensor) – x 方向的梯度张量

  • Iy (Tensor) – y 方向的梯度张量

  • kp_list (list) – 每个元素为 (x, y, level) 的角点列表

返回:

包含每个角点 SIFT 描述子的列表,形状为 [num_kp, 128]

返回类型:

descriptors

光流算法 (opticalflow)

tianmoucv.proc.opticalflow.estimator.local_norm(Diff: Tensor) Tensor[源代码]

梯度归一化

parameter:
param SD:

待归一化项

tianmoucv.proc.opticalflow.estimator.LK_optical_flow(SD: Tensor, TD: Tensor, win=5, stride=0, mask=None, ifInterploted=False) Tensor[源代码]

LK方法计算稠密光流

\[[dx,dy]*[dI/dx,dI/dy]^T + dI/dt = 0\]
parameter:
param SD:

原始SD,SD[0,1]: x,y方向上的梯度,[2,h,w],torch.Tensor

param TD:

原始SD,TD[0]: t方向上的梯度,[1,h,w],torch.Tensor

param win=5:

取邻域做最小二乘,邻域大小

param stride=0:

取邻域做最小二乘,计算步长

param mask=None:

特征点tensor,binary Tensor,[h,w]

param ifInterploted = False:

计算结果是否与COP等大

tianmoucv.proc.opticalflow.estimator.HS_optical_flow(SD: Tensor, TD: Tensor, ifInterploted=False, epsilon=1e-08, maxIteration=50, scales=4, labmda=10) Tensor[源代码]

多尺度HS方法计算稠密光流,效果更好 parameter:

param SD:

原始SD,SD[0,1]: x,y方向上的梯度,[2,h,w],torch.Tensor

param TD:

原始SD,TD[0]: t方向上的梯度,[1,h,w],torch.Tensor

param ifInterploted = False:

计算结果是否与COP等大

param epsilon = 1e-8:

收敛界

param maxIteration = 50:

最大迭代次数

param scales = 4:

尺度数量

param labmda=10:

惩罚因子,越大光流越平滑

重建算法 (reconstruct)

目标追踪 (tracking)

tianmoucv.proc.tracking.feature_tracker.feature_matching(des1: array, des2: array, ratio=0.85)[源代码]

Match SIFT descriptors between two images.

parameter:
param des1:

kp list1,[x,y],list

param des2:

kp list2,[x,y],list

param ratio:

knn中前两个匹配的距离的比例,筛选匹配得足够好的点, float

tianmoucv.proc.tracking.feature_tracker.mini_l2_cost_matching(des1, des2, num=20)[源代码]

Match SIFT descriptors between two images.

parameter:
param des1:

kp list1,[x,y],list

param des2:

kp list2,[x,y],list

param num:

筛选匹配得足够好的点, int

tianmoucv.proc.tracking.feature_tracker.align_images(image, kpList1, kpList2, matches, canvas=None)[源代码]

单应性矩阵,刚性对齐

parameter:
param image:

np图像,np.array

param kpList1:

kp list [x,y],list

param kpList2:

kp list [x,y],list

param matches:

匹配点列表 [id1,id2],list

详细示例索引