[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_图像入门连载-23FPGA 实现视频水印效果处理

文档创建者:FPGA课程
浏览次数:80
最后更新:2024-10-22
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 8-FPGA图像入门
本帖最后由 FPGA课程 于 2024-10-22 19:57 编辑

​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1 视频水印效果算法简介
数字图像水印叠加公式为 f=(1-a)f1+aw。原图表示为 f,而水印表示为 w,常熟 a 控制水印和衬底图像的相 对可见性。如果 a 为 1,则水印是不透明的,并且衬底完全是暗的;随着 a 接近 0,会逐渐看到更多的衬底图像和 更少的水印。视频水印效果就是在实时的视频流中添加特定的图片,就是图片叠加在视频流里。我们可以划定一块 区域用于填充水印,把水印图片存储在固定的 RAM 块中,每来一帧图像就刷新一次水印进去。
2 设计分析
2.1Matlab 代码分析
  1. clear;clear all;clc;

  2. row = 720;  col = 1280; n      = 3;

  3. image_sim_pass = uint8(zeros(row,col,n));   fid = fopen('image_720_ 1280  3  out.txt','r');
  4. for x = 1:row
  5. for y = 1:col
  6. RGB = fscanf(fid,'%s',1);
  7. image_sim_pass(x,y,1) = uint8(hex2dec(RGB(1:2))); image_sim_pass(x,y,2) = uint8(hex2dec(RGB(3:4))); image_sim_pass(x,y,3) = uint8(hex2dec(RGB(5:6)));
  8. end
  9. end
  10. fclose(fid);

  11. image_ 1 = imread('lena_ 1280x720.jpg');

  12. subplot(121);
  13. imshow(image_ 1), title('The original image');

  14. subplot(122);
  15. imshow(image_sim_pass),title('After processing images');

  16. imwrite(image_sim_pass,'lena_720x1280_sim_pass.jpg');
复制代码

2.2Verilog 代码分析

  1. parameter  H_ACTIVE                 = 128; //水印区域宽度                              
  2. parameter  V_ACTIVE                 = 36;  //水印区域高度
  3. parameter  BEGIN_X          = 1151; //水印起始坐标
  4. parameter  BEGIN_Y          = 0; //水印起始坐标


  5. reg  [10:0]             h_cnt;
  6. reg  [10:0]             v_cnt;
  7. reg  [10:0]             x_pos;
  8. reg  [10:0]             y_pos;
  9. reg  [12:0]                 rd_addr;
  10. reg                                        o_de;
  11. reg                                        o_de1;
  12. reg                                 hsyn_d0;
  13. reg                                        vsyn_d0;
  14. reg                                        en_pos_d0;
  15. reg                                 hsyn_d1;
  16. reg                                        vsyn_d1;
  17. reg                                        en_pos_d1;


  18. reg  [7:0]                  r_d;
  19. reg  [7:0]                  g_d;
  20. reg  [7:0]                  b_d;

  21. reg  [7:0]                  r_d1;
  22. reg  [7:0]                  g_d1;
  23. reg  [7:0]                  b_d1;

  24. wire [7:0]                  r_d0;
  25. wire [7:0]                  g_d0;
  26. wire [7:0]                  b_d0;
  27. wire                                   de_d0;//显示区域使能信号


  28. // assign o_r   = o_de ? r_d0 : 8'hff;
  29. // assign o_g   = o_de ? g_d0 : 8'hff;
  30. // assign o_b   = o_de ? b_d0 : 8'hff;

  31. assign o_r   = o_de1 ? r_d0 : r_d1;
  32. assign o_g   = o_de1 ? g_d0 : g_d1;
  33. assign o_b   = o_de1 ? b_d0 : b_d1;


  34. assign o_hs  = hsyn_d1;
  35. assign o_vs  = vsyn_d1;
  36. assign o_en  = en_pos_d1;

  37. assign de_d0 = i_en_pos && (x_pos >= BEGIN_X)&&(x_pos < BEGIN_X + H_ACTIVE)&&
  38.                            (y_pos >= BEGIN_Y)&&(y_pos < BEGIN_Y + V_ACTIVE) ? 1'b1:1'b0;

  39. //同步输出使能信号
  40. always@(posedge i_clk )
  41. begin        
  42.         hsyn_d0                <= i_hsyn;
  43.         vsyn_d0                <= i_vsyn;
  44.         en_pos_d0        <= i_en_pos;
  45.         hsyn_d1                <= hsyn_d0;        
  46.         vsyn_d1                <= vsyn_d0;        
  47.         en_pos_d1        <= en_pos_d0;        
  48.         r_d                        <= i_r;
  49.         g_d                        <= i_g;
  50.         b_d                        <= i_b;
  51.         r_d1                <= r_d;
  52.         g_d1                <= g_d;
  53.         b_d1                <= b_d;        
  54. end

  55. //x计数
  56. always@(posedge i_clk or negedge i_rst_n)
  57. begin
  58.     if(!i_rst_n)
  59.         begin
  60.         x_pos <= 11'd0;
  61.     end
  62.     else if(i_en_pos)
  63.         begin
  64.                 if(x_pos == 1280 - 1'b1)
  65.                         x_pos <= 11'd0;
  66.                 else
  67.                         x_pos <= x_pos + 11'd1;
  68.     end
  69. end

  70. //y计数
  71. always@(posedge i_clk or negedge i_rst_n)
  72. begin
  73.     if(!i_rst_n)
  74.         begin
  75.         y_pos <= 11'd0;
  76.     end
  77.     // else if(x_pos == 1280 - 1'b1)
  78.     else if(!i_en_pos && en_pos_d0)        
  79.         begin
  80.                 if(y_pos == 720 - 1'b1)
  81.                         y_pos <= 11'd0;
  82.                 else
  83.                         y_pos <= y_pos + 11'd1;
  84.     end
  85. end
  86. //显示区域行计数
  87. always@(posedge i_clk or negedge i_rst_n)
  88. begin
  89.     if(!i_rst_n)
  90.         begin
  91.         h_cnt <= 11'd0;
  92.     end
  93.     else if(de_d0)
  94.         begin
  95.                 if(h_cnt == H_ACTIVE - 1'b1)
  96.                         h_cnt <= 11'd0;
  97.                 else
  98.                         h_cnt <= h_cnt + 11'd1;
  99.     end
  100. end

  101. //显示区域场计数
  102. always@(posedge i_clk or negedge i_rst_n)
  103. begin
  104.     if(!i_rst_n)
  105.         begin
  106.         v_cnt <= 11'd0;
  107.     end
  108.     else if(h_cnt == H_ACTIVE - 1'b1)
  109.         begin
  110.                 if(v_cnt == V_ACTIVE - 1'b1)
  111.                         v_cnt <= 11'd0;
  112.                 else
  113.                         v_cnt <= v_cnt + 11'd1;
  114.     end
  115. end

  116. //显示区域存储ROM
  117. image_36_128_rom u_image_buffer
  118. (
  119.     .clka        (i_clk                        ),
  120.     .ena         (o_de                        ),
  121.     .addra         (rd_addr                ),
  122.     .douta         ({r_d0,g_d0,b_d0})
  123. );

  124. //读取地址更新
  125. always@(posedge i_clk or negedge i_rst_n)
  126. begin
  127.     if(!i_rst_n)
  128.         begin
  129.         rd_addr <= 'd0;
  130.     end
  131.     else if(de_d0)
  132.         begin
  133.                 rd_addr <= v_cnt * H_ACTIVE + h_cnt;
  134.     end
  135. end
复制代码

2.3 工程结构分析
我们将图像视频水印的模块做成 IP 后,在vivado 中进行工程的搭建,工程结构如图所示:
28d387dea2474d19be15a4831923094d.jpg
3 仿真及结果
3.1Matlab 实验结果
9fa79c9c920349f1972556287d7c22f8.jpg
3.2Modelsim 实验结果
705ef795a48a4887b66738d0db7bccf4.jpg

4 搭建 Vitis-sdk 工程
创建 soc_base  sdk  platform  和 APP  工程的过程不再重复,可以阅读 3-3-01_sdk_base_app。以下给出创建好 soc_base sdk platform 的截图和对应工程 APP 的截图。
4.1 创建 SDK Platform 工程
b102b6fbc4d34379804900cd0f35d939.jpg

4.2SDK APP 工程
9b8c49266b734272b1764da6f0c8528f.jpg
5 硬件连接
硬件连接如图所示:
d99cc9c196db44f5a670f5c90f1ade26.jpg
6 上板实验结果
实验结果如图所示:
56287d4d9aba48138947a972533be70b.jpg





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则