FPGA学习笔记——图像锐化之非锐化掩蔽

目录

一、任务

二、非锐化掩蔽

[三、FIFO IP核调用](#三、FIFO IP核调用)

四、代码

1.v代码

(1)top_mask

(2)mask

(3)template3x3

2.仿真代码

(1)tb

(2)video_source

五、实验现象


一、任务

将下面这幅图片进行非锐化掩蔽。


二、非锐化掩蔽

非锐化掩蔽是一种常用的图像锐化技术,用于增强图像的边缘和细节表现。


高斯模糊卷积核:

思路:

创建模糊版本:首先对原始图像进行高斯模糊处理,得到一个模糊版本

计算掩模:用原始图像减去模糊图像,得到高频成分(边缘和细节)

增强处理:将高频成分按比例放大后加回原始图像


三、FIFO IP核调用

FIFO调用


四、代码

1.v代码

(1)top_mask

rust 复制代码
`timescale 1ns / 1ps
module top_mask(
input            clk     ,
input            rst_n   ,
input  [23:0]    i_rgb888,
input            i_vsync ,
input            i_hsync ,
input            i_valid ,
//----------------------------
output [23:0]   o_rgb888 ,
output          o_hsync  ,
output          o_vsync  ,
output          o_valid   
    );
    
            mask mask_u1(
.     clk    (clk),
.     rst_n  (rst_n),
.     i_pixel(i_rgb888[23:16]),
.     i_vsync(i_vsync),
.     i_hsync(i_hsync),
.     i_valid(i_valid),
.    o_pixel (o_rgb888[23:16]),
.    o_hsync (o_hsync),
.    o_vsync (o_vsync),
.    o_valid (o_valid) 
    );
    
        mask mask_u2(
.     clk    (clk),
.     rst_n  (rst_n),
.     i_pixel(i_rgb888[15:8]),
.     i_vsync(i_vsync),
.     i_hsync(i_hsync),
.     i_valid(i_valid),
.    o_pixel (o_rgb888[15:8]),
.    o_hsync (),
.    o_vsync (),
.    o_valid () 
    );
    
        mask mask_u3(
.     clk    (clk),
.     rst_n  (rst_n),
.     i_pixel(i_rgb888[7:0]),
.     i_vsync(i_vsync),
.     i_hsync(i_hsync),
.     i_valid(i_valid),
.    o_pixel (o_rgb888[7:0]),
.    o_hsync (),
.    o_vsync (),
.    o_valid () 
    );
    
endmodule

(2)mask

rust 复制代码
`timescale 1ns / 1ps
module mask#(
                parameter   k = 1
)(
input            clk     ,
input            rst_n   ,
input  [7:0]     i_pixel ,
input            i_vsync ,
input            i_hsync ,
input            i_valid ,
//----------------------------
output [7:0]    o_pixel  ,
output          o_hsync  ,
output          o_vsync  ,
output          o_valid   
    );
    
    wire [7:0]   a0,a1,a2 ;
    wire [7:0]   b0,b1,b2 ;
    wire [7:0]   c0,c1,c2 ;
    
    reg [3:0]   o_hsync_r;
    reg [3:0]   o_vsync_r;
    reg [3:0]   o_valid_r;

    
    reg [15:0]  sum;
    reg [7:0]   pixel_reg0,pixel_reg1,pixel_reg2;
    reg [9:0]   mask_o;
    reg [9:0]   temp0;
    wire [8:0]   temp1;
    
    //---------------------------------
    always @(posedge clk)begin
        if(!rst_n)begin
            sum <=0 ;
        end
        else begin
            sum <= (a0+a2+c0+c2)*14 + (a1+b0+b2+c1)*24 + 40*b1;
        end
    end
    
    always @(posedge clk)begin
        if(!rst_n)begin
            pixel_reg0 <= 0;
            pixel_reg1 <= 0;
            pixel_reg2 <= 0;
        end
        else begin
            pixel_reg0 <= i_pixel;
            pixel_reg1 <= pixel_reg0;
            pixel_reg1 <= pixel_reg0;
            pixel_reg2 <= pixel_reg1;
        end
    end
    
    //----------------------------------------
    always@(posedge clk) begin
        if(!rst_n)begin
            mask_o <= 0;
        end
        else begin
            mask_o <= k*(pixel_reg1 - sum[15:8]);
        end
    end
    
    
    always @(posedge clk) begin
        if(!rst_n) begin
            temp0 <= 0;
        end
        else begin
            temp0 <= mask_o + pixel_reg2;
        end
    end
    
    assign  temp1 = temp0[9]?9'd0:temp0[8:0];
    assign  o_pixel = temp1[8]?8'hff:temp1[7:0];
    

    
    
        //----------------------------------
    always @(posedge clk) begin
        if(!rst_n)begin
            o_hsync_r <= 0;
            o_vsync_r <= 0;
            o_valid_r <= 0;
        end
        else begin
            o_hsync_r <= {o_hsync_r[2:0],i_hsync};
            o_vsync_r <= {o_vsync_r[2:0],i_vsync};
            o_valid_r <= {o_valid_r[2:0],i_valid};
        end
    end
    
    assign o_hsync = o_hsync_r[3];
    assign o_vsync = o_vsync_r[3];
    assign o_valid = o_valid_r[3];
    
            template3x3 template3x3_u(
.  clk     (clk),
.  rst_n   (rst_n),
.  i_pixel (i_pixel),
.  i_vsync (i_vsync),
.  i_hsync (i_hsync),
.  i_valid (i_valid),
. a0(a0),.a1(a1),.a2 (a2),
. b0(b0),.b1(b1),.b2 (b2),
. c0(c0),.c1(c1),.c2 (c2),
. o_hsync  (),
. o_vsync  (),
. o_valid  () 
    );
    
endmodule

(3)template3x3

rust 复制代码
`timescale 1ns / 1ps
module template3x3#(
                    parameter   HSYNC = 1280    ,
                                VSYNC = 720
)(
input            clk     ,
input            rst_n   ,
input  [7:0]     i_pixel ,
input            i_vsync ,
input            i_hsync ,
input            i_valid ,
//----------------------------
output reg [7:0]   a0,a1,a2 ,
output reg [7:0]   b0,b1,b2 ,
output reg [7:0]   c0,c1,c2 ,
output  reg        o_hsync  ,
output  reg        o_vsync  ,
output  reg        o_valid   
    );
    
    reg [15:0]  cnt_line0;
    reg [15:0]  cnt_line1;
    
    wire        fifo0_rd_en;
    wire [7:0]  fifo0_rd_data;
    
    wire        fifo1_rd_en;
    wire [7:0]  fifo1_rd_data;
    
    assign fifo0_rd_en = (cnt_line0 >= HSYNC-1  && i_valid);   //存完一行图像数据 ,并且新的一行图像数据来了
    assign fifo1_rd_en = (cnt_line1 >= HSYNC-1  && i_valid);   //存完一行图像数据 ,并且新的一行图像数据来了
    
    always @(posedge clk)begin
        if(!rst_n)
            cnt_line0 <= 0;
        else if(i_valid)begin
            if(cnt_line0 == HSYNC-1)     //存完一行图像数据
                cnt_line0 <= cnt_line0;
            else
                cnt_line0 <= cnt_line0+1;
        end
    end

    always @(posedge clk)begin
        if(!rst_n)
            cnt_line1 <= 0;
        else if(fifo0_rd_en)begin
            if(cnt_line1 == HSYNC-1)
                cnt_line1 <= cnt_line1;
            else
                cnt_line1 <= cnt_line1+1;
        end
    end


    always @(posedge clk)begin
        if(!rst_n)begin
            a0 <= 0;
            a1 <= 0;
            a2 <= 0;
            b0 <= 0;
            b1 <= 0;
            b2 <= 0;
            c0 <= 0;
            c1 <= 0;
            c2 <= 0;
        end
       else begin
            a0 <= a1;
            a1 <= a2;
            a2 <= fifo1_rd_data;
            b0 <= b1;
            b1 <= b2;
            b2 <= fifo0_rd_data;
            c0 <= c1;        
            c1 <= c2;        
            c2 <= i_pixel;   
        end
    end

    always @(posedge clk)begin
        o_vsync <= i_vsync;
        o_hsync <= i_hsync;
        o_valid <= i_valid;
    end

    fifo8x2048 fifo8x2048_u0 (
      .clk(clk),      // input wire clk
      .srst(~rst_n),    // input wire srst
      .din(i_pixel),      // input wire [7 : 0] din
      .wr_en(i_valid),  // input wire wr_en
      .rd_en(fifo0_rd_en),  // input wire rd_en
      .dout(fifo0_rd_data),    // output wire [7 : 0] dout
      .full(),    // output wire full
      .empty()  // output wire empty
    );


    fifo8x2048 fifo8x2048_u1 (
      .clk(clk),      // input wire clk
      .srst(~rst_n),    // input wire srst
      .din(fifo0_rd_data),      // input wire [7 : 0] din
      .wr_en(fifo0_rd_en),  // input wire wr_en
      .rd_en(fifo1_rd_en),  // input wire rd_en
      .dout(fifo1_rd_data),    // output wire [7 : 0] dout
      .full(),    // output wire full
      .empty()  // output wire empty
    );
    
    
endmodule

2.仿真代码

(1)tb

(2)video_source

rust 复制代码
`timescale 1ns / 1ps
`define VIDEO_1280_720
module video_source#(
parameter   VSYNC=720,
            HSYNC=1280,
            DELAY1=50_000_000              //图像处理延迟
 
)(
input          pclk         ,
input          rstn         ,
//----图像输出----------------------
output  reg    source_de_o  ,
output [23:0]  source_data_o,
//----图像输入----------------------
input          de_i         ,
input [23:0]   data_i
    );
//1280X720 74.25MHZ
`ifdef  VIDEO_1280_720
parameter  H_ACTIVE 		= 1280;// 行数据有效时??
parameter  H_FRONT_PORCH 	= 110; // 行消隐前肩时??
parameter  H_SYNC_TIME 		= 40;  // 行同步信号时??
parameter  H_BACK_PORCH 	= 220; // 行消隐后肩时??    
parameter  H_POLARITY       = 1;   // 行同步极??
parameter  V_ACTIVE 		= 720; // 列数据有效时??
parameter  V_FRONT_PORCH 	= 5;   // 列消隐前肩时??
parameter  V_SYNC_TIME  	= 5;   // 列同步信号时??
parameter  V_BACK_PORCH 	= 20;  // 列消隐后肩时??
parameter  V_POLARITY       = 1;   // 场同步极??
`endif

localparam addr_size=HSYNC*VSYNC*3+54;    //总字节数
//文件??
integer bmp_file_id;
integer bmp_dout_id;
//文件句柄
integer h;
reg		[7:0]	rd_data  [addr_size-1:0];      //根据自己图片大小    BMP格式为:位图文件头(14字节??+位图信息头(40字节??+实际像素点占内存
reg		[7:0]	wr_data  [addr_size-1:0];    
integer i=0;
integer    addr_rd=54;
integer    addr_wr=54;


initial begin
    bmp_file_id = $fopen("D:/intelFPGA_lite/haiyunjiexun/text_Vivado/filter/image_1.bmp","rb");          //打开原始图像
    bmp_dout_id = $fopen("D:/intelFPGA_lite/haiyunjiexun/text_Vivado/filter/image_1_out.bmp","wb");     //打开输出图像
    h = $fread(rd_data,bmp_file_id);                                   //读取bmp文件     读取到的数据将会依次放入rd_data??
    $fclose(bmp_file_id);                                              //读取完毕
    
       
    #DELAY1  ;                                                             //图像处理延迟

	for(i = 0; i < addr_size; i = i + 1)begin                        //图像数据写入文件
	   if(i < 54)
	       $fwrite(bmp_dout_id, "%c", rd_data[i]);//注意参数%c
	   else       
           $fwrite(bmp_dout_id, "%c", wr_data[i]);//注意参数%c
    end
    $fclose(bmp_dout_id);
    #100;
    $stop ;
    
end


//----读出图像数据--------------------------------
always@(posedge pclk)begin
    if(source_de_o) begin
        if(addr_rd >= addr_size-3)
            addr_rd<=54;
        else
            addr_rd<=addr_rd+3;
    end
end


assign source_data_o={rd_data[addr_rd],rd_data[addr_rd+1],rd_data[addr_rd+2]};    //R + G + B

//----写入图像数据--------------------------------
always@(posedge pclk)begin
    if(de_i) begin
        if(addr_wr >= addr_size-3)
            addr_wr<=54;
        else
            addr_wr<=addr_wr+3;
    end
end

always@(posedge pclk)begin
    wr_data[addr_wr]=data_i[23:16];                                   //写入存储??
    wr_data[addr_wr+1]=data_i[15:8];
    wr_data[addr_wr+2]=data_i[7:0];
end

localparam  H_TOTAL_TIME=H_ACTIVE+H_FRONT_PORCH+H_SYNC_TIME+H_BACK_PORCH;
localparam  V_TOTAL_TIME=V_ACTIVE+V_FRONT_PORCH+V_SYNC_TIME+V_BACK_PORCH;
reg [31:0] cnt_v;   //场同步计数器
reg [31:0] cnt_h;   //行同步计数器

always@(posedge pclk)begin
    if(!rstn)
        source_de_o<=0;
    else if(( cnt_h > (H_SYNC_TIME + H_BACK_PORCH -1)) &&   (cnt_h <= (H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE -1)) &&  (cnt_v > (V_SYNC_TIME + V_BACK_PORCH-1)) && (cnt_v <= (V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE-1)))
        source_de_o<=1;
   else
        source_de_o<=0;
end



always@(posedge pclk)begin
    if(!rstn)
        cnt_h<=0;
    else if(cnt_h == H_TOTAL_TIME-1)
        cnt_h<=0;
    else
        cnt_h<=cnt_h+1;
end

always@(posedge pclk)begin
    if(!rstn)
        cnt_v<=0;
    else if(cnt_h == H_TOTAL_TIME-1)begin
        if(cnt_v == V_TOTAL_TIME-1)
            cnt_v<=0;
        else
            cnt_v<=cnt_v+1;
    end
end



endmodule

五、实验现象


以上就是图像锐化之非锐化掩蔽。 (如果有错误的地方,还请大家指出来,谢谢!)

相关推荐
荆白雪2 小时前
verilog
fpga开发
Nix Lockhart3 小时前
《算法与数据结构》第七章[第1节]:图
c语言·数据结构·学习·算法
CIb0la3 小时前
非常好的学习方法是哪样
笔记·学习·学习方法
鲸鱼24013 小时前
图像分类笔记
大数据·笔记·分类
冬夜戏雪3 小时前
[学习日记][ssm p103以前]
学习
h汉堡4 小时前
类和对象(二)
开发语言·数据结构·c++·学习
全栈工程师修炼指南4 小时前
DBA | MySQL 数据库基础数据操作学习实践笔记
数据库·笔记·学习·mysql·dba
励志不掉头发的内向程序员4 小时前
【Linux系列】让 Vim “跑”起来:实现一个会动的进度条
linux·运维·服务器·开发语言·学习
天生励志1234 小时前
【学习笔记】黑马Java+AI智能辅助编程视频教程,java基础入门
java·笔记·学习