基于FPGA的图像浮雕效果实现

项目简述

为什么要做这个小项目,因为最近正在在学习FPGA开源工作室中的FPGA图像处理的文章。发现这个小例子非常容易实现。就把这个小算法给复现了。这个基本上不能称之为一个项目,因为太简单了。但是,这里面涉及了真彩图转变成灰度图像的一个方法,在书写的时候我们也用到了除法器Ip(为了介绍IP专门使用的触除法器),有符号数的使用。所以,这里我们这里进行简单的介绍。

算法原理及MATLAB实现

写了好多博客关于图像处理算法的实现,不知道大家发没发现图像处理算法很容易在FPGA中复现,这是因为图像处理的数据是整数,一般也都针对像素点处理,这在FPGA实现的过程中完全没有压力。所以这也是FPGA在图像处理中的一个优点。

图像实现浮雕效果与SOBEL是非常相似的,只不过SOBEL是与一个像素点周围的像素点有关,而浮雕处理至于自己一行的像素点有关。具体的公式如下:
i m a g e _ n e w ( i , j ) = i m s g e ( i , j ) − i m a g e ( i , j + m ) + T H image\_new(i,j)=imsge(i,j)-image(i,j+m)+TH image_new(i,j)=imsge(i,j)image(i,j+m)+TH
其中i是图像的行数,j是图像的列,TH是设置的阈值。这里需要注意的是上面的图像是灰度图像。
这里的m可以控制浮雕效果的明显程度,TH控制主背景的明亮程度。

常见的真彩图转换成灰度图像的方法主要有:
1、直接取RGB三分量其中的一种当作灰度化图像
2、将RGB三分量取平均当作灰度化图像
3、进行RGB到YCbCr格式的转换,取Y分量当作灰度化图像
本篇文章中我们使用的是第2中方法。
原理这么简单,也就不多说,MATLAB代码如下:

clc
clear all

 
image_old = imread('456.bmp');
image_gray= (image_old(:,:,1) + image_old(:,:,2)+image_old(:,:,2))/3;
[Height,Width] = size(image_gray);
image_new = zeros(Height,Width);
TH = 100;
 
for i = 1:Height
    for j=1:Width-2
        image_new(i,j)=image_gray(i,j)-image_gray(i,j+2)+TH;
        if image_new(i,j) >255
             image_new(i,j) = 255;
        elseif image_new(i,j) <0
            image_new(i,j) = 0;
        else
            image_new(i,j) =  image_new(i,j);
        end
    end
end
image_new = uint8(image_new);

imshow(image_new);

实验效果如下:
在这里插入图片描述
处理后的图像为m=2:
在这里插入图片描述
处理后的图像为m=4:
在这里插入图片描述
对比上面两张图可以发现m可以控制浮雕效果的明显程度

浮雕效果的FPGA实现

上面的MATLAB代码,我们已经详细写出了算法流程,接下来我们直接给出相应的图像处理代码,并指出几点需要注意的地方:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : image.v
// Create Time  : 2020-05-12 09:40:55
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module image(
    //System Interfaces
    input                   sclk            ,
    input                   rst_n           ,
    //Communication Interfaces
    input           [31:0]  rgb_data        ,
    input                   rgb_data_en     ,
    output  wire    [31:0]  data_wr         ,
    output  reg             data_wr_en 
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
reg                 [15:0]  gray_data       ;
reg                         rgb_data_en_r   ;
wire                [23:0]  divider_data    ; 
wire                        divider_data_en ;
reg                 [23:0]  divider_data_r  ; 
reg                 [23:0]  divider_data_r2 ;
reg     signed      [10:0]  count_data      ; 
reg                 [ 7:0]  dout            ;   

 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
assign      data_wr         =       {
   
   8'h00,dout,dout,dout};

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        gray_data           <=          16'd0; 
    else
        gray_data           <=          rgb_data[31:24] + rgb_data[23:16] + rgb_data[15:8] + rgb_data[7:0];

always @(posedge sclk)
    rgb_data_en_r           <=          rgb_data_en;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)begin
        divider_data_r      <=          8'd0;
        divider_data_r2     <=          8'd0;
    end else if(divider_data_en == 1'b1)begin
        divider_data_r      <=          divider_data;
        divider_data_r2     <=          divider_data_r;
    end 
    
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        count_data          <=          11'd0; 
    else if(divider_data_en == 1'b1)
        count_data          <=          divider_data_r2[23:8] -  divider_data[23:8] + 100;
    else
        count_data          <=          count_data;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        dout                <=          8'd0;
    else if(count_data > 255)
        dout                <=          8'd255;
    else if(count_data < 0)
        dout                <=          8'd0;
    else 
        dout                <=          count_data[7:0];

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        data_wr_en          <=          1'b0;  
    else
        data_wr_en          <=          divider_data_en;   
                
div_gen_0 div_gen_0_inst (
  .aclk                                 (sclk                           ),                                      // input wire aclk
  .s_axis_divisor_tvalid                (rgb_data_en_r                  ),    // input wire s_axis_divisor_tvalid
  .s_axis_divisor_tdata                 (8'd3                           ),      // input wire [7 : 0] s_axis_divisor_tdata
  .s_axis_dividend_tvalid               (rgb_data_en_r                  ),  // input wire s_axis_dividend_tvalid
  .s_axis_dividend_tdata                (gray_data                      ),    // input wire [15 : 0] s_axis_dividend_tdata
  .m_axis_dout_tvalid                   (divider_data_en                ),          // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata                    (divider_data                   )            // output wire [23 : 0] m_axis_dout_tdata
);

endmodule

1、除法器的输出为什么使用了前16位,这里是引文后面的8位是小数位:
在这里插入图片描述
2、这里要使用下面的判断:
在这里插入图片描述
count_data必须在程序中定义成有符号数。
在这里插入图片描述

FPGA工程代码

这里为了方便大家的学习,我们给出整个FPGA工程的代码,整个项目的流程参考前面的SOBEL边缘检测部分,这里不多家赘述:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : top.v
// Create Time  : 2020-03-01 20:33:42
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module top(
    //System Interfaces
    input                       sclk                    ,
    input                       rst_n                   ,
    //DDR3 Interfaces           
    output  wire    [13:0]      ddr3_addr               ,
    output  wire    [ 2:0]      ddr3_ba                 ,
    output  wire                ddr3_cas_n              ,
    output  wire                ddr3_ck_n               ,
    output  wire                ddr3_ck_p               ,
    output  wire                ddr3_cke                ,
    output  wire                ddr3_ras_n              ,
    output  wire                ddr3_reset_n            ,
    output  wire                ddr3_we_n               ,
    inout           [31:0]      ddr3_dq                 ,
    inout           [ 3:0]      ddr3_dqs_n              ,
    inout           [ 3:0]      ddr3_dqs_p              ,
    output  wire    [ 0:0]      ddr3_cs_n               ,
    output  wire    [ 3:0]      ddr3_dm                 ,
    output  wire    [ 0:0]      ddr3_odt                ,
    //Gigbit Interfaces
    output  wire                phy_rst_n               ,
    input           [ 3:0]      rx_data                 ,
    input                       rx_ctrl                 ,
    input                       rx_clk                  ,
    //USB3 Interfaces
    output  wire                USBSS_EN                ,
    input                       USB_clk                 ,
    inout           [15:0]      data                    ,
    inout           [ 1:0]      be                      ,
    input                       rxf_n                   ,
    input                       txf_n                   ,
    output  wire                oe_n                    ,
    output  wire                wr_n                    ,
    output  wire                siwu_n                  ,
    output  wire                rd_n                    ,
    output  wire                wakeup                  ,
    output  wire    [ 1:0]      gpio                                 
    );
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
//clk_wiz_0_inst
wire                            clk_200m                ;
wire                            locked                  ;
wire                            clk_125m                ; 
//ddr3_drive_inst
wire                            init_calib_complete     ;
wire                            c3_p0_cmd_clk           ;
wire                            c3_p0_cmd_en            ;
wire                [ 2:0]      c3_p0_cmd_instr         ;
wire                [27:0]      c3_p0_cmd_byte_addr     ;
wire                [ 6:0]      c3_p0_cmd_bl            ;
wire                            c3_p0_wr_clk            ;
wire                            c3_p0_wr_en             ;
wire                [31:0]      c3_p0_wr_mask           ;
wire                [255:0]     c3_p0_wr_data           ;
wire                [10:0]      c3_p0_wr_count          ; 

wire                        	c3_p1_cmd_clk           ;
wire                        	c3_p1_cmd_en            ;
wire                [ 2:0]  	c3_p1_cmd_instr         ;
wire                [27:0]  	c3_p1_cmd_byte_addr     ;
wire                [ 6:0]  	c3_p1_cmd_bl            ;
wire                        	c3_p1_rd_clk            ;
wire                        	c3_p1_rd_en             ;
wire                [255:0] 	c3_p1_rd_data           ;
wire                [10:0]  	c3_p1_rd_count          ;

//sensor_data_gen_inst
wire                            clk_24m                 ;
wire                            data_wr_en              ;
wire                [31:0]      data_wr                 ;

//usb3_drive_inst
wire                [15:0]      data_in                 ; 
wire                            data_req                ;

wire                [ 7:0]      image_data              ;
wire                            image_data_en           ;
wire                [31:0]      rlst                    ;     
wire                            rlst_flag               ;

wire                [31:0]      rgb_data                ;
wire                            rgb_data_en             ;    



 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
clk_wiz_0 clk_wiz_0_inst(
    // Clock out ports
    .clk_out1                       (clk_200m                       ),     // output clk_out1
    .clk_out2                       (clk_125m                       ),
    .clk_out3                       (clk_50m                        ),
    // Status and control signals
    .reset                          (~rst_n                         ), // input reset
    .locked                         (locked                         ),       // output locked
    // Clock in ports
    .clk_in1                        (sclk                           )
);      // input clk_in1

ddr3_top ddr3_top_inst(
    //System Interfaces
    .rst_n                          (rst_n                          ),
    .locked                         (locked                         ),
    .clk_200m                       (clk_200m                       ), 
    //DDR3 Interfaces           
    .ddr3_addr                      (ddr3_addr                      ),
    .ddr3_ba                        (ddr3_ba                        ),
    .ddr3_cas_n                     (ddr3_cas_n                     ),
    .ddr3_ck_n                      (ddr3_ck_n                      ),
    .ddr3_ck_p                      (ddr3_ck_p                      ),
    .ddr3_cke                       (ddr3_cke                       ),
    .ddr3_ras_n                     (ddr3_ras_n                     ),
    .ddr3_reset_n                   (ddr3_reset_n                   ),
    .ddr3_we_n                      (ddr3_we_n                      ),
    .ddr3_dq                        (ddr3_dq                        ),
    .ddr3_dqs_n                     (ddr3_dqs_n                     ),
    .ddr3_dqs_p                     (ddr3_dqs_p                     ),
    .ddr3_cs_n                      (ddr3_cs_n                      ),
    .ddr3_dm                        (ddr3_dm                        ),
    .ddr3_odt                       (ddr3_odt                       ),
    //User Interfaces
    .init_calib_complete            (init_calib_complete            ),
    .c3_p0_cmd_clk                  (c3_p0_cmd_clk 					),
    .c3_p0_cmd_en                   (c3_p0_cmd_en                   ),
    .c3_p0_cmd_bl                   (c3_p0_cmd_bl                   ),
    .c3_p0_cmd_byte_addr            (c3_p0_cmd_byte_addr            ),
    .c3_p0_cmd_empty                (								),
    .c3_p0_cmd_full                 (								),
    .c3_p0_wr_clk                   (c3_p0_wr_clk                   ),
    .c3_p0_wr_en                    (c3_p0_wr_en                    ),
    .c3_p0_wr_mask                  (c3_p0_wr_mask                  ),
    .c3_p0_wr_data                  (c3_p0_wr_data                  ),
    .c3_p0_wr_full                  (								),
    .c3_p0_wr_empty                 (								),
    .c3_p0_wr_count                 (c3_p0_wr_count                 ),

    .c3_p1_cmd_clk           		('d0							),
    .c3_p1_cmd_en            		('d0							),
    .c3_p1_cmd_bl            		('d0							),
    .c3_p1_cmd_byte_addr     		('d0							),
    .c3_p1_cmd_empty         		(								),
    .c3_p1_cmd_full          		(								),
    .c3_p1_wr_clk            		('d0							),
    .c3_p1_wr_en             		('d0							),
    .c3_p1_wr_mask           		('d0							),
    .c3_p1_wr_data           		('d0							),
    .c3_p1_wr_full           		(								),
    .c3_p1_wr_empty          		(								),
    .c3_p1_wr_count          		(								),

    .c3_p2_cmd_clk           		(c3_p1_cmd_clk                  ),
    .c3_p2_cmd_en            		(c3_p1_cmd_en                   ),
    .c3_p2_cmd_bl            		(c3_p1_cmd_bl                   ),
    .c3_p2_cmd_byte_addr     		(c3_p1_cmd_byte_addr            ),
    .c3_p2_cmd_empty         		(								),
    .c3_p2_cmd_full          		(								),
    .c3_p2_rd_clk            		(c3_p1_rd_clk                   ),
    .c3_p2_rd_en             		(c3_p1_rd_en                    ),
    .c3_p2_rd_data           		(c3_p1_rd_data                  ),
    .c3_p2_rd_full           		(								),
    .c3_p2_rd_empty          		(								),
    .c3_p2_rd_count          		(c3_p1_rd_count    		        ),

    .c3_p3_cmd_clk           		('d0							),
    .c3_p3_cmd_en            		('d0							),
    .c3_p3_cmd_bl            		('d0							),
    .c3_p3_cmd_byte_addr     		('d0							),
    .c3_p3_cmd_empty         		(								),
    .c3_p3_cmd_full          		(								),
    .c3_p3_rd_clk            		('d0							),
    .c3_p3_rd_en             		('d0							),
    .c3_p3_rd_data           		(								),
    .c3_p3_rd_full           		(								),
    .c3_p3_rd_empty          		(								),
    .c3_p3_rd_count                 (								)

);

ddr3_drive ddr3_drive_inst(
    //System Interfaces
    .rst_n                   		(init_calib_complete			    ),
    //DDR3 Interfaces           	
    .c3_p0_cmd_clk           		(c3_p0_cmd_clk           			),
    .c3_p0_cmd_en            		(c3_p0_cmd_en            			),
    .c3_p0_cmd_instr         		(c3_p0_cmd_instr         			),
    .c3_p0_cmd_byte_addr     		(c3_p0_cmd_byte_addr     			),
    .c3_p0_cmd_bl            		(c3_p0_cmd_bl            			),
    .c3_p0_wr_clk            		(c3_p0_wr_clk            			),
    .c3_p0_wr_en             		(c3_p0_wr_en             			),
    .c3_p0_wr_mask           		(c3_p0_wr_mask           			),
    .c3_p0_wr_data           		(c3_p0_wr_data           			),
    .c3_p0_wr_count          		(c3_p0_wr_count          			),

    .c3_p1_cmd_clk           		(c3_p1_cmd_clk           			),
    .c3_p1_cmd_en            		(c3_p1_cmd_en            			),
    .c3_p1_cmd_instr         		(c3_p1_cmd_instr         			),
    .c3_p1_cmd_byte_addr     		(c3_p1_cmd_byte_addr     			),
    .c3_p1_cmd_bl            		(c3_p1_cmd_bl            			),
    .c3_p1_rd_clk            		(c3_p1_rd_clk            			),
    .c3_p1_rd_en             		(c3_p1_rd_en             			),
    .c3_p1_rd_data           		(c3_p1_rd_data           			),
    .c3_p1_rd_count          		(c3_p1_rd_count          			),
    //Write DDR3
    .clk_24m                        (clk_125m                           ),
    .data_wr_en                     (data_wr_en                         ),
    .data_wr                        (data_wr                            ),
    ////Read DDR3
    .USB_clk                        (USB_clk                            ),
    .wr_n                           (data_req                           ),
    .data_in                        (data_in                            )
);

gbit_top gbit_top_inst(
    //System Interfaces
    .clk_50m                        (clk_50m                            ),
    .clk_125m                       (clk_125m                           ),
    .rst_n                          (locked                             ),
    //Gigbit Interfaces
    .phy_rst_n                      (phy_rst_n                          ),
    .rx_data                        (rx_data                            ),
    .rx_ctrl                        (rx_ctrl                            ),
    .rx_clk                         (rx_clk                             ),
    //Communication Interfaces
    .image_data                     (image_data                         ),
    .image_data_en                  (image_data_en                      ),
    .rlst                           (rlst                               ),
    .rlst_flag                      (rlst_flag                          )
);

conver_bit conver_bit_inst(
    //System Interfaces
    .sclk                           (clk_125m                           ),
    .rst_n                          (locked                             ),
    //Gigbit Interfaces
    .image_data                     (image_data                         ),
    .image_data_en                  (image_data_en                      ),
    //Communication Interfaces
    .rgb_data                       (rgb_data                           ),
    .rgb_data_en                    (rgb_data_en                        )
); 

image image_inst(
    //System Interfaces
    .sclk                           (clk_125m                           ),
    .rst_n                          (locked                             ),
    //Communication Interfaces
    .rgb_data                       (rgb_data                           ),
    .rgb_data_en                    (rgb_data_en                        ),
    .data_wr                        ({
   
   data_wr[15:8],data_wr[23:16],data_wr[31:24],data_wr[7:0]}     ),
    .data_wr_en                     (data_wr_en                         )
);

//sensor_data_gen sensor_data_gen_inst(
//    .clk                            (clk_24m                            ),
//    .rst_n                          (init_calib_complete                ),
//    .rgb                            ({data_wr[15:0],data_wr[31:16]}     ),
//    .de                             (data_wr_en                         ),
//    .vsync                          (                                   ),
//    .hsync                          (                                   )
//);
//lways @(posedge clk_24m)
//   if(init_calib_complete == 1'b0)
//       data_wr_en      <=      1'b0;
//   else  
//       data_wr_en      <=      1'b1;

//lways @(posedge clk_24m)
//   if(init_calib_complete == 1'b0)
//       data_wr         <=      32'd0;
//   else if(data_wr_en == 1'b1) 
//       data_wr         <=      data_wr + 1'b1;
    

usb3_drive usb3_drive_inst(
    //System Interfaces
    .rst_n                          (init_calib_complete                ),
    //USB3 Interfaces
    .USBSS_EN                       (USBSS_EN                           ),
    .sclk                           (USB_clk                            ),
    .data                           (data                                ),
    .be                             (be                                 ),
    .rxf_n                          (rxf_n                              ),
    .txf_n                          (txf_n                              ),
    .oe_n                           (oe_n                               ),
    .wr_n                           (wr_n                               ),
    .siwu_n                         (siwu_n                             ),
    .rd_n                           (rd_n                               ),
    .wakeup                         (wakeup                             ),
    .gpio                           (gpio                               ),
    //Communication Interfaces
    .data_in                        (data_in                            ),
    .data_req                       (data_req                           )              
);
 
//========================================================================================\
//*******************************     Debug    **********************************
//========================================================================================/

ila_3 ila_3_inst (
    .clk                            (clk_125m                           ), // input wire clk

    .probe0                         (image_data                         ), // input wire [7:0]  probe0  
    .probe1                         (image_data_en                      ), // input wire [0:0]  probe1 
    .probe2                         (data_wr                            ), // input wire [31:0]  probe2 
    .probe3                         (data_wr_en                         ) // input wire [0:0]  probe3
);

endmodule

ddr3_top模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : ddr3_top.v
// Create Time  : 2020-02-27 23:16:16
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX   
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值