基于FPGA的二值圖像的邊界提取算法的實(shí)現(xiàn)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
基于FPGA的二值圖像的邊界提取算法的實(shí)現(xiàn)
1 背景知識(shí)
二值圖像(Binary Image)是指將圖像上的每一個(gè)像素只有兩種可能的取值或灰度等級(jí)狀態(tài),人們經(jīng)常用黑白、B&W、單色圖像表示二值圖像。二值圖像是指在圖像中,灰度等級(jí)只有兩種,也就是說,圖像中的任何像素不是0就是1,再無其他過渡的灰度值。
二值圖像的邊界提取主要基于黑白區(qū)域的邊界查找。和許多邊界查找算法相比它適合于二值圖像。
圖1 二值圖像邊界提取演示
如圖1 所示,圖1 a為一幅簡(jiǎn)單的二值圖像,經(jīng)過邊界提取后形成如圖1 b 所示的圖像,顯示出了白色區(qū)域的輪廓。
2 邊界提取算法
使用黑色提取,背景為白色,‘1’表示白色,‘0’表示黑色。
圖2 二值圖像邊界提取演示
我們使用3x3模板進(jìn)行邊界提取,所以當(dāng)3x3九個(gè)點(diǎn)都是‘1’的時(shí)候,輸出為‘1’,當(dāng)九個(gè)點(diǎn)都是‘0’的時(shí)候,輸出為‘1’,其他情況輸出均為‘0’。
3 FPGA二值圖像邊界提取算法實(shí)現(xiàn)
圖3二值圖像膨脹FPGA模塊架構(gòu)
圖3中我們使用串口傳圖傳入的是二值圖像。
FPGA源碼:
/*
Module name: boundary_extraction.v
Description: binary image boundary extraction
*/
`timescale 1ns/1ps
module boundary_extraction(
input clk, //pixel clk
input rst_n,
input hs_in,
input vs_in,
input [15:0] data_in,
input data_in_en,
output hs_out,
output vs_out,
output reg [15:0] data_out,
output data_out_en
);
wire [15:0] line0;
wire [15:0] line1;
wire [15:0] line2;
reg [15:0] line0_data0;
reg [15:0] line0_data1;
reg [15:0] line0_data2;
reg [15:0] line1_data0;
reg [15:0] line1_data1;
reg [15:0] line1_data2;
reg [15:0] line2_data0;
reg [15:0] line2_data1;
reg [15:0] line2_data2;
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;
wire[18:0] result_data;
line3x3 line3x3_inst(
.clken(data_in_en),
.clock(clk),
.shiftin(data_in),
.shiftout(),
.taps0x(line0),
.taps1x(line1),
.taps2x(line2)
);
//------------------------------------------------------------------------------
// Form an image matrix of three multiplied by three
//------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
line0_data0 <= 16'b0;
line0_data1 <= 16'b0;
line0_data2 <= 16'b0;
line1_data0 <= 16'b0;
line1_data1 <= 16'b0;
line1_data2 <= 16'b0;
line2_data0 <= 16'b0;
line2_data1 <= 16'b0;
line2_data2 <= 16'b0;
data_out_en0 <= 1'b0;
data_out_en1 <= 1'b0;
data_out_en2 <= 1'b0;
hs_r0 <= 1'b0;
hs_r1 <= 1'b0;
hs_r2 <= 1'b0;
vs_r0 <= 1'b0;
vs_r1 <= 1'b0;
vs_r2 <= 1'b0;
end
else if(data_in_en) begin
line0_data0 <= line0;
line0_data1 <= line0_data0;
line0_data2 <= line0_data1;
line1_data0 <= line1;
line1_data1 <= line1_data0;
line1_data2 <= line1_data1;
line2_data0 <= line2;
line2_data1 <= line2_data0;
line2_data2 <= line2_data1;
data_out_en0 <= data_in_en;
data_out_en1 <= data_out_en0;
data_out_en2 <= data_out_en1;
hs_r0 <= hs_in;
hs_r1 <= hs_r0;
hs_r2 <= hs_r1;
vs_r0 <= vs_in;
vs_r1 <= vs_r0;
vs_r2 <= vs_r1;
end
end
//-------------------------------------------------------------------
// line0_data0 line0_data1 line0_data2
// line1_data0 line1_data1 line1_data2
// line2_data0 line2_data1 line2_data2
//--------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_out <= 16'h0000;
else if(data_out_en1)
if((line0_data0 == 16'h0000) && (line0_data1 == 16'h0000) && (line0_data2 == 16'h0000) && (line1_data0 == 16'h0000) && (line1_data1 == 16'h0000) && (line1_data2 == 16'h0000) && (line2_data0 == 16'h0000) && (line2_data1 == 16'h0000) && (line2_data2 == 16'h0000))
data_out <= 16'hffff;
else if((line0_data0 == 16'hffff) && (line0_data1 == 16'hffff) && (line0_data2 == 16'hffff) && (line1_data0 == 16'hffff) && (line1_data1 == 16'hffff) && (line1_data2 == 16'hffff) && (line2_data0 == 16'hffff) && (line2_data1 == 16'hffff) && (line2_data2 == 16'hffff))
data_out <= 16'hffff;
else
data_out <= 16'h0000;
end
endmodule
4實(shí)驗(yàn)結(jié)果
圖4 實(shí)驗(yàn)原圖1
圖5實(shí)驗(yàn)原圖2
圖6 實(shí)驗(yàn)結(jié)果圖1
圖7 實(shí)驗(yàn)結(jié)果圖2
結(jié)果分析:圖4和圖6對(duì)比,比較粗的線都被查找出了邊緣,只有最細(xì)的那條沒有被提取出來,并且被加粗,原因是最細(xì)的線條只有三個(gè)像素當(dāng)查找出邊緣后顯示為黑色,兩邊黑色連在一起所以線條就變粗了。圖5和圖7邊緣查找沒有問題。