完美是没有极限的,前面我们已经实现了固定阀值下,图像的边缘检测结果。不过如何能手动输入,或者控制阀值的大小,那其实更完美一点点。 既然我们能够在努力一点点,为何要放弃??? 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,可见我们得到了更多的边缘细节。 调节K1,如下图所谓为Sobel_Threshold=90时的边缘检测结果,此时LED显示1111,可见我们得到了更细腻的边缘检测结果。 Sobel_Threshold的键控方法,不仅仅适用于Sobel边缘检测。在用户设计实现对比度、亮度,以及其他一些需要阀值的算法时,该模块能够很好的进行调试,以获取当前背景光下的最佳选择! 本节作为在均值/中值滤波的基础上,进一步的VIP图像处理,是本教程中相对复杂度较高的算法,当然仅限于本教程的难度。在视频的跟踪、识别中,边缘检测具有极其重要的作用。通过FPGA硬件加速实现边缘检测视频,获得边缘检测的图像源,势必在VIP领域有极大的作用,请读者掌握这一节的内容。 备注:之前版本提供的代码中,Sobel一开始并没有在中值滤波之后进行处理,这里还是脑补下,在中值滤波前或者后进行Sobel边检检测 上图左为灰度→Sobel算法后的图像,上图右为灰度→中值滤波→Sobel算法后的图像。由于图像源的问题,效果不是很明朗,但可以从细节观察出右图的早上比左图要少,同时边缘相对要均匀一些。若是要用与某些模式识别等算法中,在中值滤波后的边缘检测结果,由于图像质量的改变,能让结果更令人满意。 |
|