02.29 「博文連載」動態Sobel閥值的HDL實現

完美是沒有極限的,前面我們已經實現了固定閥值下,圖像的邊緣檢測結果。不過如何能手動輸入,或者控制閥值的大小,那其實更完美一點點。

既然我們能夠在努力一點點,為何要放棄???

OK,Bingo這裡打算教大家使用VIP Mini開發板上的2個按鍵來,來實現閥值的增大與減小!

首先在HDL-Logic中已經詳細的介紹過按鍵檢測的模塊key_counter_scan。這裡直接調用該模塊,獲取key_flag與key_value信號。新建Sobel_Threshold_Adj模塊,信號列表如下所示:

`timescale 1ns/1ns

module Sobel_Threshold_Adj

(

//global clock

input clk, //100MHz

input rst_n, //global reset

//user interface

input key_flag, //key down flag

input [1:0] key_value, //key control data

output reg [3:0] Sobel_Grade, //Sobel Grade output

output reg [7:0] Sobel_Threshold //lcd pwn signal, l:valid

);

剛好板卡有2個按鍵,K1控制Sobel_Threshold的增加,而K2控制Sobel_Threshold的減小。閥值的級別我們設定16級,因此K1、K2控制Sobel_Grade這個變量的增減,如下:

//---------------------------------

//Sobel Threshold adjust with key.

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

Sobel_Grade <= 4'd8;

else if(key_flag)

begin

case(key_value) //{Sobel_Threshold--, Sobel_Threshold++}

2'b10: Sobel_Grade <= (Sobel_Grade == 4'd0) ? 4'd0 : Sobel_Grade - 1'b1;

2'b01: Sobel_Grade <= (Sobel_Grade == 4'd15) ? 4'd15 : Sobel_Grade + 1'b1;

default:;

endcase

end

else

Sobel_Grade <= Sobel_Grade;

End

最後,分配每個閥值級的Sobel_Threshold大小,如下所示,從20~90:

//---------------------------------

//Sobel Grade Mapping with Sobel Threshold

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

Sobel_Threshold <= 55;

else

case(Sobel_Grade)

4'h0: Sobel_Threshold <= 20;

4'h1: Sobel_Threshold <= 25;

4'h2: Sobel_Threshold <= 30;

4'h3: Sobel_Threshold <= 35;

4'h5: Sobel_Threshold <= 40;

4'h6: Sobel_Threshold <= 45;

4'h7: Sobel_Threshold <= 50;

4'h8: Sobel_Threshold <= 55;

4'h9: Sobel_Threshold <= 60;

4'ha: Sobel_Threshold <= 65;

4'hb: Sobel_Threshold <= 70;

4'hc: Sobel_Threshold <= 75;

4'hd: Sobel_Threshold <= 80;

4'he: Sobel_Threshold <= 85;

4'hf: Sobel_Threshold <= 90;

default:;

endcase

end

在工程頂層模塊中例化相關模塊,如下所示:

//Key scan with jitter detect

wire key_flag;

wire [1:0] key_value;

key_counter_scan

#(

.KEY_WIDTH (2)

)

u_key_counter_scan

(

//global

.clk (clk_ref),

.rst_n (rst_n),

//key interface

.key_data (key_data),

//user interface

.key_flag (key_flag),

.key_value (key_value)

);

//------------------------------------

//Sobel Threshold adjust with key.

wire [3:0] Sobel_Grade;

wire [7:0] Sobel_Threshold;

Sobel_Threshold_Adj u_Sobel_Threshold_Adj

(

//global clock

.clk (clk_ref), //100MHz

.rst_n (sys_rst_n), //global reset

//user interface

.key_flag (key_flag), //key down flag

.key_value (key_value), //key control data

.Sobel_Grade (Sobel_Grade), //Sobel Grade output

.Sobel_Threshold (Sobel_Threshold) //Sobel Threshold

);

//---------------------------

//The driver of 74HC595

led_74595_driver u_led_74595_driver

(

//global clock

.clk (clk_ref),

.rst_n (sys_rst_n),

//74hc595 interface

.led595_dout (led595_dout), //74hc595 serial data input

.led595_clk (led595_clk), //74hc595 shift clock (rising edge)

.led595_latch (led595_latch), //74hc595 latch clock (risign edge)

//user interface

.led_data ({4'd0, Sobel_Grade}) //led data input

);

從代碼分析,可見Bingo將Sobel_Grade發送到了LED顯示模塊,作為閥值大小的直觀顯示。

最後,還是全編譯,生成並下載sof文件,重啟後用USB_VIP_Panel或者VGA測試測試。調節K2,如下圖所示,為Sobel_Threshold=30時的邊緣檢測結果,此時LED顯示10,可見我們得到了更多的邊緣細節。

「博文连载」动态Sobel阀值的HDL实现

調節K1,如下圖所謂為Sobel_Threshold=90時的邊緣檢測結果,此時LED顯示1111,可見我們得到了更細膩的邊緣檢測結果。

「博文连载」动态Sobel阀值的HDL实现

Sobel_Threshold的鍵控方法,不僅僅適用於Sobel邊緣檢測。在用戶設計實現對比度、亮度,以及其他一些需要閥值的算法時,該模塊能夠很好的進行調試,以獲取當前背景光下的最佳選擇!

本節作為在均值/中值濾波的基礎上,進一步的VIP圖像處理,是本教程中相對複雜度較高的算法,當然僅限於本教程的難度。在視頻的跟蹤、識別中,邊緣檢測具有極其重要的作用。通過FPGA硬件加速實現邊緣檢測視頻,獲得邊緣檢測的圖像源,勢必在VIP領域有極大的作用,請讀者掌握這一節的內容。

「博文连载」动态Sobel阀值的HDL实现

備註:之前版本提供的代碼中,Sobel一開始並沒有在中值濾波之後進行處理,這裡還是腦補下,在中值濾波前或者後進行Sobel邊檢檢測

「博文连载」动态Sobel阀值的HDL实现

上圖左為灰度→Sobel算法後的圖像,上圖右為灰度→中值濾波→Sobel算法後的圖像。由於圖像源的問題,效果不是很明朗,但可以從細節觀察出右圖的早上比左圖要少,同時邊緣相對要均勻一些。若是要用與某些模式識別等算法中,在中值濾波後的邊緣檢測結果,由於圖像質量的改變,能讓結果更令人滿意。


分享到:


相關文章: