默认迭代次数为1,只进行一次腐蚀、膨胀
一、图像腐蚀
1.相关定义
2.图像腐蚀效果图
3.fpga实现
彩色图像灰度化,灰度图像二值化,图像缓存生成滤波模块(3*3),图像腐蚀算法
`timescale 1ns / 1ps
//
// Description: 图像腐蚀 (前景色是黑色(0),背景色是白色(1) 腐蚀黑色)
//
module image_erode(
input wire clk ,
input wire reset ,
input wire [10:0] img_width ,
input wire [9:0] img_height ,
input wire valid_i ,
input wire [23:0] last_line_data ,
input wire [23:0] cur_line_data ,
input wire [23:0] next_line_data ,
output reg valid_o ,
output reg [23:0] img_data_o
);
//常量声明
parameter N = 3; //窗口大小
//结构系数模版为{1,1,1,
// 1,1,1,
// 1,1,1}
//变量声明
reg valid_d1;
reg [23:0] last_line_data_d1, last_line_data_d2;
reg [23:0] cur_line_data_d1 , cur_line_data_d2 ;
reg [23:0] next_line_data_d1, next_line_data_d2;
//中心点位置,为cur_line_data_d1
always@(posedge clk or posedge reset) begin
if(reset) begin
valid_d1 <= 0;
{last_line_data_d1, last_line_data_d2} <= 0;
{cur_line_data_d1 , cur_line_data_d2 } <= 0;
{next_line_data_d1, next_line_data_d2} <= 0;
end else begin
valid_d1 <= valid_i;
last_line_data_d1 <= last_line_data;
last_line_data_d2 <= last_line_data_d1;
cur_line_data_d1 <= cur_line_data;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d1 <= next_line_data;
next_line_data_d2 <= next_line_data_d1;
end
end
//模板窗口范围内判断,前景色是黑色,背景色是白色,腐蚀处理就是前景色黑色减少
//简单理解也就是,3*3窗口中所有像素值都是0时,才能将当前像素值为0输出
always@(posedge clk or posedge reset) begin
if(reset) begin
valid_o <= 0;
img_data_o <= 0;
end
else if(valid_d1) begin
if({last_line_data_d2, last_line_data_d1, last_line_data,
cur_line_data_d2 , cur_line_data_d1 , cur_line_data ,
next_line_data_d2, next_line_data_d1, next_line_data} == {27{8'd0}}) begin
img_data_o <= cur_line_data_d1;
end
else begin
img_data_o <= {3{8'd255}};
end
valid_o <= 1'b1;
end
else begin
valid_o <= 0;
img_data_o <= 0;
end
end
endmodule
明显可以看书汉字部分,经过腐蚀运算之后,白色字体变宽了(要是清晰显示文字,应该腐蚀白色,效果可能更好一点)
二、图像膨胀
1.相关定义
2.图像膨胀与图像腐蚀的联系
3.FPGA实现
`timescale 1ns / 1ps
//
// Description: 图像膨胀 (前景色是黑色,背景色是白色 只要覆盖区域有前景色则膨胀黑色)
//
module image_dilate(
input wire clk ,
input wire reset ,
input wire [10:0] img_width ,
input wire [9:0] img_height ,
input wire valid_i ,
input wire [23:0] last_line_data ,
input wire [23:0] cur_line_data ,
input wire [23:0] next_line_data ,
output reg valid_o ,
output reg [23:0] img_data_o
);
//常量声明
parameter N = 3; //窗口大小
//结构系数模版为{1,1,1,1,1,1,1,1,1}
//变量声明
reg valid_d1;
reg [23:0] last_line_data_d1, last_line_data_d2;
reg [23:0] cur_line_data_d1 , cur_line_data_d2 ;
reg [23:0] next_line_data_d1, next_line_data_d2;
//中心点位置,为cur_line_data_d1
always@(posedge clk or posedge reset) begin
if(reset) begin
valid_d1 <= 0;
{last_line_data_d1, last_line_data_d2} <= 0;
{cur_line_data_d1 , cur_line_data_d2 } <= 0;
{next_line_data_d1, next_line_data_d2} <= 0;
end else begin
valid_d1 <= valid_i;
last_line_data_d1 <= last_line_data;
last_line_data_d2 <= last_line_data_d1;
cur_line_data_d1 <= cur_line_data;
cur_line_data_d2 <= cur_line_data_d1;
next_line_data_d1 <= next_line_data;
next_line_data_d2 <= next_line_data;
end
end
//模板窗口范围内判断,前景色是黑色,背景色是白色,膨胀处理就是前景色黑色扩张
//简单理解也就是,3*3窗口中所有像素值都是255(白)时,才能将当前像素值为255输出
always@(posedge clk or posedge reset) begin
if(reset) begin
valid_o <= 0;
img_data_o <= 0;
end else if(valid_d1) begin
if({last_line_data_d2, last_line_data_d1, last_line_data,
cur_line_data_d2 , cur_line_data_d1 , cur_line_data ,
next_line_data_d2, next_line_data_d1, next_line_data} == {27{8'd255}}) begin
img_data_o <= cur_line_data_d1;
end else begin
img_data_o <= 0;
end
valid_o <= 1'b1;
end else begin
valid_o <= 0;
img_data_o <= 0;
end
end
endmodule
三、图像处理的开运算,闭运算和梯度运算
1.相关定义
2.fpga实现
开运算:
闭运算 :
梯度运算:
module image_process_top(
input wire clk,
input wire reset,
input wire [10:0] img_width,
input wire [9:0] img_height,
input wire valid_i,
input wire [23:0] img_data_i,
output wire valid_o,
output wire [23:0] img_data_o
);
//参数定义
wire rgb2gray_valid;
wire [23:0] rgb2gray_data;
wire binary_valid;
wire [23:0] binary_data;
wire line_valid;
wire [23:0] last_line_data, cur_line_data, next_line_data;
wire erode_valid;
wire [23:0] erode_data;
wire dilate_valid;
wire [23:0] dilate_data;
wire line1_valid;
wire [23:0] last_line1_data, cur_line1_data, next_line1_data;
//灰度化处理
image_rgb2gray u_image_rgb2gray(
.clk ( clk ),
.reset ( reset ),
.valid_i ( valid_i ),
.img_data_i ( img_data_i ),
.valid_o ( rgb2gray_valid ),
.img_data_o ( rgb2gray_data )
);
//二值化处理
image_binary u_image_binary(
.clk ( clk ),
.reset ( reset ),
.valid_i ( rgb2gray_valid ),
.img_data_i ( rgb2gray_data ),
.valid_o ( binary_valid ),
.img_data_o ( binary_data )
);
//开运算
/*
//3行缓存
image_line_buffer u_image_line_buffer(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( binary_valid ),
.img_data_i ( binary_data ),
.valid_o ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data )
);
//图像腐蚀
image_erode u_image_erode(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data ),
.valid_o ( erode_valid ),
.img_data_o ( erode_data )
);
//3行缓存
image_line_buffer u_image_line_buffer1(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( erode_valid ),
.img_data_i ( erode_data ),
.valid_o ( line1_valid ),
.last_line_data ( last_line1_data ),
.cur_line_data ( cur_line1_data ),
.next_line_data ( next_line1_data )
);
//图像膨胀
image_dilate u_image_dilate(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line1_valid ),
.last_line_data ( last_line1_data ),
.cur_line_data ( cur_line1_data ),
.next_line_data ( next_line1_data ),
.valid_o ( valid_o ),
.img_data_o ( img_data_o )
);
*/
//闭运算
/*
//3行缓存
image_line_buffer u_image_line_buffer(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( binary_valid ),
.img_data_i ( binary_data ),
.valid_o ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data )
);
//图像膨胀
image_dilate u_image_dilate(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data ),
.valid_o ( dilate_valid ),
.img_data_o ( dilate_data )
);
//3行缓存
image_line_buffer u_image_line_buffer1(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( dilate_valid ),
.img_data_i ( dilate_data ),
.valid_o ( line1_valid ),
.last_line_data ( last_line1_data ),
.cur_line_data ( cur_line1_data ),
.next_line_data ( next_line1_data )
);
//图像腐蚀
image_erode u_image_erode(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line1_valid ),
.last_line_data ( last_line1_data ),
.cur_line_data ( cur_line1_data ),
.next_line_data ( next_line1_data ),
.valid_o ( valid_o ),
.img_data_o ( img_data_o )
);
*/
//梯度运算
//3行缓存
image_line_buffer u_image_line_buffer(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( binary_valid ),
.img_data_i ( binary_data ),
.valid_o ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data )
);
//图像膨胀
image_dilate u_image_dilate(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data ),
.valid_o ( dilate_valid ),
.img_data_o ( dilate_data )
);
//图像腐蚀
image_erode u_image_erode(
.clk ( clk ),
.reset ( reset ),
.img_width ( img_width ),
.img_height ( img_height ),
.valid_i ( line_valid ),
.last_line_data ( last_line_data ),
.cur_line_data ( cur_line_data ),
.next_line_data ( next_line_data ),
.valid_o ( erode_valid ),
.img_data_o ( erode_data )
);
assign valid_o = dilate_valid;
assign img_data_o = (dilate_data == 0)&&(erode_data == {3{8'd255}}) ? 0 : {3{8'd255}};
endmodule