FPGA-图像处理-仿真

文章目录

  • 说明
  • 图片读取和写入
  • 灰度转换
  • 高斯滤波
  • 二值化
  • 边缘检测(sobel)
  • 顶层文件
  • 改进中- - - -

任务
读入一张bmp图片,对图片进行灰度处理,二值化以及边缘检测(sobel算子),将处理后的数据写入bmp显示,全部过程以仿真形式。我这用的vivado。

说明

在图像处理领域,要实现Sobel或者均值滤波等算法,则需要按照3*3矩阵的格式提取数据,
FPGA-图像处理-仿真_第1张图片
需要用到移位寄存器SHIFT RAM IP核。
Altera厂家的EDA环境下移位寄存器IP核可以实现多行的缓存输出,但是Xilinx下的Vivado环境,仅仅支持缓存输出一行数据,不过其实也无关紧要,我们这里可以使用两个SHIFT RAM IP核和正在输入的一行数据三者共同组成3行数据。

图片读取和写入

可参考FPGA-仿真读写bmp图片
使用图片(128*128):
FPGA-图像处理-仿真_第2张图片

本次实验的图片读取写入tb

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       top_tb.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.9.29                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.9.29                
*                                                                               
******************************************************************************/ 
`timescale 1ns / 1ns

module top_tb;

reg 	clk;
reg     rst;

wire	[23:0]   dout;

reg     din_vld;
wire    dout_vld;


//图像属性:图像宽度 图像高度 图像尺寸 图像像素点起始位
integer bmp_width;
integer bmp_high;
integer bmp_size;
integer start_index;

//bmp file id
integer bmp_file_id;
integer bmp_dout_id;
integer dout_txt_id;

//文件句柄
integer h;
//文件bmp文件数据
reg		[7:0]	rd_data  [0:49300];
reg     [7:0]   rd_data2 [0:49300];

//写操作
reg		[23:0]	wr_data;
integer i = 0;
integer index;
integer j = 0;

parameter CYCLE=20;

always #(CYCLE/2) clk=~clk;
initial
begin
    clk=1'b1;
    rst=1'b0;
    #(CYCLE);
    rst=1'b1;
    #CYCLE;
    rst=1'b0;
    
    din_vld=1'b0;
    
	//打开原始图像
	bmp_file_id = $fopen("D:\\python\\pic\\er.bmp","rb");

	//打开输出数据
	dout_txt_id = $fopen("D:\\python\\pic\\output_file.txt","w+");

	//读取bmp文件
	h = $fread(rd_data,bmp_file_id);

    // 图像宽度
	bmp_width = {rd_data[21], rd_data[20], rd_data[19], rd_data[18]};
	// 图像宽度
	bmp_high = {rd_data[25], rd_data[24], rd_data[23], rd_data[22]};
	// 像素起始位置
	start_index = {rd_data[13], rd_data[12], rd_data[11], rd_data[10]};
	// 图像尺寸
	bmp_size = {rd_data[5], rd_data[4], rd_data[3], rd_data[2]};
	$fclose(bmp_file_id);
    //输出txt
    for(index = start_index; index < bmp_size-2; index = index + 3)begin  //将像素点数据写入txt文件
    	din_vld=1'b1;
        wr_data = {rd_data[index + 2], rd_data[index + 1], rd_data[index]};
        $fwrite(dout_txt_id, "%d,", wr_data[7:0]);
        $fwrite(dout_txt_id, "%d,", wr_data[15:8]);
        $fwrite(dout_txt_id, "%d\n", wr_data[23:16]);
        #(CYCLE);
    end
    din_vld=1'b0;
    $fclose(dout_txt_id);
end

initial
begin
	 #(3*CYCLE);
	//打开输出图像
	bmp_dout_id = $fopen("D:\\python\\pic\\output_file.bmp","wb");//将数据写入bmp
	
	for(i = 0; i < start_index; i = i + 1)begin //写入文件头部信息
        $fwrite(bmp_dout_id, "%c", rd_data[i]);
    end
	
	j=start_index;
	while(j<bmp_size) //写入像素点信息
	begin
		if(dout_vld==1'b1)
		begin
			$fwrite(bmp_dout_id, "%c", dout[7:0]);
			$fwrite(bmp_dout_id, "%c", dout[15:8]);
			$fwrite(bmp_dout_id, "%c", dout[23:16]);
			j=j+3;
		end
		else
		begin
			j=j;
		end
		#CYCLE;
	end
	$fclose(bmp_dout_id);
end


top  u_top
(
    //clock and reset
   .rst       (rst),                        //reset
   .clk       (clk),                        //clock

   .rgb_din   (wr_data),                     //输入数据
   .din_vld   (din_vld),                    //数据有效
   
   .rgb_out   (dout),                    //输出数据
   .dout_vld  (dout_vld)                 //数据有效
);

endmodule

灰度转换

对于彩色图像转化为灰度图像,有一个著名的色彩心理学公式,即:
在这里插入图片描述
但是在实际应用时,由于FPGA希望避免复杂的浮点运算,所以这里我们采用整数运算。将R、G、B三个分量对应的系数放大256倍得到整数结果:

在这里插入图片描述

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       rgb2gray.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.9.30                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.9.30                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                            
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module rgb2gray
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock 
    
    din,
    din_vld,
    
    dout,
    dout_vld                                        
                                                                                
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock                 
                                                                  
input	[23:0]				din;
input                       din_vld;

output  [7:0]               dout;
output                      dout_vld;                                              
                                                            
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock   

wire	[23:0]              din;
wire                        din_vld;

reg     [7:0]               dout;
reg                         dout_vld;              
                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------        
    
 //RGB 
reg		[7:0]				data_r;
reg     [7:0]               data_g;
reg     [7:0]               data_b;
//加权值后RGB
reg     [17:0]      		pixel_r ;
reg     [17:0]      		pixel_g ;
reg     [17:0]      		pixel_b ;
//vld
reg     [1:0]               vld;
//
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	data_r<=8'b0;
    	data_g<=8'b0;
    	data_b<=8'b0;
    end
    else
    begin
    	data_r<=din[23:16];
    	data_g<=din[15:8];
    	data_b<=din[7:0];        
    end
end

//vld 寄存
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	vld<=2'b0;
    end
    else
    begin
        vld<={vld[0],din_vld};
    end
end
                    		
//RGB权值
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	pixel_r<=17'b0;
    	pixel_g<=17'b0;
    	pixel_b<=17'b0;
    end
    else if(vld[0]==1'b1)
    begin
    	pixel_r<=data_r*77;
    	pixel_g<=data_g*150;
    	pixel_b<=data_b*29;        
    end
end

//
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout<=19'b0;
    end
    else if(vld[1]==1'b1)
    begin
        dout<=(pixel_r+pixel_g+pixel_b)>>8;   
    end
end  
//vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout_vld<=1'b0;
    end
    else 
    begin
        dout_vld<=vld[1]; 
    end

end 
  
                                                                                
endmodule                                                                       

效果展示
FPGA-图像处理-仿真_第3张图片

高斯滤波

在灰度转换过程中,可能会因为取整操作引入噪声,所以接下来使用高斯滤波算法来去除灰度转化过程中引入的噪声。在本次使用实际处理过程中发现使用了高斯滤波最后效果并不理想,最后是去掉了这个模块,有兴趣的童鞋可以研究。

高斯滤波的具体操作是使用一个NN卷积模板对整幅图像扫描,用模板确定的邻域内的像素加权平均值代替模板中心像素点的值。本文使用的33卷积模板如下:
FPGA-图像处理-仿真_第4张图片
FPGA-图像处理-仿真_第5张图片
其中,I(x,y)表示原图像中坐标为(x,y)的像素值;G(x,y)表示高斯滤波之后的值。这里为了计算方便,选取的模板H的权重系数都是2的系数。模板中心的权值最大,这样有利于克服边界效应,避免经过高斯滤波之后图像模糊。

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       gauss.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.10.8                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.10.8                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                            
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module gauss
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock                                         
                                        
    din,
    din_vld,
    
    dout,
    dout_vld                                                                            
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock                 

input       [7:0]           din;
input                       din_vld;

output      [7:0]           dout;
output                      dout_vld;                                                                      
                                                                                
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock   

wire        [7:0]           din;
wire                        din_vld;

reg         [7:0]           dout;
reg                         dout_vld;              
                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------        
    
wire		[7:0]			row1_data;
wire        [7:0]	        row2_data;
wire        [7:0]	        row3_data;  

wire        [7:0]           row1_data_r;
wire        [7:0]           row2_data_r;
//有效值
reg         [2:0]           vld;
//3*3
reg         [7:0]           row1_1;
reg         [7:0]           row1_2;
reg         [7:0]           row1_3;
reg         [7:0]           row2_1;
reg         [7:0]           row2_2;
reg         [7:0]           row2_3;
reg         [7:0]           row3_1;
reg         [7:0]           row3_2;
reg         [7:0]           row3_3;
//sum
reg         [9:0]           sum_1;
reg         [9:0]           sum_2;
reg         [9:0]           sum_3;
reg         [11:0]          sum;
                        

 

//缓存三行 第一级流水
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	row1_1<=7'b0;row1_2<=7'b0;row1_3<=7'b0;
    	row2_1<=7'b0;row2_2<=7'b0;row2_3<=7'b0;
    	row3_1<=7'b0;row3_2<=7'b0;row3_3<=7'b0;
    end
    else if(vld[0]==1'b1)
    begin
        row1_1<=row1_data;row1_2<=row1_1;row1_3<=row1_2;
        row2_1<=row2_data;row2_2<=row2_1;row2_3<=row2_2;
        row3_1<=row3_data;row3_2<=row3_1;row3_3<=row3_2;    
    end
end

//第二级流水
always@(posedge clk,posedge rst)
begin
  	if(rst==1'b1)begin
  	    sum_1 <= 10'b0;
  	    sum_2 <= 10'b0;
  	    sum_3 <= 10'b0;

 	end
 	else if(vld[1]==1'b1)begin
 	    sum_1 <= {2'd0,row1_1} + {1'd0,row1_2,1'd0} + {2'd0,row1_3};
 	    sum_2 <= {1'b0,row2_1,1'b0} + {row2_2,2'd0} + {1'd0,row2_3,1'b0};
 	    sum_3 <= {2'd0,row3_1} + {1'd0,row3_2,1'd0} + {2'd0,row3_3};
 	  
 	end 
end

//第三级流水sum
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)begin                                                        
      	sum<=12'b0;                                                
    end                                                             
    else if(vld[2]==1'b1)begin                                            
        sum<=sum_1+sum_2+sum_3;
    end                                                             
  
end

//vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	vld<=3'b0;
    end
    else
    begin
       vld<={vld[1:0],din_vld}; 
    end
end

//dout_vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout_vld<=1'b0;
    end
    else
    begin
        dout_vld<=vld[2]; 
    end
end

//dout
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout<=8'b0;
    end
    else
    begin
        dout<=sum[4+:8];//从第4个开始,位宽为8
    end
end

  
assign row1_data=row1_data_r;
assign row2_data=row1_data_r;
assign row3_data=din;

c_shift_ram_1 u_shift_ram_0 (
  .D(din),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row2_data_r)        // output wire [0 : 0] Q
);    

c_shift_ram_1 u_shift_ram_1 (
  .D(row2_data_r),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row1_data_r)        // output wire [0 : 0] Q
); 
                                                                                
endmodule                                                                       

效果展示:(不理想,所以最后没有用这个模块)
FPGA-图像处理-仿真_第6张图片

二值化

了解更多二值化操作可参考图像二值化算法

首先使用的是全局二值化,给定一个全局阈值

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       gray2bin.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.9.30                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.9.30                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                            
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module gray2bin
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock    
    
    din,
    din_vld,
    
    dout,
    dout_vld                                     
                                                                                
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock                 

input		[7:0]           din;
input                       din_vld;

output                      dout;
output                      dout_vld;                                                                                
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock                 

wire        [7:0]           din;
wire                        din_vld;

reg                         dout;
reg                         dout_vld;                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------        

//阈值比较
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout_vld<=1'b0;
    	dout<=1'b0;
    end
    else
    begin
        dout_vld<=din_vld;
        dout<=(din>100);
    end
end   
   
                                                                                
endmodule                                                                       

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       gray2local_bin.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.10.11                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.10.11                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                            
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module gray2local_bin
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock      
    
    din,
    din_vld,
    
    dout,
    dout_vld                                   
                                                                                
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock     

input		[7:0]           din;
input                       din_vld;

output                      dout;
output                      dout_vld;            
                                                                                
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock                 
                                                                    
wire  		[7:0]           din;
wire                        din_vld;

reg                         dout;
reg                         dout_vld;                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------        
    

wire	  [7:0]			    row1_data;
wire      [7:0] 	        row2_data;
wire      [7:0] 	        row3_data;  

wire      [7:0]             row1_data_r;
wire      [7:0]             row2_data_r;
//有效值
reg       [3:0]             vld;
//3*3
reg       [7:0]             row1_1;
reg       [7:0]             row1_2;
reg       [7:0]             row1_3;
reg       [7:0]             row2_1;
reg       [7:0]             row2_2;
reg       [7:0]             row2_3;
reg       [7:0]             row3_1;
reg       [7:0]             row3_2;
reg       [7:0]             row3_3;
//sum
reg   	  [12:0]             sum;

//阈值
reg       [7:0]             thresh;  

//中心值延迟
reg       [7:0]             value_delay1;
reg       [7:0]             value_delay2;

//3*3滑动窗口
parameter     NUM = 5'd9;

//缓存三行 第一级流水
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	row1_1<=1'b0;row1_2<=1'b0;row1_3<=1'b0;
    	row2_1<=1'b0;row2_2<=1'b0;row2_3<=1'b0;
    	row3_1<=1'b0;row3_2<=1'b0;row3_3<=1'b0;
    end
    else if(vld[0]==1'b1)
    begin
        row1_1<=row1_data;row1_2<=row1_1;row1_3<=row1_2;
        row2_1<=row2_data;row2_2<=row2_1;row2_3<=row2_2;
        row3_1<=row3_data;row3_2<=row3_1;row3_3<=row3_2;    
    end
end


//第二级流水sum 
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)begin                                                        
      	sum<= 13'b0;                                               
    end                                                             
    else if(vld[1]==1'b1)begin                                            
        sum<=row1_1+row1_2+row1_3+row2_1+row2_2+row2_3+row3_1+row3_2+row3_3;
    end                                                             
  
end
//第三级流水均值+k
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)begin
        thresh <= 8'b0;
    end
    else if(vld[2]==1'b1)begin
        thresh <= (sum+{sum,3'b0})>>7;//取近似 sum*0.9/NUM~sum*9/96   >>6 >>5  NUM==9
        //thresh <= sum>>3;
    end
end

//vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	vld<=4'b0;
    end
    else
    begin
       vld<={vld[2:0],din_vld}; 
    end
end

//dout_vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout_vld<=1'b0;
    end
    else
    begin
        dout_vld<=vld[3]; 
    end
end

//输出阈值大于thresh输出1
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout<=1'b0;
    end
    else if(thresh<value_delay2)
    begin
        dout<=1'b1;   
    end
    else
    begin
    	dout<=1'b0;
    end
end

//当前中心值
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	value_delay1<=8'b0;
    	value_delay2<=8'b0;
    end
    else
    begin
        value_delay1<=row2_2;
        value_delay2<=value_delay1;
    end
end  
assign row1_data=row1_data_r;
assign row2_data=row1_data_r;
assign row3_data=din;

c_shift_ram_1 u_shift_ram_0 (
  .D(din),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row2_data_r)        // output wire [0 : 0] Q
);    

c_shift_ram_1 u_shift_ram_1 (
  .D(row2_data_r),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row1_data_r)        // output wire [0 : 0] Q
);                                                                                                        
endmodule                                                                       

效果展示:
FPGA-图像处理-仿真_第7张图片
如果换张图片带有阴影:
FPGA-图像处理-仿真_第8张图片
会是怎样呢?

边缘检测(sobel)

Sobel算子主要用于检测图像边缘,在物体的边缘通常都有像素的变化,反映了物体与背景之间的差异,或者两个物体之间的差异。它是一个离散差分算子,用来计算像素点上下、左右领域内像素点的加权差,根据在边缘处达到极值来检测边缘。另外,Sobel算子对噪声也有一定的平滑作用,检测出精确的边缘信息,但是边缘定位精度不高。
Sobel算子在水平方向和垂直方向各采用一个模板,检测各方向上的边缘,其优点是计算简单,速度快;但是对于纹理较为复杂的图像,检测效果不理想。水平方向模板Sx和垂直方向模板Sy如下:
FPGA-图像处理-仿真_第9张图片
FPGA-图像处理-仿真_第10张图片

图像中每个像素点对应的梯度值按照以下公式计算:
在这里插入图片描述
图像中每个像素点对应的梯度值按照以下公式计算:
在这里插入图片描述

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       sobel.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.10.8                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.10.8                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                            
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module sobel
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock   
    
    din,						//输入二值化图像
    din_vld,
    
    dout,
    dout_vld                                      
                                                                                
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock  

input                       din;
input                       din_vld;

output                      dout;
output                      dout_vld;               
                                                                                
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock     

wire                        din;
wire                        din_vld;

reg                         dout;
reg                         dout_vld;            
                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------    
wire	  					row1_data;
wire         		        row2_data;
wire         		        row3_data;  

wire                        row1_data_r;
wire                        row2_data_r;
//有效值
reg       [3:0]             vld;
//3*3
reg                         row1_1;
reg                         row1_2;
reg                         row1_3;
reg                         row2_1;
reg                         row2_2;
reg                         row2_3;
reg                         row3_1;
reg                         row3_2;
reg                         row3_3;
//x, y sum
reg      [2:0]              x0_sum;
reg      [2:0]              x2_sum;
reg      [2:0]              y0_sum;
reg      [2:0]              y2_sum;
//x,y abs
reg      [2:0]              x_abs;
reg      [2:0]              y_abs;
//阈值
reg      [2:0]              g;  

 

//缓存三行 第一级流水
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	row1_1<=1'b0;row1_2<=1'b0;row1_3<=1'b0;
    	row2_1<=1'b0;row2_2<=1'b0;row2_3<=1'b0;
    	row3_1<=1'b0;row3_2<=1'b0;row3_3<=1'b0;
    end
    else if(vld[0]==1'b1)
    begin
        row1_1<=row1_data;row1_2<=row1_1;row1_3<=row1_2;
        row2_1<=row2_data;row2_2<=row2_1;row2_3<=row2_2;
        row3_1<=row3_data;row3_2<=row3_1;row3_3<=row3_2;    
    end
end

//第二级流水
always@(posedge clk,posedge rst)
begin
  	if(rst==1'b1)begin
  	    x0_sum <= 3'b0;
  	    x2_sum <= 3'b0;
  	    y0_sum <= 3'b0;
  	    y2_sum <= 3'b0;
 	end
 	else if(vld[1]==1'b1)begin
 	    x0_sum <= {2'd0,row1_1} + {1'd0,row1_2,1'd0} + {2'd0,row1_3};
 	    x2_sum <= {2'd0,row3_1} + {1'd0,row3_2,1'd0} + {2'd0,row3_3};
 	    y0_sum <= {2'd0,row1_1} + {1'd0,row2_1,1'd0} + {2'd0,row3_1};
 	    y2_sum <= {2'd0,row1_3} + {1'd0,row2_3,1'd0} + {2'd0,row3_3};
 	end 
end

//第三级流水abs
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)begin                                                        
      	x_abs <= 3'b0;                                                 
      	y_abs <= 3'b0;                                                 
    end                                                             
    else if(vld[2]==1'b1)begin                                            
        x_abs <= (x0_sum >= x2_sum)?(x0_sum-x2_sum):(x2_sum-x0_sum);
        y_abs <= (y0_sum >= y2_sum)?(y0_sum-y2_sum):(y2_sum-y0_sum);
    end                                                             
  
end
//第四级流水计算梯度
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)begin
        g <= 3'b0;
    end
    else if(vld[3]==1'b1)begin
        g <= x_abs + y_abs;//绝对值之和 近似 平方和开根号
    end
end

//vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	vld<=4'b0;
    end
    else
    begin
       vld<={vld[2:0],din_vld}; 
    end
end

//dout_vld
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout_vld<=1'b0;
    end
    else
    begin
        dout_vld<=vld[3]; 
    end
end

//输出阈值大于3输出1
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	dout<=1'b0;
    end
    else if(g>2)
    begin
        dout<=1'b1;   
    end
    else
    begin
    	dout<=1'b0;
    end
end

  
assign row1_data=row1_data_r;
assign row2_data=row1_data_r;
assign row3_data=din;

c_shift_ram_0 u_shift_ram_0 (
  .D(din),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row2_data_r)        // output wire [0 : 0] Q
);    

c_shift_ram_0 u_shift_ram_1 (
  .D(row2_data_r),        // input wire [0 : 0] D
  .CLK(clk),    // input wire CLK
  .SCLR(rst),  // input wire SCLR
  .Q(row1_data_r)        // output wire [0 : 0] Q
);                                                                                              
endmodule                                                                       

效果展示
FPGA-图像处理-仿真_第11张图片

顶层文件

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       top.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.9.23                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.9.23                
*                                                                               
******************************************************************************/ 
`timescale 1ns/100ps                                                           
                                                                                
//----------------------------------------------------------------------        
//  MODULE DEFINTION                                                            
//----------------------------------------------------------------------        
                                                                                
module top
(                                                                               
    //clock and reset                                                           
    rst,                        //reset                                         
    clk,                        //clock                                         
      
    rgb_din,                     //
    din_vld,
    
    rgb_out,                    //
    dout_vld
                                                   
);                                                                              
//interface parameter                                                           
                                                                                
//----------------------------------------------------------------------        
//   PORT SIGNAL DEFINATION                                                     
//----------------------------------------------------------------------        
//clock and reset                                                               
input                       rst;                        //reset                 
input                       clk;                        //clock  

input     [23:0]            rgb_din;
input                       din_vld;

output    [23:0]            rgb_out;   
output                      dout_vld;        
                                                                                
//----------------------------------------------------------------------        
//  PORT SIGNAL TYPE                                                            
//----------------------------------------------------------------------        
//clock and reset                                                               
wire                        rst;                        //reset                 
wire                        clk;                        //clock   

wire      [23:0]            rgb_din;
wire                        din_vld;

reg       [23:0]            rgb_out;
reg                         dout_vld;              
                                                                                
//----------------------------------------------------------------------        
//  INTERNAL SIGNAL DEFINATION                                                  
//----------------------------------------------------------------------   
//灰度
wire	[7:0]	dout_gray;
wire 			gray_vld;
//高斯滤波
wire    [7:0]   dout_gauss;
wire            gauss_vld;
//二值化
wire            dout_bin;
wire            bin_vld;
//sobel
wire            dout_sobel;
wire            sobel_vld;
//灰度转化
rgb2gray u_rgb2gray
(                                                                               
    //clock and reset                                                           
    .rst 			(rst 		),                        //reset                                         
    .clk			(clk		),                        //clock 

    .din			(rgb_din    ),
    .din_vld        (din_vld    ),

    .dout			(dout_gray  ),
    .dout_vld 		(gray_vld   )                                       
                                                                                
);  
//对灰度图进行高斯滤波
//gauss u_gauss
//(
//    //clock and reset
//    .rst            (rst       ),                        //reset
//    .clk            (clk       ),                        //clock
//
//    .din            (dout_gray ),
//    .din_vld        (gray_vld  ),
//
//    .dout           (dout_gauss),
//    .dout_vld       (gauss_vld )
//);            
//灰度转全局二值化
gray2bin u_gray2bin
(                                                                               
    //clock and reset                                                           
    .rst			(rst		),                        //reset                                         
    .clk			(clk		),                        //clock    
           
    .din			(dout_gray  ),
    .din_vld		(gray_vld	),

    .dout			(dout_bin	),
    .dout_vld  		(bin_vld  	)                                   
                                                                                
); 
//局部二值化
//gray2local_bin u_gray2local_bin
//(                                                                               
//    //clock and reset                                                           
//    .rst			(rst		),                        //reset                                         
//    .clk			(clk		),                        //clock    
//           
//    .din			(dout_gray  ),
//    .din_vld		(gray_vld	),
//
//    .dout			(dout_bin	),
//    .dout_vld  		(bin_vld  	)                                   
//                                                                                
//);               
//sobel
sobel u_sobel
(                                                                               
    //clock and reset                                                           
    .rst			(rst		),                        //reset                                         
    .clk			(clk		),                        //clock   
                                
    .din			(dout_bin   ),						//输入二值化图像
    .din_vld		(bin_vld	),
                                
    .dout			(dout_sobel ),
    .dout_vld       (sobel_vld  )                               
                                                                                
);         
always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
    	rgb_out<=24'b0;
    	dout_vld<=1'b0;
    end
    else
    begin
        rgb_out<={24{dout_sobel}};
        dout_vld<=sobel_vld;
//        rgb_out<={3{dout_gauss}};
//        dout_vld<=gauss_vld;
    end
end
                                                                      
endmodule                                                                       


改进中- - - -

你可能感兴趣的:(FPGA,fpga开发,图像处理,人工智能)