【FPGA/图像处理】几何变换-旋转

少女dtysky

世界Skill

时刻2015.05.30

旋转同样是仿射变换的一种特例,它接受一个角度,将图像绕着某个中心进行转动,适合逆向映射。旋转的实现有多种,比如两次错切的旋转[26]、直接坐标变换[27]等,中心点的选取方式也有许多,但对于FPGA采用图像的几何中心较为合适。。本节将会说明如何用FPGA实现旋转的模块。
这个IP核的资源在这里:
Rotate


3 算法实现

明确了设计和架构,便可以进行算法的实现。本章将会说明如何实现图像处理的算法,以及如何运用它们。

3.21 几何变换-旋转

旋转同样是仿射变换的一种特例,它接受一个角度,将图像绕着某个中心进行转动,适合逆向映射。旋转的实现有多种,比如两次错切的旋转[26]、直接坐标变换[27]等,中心点的选取方式也有许多,但对于FPGA采用图像的几何中心较为合适。。本节将会说明如何用FPGA实现旋转的模块。

3.21.1 原理

此设计中旋转的前向映射基本原理如式3-21-1,其中angle为旋转角度,$x_c$和$y_c$分别为图像中心横纵坐标。对于逆向映射应该对此式进行调整,变换为3-21-2的形式,可见旋转操作比较复杂,不仅涉及多次符号乘法、符号加法,还涉及到三角函数的计算。

{Q[xt,yt]=I[x,y]xt=xc+(xxc)cos(a)(yyc)sin(a)yt=yc+(xxc)sin(a)+(yyc)cos(a)x[0,w),y[0,h) .        (3211)\begin{cases}Q[x_t,y_t] = I[x,y] \\x_t = xc + (x - xc) * cos(a) - (y - yc)*sin(a)\\ y_t = yc + (x - xc) * sin(a) + (y - yc)*cos(a)\\x \in[0, w) ,y \in[0, h)\ \end{cases}.\ \ \ \ \ \ \ \ (3-21-1) {I[x,y]=Q[xt,yt]x=(xtxc)cos(a)+(ytyc)sin(a)+xcy=(xt+xc)sin(a)+(ytyc)cos(a)+ycxt[0,w),yt[0,h) .        (3212)\begin{cases}I[x,y] = Q[x_t,y_t] \\x = (x_t - xc) * cos(a) + (y_t - yc) * sin(a) + xc\\ y = (-x_t + xc) * sin(a) + (y_t - yc) * cos(a) + yc\\x_t \in[0, w) ,y_t \in[0, h)\ \end{cases}.\ \ \ \ \ \ \ \ (3-21-2)

首先要考虑三角函数的计算,如3.1中所述,FPGA中的特殊函数计算需要用查找表来实现,所以需要编写一个脚本来生成查找表,同时由于三角函数的值可能为负数,并且verilog中符号系统是补码系统,所以需要生成的是角度和此角度下三角函数值的补码。由于正弦和余弦的值域为[-1, 1],同时一般用于变换的角度为[0,359],所以综合考虑,最终选择将角度划分为360个点,使用1位符号位、1位整数位和18位的小数位的数据来表示函数值,这其中的难点在于如何将一个浮点数转换为20位的定点数补码,实现函数如下。

  def format(num):
    r, d = format(num, 'f').split('.')
    r = '0' + r[0] if len(r) == 1 else '1' + r[1]
    d = float('0.' + d)
    res = ''
    for i in xrange(18):
        d = d * 2
        res += '1' if d >= 1 else '0'
        d = d - 1 if d >= 1 else d
    res = r[1] + res
    if r[0] == '1':
        if eval(res) == 0:
            res = '0'
        else:
            res = bin(2 ** 19 - eval('0b' + res))[2:]
        for i in xrange(19 - len(res)):
            res = '0' + res
    res = r[0] + res
    if res == '10000000000000000000':
        res = '00000000000000000000'
    return res

旋转变换同样需要符号舍入,但整数位只有1位,所以没有溢出风险,可以将其简化,仅仅裁剪输出即可。

3.21.2 设计

根据原理可知,Rotate核(以下简称RTT核)需要四次符号乘法、四次符号舍入操作和四次符号加法,并且需要和基于行列计数的帧控制器进行合作。故其需要的配置参数与端口如表3-21-1和表3-21-2。

名字 类型 范围 默认值 说明
work_mode 无符号 0为流水线模式,1为请求响应模式 0 模块的工作模式。
data_width 无符号 1 - 12 8 数据位宽。
im_width 无符号 1 - 4096 320 图像宽度。
im_height 无符号 1 - 4096 240 图像高度。
im_width_bits 无符号 取决于图像宽度 9 图像宽度的位宽。
mul_delay 无符号 取决于乘法器配置,1-14 3 乘法器延迟。
ram_RL 无符号 取决于帧控制器 7 帧控制器输出延迟。
表3-21-1 配置参数


名字 端口 类型 范围 默认值 说明
clk 输入 无符号 Clock.
rst_n 输入 无符号 复位,低有效。
angle input 无符号 0 - 359 旋转角度。
in_enable 输入 无符号 输入数据使能,在流水线模式下,它是另一个复位信号,在请求响应模式下,只有在它有效的时候in_data才会被真正地改变。
frame_in_ready 输入 无符号 连接到帧控制器的out_ready。
frame_in_data 输入 无符号 data_width - 1 : 0 连接到帧控制器的out_data。
frame_enable output 无符号 连接到帧控制器的in_enable。
frame_out_count_x output 无符号 im_width_bits - 1 : 0 连接到帧控制器的in_count_x。
out_count_y output 无符号 im_width_bits - 1 : 0 连接到帧控制器的in_count_y。
out_ready output 无符号 输出数据有效,在两种模式下,这个信号都会在out_data可以被读取的时候有效。
out_data output 无符号 color_width - 1 : 0 输出数据,将会和out_ready同步输出。
表3-21-2 端口



名字 类型 说明
Sin SinLUT 获取角度的正弦。
Cos CosLUT 获取角度的余弦。
MulX1 Multiplier13Sx20SRTT 13位有符号数和20位有符号数的乘法器,被用于定点数的乘法。你可以自己配置这个乘法器,然后更改"mul_delay",但所有的乘法器必须拥有相同的流水线级数,并且不能更改端口的配置!
MulX2 Multiplier13Sx20SRTT 13位有符号数和20位有符号数的乘法器,被用于定点数的乘法。你可以自己配置这个乘法器,然后更改"mul_delay",但所有的乘法器必须拥有相同的流水线级数,并且不能更改端口的配置!
MulY1 Multiplier13Sx20SRTT 13位有符号数和20位有符号数的乘法器,被用于定点数的乘法。你可以自己配置这个乘法器,然后更改"mul_delay",但所有的乘法器必须拥有相同的流水线级数,并且不能更改端口的配置!
MulY2 Multiplier13Sx20SRTT 13位有符号数和20位有符号数的乘法器,被用于定点数的乘法。你可以自己配置这个乘法器,然后更改"mul_delay",但所有的乘法器必须拥有相同的流水线级数,并且不能更改端口的配置!
FRSX1 FixedRoundSigned 用于有符号浮点数的舍入。
FRSX2 FixedRoundSigned 用于有符号浮点数的舍入。
FRSY1 FixedRoundSigned 用于有符号浮点数的舍入。
FRSY2 FixedRoundSigned 用于有符号浮点数的舍入。
表3-3-3 子模块

3.21.3 实现

根据3.21.2的设计便可以实现一个RTT核,流水线模式和请求响应模式实现如下。

3.21.3.1 流水线模式

在帧控制器的输出使能后1个周期第一个结果被输出,开始流水化工作,波形如图3-21-1。

图3-21-1 流水线模式时序
图3-21-1 流水线模式时序

3.21.3.2 请求响应模式读取

基本同3.21.3.1,但只有在in_enable上升沿时计数器才会加1才会被改变,波形如图3-21-2。

图3-21-1 流水线模式时序
图3-21-1 流水线模式时序

3.21.3.3 IP核GUI

完成功能后对RTT核进行了封装,封装如图3-21-3。

图3-21-3 RTT核的GUI
图3-21-3 RTT核的GUI

3.21.4 仿真

只对RGB图像和灰度图像进行测试,考虑到仿真设计模块比较多,出于仿真压力,我选择了一张图像的灰度模式进行三套参数的测试,原始图像如图3-21-4。

图3-21-4 仿真原始图像
图3-21-4 仿真原始图像

仿真参数如表3-16-4所示,选择原则是可以被二进制表示和不可以被表示的值都包含。

angle
45
131
270
表3-16-4 仿真参数

仿真并进行PSNR测试,仿真结果如图3-21-5所示。

图3-21-5 仿真结果
图3-21-5 仿真结果,左侧为流水线模式下的HDL功能仿真结果,中间为请求响应模式下的HDL功能仿真结果,右侧为软件仿真结果

3.21.5 资源和时序

最终实现与图像大小和数据位宽有关,这里只分析大小为512x512和数据位宽为8时的状况,根据Vivado生成的报表,主要资源耗费如表3-21-5。

Slice LUTs* Slice Registers DSP
543 245 4
表3-21-5 主要资源耗费

同时根据时序报告,最大的Data Path Delay(数据路径延迟)为4.414ns,即:

FMax = 226.55MHz

即说明,Rotate核在流水线模式下,理论上在处理1080p全高清图像时可以达到109帧。
与3.20相同,此FMax低于期望值,也来自于舍入核的加法,考虑时间此处暂时不做优化。
由于数据路径延迟和应用的最终约束设置强相关,所以仅供参考。

3.21.6 分析与结论

PSNR如表3-21-6。

1-131 1-270 1-45 Total
1000000.00 54.89 1000000.00 666684.96
表3-21-6 PSNR

PSNR对于某些参数为最大值,对于一些不是,最终误差来自于符号乘法和查找表自身的误差,但PSNR均为50以上,可见在测试范围内,RTT核可以满足处理需求,设计成功。


参考文献

[26] 陈芳.一种基于错切原理的图像旋转方法[J].淮阴师范学院学报(自然科学版),2004,3(4):319-322.DOI:10.3969/j.issn.1671-6876.2004.04.016.
[27] 王金辉.实时图像旋转系统的研究与FPGA实现[D].华中科技大学,2012.


感谢

仿真图像来源:
041-マツムシソウ

如果不是自己的创作,少女是会标识出来的,所以要告诉别人是少女写的哦。