基于FPGA灰度圖像的laplacian算子的實(shí)現(xiàn)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
基于FPGA灰度圖像的laplacian算子的實(shí)現(xiàn)
1 背景知識(shí)
Laplacian 算子是n維歐幾里德空間中的一個(gè)二階微分算子,定義為梯度grad的散度div??墒褂眠\(yùn)算模板來(lái)運(yùn)算這定理定律。
如果f是二階可微的實(shí)函數(shù),則f的拉普拉斯算子定義為:
(1) f的拉普拉斯算子也是笛卡兒坐標(biāo)系中的所有非混合二階偏導(dǎo)數(shù)求和:
(2) 作為一個(gè)二階微分算子,拉普拉斯算子把C函數(shù)映射到C函數(shù),對(duì)于k ≥ 2。表達(dá)式(1)(或(2))定義了一個(gè)算子Δ : C(R) → C(R),或更一般地,定義了一個(gè)算子Δ : C(Ω) → C(Ω),對(duì)于任何開(kāi)集Ω。
對(duì)于階躍狀邊緣,導(dǎo)數(shù)在邊緣點(diǎn)出現(xiàn)零交叉,即邊緣點(diǎn)兩旁二階導(dǎo)數(shù)取異號(hào)。據(jù)此,對(duì)數(shù)字圖像{f(i,j)}的每個(gè)像素,取它關(guān)于x軸方向和y軸方向的二階差分之和,表示為:
運(yùn)算模板:
函數(shù)的拉普拉斯算子也是該函數(shù)的黑塞矩陣的跡,可以證明,它具有各向同性,即與坐標(biāo)軸方向無(wú)關(guān),坐標(biāo)軸旋轉(zhuǎn)后梯度結(jié)果不變。如果鄰域系統(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 |
前面提過(guò),Laplacian 算子對(duì)噪聲比較敏感,所以圖像一般先經(jīng)過(guò)平滑處理,因?yàn)槠交幚硪彩怯媚0暹M(jìn)行的,所以,通常的分割算法都是把Laplacian 算子和平滑算子結(jié)合起來(lái)生成一個(gè)新的模板。
2 matlab 實(shí)現(xiàn)
clc
clear all
img=imread('lena.jpg');
figure,imshow(img);
title('lena');
AW=edge(rgb2gray(img),'sobel');%將真彩圖像轉(zhuǎn)為灰度圖,再用edge函數(shù)調(diào)用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');
實(shí)現(xiàn)結(jié)果:
3 FPGA實(shí)現(xiàn)
圖1 FPGA基于串口傳圖實(shí)現(xiàn)laplacian算子邊緣檢測(cè)架構(gòu)
來(lái)實(shí)現(xiàn)邊緣檢測(cè)算法。
/*
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
微信公眾號(hào): FPGA開(kāi)源工作室
*/
`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
實(shí)驗(yàn)結(jié)果:
lena
Mask1
Mask2