基于FPGA灰度圖像的laplacian算子的實現(xiàn)
掃描二維碼
隨時隨地手機看文章
基于FPGA灰度圖像的laplacian算子的實現(xiàn)
1 背景知識
Laplacian 算子是n維歐幾里德空間中的一個二階微分算子,定義為梯度grad的散度div。可使用運算模板來運算這定理定律。
如果f是二階可微的實函數(shù),則f的拉普拉斯算子定義為:
(1) f的拉普拉斯算子也是笛卡兒坐標系中的所有非混合二階偏導數(shù)求和:
(2) 作為一個二階微分算子,拉普拉斯算子把C函數(shù)映射到C函數(shù),對于k ≥ 2。表達式(1)(或(2))定義了一個算子Δ : C(R) → C(R),或更一般地,定義了一個算子Δ : C(Ω) → C(Ω),對于任何開集Ω。
對于階躍狀邊緣,導數(shù)在邊緣點出現(xiàn)零交叉,即邊緣點兩旁二階導數(shù)取異號。據(jù)此,對數(shù)字圖像{f(i,j)}的每個像素,取它關于x軸方向和y軸方向的二階差分之和,表示為:
運算模板:
函數(shù)的拉普拉斯算子也是該函數(shù)的黑塞矩陣的跡,可以證明,它具有各向同性,即與坐標軸方向無關,坐標軸旋轉后梯度結果不變。如果鄰域系統(tǒng)是4 鄰域,Laplacian 算子的模板為:
0 |
1 |
0 |
1 |
-4 |
1 |
0 |
1 |
0 |
如果鄰域系統(tǒng)是8 鄰域,Laplacian 算子的模板為:
1 |
1 |
1 |
1 |
-8 |
1 |
1 |
1 |
1 |
前面提過,Laplacian 算子對噪聲比較敏感,所以圖像一般先經(jīng)過平滑處理,因為平滑處理也是用模板進行的,所以,通常的分割算法都是把Laplacian 算子和平滑算子結合起來生成一個新的模板。
2 matlab 實現(xiàn)
clc
clear all
img=imread('lena.jpg');
figure,imshow(img);
title('lena');
AW=edge(rgb2gray(img),'sobel');%將真彩圖像轉為灰度圖,再用edge函數(shù)調用sobel prewitt,laplacian算子
figure,imshow(AW);
title('lena sobel');
BW=edge(rgb2gray(img),'prewitt');
figure,imshow(BW);
title('lena prewitt');
CW=edge(rgb2gray(img),'log');
figure,imshow(CW);
title('lena laplacian');
DW=edge(rgb2gray(img),'canny');
figure,imshow(DW);
title('lena canny');
實現(xiàn)結果:
3 FPGA實現(xiàn)
圖1 FPGA基于串口傳圖實現(xiàn)laplacian算子邊緣檢測架構
來實現(xiàn)邊緣檢測算法。
/*
Module name: laplace.v
Description: laplace
0 -1 0
-1 5 -1
0 -1 0
Data: 2017/03/05
Engineer: lipu
e-mail: 137194782@qq.com
微信公眾號: FPGA開源工作室
*/
`timescale 1ns/1ps
`define D_WIDTH 8
module laplace(
input clk, //pixel clk
input rst_n,
input hs_in,
input vs_in,
input [`D_WIDTH-1:0] data_in,
input data_in_en,
output hs_out,
output vs_out,
output [`D_WIDTH-1:0] data_out,
output data_out_en
);
// mask 1
//-------------------------------------------//
// 0 -1 0
// -1 5 -1
// 0 -1 0
//-------------------------------------------//
parameter X1 = 4'h0, X2 = 4'hf, X3 = 4'h0;
parameter X4 = 4'hf, X5 = 4'h5, X6 = 4'hf;
parameter X7 = 4'h0, X8 = 4'hf, X9 = 4'h0;
// mask 2
//-------------------------------------------//
// 0 1 0
// 1 -4 1
// 0 1 0
//-------------------------------------------//
//parameter X1 = 4'h0, X2 = 4'h1, X3 = 4'h0;
//parameter X4 = 4'h1, X5 = 4'hc, X6 = 4'h1;
//parameter X7 = 4'h0, X8 = 4'h1, X9 = 4'h0;
// mask 3
//-------------------------------------------//
// 0 -1 0
// -1 4 -1
// 0 -1 0
//-------------------------------------------//
//parameter X1 = 4'h0, X2 = 4'hf, X3 = 4'h0;
//parameter X4 = 4'hf, X5 = 4'h4, X6 = 4'hf;
//parameter X7 = 4'h0, X8 = 4'hf, X9 = 4'h0;
wire [`D_WIDTH-1:0] line0;
wire [`D_WIDTH-1:0] line1;
wire [`D_WIDTH-1:0] line2;
wire [13:0] Mac_x0;
wire [13:0] Mac_x1;
wire [13:0] Mac_x2;
wire [15:0] Pa_x;
reg data_out_en0;
reg data_out_en1;
reg data_out_en2;
reg hs_r0;
reg hs_r1;
reg hs_r2;
reg vs_r0;
reg vs_r1;
reg vs_r2;
line3x3 line3x3_inst(
.clken(data_in_en),
.clock(clk),
.shiftin(data_in),
.shiftout(),
.taps0x(line0),
.taps1x(line1),
.taps2x(line2)
);
// X
MAC_3 x0 (
.aclr3(!rst_n),
.clock0(clk),
.dataa_0(line0),
.datab_0(X9),
.datab_1(X8),
.datab_2(X7),
.result(Mac_x0)
);
MAC_3 x1 (
.aclr3(!rst_n),
.clock0(clk),
.dataa_0(line1),
.datab_0(X6),
.datab_1(X5),
.datab_2(X4),
.result(Mac_x1)
);
MAC_3 x2 (
.aclr3(!rst_n),
.clock0(clk),
.dataa_0(line2),
.datab_0(X3),
.datab_1(X2),
.datab_2(X1),
.result(Mac_x2)
);
PA_3 pa0 (
.clock(clk),
.data0x(Mac_x0),
.data1x(Mac_x1),
.data2x(Mac_x2),
.result(Pa_x)
);
assign data_out = Pa_x[10:3];
endmodule
實驗結果:
lena
Mask1
Mask2