基于 IMU 传感器的视频稳定混合运动估计
Abstract
在本文中,我们提出了一种混合方法来估计运动并通过切换函数稳定视频,该方法在
Kanade-Lucus-Tomasi (KLT) 跟踪器和 IMU
辅助运动估计器之间切换估计的运动。为了实现这一点,由于 KLT
跟踪器在较大运动期间的性能不佳,我们使用 KLT
跟踪器来校正低旋转的运动,并使用 IMU
辅助运动估计器来校正高旋转,此外,卡尔曼滤波器用于去除不需要的运动,从而平滑轨迹。
Introduction
在相机市场,光学图像稳定(OIS)系统安装在相机镜头或图像传感器上,价格相当昂贵
[3]。另一方面,数字稳定系统通过在相机移动时补偿捕获图像的移动来处理图像,它可以分为三个步骤,即运动估计、运动平滑和图像扭曲
[4,5]。
数字视频稳定中运动估计的常用技术是分别使用块匹配 [9]、KLT
(Kanade-Lucus-Tomasi) 跟踪器 [10,11]、SIFT [12] 和 SURF [13]。最近,Dong
et al. [14] and Lim 等人 [15] 使用 KLT
跟踪器以高帧率和低计算成本实时估计运动, KLT 跟踪器通过 Good Feat ...
EIS 电子防抖基本原理
投影
这里以小孔成像模型为例,全相模型是相同的流程只是投影模型不一样而已。在相机校准模型一文中已经介绍了将像素坐标系变换到相机坐标系中
相机校准模型
如下:
\[
\begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix}
\frac{1}{d_x}& 0 &u_o \\ 0 & \frac{1}{d_y}& v_0\\ 0
& 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}
= \frac{1}{z_c}\begin{bmatrix} \frac{f}{d_x}& 0 &u_o \\ 0 &
\frac{f}{d_y}& v_0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}
x_c\\ y_c\\ z_c \end{bmatrix}
\]
这里我们取 \(z_c = 1\)
再做一个 ...
相机校准模型
小孔成像模型
各坐标系定义及相机的内参和外参
像素坐标系
像素坐标就是像素在图像中的位置。一般像素坐标系的左上角的顶点就是原点,水平向右是
u,垂直向下是 v 轴。
图像坐标系
在像素坐标系中,每个像素的坐标是用像素来表示的,然而,像素的表示方法却不能反应图像中物体的物理尺寸,因此,有必要将像素坐标转换为图像坐标。将像素坐标系的原点平移到图像的中心,就定为图像坐标系的原点,图像坐标系的
x 轴与像素坐标系的 u 轴平行,方向相同,而图像坐标系的 y 轴与像素坐标系的
v 轴平行,方向相同。
在图中,假设在像素坐标系下图像中心的像素坐标是(u0,v0),相机中感光器件每个像素的物理尺寸是
dx *
dy,那么,图像坐标系的坐标(x,y)与像素坐标系的坐标(u,v)之间的关系可以表示为:
\[u = \frac{x}{d_x} + u_0 \\ v =
\frac{y}{d_y} + v_0 \]
写成矩阵的形式就为:
\[\begin{bmatrix} u \\ v \end{bmatrix} =
\begin{bmatrix} \frac{1}{d_x} &a ...
Linux 驱动之 V4L2 子系统
概述
V4L2 是专门为 linux 设备设计的一套视频框架,其主体框架在 linux
内核,可以理解为是整个 linux
系统上面的视频源捕获驱动框架。其广泛应用在嵌入式设备以及移动端、个人电脑设备上面,市面上的编码产品类如:SDV、手机、IPC、行车记录仪都会用到这个框架来进行视频采集。
框架
该图描述了 v4l2 驱动框架的整体结构,v4l2
本质上也是一个字符设备驱动程序,图中芯片模块对应 Soc
的各个子模块,video_device 结构体主要用来控制 Soc 的 video
模块,v4l2_device 会包含多个 v4l2_subdev ,每个 v4l2_subdev
用来控制各自的子模块,某些驱动不需要 v4l2_subdev ,依靠 video
模块就能实现功能。
video_device:一个字符设备,为用户空间提供设备节点(/dev/videoX),提供系统调用的相关操作,是采集设备的抽象接口。
vb2_queue:与 vb2_v4l2_buffer 一起用于数据流的实际逻辑和 DMA
操作。
v4l2_device:表示一个 v4l2 设备的实例。
v4l ...
Linux 驱动之 Regulator 子系统
概述
该框架旨在提供标准内核接口来控制电压和电流
Regulator。其目的是允许系统动态控制 Regulator
功率输出,以节省功率并延长电池寿命。 这适用于电压
Regulator(电压输出可控)和电流 Regulator(电流限制可控)。
命名法
Regulator:
为其他设备供电的电子设备。大多数稳压器可以启用和禁用其输出,而有些可以控制其输出电压和/或电流。输入电压
-> 稳压器 -> 输出电压
PMIC:
电源管理 IC。 包含多个稳压器且通常包含其他子系统的 IC
Consumer:
由稳压器供电的电子设备。 消费者可分为两类:
静态:消费者不会改变其电源电压或电流限制。 它只需要启用或禁用其电源。
其电源电压由硬件、引导加载程序、固件或内核板初始化代码设置
动态:消费者需要改变其电源电压或电流限制以满足操作需求
Power Domain:
由稳压器、开关或其他电源域的输出电源提供其输入电源的电子电路。电源
Regulator 可能位于一个或多个开关后面,例如:
Regulator -+-> Switch-1 -+-> Switch-2 ...
Linux 驱动之 RTC
概述
RTC
和系统时钟有不同的用途。前者是硬件时钟,以非易失方式维护绝对时间和日期,而后者是内核维护的软件时钟,用于实现
gettimeofday(2)和
time(2)系统调用,以及在文件上设置时间戳等。系统时钟报告从起点开始的秒和微秒,起点定义为
POSIX 纪元:1970-01-0100:00:00 +0000(UTC)。
数据结构
rtc 数据结构如下:原图
rtc_device: 内核中使用 rtc_device 结构体来抽象一个 rtc
设备,rtc_device 结构体屏蔽了不同 RTC 硬件之间的差异,通过 rtc_class_ops
结构体为上层提供了访问硬件设备的统一接口
rtc_class_ops: 该结构体提供了对底层差异的抽象,rtc_device
用于描述一个 rtc
设备,而访问该设备的方法对于不同的设备是不同的,rtc_class_ops 用于抽象对
rtc 设备的访问,对上屏蔽了底层操作的差异。编写一个 rtc
设备驱动就是构造一个 rtc_device 结构体并注册进系统,rtc 的访问方法就是
rtc_class_ops 结构体
rtc_t ...
Linux 驱动之 CCF 子系统
概述
CCF 主要用于系统 clock 的管理等操作。clk 的种类说明:
如上图所示,时钟源大概可分为如下几种:
提供基础时钟源的晶振(可分为有源晶振、无源晶振两种)
用于倍频的锁相环
用于分频的 divider
用于多路时钟源选择的 mux
用于时钟使能的与门电路等
而在 CCF 子系统的抽象中,这五种均抽象为 clk,但是针对这 5
种类型的时钟也提供了单独的时钟注册函数(也就是对 clk_register
函数的封装,并针对不同的时钟类型定义了不同的结构体)。
在 CCF 子系统中,针对硬件时钟的操作接口,也抽象了对应的结构体 struct
clk_ops,包含时钟的使能接口、时钟频率的修改接口等等。而针对上述所说的不同种类的时钟源,其并不需要实现所有
struct clk_ops 中定义的接口。针对“时钟使能的与门电路”而言,仅需要实现
enabel、disable、is_enable 接口即可;针对多路时钟源选择的 mux
而言,则需要实现父时钟源的设置及获取的接口 set_parent、get_parent
等;对于倍频、分频而言,则需要实现时钟频率相关的接口
se ...
Linux 驱动之 Input 子系统
概述
按键输入、键盘、鼠标、触摸屏等等这些都属于输入设备,按键和键盘就是代表按键信息,鼠标和触摸屏代表坐标信息,因此在应用层的处理就不同。为此
input 子系统分为 input 驱动层、 input 核心层、 input
事件处理层,最终给用户空间提供可访问的设备节点,input 子系统框架如图
所示:
驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。
核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行处理。
事件层:主要和用户空间进行交互。
数据结构
Input 子系统实现的数据结构如下:原图
input_dev:
input_dev 结构体用于描述一个 input
设备,例如按键、鼠标、键盘等,我们编写设备驱动主要就是构造这个结构体。该结构体包含设备类型,消息类型,事件
code 等信息。该数据结构在内核里会挂载到一个全局链表
input_dev_list,所有注册的 input 设备都会挂载到该链表中
input_handler:
input_handler 用于表示一个 input 事件,用于上报 input
事 ...
Linux 驱动之 Regmap 子系统
概述
内核版本 3.1 中引入了 Regmap API,用于统一内核开发人员访问 SPI/IIC
设备的方式,无论是 SPI 设备还是 IIC 设备,只需要初始化,配置 Regmap
就可以通过 Regmap 读写设备。Regmap 子系统主要提供如下两种功能:
第一是为 IIC/SPI/MMIO 等提供统一的访问接口,linux 中大量的 iic 和
spi 设备就可以通过统一的接口进行访问尤其对于那些同时支持 iic 和 spi
接口的设备。
第二是提供缓存访问机制用于加速设备访问设备,对于支持缓存的设备这将大大加快设备的当问速度。
下面看一下 Regmapz 子系统在驱动中的位置,如下:原图
数据结构
regmap 子系统的实现比较简单,数据结构也是很简单的,整体结构如下:原图
regmap_bus:
regmap_bus 数据结构用于对具体的 bus 进行封装,例如对 IIC 或 SPI
总线进行封装,这些 bus
下可以挂载很多设备,他们都从属于一个总线那么就有很多共性操作,对这个结构的封装就用
regmap_bus
结构。该结构主要提供同步读写、异步读写、格式化 ...
Linux 驱动之 Pinctrl 子系统
Pinctrl 概述
关于 pinctrl 主要可以归结为两类设置,其中一类是功能选择,即一组 gpio
是用于 iic 还是 uart 还是就作为普通 gpio 来用,另一类是 gpio
的特性配置,即上拉、下拉、驱动能力和速率的配置。而 pinctrl
主要负责这两类配置的管理工作。总结起来 pinctrl
主要完成以下三种功能:
引脚枚举与命名 (Enumerating and naming)
引脚复用 (Multiplexing):比如用作 GPIO、I2C 或其他功能
引脚配置 (Configuration):比如上拉、下来、open
drain、驱动强度等
dts 配置
以全志平台的写法如下(虚构的):
123456789101112131415uart0_pins: uart0-pins { pins = "PA4", "PA5"; function = "uart0";};uart0_sleep_pins: uart0-pins { pins = "PA4", "PA5"; function = "gpio";};...&uart0 ...