基于FPGA的半透明字幕叠加系统实现

我之所以做了这个半透明字幕叠加,得谢谢CB哥给我分配的任务。当时,他给了我这样的一条公式:

其中A为图像源,B为字幕,C为字幕叠加后的图像,a%为透明度。

CB哥让我在48小时内用FPGA实现,最后我也按时完成任务了。接下来,我将介绍该设计的实现过程。当拿到这个任务后,我就用VC++验证了半透明字幕叠加的效果,如下所示:

用软件测试了之后,发现效果挺不错的。呵呵,接下来该把它移植到FPGA上了。首先,我们可以从公式中看出它其实进行了浮点数计算,如果在FPGA中也进行浮点数计算,结果你会发现实现起来真的很复杂、很吃力。然而,FPGA对整数的运算却是非常的简单。既然这样,我们何不一开始对把它进行适当的缩放,然后进行整数运算,最后对结果进行缩放以得到预期的数据。为了实现这个目的,我对公式的两边同时乘以256。例如,对于

公式两边乘以256后为

最后再将结果8’d256*C向右移8位以得到预期的图像数据C。大概的思路就是这样~~它的代码实现如下:

/*******************************************************
Author       :  crazyBird
Filename     :  lcd_driver.v
Data         :  2015-3-4
Description  :  driver of lcd
********************************************************/ `timescale 1ns/1ps module lcd_driver
( 
//global clock 
    input          clk,         //system clock 
    input          rst_n,       //sync reset 
 
//lcd interface 
    output         lcd_dclk,    //lcd pixel clock 
    output         lcd_blank,   //lcd blank 
    output         lcd_sync,    //lcd sync 
    output         lcd_hs,      //lcd horizontal sync 
    output         lcd_vs,      //lcd vertical sync 
    output         lcd_en,      //lcd display enable 
    output [23:0]  lcd_rgb,     //lcd display data 
 
//user interface 
    output         lcd_request, //lcd data request 
    output [10:0]  lcd_xpos,    //lcd horizontal coordinate 
    output [10:0]  lcd_ypos,    //lcd vertical coordinate 
    input  [23:0]  lcd_data,    //lcd data 
    input  [ 7:0]  ret_data
);
`include "lcd_para.v" 
//------------------------------------------ 
//h_sync counter & generator 
reg [10:0] hcnt; 
 
always @(posedge clk or negedge rst_n) 
begin 
    if (!rst_n)
        hcnt <= 11‘d0; 
    else 
        begin 
        if(hcnt < `H_TOTAL - 1‘b1)  
            hcnt <= hcnt + 1‘b1; 
        else
            hcnt <= 11‘d0; 
        end 
end 
 
assign lcd_hs = (hcnt <= `H_SYNC - 1‘b1) ? 1‘b0 : 1‘b1; 
//------------------------------------------ 
//v_sync counter & generator 
reg [10:0] vcnt; 
 
always@(posedge clk or negedge rst_n) 
begin 
    if (!rst_n)
        vcnt <= 11‘b0; 
    else if(hcnt == `H_TOTAL - 1‘b1)  
        begin 
        if(vcnt < `V_TOTAL - 1‘b1)  
            vcnt <= vcnt + 1‘b1; 
        else
            vcnt <= 11‘d0; 
        end 
end 
 
assign lcd_vs = (vcnt <= `V_SYNC - 1‘b1) ? 1‘b0 : 1‘b1; 
//------------------------------------------ 
assign lcd_dclk  = ~clk; 
assign lcd_blank = lcd_hs & lcd_vs; 
assign lcd_sync  = 1‘b0; 
//------------------------------------------ 
//ahead x clock 
localparam H_AHEAD = 11‘d1; 
localparam ROM_ADDR_AHEAD = 11‘d2; 
assign lcd_request = (hcnt >= (`H_SYNC + `H_BACK - H_AHEAD)           &&
                      hcnt < (`H_SYNC + `H_BACK + `H_DISP - H_AHEAD)) &&
                     (vcnt >= (`V_SYNC + `V_BACK)                     &&
                      vcnt <  (`V_SYNC + `V_BACK + `V_DISP)) ? 1‘b1 : 1‘b0; 
//lcd xpos & ypos 
assign lcd_xpos = lcd_request ? (hcnt - (`H_SYNC+`H_BACK-H_AHEAD)) : 11‘d0; 
assign lcd_ypos = lcd_request ? (vcnt - (`V_SYNC + `V_BACK)) : 11‘d0; 
wire [10:0] rom_xpos = lcd_request ? (hcnt - (`H_SYNC + `H_BACK - ROM_ADDR_AHEAD)) : 11‘d0; 
wire [10:0] rom_ypos = lcd_request ? (vcnt - (`V_SYNC + `V_BACK)) : 11‘d0; 
//-------------------------------------------------------- 
wire [ 2:0] word_data; 
wire area1 = (rom_ypos < 11‘d160); 
wire [16:0] rom_addr = area1?{6‘b0,rom_xpos}+({6‘b0,rom_ypos})*10‘d640: 17‘d0;
word u_word
(
    .address(rom_addr ),
    .clock  (clk      ),
    .q      (word_data)
); 
 
reg [15:0]  lcd_data_r = 16‘b0; 
reg [15:0]  lcd_data_g = 16‘b0; 
reg [15:0]  lcd_data_b = 16‘b0; 
 
always @(*) 
begin 
    if(word_data == 3‘b111)  
        begin
        lcd_data_r = {lcd_data[23:16],8‘b0}; 
        lcd_data_g = {lcd_data[15: 8],8‘b0}; 
        lcd_data_b = {lcd_data[ 7: 0],8‘b0}; 
        end 
    else 
        begin
        lcd_data_r = lcd_data[23:16] * ret_data + {8{word_data[2]}} *  
                    (8‘d255 - ret_data); 
        lcd_data_g = lcd_data[15: 8] * ret_data + {8{word_data[1]}} * 
                    (8‘d255 - ret_data); 
        lcd_data_b = lcd_data[ 7: 0] * ret_data + {8{word_data[0]}} * 
                    (8‘d255 - ret_data); 
        end 
end 
//----------------------------------------- 
assign lcd_en = (hcnt >= (`H_SYNC + `H_BACK)            &&
                 hcnt <  (`H_SYNC + `H_BACK + `H_DISP)) &&
                (vcnt >= (`V_SYNC + `V_BACK)            &&
                vcnt <  (`V_SYNC + `V_BACK + `V_DISP)) ? 1‘b1 : 1‘b0; 
assign lcd_rgb = lcd_en ? {lcd_data_r[15:8],lcd_data_g[15:8],lcd_data_b[15:8]} : 24‘h0;  
 
endmodule

上述代码中的ret_data是来自外部模块的,它的值由按键控制,即透明度可调。

FPGA测试结果如下:

先写到这吧,更详细地以后再补充~~~又是该睡觉的时候了,晚安,88*^_^*

时间: 2024-08-03 00:52:32

基于FPGA的半透明字幕叠加系统实现的相关文章

基于FPGA的音频信号的FIR滤波(Matlab+Modelsim验证)

1 设计内容 本设计是基于FPGA的音频信号FIR低通滤波,根据要求,采用Matlab对WAV音频文件进行读取和添加噪声信号.FFT分析.FIR滤波处理,并分析滤波的效果.通过Matlab的分析验证滤波效果后,将叠加噪声信号的音频信号输出到txt文件里.然后使用Matlab语言编写滤波器模块和测试模块,通过Modelsim软件读取txt文件的数据,将数据送入滤波模块,最后将滤波的结果输出到txt文件里,最后用Matlab将处理的结果从txt文件读出.显示.FFT分析用Verilog设计的FIR滤

基于FPGA的跨时钟域信号处理——亚稳态(V3-FPGA学院)

(V3-FPGA学院教你学习FPGA) 基于FPGA的跨时钟域信号处理--亚稳态 基于FPGA的跨时钟域信号处理--亚稳态 什么是亚稳态? 所有数字器件(例如FPGA)的信号传输都会有一定的时序要求,从而保证每 个寄存器将捕获的输入信号正确输出.为了确保可靠的操作,输入寄存器的信号必须在时钟沿的某段时间(寄存器的建立时间Tsu)之前保持稳定,并且持续到时钟沿之后的某段时间(寄存器的保持时间Th)之后才能改变.而该寄存器的输入反映到输出则需要经过一定的延时(时钟到输出的时间Tco).如果数据信号的

基于FPGA的图像开发平台 其他摄像头附件说明(OV5642 OV9655)

基于FPGA的图像开发平台 其他摄像头附件说明 FPGA_VIP_V101 编者 奇迹再现 个人博客 http://www.cnblogs.com/ccjt/ 联系邮箱 [email protected] 淘宝网址 http://ccjt.taobao.com 修订记录 见下页 版权归奇迹再现所有,抄袭请注明出处, 参考文献:CrazyBingo原创相关文档.请尊重原创. 前言: 本系统方案理论适合DVP绝大部分摄像头测试,调试及开发,针对其他摄像头,因为寄存器参数不同,需要进行相应移植. 目前

基于FPGA的均值滤波算法实现

我们为了实现动态图像的滤波算法,用串口发送图像数据到FPGA开发板,经FPGA进行图像处理算法后,动态显示到VGA显示屏上,前面我们把硬件平台已经搭建完成了,后面我们将利用这个硬件基础平台上来实现基于FPGA的一系列图像处理基础算法. 椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素.椒盐噪声是一种因为信号脉冲强度引起的噪声,产生清楚该噪声的算法也比较简单. 均值滤波的方法将数据存储成3x3的矩阵

基于FPGA的简易数字时钟

基于FPGA的可显示数字时钟,设计思路为自底向上,包含三个子模块:时钟模块,进制转换模块.led显示模块.所用到的FPGA晶振频率为50Mhz,首先利用它得到1hz的时钟然后然后得到时钟模块.把时钟模块输出的时.分.秒输入到进制转换模块后得到十进制的值再输入到led显示模块,该project已经在FPGA开发板上亲測可用. 下图为模块示意图(实际project中并没有採用原理图的输入方法.这里仅作示意). 以下分模块说明: clk1:  时钟模块,设计思路为首先依据50M晶振得到1hz的时钟,然

基于FPGA的数字频率计(设计全过程)

小序: 前几天看全国大学生电子设计竞赛历年试题,无意间发现了一道题目<简易数字频率计>,跟之前我用verilog写的一个频率计差不多,于是想尝试做一下,题目具体要求如下图中所示,我所用的开发板为 xilinx spartan 3ES, 最后结果还算理想,在要求的范围内的频率测量精度比较高,但是由于板子的限制没能实现脉冲宽度测量等功能,但是其原理比较简单,下文中将会给出设计过程,结果展示图片以及整个工程代码的下载链接. 数字频率计总体设计采用分块的思想,自底向上设计方向,三个子模块包括频率测量模

基于FPGA的OLED真彩色动态图像显示的实现

源:基于FPGA的OLED真彩色动态图像显示的实现 作为第3代显示器,有机电致发光器件(Organic Light Emitting Diode,OLED)由于其主动发光.响应快.高亮度.全视角.直流低压驱动.全固态以及不易受环境影响等优异特性,具有LCD无法比拟的优点,在手机.个人电子助理(PDA).数码相机.车载显示.笔记本电脑.壁挂电视以及军事领域都具有广阔的应用前景,因而得到了业界广泛的关注.OLED发展至今,已经由最初的单色发展到现在的全彩,与此同时对驱动电路也提出了更高的要求,由最初

基于FPGA的Ethercat定制栈最大可实现32轴

基于FPGA的Ethercat主栈协议 (最大可带32轴同步运行,同步抖动±75ns,控制精度125us) 各位老板:我司有多年的FPGA研发经验:基于FPGA的Ethercat定制栈更是达到行业领先水平感谢抽空阅读,欢迎合作 市场痛点[PLC厂家的痛点]目前,国内的大多数PLC厂家主要通过增加运控模块来实现轴的运动控制,可控制的轴数比较少(通常是4-6轴),并且模块的价格高昂(一个模块几万).如果要控制多轴成本就更高,而且控制精度不高,轴与轴之间的精度很大,这意味着不能进入高精尖控制领域.[应

基于FPGA的RGB图像转灰度图像算法实现

一.前言 最近学习牟新刚编著<基于FPGA的数字图像处理原理及应用>的第六章直方图操作,由于需要将捕获的图像转换为灰度图像,因此在之前代码的基础上加入了RGB图像转灰度图像的算法实现. 2020-02-29 10:38:40 二.RGB图像转灰度图像算法原理 将彩色图像转换为灰度图像的方法有两种,一个是令RGB三个分量的数值相等.输出后便可以得到灰度图像,另一种是转换为YCbCr格式,将Y分量提取出来,YCbCr格式中的Y分量表示的是图 像的亮度和浓度,所以只输出Y分量,得到图像就是灰度图像.