本文将继续讲述图像处理算法的FPGA实现,后续可能更新图像旋转(1080P)、画中画、快速DCT等算法。视频场景切换检测常用于视频编解码领域,我选用的算法是双阈值灰度直方图检测法,起初在MATLAB上实现并测出最佳双阈值,然后将其转换为verilog代码,最终在XILINX K7开发板上实现视频场景切换检测的效果。

  双阈值灰度直方图算法,顾名思义是采用两个灰度阈值来判断视频场景的切换。其中一个是渐变阈值T1,表明视频场景可能发生改变;另一个是突变阈值T2,表示阈值已经发生改变。当相邻帧灰度直方图差值比大于阈值T2时表明为场景突变帧,而当差值比大于阈值T1而小于阈值T2时则表示为场景渐变帧,差值比小于阈值T1则为连续帧。其中,相邻灰度直方图差值实际指的是一个权重,即当前灰度帧差与平均帧差的比,如公式(1)所示。这个比值越大,说明图像变化越大,就越有可能发生场景切换,反之则相反。

            Prop_CurrentFrame=FrameDiff/AveFrameDiff   (1)

  双阈值灰度算法的MATALAB实现较为简单,更多的是依靠公式进行计算,并对差值进行判别。当然由于读取的是1080P视频,又需要遍历整帧的像素点,所以程序运行的比较慢。而程序实现的思路较为清晰,即:视频从第二帧开始读取,一次选取两帧,并将读取的图像数据转YUV格式,提取其中的Y分量;然后利用imhist()函数求取其对应的灰度直方图,并计算其相邻帧差,同时统计平均帧差;最后根据统计的平均帧差和当前帧差作比较,并根据阈值跳转到渐变帧或者突变帧,记录突变帧位置和突变次数。部分代码如下所示:

for i=2:FrameNum
Frame_0=read(Obj,i-1);%前一帧
Frame_1=read(Obj,i);%当前帧
ImageYuv_0=rgb2ycbcr(Frame_0);
ImageYuv_1=rgb2ycbcr(Frame_1);
Y_0=ImageYuv_0(:,:,1);%Y
Y_1=ImageYuv_1(:,:,1);%Y
GrayHist_0=imhist(Y_0); %获取灰度直方图
GrayHist_1=imhist(Y_1); %获取灰度直方图
FrameDiff=sum(abs(GrayHist_1-GrayHist_0));%当前帧与前一帧灰度直方图帧差
SumFrameDiff=(SumFrameDiff+FrameDiff);
AveFrameDiff=SumFrameDiff/(GapFrameCnt-1);
end

  最终经过大量测试,确定双阈值在分别为3和5时检测效果较好,视频场景检测效率大概为90%。

而对于视频场景切换检测算法的FPGA实现,比较关键的内容在于帧差的求取。帧差,顾名思义,两帧的像素之差,而本文使用的两帧的亮度分量(Y)差。对于1080P的图像存储,自然会使用到DDR。而计算帧差最少需要两帧数据,假如使得DDR同时输出相邻的两帧,然后对数据流分别统计求直方图,依次相减,再求和,倒的确是能得到两帧的亮度差。但是该方法DDR控制较为复杂,且最终得到像素差位宽太大,所以不采用。本文选用DDR缓存整帧图像+bram存储图像亮度直方图的方式实现。即选用两组bram乒乓操作,一组对DDR输出一帧图像数据进行抽样,在行方向每4个点抽取一次,在列方向每4列抽取一列,且像素位宽由10bit降为8bit,求取对应的灰度直方图数据,并将其写入bram中;另一组bram在当前帧做完灰度直方图统计时,依次读取上一帧缓存的对应位置灰度直方图数据,并依次做差求和,最终求出灰度直方图帧差以及平均帧差。

其中,灰度直方图的统计也是极其重要的一个环节。由前面的分析可知,为缩小数据量对一帧图像进行采样,数据量由原来的1920*1080变为现在的129600(17bit),可这仍然是一个非常大的数字,尤其在帧差计算时带来的累积求和,所以进一步降低统计数据量, 采用2级双口BRAM实现灰度直方图统计。即第一级bram采用9bit位宽,第二级bram为8bit。特选用像素灰度值寻址,当一个8bit亮度统计值计满512时则第二级bram对应地址数值加一,直到统计完所有采样点。在这之中,选用双口bram的原因在于灰度直方图的统计过程中,

当一个新的像素点传来时,需提前一拍读取该地值统计值,然后累加。部分RTL代码如下所示:

//bram读地址,提前2拍,一拍是先于bram写,一拍是bram读延迟
always @(posedge vid_clk or posedge reset)begin
if(reset)begin
BRAM_addrb_0<='h0;
BRAM_addrb_1<='h0;
end
else if(HistData_rden)begin//外部读取直方图数据
if(pos_HistData_rden)begin
BRAM_addrb_0<= odd_frame ? 'h0 : BRAM_addrb_0;
BRAM_addrb_1<=~odd_frame ? 'h0 : BRAM_addrb_1;
end
else begin
BRAM_addrb_0<= odd_frame ? BRAM_addrb_0+1'b1 : BRAM_addrb_0;//奇数帧读bram0
BRAM_addrb_1<=~odd_frame ? BRAM_addrb_1+1'b1 : BRAM_addrb_1;//偶数帧读bram1
end
end
else begin//写直方图数据前提前2拍读
BRAM_addrb_0<= (Hist_wren && ~odd_frame) ? Hist_addr:BRAM_addrb_0;//偶数帧写bram0
BRAM_addrb_1<= (Hist_wren && odd_frame) ? Hist_addr:BRAM_addrb_1;//奇数帧读bram1
end
end

  最终,为更为方便观察视频场景切换的效果,特在检测到视频场景切换时,使得边框变为红色,持续0.5s。最后检测的效果与MATLAB上测试的效果相当,正确检测率在90%左右,基本检测出了视频场景的切换。

  我个人认为,双阈值灰度直方图算法有一定局限性。即当视频中的场景较为稳定时,平均帧差很小,突然来一个变动比较大的画面时,当前帧差较大,对应的帧差比就偏大,进而产生误警。当然,这也能解释该算法在一些场景下发生错误检测的现象。

视频场景切换检测的FPGA实现的更多相关文章

  1. 【Cocos2d-x 3.x】 场景切换生命周期、背景音乐播放和场景切换原理与源码分析

    大部分游戏里有很多个场景,场景之间需要切换,有时候切换的时候会进行背景音乐的播放和停止,因此对这块内容进行了总结. 场景切换生命周期 场景切换用到的函数: bool Setting::init() { ...

  2. 自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药

    自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  3. Unity 中场景切换

    Unity游戏开发中,单个Scene解决所有问题似乎不可能,那么多个Scene之间的切换是必然存在.如果仅仅是切换,似乎什么都好说,但是在场景比较大的时候不想让玩家等待加载或者说场景与场景之间想通过一 ...

  4. Cocos2d-x Lua中多场景切换生命周期

    在多个场景切换时候,场景的生命周期会更加复杂.这一节我们介绍一下场景切换生命周期.多个场景切换时候分为几种情况:情况1,使用pushScene函数从实现GameScene场景进入SettingScen ...

  5. Faster-RCNN用于场景文字检测训练测试过程记录(转)

    [训练测试过程记录]Faster-RCNN用于场景文字检测 原创 2017年11月06日 20:09:00 标签: 609 编辑 删除 写在前面:github上面的Text-Detection-wit ...

  6. texturepacker打包图片,场景切换时背景图有黑边

    在使用TexturePacker打包图片之后,背景图在场景切换(有切换动画)时,明显能看到有黑边,在百度之后解决了. 知乎上边有网友贴出了两种解决方法,我抄过来如下: 第一种: 修改 ccConfig ...

  7. cocos2d-x 帧循环不严谨造成场景切换卡顿

    最近在用cocos2d-x做引导界面,2dx版本是2.2.3,场景切换加上了效果,所有资源都已经使用texturepacker打包预加载,但是在实际运行调试中,场景切换相当卡顿. 各种纠结后,无意中将 ...

  8. JavaScript强化教程 -- cocosjs场景切换

    场景切换 在main.js,将StartScene作为我们初始化运行的场景,代码如下: cc.LoaderScene.preload(g_resources, function () { cc.dir ...

  9. cocos2d-x场景切换动画

    void StartScene::beginGame() {     CCLog("beginGame");          //CCTransitionScene *trans ...

随机推荐

  1. 华为计算平台MDC810发布量产

    华为计算平台MDC810发布量产 塞力斯的发布会刚刚结束,会上塞力斯SF5自由远征版也确实让人眼前一亮. 全球首款4S级加速能力.1000+km续航新能源作为这款车的卖点. 续航1000+km成了最近 ...

  2. TensorFlow分布式在Amazon AWS上运行

    TensorFlow分布式在Amazon AWS上运行 Amazon AWS 提供采用 NVIDIA K8 GPU 的 P2.x 机器.为了能够使用,第一步还需要创建一个 Amazon AWS 账户, ...

  3. 尚硅谷Java——宋红康笔记【day25-day29】

    day25 Map接口 一.Map的实现类的结构: |----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x) |----HashMap:作为Map的主要实现 ...

  4. 07:JS(03)

    BOM与DOM操作 # 截至目前为止 我们虽然已经学会了js语法 但是你会发现跟浏览器和html文件还是一点关系没有 """ BOM 浏览器对象模型 Browser Ob ...

  5. 重新点亮linux 命令树————帮助命令[一]

    前言 重新整理一下linux的命令. 正文 这里首先介绍帮助命令. 帮助命令常用的有三个: man help info 那么就来看下这三个. man 第一个man,man不是男人的意思,而是manua ...

  6. Windows10 上Docker 安装运行Consul

    背景简介 Consul是一种服务网格解决方案,提供具有服务发现,配置和分段功能的全功能控制平面. 这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全服务网格. Consul需要数据平面并 ...

  7. lms框架服务注册中心

    服务注册中心原理 在分布式系统里的注册中心.原理是将部署服务的机器地址记录到注册中心,服务消费者在有需求的时候,只需要查询注册中心,输入提供的服务名,就可以得到地址,从而发起调用. 在微服务架构下,主 ...

  8. 8、inotify和resync的优缺点

    只有对外提供访问的服务需要有端口号,本地服务无端口号: 8.1.inotify的优缺点: 1.优点: 监控文件系统事件变化,通过同步工具实现实时的数据同步 2.缺点: 并发如果大于200个文件(10- ...

  9. ICMP路由重定向攻击

    ICMP介绍 ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制消息.控 ...

  10. acwing 868. 筛质数

    线性筛 #include<bits/stdc++.h> #define N 1000010 using namespace std; int v[N],p[N]; void pr(int ...