FPGA study notes
Image processing algorithm
1. 灰度图像高斯滤波算法
1.1 原理
1.2 FPGA实现灰度图像高斯滤波算法
1. Grayscale image Gaussian filtering algorithm
1.1 Principle
- Gaussian filter : linear smoothing filter, low-pass filter, used to eliminate Gaussian noise
- Principle : Weighted average is performed on the entire image, and the value of each pixel is obtained by weighted average of its own and other pixel values in the field.
- Advantages : It overcomes the boundary effect, and has a softer smoothing effect than the mean filter, and better edge retention.
1.2 FPGA implementation of gray-scale image mean filtering algorithm
-
FPGA implementation steps :
- F(x,y): (x,y) point pixel value
- G(x,y): The value of (x,y) point after Gaussian filter processing
- Use a template (or convolution, mask) to determine the weighted average gray value of neighboring pixels instead of the value of the original center pixel: G(x,y)=(1/16) (f(x-1,y- 1)+2 f(x,yi)+f(x+1,y-1)+2f(x-1,y)+4f(x,y)+2f(x+1,y)+f(x -1,y+1)+2f(x,y+1)+f(x+1,y+1))
- Scan every pixel of the image with Gaussian filter template
-
FPGA implementation method :
Methods (2 kinds): 1. R/G/B single channel forms grayscale image and enters Gaussian filtering. 2. Y channel of Ycbcr image forms grayscale image and enters Gaussian filtering.
1. R/G/B Single channel to form grayscale image into Gaussian filter
- The Y channel of the Ycbcr image forms a grayscale image and enters the Gaussian filter
- Verilog code
/*
F(x,y): (x,y) 点的像素值
G(x,y): (x,y)点经过高斯滤波处理后的值
1. 用模板(或称卷积,掩膜)确定邻域像素的加权平均灰度值代替原中心像素点的值
G(x,y)=(1/16)*(f(x-1,y-1)+2*f(x,y-i)+f(x+1,y-1)+2f(x-1,y)+4f(x,y)+2f(x+1,y)+f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1))
2. 用高斯滤波模板扫描图像的每一个像素
*/
module gauss_filter_r0(
input clk,
input rst_n,
input [15:0] data_in,//输入像素
input data_in_en,//LCD显示区使能信号
output reg [15:0] data_out,//输出高斯滤波处理后的像素
output wire data_out_en
);
wire [15:0] r0;
wire [15:0] r1;
wire [15:0] r2;
reg [15:0] r0_c0;
reg [15:0] r0_c1;
reg [15:0] r0_c2;
reg [15:0] r1_c0;
reg [15:0] r1_c1;
reg [15:0] r1_c2;
reg [15:0] r2_c0;
reg [15:0] r2_c1;
reg [15:0] r2_c2;
reg de_reg0;
reg de_reg1;
reg de_reg2;
reg de_reg3;
reg [31:0] guass_add;
reg [31:0] guass_reg0;
reg [31:0] guass_reg1;
reg [31:0] guass_reg2;
//----3行像素缓存-----------------------------------------
shifter3_3 shifter3_3(
.clken(data_in_en),
.clock(clk),
.shiftin(data_in),
.shiftout(),
.taps0x(r0),
.taps1x(r1),
.taps2x(r2)
);
//-------------------------------------------------------
//----3*3 matrix from image------------------------------
//----r0---------------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r0_c0 <= 16'd0;
r0_c1 <= 16'd0;
r0_c2 <= 16'd0;
end
else if(data_in_en)begin
r0_c0 <= r0;
r0_c1 <= r0_c0;
r0_c2 <= r0_c1;
end
end
//----r1---------------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r1_c0 <= 16'd0;
r1_c1 <= 16'd0;
r1_c2 <= 16'd0;
end
else if(data_in_en)begin
r1_c0 <= r1;
r1_c1 <= r1_c0;
r1_c2 <= r1_c1;
end
end
//----r2---------------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r2_c0 <= 16'd0;
r2_c1 <= 16'd0;
r2_c2 <= 16'd0;
end
else if(data_in_en)begin
r2_c0 <= r2;
r2_c1 <= r2_c0;
r2_c2 <= r2_c1;
end
end
//--------------------------------------------------------
//----Timing----------------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
de_reg0 <= 1'd0;
de_reg1 <= 1'd0;
de_reg2 <= 1'd0;
de_reg3 <= 1'd0;
end
else if(data_in_en)begin
de_reg0 <= data_in_en;
de_reg1 <= de_reg0;
de_reg2 <= de_reg1;
de_reg3 <= de_reg2;
end
end
assign data_out_en = de_reg3;
//-------------------------------------------------------
//----guass filter---------------------------------------
/*
|(x-1,y-1),(x,y-i),(x+1,y-1) | |r0_c0,r0_c1,r0_c2 |
| (x-1,y), (x,y), (x+1,y) | <--> |r1_c0,r1_c1,r1_c2 |
|(x-1,y+1),(x,y+1),(x+1,y+1) | |r2_c0,r2_c1,r2_c2 |
高斯滤波公式:G(x,y)=(1/16)*(f(x-1,y-1)+2*f(x,y-i)+f(x+1,y-1)+
2f(x-1,y)+4f(x,y)+2f(x+1,y)+
f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1))
*/
//----pipeline-------------------------------------------
//----1. MAC of each line-------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
guass_reg0 <= 32'd0;
guass_reg1 <= 32'd0;
guass_reg2 <= 32'd0;
end
else if(data_in_en)begin
guass_reg0 <= r0_c0+2*r0_c1+r0_c2;
guass_reg1 <= 2*r1_c0+4*r1_c1+2*r1_c2;
guass_reg2 <= r2_c0+2*r2_c1+r2_c2;
end
else;
end
//----2. ADD all-------------------------------
always@(posedge clk or negedge rst_n)
if(!rst_n)
guass_add <= 32'd0;
else if(data_in_en)
guass_add <= guass_reg0 + guass_reg1 +guass_reg2;
else;
//----3. divide 16-----------------------------
always@(posedge clk or negedge rst_n)
if(!rst_n)
data_out <= 16'd0;
else if(data_in_en)
data_out <= guass_add >>4;
//-------------------------------------------------------
endmodule
- Results
5-inch TFT capacitive touch screen
Image: 800*480 pixels
(1). (Yiyanqianxi^^) Original network image:
(2). FPGA display original image:
(3). FPGA grayscale processing image:
( 4). FPGA average filter diagram:
(5). FPGA Gaussian filter diagram:
Result analysis:
- Compared with the gray-scale processed image, the image after Gaussian filtering is softer and the smoothing effect is better;
- Compared with the mean filter map, the image after Gaussian filtering can protect the details of the image well;
Reference materials: "FPGA System Design and Verification Practical Guide"
[Note]: Personal study notes, if there are mistakes, please feel free to enlighten me, this is polite~~~