简介
串口传图进FPGA,对图片进行灰度化后进行sobel边缘检测,再通过vga显示。
开发板:DE2
开发工具:Quartus 13.0
sobel算子原理
以下内容来自crazybingo:
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面
卷积,即可分别得出横向及纵向的亮度差分近似值。如果以 A 代表原始
图像,Gx 及 Gy 分别代表经横向及纵向边缘检测的图像灰度值,其公式
如下:
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算
该点灰度的大小:
如果梯度 G 大于某一阀值 则认为该点(x,y)为边缘点。
sobel边缘检测模块简介
module Sobel_Edge_Detect(
input clk,
input rst_n,
// sobel边缘检测的阈值
input [7:0] Sobel_Threshold,
input iValid,
input [7:0] iData,
output oValid,
output reg [7:0] oData
);
输入和输出依旧是valid+data形式,不过比之前的图像处理模块多了个sobel边缘阈值输入,当然,不要这个输入,用固定的阈值也行。
流水线方式实现sobel边缘检测
分析上述公式,总体上分为三步,我们首先要算出Gx和Gy,然后求平方和开根号,最后根据阈值决定是不是边缘点。可以分为5级流水线:
- 第一级 计算Gx模板的左列和、右列和,计算Gy模板的上行和、下行和
- 第二级 计算Gx和Gy
- 第三级 计算Gx和Gy的平方和
- 第四级 对平方和开根号
- 第五级 根据阈值决定边缘点
获取3x3卷积模板
第一步自然是先获取3x3卷积模板,在之前的博客中有介绍过,这一步消耗2时钟周期。
filter_3x3 inst_filter_3x3(
.clk (clk),
.rst_n (rst_n),
.iValid (iValid),
.iData (iData),
.oValid (filter_oValid),
.oData_11 (filter_11), .oData_12 (filter_12), .oData_13 (filter_13),
.oData_21 (filter_21), .oData_22 (filter_22), .oData_23 (filter_23),
.oData_31 (filter_31), .oData_32 (filter_32), .oData_33 (filter_33)
);
第一级流水线
计算Gx模板的左列和、右列和,计算Gy模板的上行和、下行和
always @(posedge clk, negedge rst_n) begin
if(!rst_n) begin
Gx_col_1 <= 0;
Gx_col_3 <= 0;
Gy_row_1 <= 0;
Gy_row_3 <= 0;
end else begin
// Gx模板的左列和与右列和
Gx_col_1 <= filter_11 + (filter_21 << 1) + filter_31;
Gx_col_3 <= filter_13 + (filter_23 << 1) + filter_33;
// Gy模板的上行和与下行和
Gy_row_1 <= filter_11 + (filter_12 << 1) + filter_13;
Gy_row_3 <= filter_31 + (filter_32 << 1) + filter_33;
end
end
第二级流水线
计算Gx和Gy
always @(posedge clk, negedge rst_n) begin
if(!rst_n) begin
Gx <= 0;
Gy <= 0;
end else begin
Gx <= (Gx_col_1 >= Gx_col_3) ? (Gx_col_1 - Gx_col_3) : (Gx_col_3 - Gx_col_1);
Gy <= (Gy_row_1 >= Gy_row_3) ? (Gy_row_1 - Gy_row_3) : (Gy_row_3 - Gy_row_3);
end
end
第三级流水线
计算Gx和Gy的平方和
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
G_square <= 0;
else
G_square <= Gx * Gx + Gy * Gy;
end
第四级流水线
对平方和开根号,这一步直接用Quartus中的ip核,设置其时钟周期消耗为1
ALT_SQRT inst_ALT_SQRT(
.clk(clk),
.radical(G_square),
.q(G_sqrt),
.remainder()
);
第五级流水线
根据阈值决定边缘点,这里选择白色背景,黑色边缘。
always @(posedge clk, negedge rst_n) begin
if(!rst_n)
oData <= 8'd255;
else if(G_sqrt > Sobel_Threshold)
oData <= 0;
else
oData <= 8'd255;
end
由于3x3模板消耗了2时钟周期,sobel边缘检测消耗了5时钟周期,所以总共消耗7时钟周期,oValid需要比iValid延后7个时钟周期。
效果演示
阈值输入为80,发送的图片为:
VGA显示为: