本文主要介绍如何基于FPGA实现视频的任意角度旋转,关于视频180度实时旋转、90/270度视频无裁剪旋转,请见本专栏前面的文章,旋转效果示意图如下:
为了实时对比旋转效果,采用分屏显示进行处理,左边代表旋转前的视频在屏幕中的位置,右边代表旋转后的视频在屏幕中的位置。 分屏显示的实现方式见本专栏前面的文章详解。
本旋转方案不仅仅适用于国产安路FPGA,只有板卡上带有支持AXI4总线操作DDR的IP核,均可以进行方案移植
关于FPGA实现视频180度实时旋转,点击跳转文章链接
关于FPGA实现视频90度/270度无裁剪旋转,点击跳转文章链接
一、前言
-
后续文章的工程代码不在免费上传至Github,方案是开源的,工程代码可以私信我或者是评论区留言,有偿提供(价格不贵,此文章对应的工程文件为 ¥88)。前面已经发布的文章方案和代码均是开源的,可以直接去github下载。
-
免费内容太容易被剽窃了,付费是某种意义上的版权保护
-
付费即意味着责任,有利于提高文章质量、同时也能提高更新动力。
二、设计概述
除去DDR3控制器、FIFO等常用IP,本设计所用到的主要的IP模块如下。
IP | 功能 | 来源 |
---|---|---|
uidbuf | 基于FDMA信号时序的缓存控制器 适合用于基于RGB时序的视频数据或者数据流传输 | 米联客 |
uiFDMA | 基于AXI总线的自定义内存控制器 简化AXI总线的控制,完成数据的搬运 | 米联客 |
coor_trans | 旋转坐标计算模块 该模块使用查找表的方式存储了不同角度的sin、cos值 | 公众号:数字积木 |
uidbuf_r_active_rotate | 在uidbuf的基础上进行更改 用于视频任意角度旋转 | 个人开发 |
uivtc_video_rotate | 在uivtc的基础上进行更改 读取两路视频,一路是旋转之前的视频,一路是旋转之后的视频 | 个人开发 |
uivtc_reduce_frame_rate | 在uivtc的基础上进行更改 视频降帧处理,在不改变时钟频率的情况下,通过调整参数改变视频数据读写帧率 | 个人开发 |
三、系统实现方案
3.1 理论分析
前文提到对于90/270度比较有规律的旋转,我们可以采用正向映射的方案进行处理,把输入进的待旋转视频数据依次写入旋转后对应的像素点位置。
而对于任意角度旋转,不可以采用正向映射,因为如果采用正向映射,由于计算误差以及像素对应的DDR地址都是一个一个的整数,会导致有些地址没有被填充数据,从而产生空洞。
而逆向映射便不会有这种现象产生,因为我们拿旋转后的图像坐标去对应原图像的像素坐标,即便有计算误差的存在,但是总是可以对应到的,无非就是对应的不是绝对的精确。所以便可以保证旋转后的图像每个地址都被填充了像素数据。
下图给出正向旋转和逆向旋转的区别,实际上板验证和这个结果类似。(该图来自于一篇硕士论文)
在使用安路的板卡时,其DDR3 IP控制器从发起写请求到一个像素点完全写入需要的时间比从发起读请求到一个像素点数据被读出需要的时间要短很多。所以在相同的分辨率情况下,正向映射可以达到的帧率比逆向映射要高。 在进行移植时,能达到多高的帧率需要自行分析一下。
3.2 数据流
为了处理输入进的60hz的待旋转视频,视频像素点的数据流如上图所示,其经历了二进二出DDR3,最终输出至显示器进行显示。
- 第一次写DDR3:在前文90/270度旋转实现方式中提到,在突发传输长度为1的情况下,为了保证每一次只传输一个像素数据,我们把DDR3中存储的128bit数据全部设置为某一个像素点的数据,所以第一次写DDR3的目的是先把视频像素点数据写入DDR3,并且保证一个像素点的数据(16bit)对应DDR3中存储的128bit数据,方便后续一个一个读取像素点。
- 第一次读DDR3:以一个较低的帧率,根据旋转后的图像坐标去对应原图中的图像坐标,一个一个读取原图中的像素点,如果该像素点对应不到原图像中的坐标,则赋值为16‘hffff,即为白色。
- 第二次写DDR3:把刚刚经过旋转排列好的像素点再次写入DDR3
- 第二次读DDR3:以正常的帧率把视频像素数据读出即可。
上述处理的核心在于旋转模块的实现。
3.3 uidbuf_r_active_rotate模块
此模块采用逆向映射的方法,依次计算旋转后的像素点坐标在原图像中的位置,然后通过FDMA读取原图像的数据,实现任意角度的旋转功能,相比于uibuf模块,不同的部分用红框圈出。
此方案中,使用AXI4总线读写DDR时,AXI4总线的数据宽度为128,像素点的数据位宽为16,由于DDR3采用的是8-bit预取,DDR3的位宽配置为16bit,所以在突发长度为1的情况下,一次可以读出8个16bit数据(128bit),在常规情况下,一次能读出8个像素点数据。
然而,在进行旋转时,为了保证每一次只传输一个像素数据,我们把这128bit全部设置为某一个像素点的数据即可。
该模块中核心的部分在于地址计算以及像素点数据的赋值,详见源代码。
四、移植注意事项
1、本工程视频源输入的视频分辨率为1280×720@60hz
2、此模块实现的是视频自动旋转,每四帧后旋转角度+1,可以自行修改,选择从外部传入参数,控制旋转角度
五、上板验证
视频旋转效果图如下