TianMouCV 算法库
TianMouCV是一个专门为Tianmouc传感器(混合时空差分-帧的互补视觉传感器)设计的高性能计算机视觉库。 它结合了传统基于帧(Frame-based)的视觉算法和新兴的基于时空差分数据(TSD-based)的视觉处理技术 旨在提供高动态范围(HDR)、高帧率重建,支持低延迟追踪、检测、交互和稳健的光流估计等功能。
目前文档基于 Tianmoucv-0.4.2.0 版本
安装指南
Unix 系统安装
安装基本的编译工具:
sudo apt-get update
sudo apt-get install make cmake build-essential
注:macOS 使用 brew 安装 gcc/g++,install 默认使用 g++。
brew install make cmake gcc
安装 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
执行自动安装脚本:
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 系统安装
安装基本的编译工具(MinGW, Make, CMake, Git):
MinGW-w64 (建议下载最新预编译版本)
注意:将 MinGW 的 bin 文件夹路径添加到系统环境变量 PATH 中。
安装 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
执行自动安装脚本:
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)
仿真器分析: 天眸传感器仿真器 (sim) 详细分析报告 (详细的传感器建模分析报告)。
交互式仿真:
simulator/sim.ipynb(展示如何将普通视频序列转换为仿真 Tianmouc 数据流)。
核心算法应用 (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)[源代码]
- 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