zoukankan      html  css  js  c++  java
  • Sobel边缘检测-FPGA

    Sobel边缘检测

     

    // sobel 算法
    `timescale 1ns/1ns
    module sobel_top(
    	clk			,
    	rst_n		,
    	pre_vs		,
    	pre_hs		,
    	pre_en		,
    	pre_img_Y   ,
    	
    	post_vs		,
    	post_hs		,
    	post_en		,
    	post_img_Y
    );
    
    /************************** input and output ******************/
    	input			clk			;
    	input			rst_n		;
    	input			pre_vs		;
    	input			pre_hs		;
    	input			pre_en		;
    	input	[7:0]	pre_img_Y   ;
    	
    	output			post_vs		;
    	output			post_hs		;
    	output			post_en		;
    	output	[7:0]	post_img_Y  ;
    
    /************************* main code **************************/
    wire [7:0] matrixp11 ;
    wire [7:0] matrixp12 ;
    wire [7:0] matrixp13 ;
    wire [7:0] matrixp21 ;
    wire [7:0] matrixp22 ;
    wire [7:0] matrixp23 ;
    wire [7:0] matrixp31 ;
    wire [7:0] matrixp32 ;
    wire [7:0] matrixp33 ;
    wire       matrix_vs ;
    wire       matrix_hs ;
    wire       matrix_en ;
    
    Generate_Matrix_3x3_8bit Generate_Matrix_3x3_8bit(
    	//system 
    	.clk			(clk		),         //鍍忕礌鏃堕挓鐨勫悓姝ワ紝coms_clk , vga_clk
    	.rst_n			(rst_n		),		  //澶嶄綅淇″彿		
    	//coms or vga
    	.pre_vs			(pre_vs		),          //鍓嶈�鍚屾�				
    	.pre_hs			(pre_hs		),          //鍓嶅満鍚屾�  			
    	.pre_en			(pre_en		),          //鍓嶆暟鎹�湁鏁	
    	.pre_img_Y		(pre_img_Y	),		 //鏁版嵁鐏板害鍥惧儚		
    	.matrixp11		(matrixp11	),
    	.matrixp12		(matrixp12	),
    	.matrixp13		(matrixp13	),
    	.matrixp21		(matrixp21	),
    	.matrixp22		(matrixp22	),
    	.matrixp23		(matrixp23	),
        .matrixp31		(matrixp31	),
    	.matrixp32		(matrixp32	),
    	.matrixp33		(matrixp33	),
    	.matrix_vs		(matrix_vs	),
    	.matrix_hs		(matrix_hs	),
    	.matrix_en		(matrix_en	)
    );
    
    
    
    //消耗4个时钟
    wire [7:0] sobel_data;
    sobel sobel(
    	.clk			(clk		),
    	.rst_n			(rst_n		),
    	.Soble_Threshold(8'd15		),
    	.matrixp11		(matrixp11	),
    	.matrixp12		(matrixp12	),
    	.matrixp13		(matrixp13	),
    	.matrixp21		(matrixp21	),
    	.matrixp22		(matrixp22	),
    	.matrixp23		(matrixp23	),
    	.matrixp31		(matrixp31	),
    	.matrixp32		(matrixp32	),
    	.matrixp33		(matrixp33	),
    	.sobel_data	    (sobel_data )
    );
    
    //延迟4个时钟
    reg [3:0] matrix_vs_r;
    reg [3:0] matrix_hs_r;
    reg [3:0] matrix_en_r;
    always@(posedge clk or negedge rst_n) begin
    	if(!rst_n) begin
    		matrix_vs_r <= 'd0;
    		matrix_hs_r <= 'd0;
    		matrix_en_r <= 'd0;
    	end
    	else begin
    		matrix_vs_r <= {matrix_vs_r[2:0],matrix_vs};
    	    matrix_hs_r <= {matrix_hs_r[2:0],matrix_hs};
    	    matrix_en_r <= {matrix_en_r[2:0],matrix_en};
    	end
    end
    
    	assign  post_vs	= matrix_vs_r[3];	
    	assign  post_hs	= matrix_hs_r[3];	
    	assign  post_en	= matrix_en_r[3];	
        assign  post_img_Y = post_en ? sobel_data : 8'd0;
    
    
    endmodule
    

      

    //sobel边缘检测算法
    /*
          [ -1  0  +1 ]            [ +1  +2  +1 ]
    Gx =  [ -2  0  +2 ]*A    Gy =  [  0   0   0 ] * A
          [ -1  0  +1 ]            [ -1  -2  -1 ]
    
    G = sqrt(Gx^2 + Gy^2);
    G = |Gx| + |Gy| ;
    */
    
    module sobel
    (
        clk            ,
        rst_n        ,
        Soble_Threshold,   //阈值的选取,可以做一个按键调节
        matrixp11    ,
        matrixp12    ,
        matrixp13    ,
        matrixp21    ,
        matrixp22    ,
        matrixp23    ,
        matrixp31    ,
        matrixp32    ,
        matrixp33    ,
        sobel_data  
    );
    
    //************************ input and output *******************//
        
        input         clk;
        input          rst_n;
        input  [7:0]  Soble_Threshold; 
        input  [7:0]  matrixp11 ;
        input  [7:0]  matrixp12 ;
        input  [7:0]  matrixp13 ;
        input  [7:0]  matrixp21 ;
        input  [7:0]  matrixp22 ;
        input  [7:0]  matrixp23 ;
        input  [7:0]  matrixp31 ;
        input  [7:0]  matrixp32 ;
        input  [7:0]  matrixp33 ;
        output reg [7:0]  sobel_data;
    
    //************************ main code **************************//
    //      [ -1  0  +1 ]            [ +1  +2  +1 ]
    //Gx =  [ -2  0  +2 ]*A    Gy =  [  0   0   0 ] * A
    //      [ -1  0  +1 ]            [ -1  -2  -1 ]
    //        matrixp11*(-1)+matrixp12*(0)+matrixp13*(1),
    //Gx    matrixp21*(-2)+matrixp22*(0)+matrixp23*(2),
    //         matrixp31*(1)+matrixp32*(0) +matrixp33*(1),
    //        matrixp11*(1)+matrixp12*(2)+matrixp13*(1),
    //Gy    matrixp21*(0)+matrixp22*(0)+matrixp23*(0),
    //         matrixp31*(-1)+matrixp32*(-2)+matrixp33*(-1),
    
    reg        [11:0]    Gx_data_col1;
    reg        [11:0]    Gx_data_col3;
    reg        [11:0]    Gy_data_row1;
    reg        [11:0]    Gy_data_row3;
    //求卷积 第一步
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            Gx_data_col1 <= 'd0;
            Gx_data_col3 <= 'd0;        
        end
        else begin
            Gx_data_col1 <= matrixp11 + (matrixp21 << 1) + matrixp31;
            Gx_data_col3 <= matrixp13 + (matrixp23 << 1) + matrixp33;    
        end
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            Gy_data_row1 <= 'd0;
            Gy_data_row3 <= 'd0;    
        end
        else begin
            Gy_data_row1 <= matrixp11 + (matrixp12 << 1) + matrixp13;
            Gy_data_row3 <= matrixp31 + (matrixp32 << 1) + matrixp33;
        end
    end
    
    //判断大小 第二步
    reg [11:0]  Gx_data;
    reg [11:0]  Gy_data;
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            Gx_data <= 'd0;
        else if(Gx_data_col1 >= Gx_data_col3)
            Gx_data <= Gx_data_col1 - Gx_data_col3;
        else 
            Gx_data <= Gx_data_col3 - Gx_data_col1;
    end
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            Gy_data <= 'd0;
        else if(Gy_data_row1 >= Gy_data_row3)
            Gy_data <= Gy_data_row1 - Gy_data_row3;
        else 
            Gy_data <= Gy_data_row3 - Gy_data_row1;
    end
    
    //第三步 求平方
    reg [20:0] sum_data;
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) 
            sum_data <= 'd0;
        else 
            sum_data <= Gx_data*Gx_data + Gy_data*Gy_data;
    end
    
    //第四步 开方
    wire [10:0] q;
    sqrt sqrt(
        .radical        (sum_data),
        .q                (q),
        .remainder  ()    
    );
    
    //第五步 取阈值
    //White: 24'hFF;    Black: 24'h00
    //实际情况大于Soble_Threshold为黑色,在后期处理需要注意
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            sobel_data <= 'd0;
        else if(q >= Soble_Threshold)
            sobel_data <= 8'd255;
        else
            sobel_data <= 8'd0;
    end
    
    endmodule
    `timescale 1ns/1ns
    module sobel_top_tb;
    
    
    
    
        //system 
        reg                clk                ;          //像素时钟的同步,coms_clk , vga_clk
        reg                rst_n            ;          //复位信号        
        //coms or vga                
        reg                pre_vs            ;       //前行同步
        reg                pre_hs            ;       //前场同步  
        reg                pre_en            ;       //前数据有效
        reg        [7:0]    pre_img_Y        ;         //数据灰度图像
        
        wire            post_vs            ;       //输出行同步
        wire            post_hs            ;       //输出场同步  
        wire            post_en            ;       //输出数据有效
        wire    [7:0]    post_img_Y        ;         //输出数据灰度图像
    
    initial clk = 1;
        always #5 clk = ~clk;
        
        initial begin
            rst_n = 0;
            pre_vs =0 ;
            pre_hs = 0;
            pre_en = 0;
            pre_img_Y = 0;
            #51;
            rst_n = 1;
            pre_vs = 1;
            #20;
            pre_hs = 1;
            #20;
            pre_en = 1;
            #60;
            pre_en = 0;
            #20;
            pre_hs = 0;
            #20;
            pre_hs = 1;
            #20;
            pre_en = 1;
            #60;
            pre_en = 0;
            #20;
            pre_hs = 0;
            #20;
            pre_hs = 1;
            #20;
            pre_en = 1;
            #60;
            pre_en = 0;
            #20;
            pre_hs = 0;
            #20;
            pre_hs = 1;
            #20;
            pre_en = 1;
            #60;
            pre_en = 0;
            #20;
            pre_hs = 0;
            #20;
            pre_hs = 1;
            #20;
            pre_en = 1;
            #60;
            pre_en = 0;
            #20;
            pre_hs = 0;
            $stop;
        end
        
        reg [7:0] shiftin;
        always@(posedge clk or negedge rst_n ) begin
            if(!rst_n)
                shiftin <= 'd1;
            else if(pre_en) 
                shiftin <= shiftin + 1'b1;
            else
                shiftin <= shiftin;
        end
    
    
    sobel_top sobel_top(
        //system 
        .clk                (clk        ),          //像素时钟的同步,coms_clk , vga_clk
        .rst_n                (rst_n        ),          //复位信号        
        //coms or vga                    
        .pre_vs                (pre_vs        ),       //前行同步
        .pre_hs                (pre_hs        ),       //前场同步  
        .pre_en                (pre_en        ),       //前数据有效
        .pre_img_Y            (shiftin    ),         //数据灰度图像
        //output                                
        .post_vs            (post_vs    ),       //输出行同步
        .post_hs            (post_hs    ),       //输出场同步  
        .post_en            (post_en    ),       //输出数据有效
        .post_img_Y            (post_img_Y    )     //输出数据灰度图像
    
    );
    
    
    
    
    endmodule

    还有一个开方ip核

  • 相关阅读:
    信号量Semaphore的使用
    Future和FutureTask
    阻塞队列和线程池
    Java多线程基础
    Java常用方法
    Scanner和BufferedReader的区别和用法
    QT学习笔记9:QTableWidget的用法总结
    WordPress 建站教程:新手搭建 WordPress个人博客图文教程(完全版)
    Let's do it
    jdk alternatives
  • 原文地址:https://www.cnblogs.com/wanglinwensi/p/12851814.html
Copyright © 2011-2022 走看看