zoukankan      html  css  js  c++  java
  • FPGA实现视频图像的水印添加

      图像水印到处可见,如微博图片右下角会有原创者 ID 水印,很多 PDF 文件中也夹有水印,而视频图像同样可以添加水印,最著名的视频图像水印便是电视台的标志了。图像水印在文化产权上起到非常重要的作用,对所有者的权益起到一定的保护。

      数字图像的水印叠加公式为:fx = (1-a)f + aw
      未加水印的图像表示为 f,水印表示为 w,常数 a 控制水印和衬底图像的相对可见性。如果 a 为 1,则水印是不透明的,并且衬底图像完全是暗的;随着 a 接近 0,会逐渐看到更多的衬底图像和更少的水印,通常 a 在 0 和 1 之间。
      本篇博客整理一下如何使用 FPGA 为视频图像添加自定义的水印图案。
     
    一、水印图像
      水印图像可以自己找一张喜欢的图片或字符,但不要太大,否则就喧宾夺主了。如下是我本次实验选取的水印图案:
      这是我博客的头像,我将其分辨率改为 50x50。
     
    二、图像转mif文件
      网上很多图像转 16位 mif 文件的小软件,当然如果你 MATLAB 学的好,也可以用 MATLAB 来实现。此次我使用的是正点原子开发的 “PicToMif_V1.0.exe”。
     
    三、rom生成
      rom的位宽设置为 16,深度设置为 2500(水印图像分辨率),然后把第二步生成的 mif 文件包含进去即可,不添加锁存器,让数据输出的延时为1个时钟周期,rden信号也不需要,有读地址就够了。
     
    四、添加水印图案的设计
    1、直接添加水印
      可以单独设计一个 .v 模块为水印图案模块,这个设计代码量小,我直接写在顶层模块的 TFT_driver 之后,连接管脚之前。代码如下所示:
    //==========================================================================
    //==                        TFT
    //==========================================================================
    TFT_driver u_TFT_driver 
    (
        .clk                    (clk_10m                ), 
        .rst_n                  (rst_n                  ),
        .TFT_req                (rd_en                  ),
        .TFT_x                  (TFT_x                  ),
        .TFT_y                  (TFT_y                  ),
        .TFT_din                (rd_data                ),
        .TFT_clk                (TFT_clk                ),
        .TFT_de                 (TFT_de                 ),
        .TFT_pwm                (TFT_pwm                ),
        .TFT_hsync              (TFT_hsync              ),
        .TFT_vsync              (TFT_vsync              ),
        .TFT_data               (rgb                    )   
    );
    //==========================================================================
    //==                        添加视频水印
    //==========================================================================
    mark_rom u_mark_rom
    (
        .clock                  (clk_10m                ),
        .address                (rom_addr               ),
        .q                      (rom_data               )
    );
    //--------------------------------------------------------------------------
    //水印范围
    assign rom_rden = (TFT_x >= 1) && (TFT_x <=50) && 
                      (TFT_y >= 1) && (TFT_y <=50);
    
    //rom地址
    always @(posedge clk_10m or negedge rst_n) begin
        if(!rst_n)
            rom_addr <= 12'b0;
        else if(rom_addr==2500-1)
            rom_addr <= 12'b0;
        else if(rom_rden)
            rom_addr <= rom_addr + 1'b1;
    end
    
    //数据显示 
    always @(*) begin
        if(rom_rden) begin
            TFT_data <= rom_data;      //显示水印
        end
        else
            TFT_data <= rgb;               //显示原图
    end

       其中 rgb 是原本输出到管脚上的,拿来到“添加视频水印”模块做进一步的处理,而 TFT_x、TFT_y 信号是 TFT_driver 里就设计好的坐标信号,这里不得不又说一下,模块设计的好,移植性就非常强!

      如果你的 TFT 或 VGA 驱动模块没有设计坐标信号,那么在后面用 de 使能信号设计一下就行,其实就是行列规划的计数器而已。

      OK来看看下效果:

      设计成功!我的FPGA开发板引脚有问题,那些红点并不是本工程的 bug 。
     
    2、半透明水印
      上面添加的水印比较生硬,可不可以美化一下呢?是可以的,我们可以让其变得半透明,并且会随着图像的变换跟着变换,仿佛是融入了图像内部一样。
      代码如下所示:
    always @(*) begin
        if(rom_rden) begin
            TFT_data <= rom_data + rgb;   //显示水印
        end
        else
            TFT_data <= rgb;              //显示原图
    end

       将 rom_data 和 rgb 数据相加,最后实现的效果如下所示:

      ......好像有点打脸?
      是打脸,也不是打脸,怎么说呢?因此我的水印图案是彩色缤纷的,和原本像素值相加后效果不好,白色的略去了,但是其他色彩也变形了。但是如果我们把水印图案的主要符号选择为黑色,效果就会非常好,感兴趣的同学可以试试。
     
    3、略去背景的水印图案
      如果不喜欢上面第2种效果,那我们再改进一下吧,水印图案的输出就不进行和原像素相加了。观察一下我的水印图案,背景是白色的,因此我们可以想办法把白色背景略去,只保留中心的图案。代码如下所示:
    always @(*) begin
        if(rom_rden) begin
            if(rom_data==16'hffff)              //背景白色显示原图
                TFT_data <= rgb;
            else
                TFT_data <= rom_data;// + rgb;  //否则显示水印
        end
        else
            TFT_data <= rgb;                    //显示原图
    end

       对水印图案进行判断,如果是白色,则显示原图,否则显示水印,非水印区域也显示原图。最后效果如下所示:

      效果还是不错的,水印图案还是没有选的特别好,头发那有些白点没有略去,那的像素并不是肉眼以为的纯白,而是一些像白色的灰度数据。如果要达到最好的效果,可以好好对水印图案进行一番选择。
      实验整体效果如下所示:
      从视频上可以看到,最后的效果还是不错的,可惜我的板卡有问题,很多地方有红点,而且颜色有些失真了,此外 OV7670 摄像头的成像效果本身也不行。不过我们关注水印就够了,本次FPGA实现视频图像的水印添加实验宣告成功!
     
    后记
      熟悉rom的同学会发现本工程的代码时序应该再调整一下,因为ROM给出地址到出数据是有一定延迟的。但是本工程只是为了看看水印效果,要时序完美对齐也很简单,但代码量明显增多,de,vsync,hsync等都得拿出来打拍。而且现在这样效果挺完美,就这样吧。
     
     
    参考资料:[1]OpenS Lee:FPGA开源工作室(公众号)
     
     
  • 相关阅读:
    电商 JQuery 抓取联系人信息 复制的代发兔
    Linux-Centos下安装工具用来解压压缩
    Linux远程连接及上传文件
    虚拟机-Linux-Centos8.1 与宿主主机ping互通
    虚拟机-Linux-Centos8.1联网
    数字量输入模块和模拟量输入模块的区别是什么?
    串口转以太网模块设备介绍和使用说明
    以太网模块是什么,以太网模块的功能和特点
    4G DTU连接阿里云说明手册
    react07
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/12508476.html
Copyright © 2011-2022 走看看