索贝尔算子(Sobeloperator)主要用于获得数字图像的一阶梯度,是一种离散性差分算子。它是prewitt算子的改进形式,改进之处在于sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。

  在边缘检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边缘的 ;另一个是检测垂直边缘的 。与Prewitt算子相比,Sobel算子对于象素的位置的影响做了加权,可以降低边缘模糊程度,因此效果更好。
Sobel算子另一种形式是各向同性Sobel(Isotropic Sobel)算子,也有两个,一个是检测水平边缘的 ,另一个是检测垂直边缘的 。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。将Sobel算子矩阵中的所有2改为根号2,就能得到各向同性Sobel的矩阵。

  Sobel算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:

  

  图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小:

                   

  可大略的简化成:

                  

  根据该公式可以编写Verilog代码,难点主要在于3*3矩阵的构建。笔者这里是通过使用两个FIFO来进行矩阵构建的,具体代码如下:

  Sobel_Edge.v

  1 //**************************************************************************
2 // *** file name : Sobel_Edge.v
3 // *** version : 1.0
4 // *** Description : Sobel algorithm for edge detection
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.08.18
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Sobel_Edge
12 #(
13 parameter THRESHOLD = 40
14 )
15 (
16 input i_sys_clk ,
17 input i_sys_rstn ,
18 input i_frame_rst ,
19 input i_edge_en ,
20 input [9:0] i_s_stream_data ,
21 input i_s_stream_valid ,
22 output o_s_stream_ready ,
23 output [25:0] o_m_stream_data ,
24 output o_m_stream_valid ,
25 input i_m_stream_ready
26 );
27
28 wire w_rst_all ;
29 wire w_valid ;
30 wire [9:0] w_matrix_00 ;
31 wire [9:0] w_matrix_10 ;
32 wire [9:0] w_matrix_20 ;
33 wire [9:0] w_matrix_10T ;
34 wire [9:0] w_matrix_20T ;
35 wire w_line0_rd ;
36 wire w_line1_rd ;
37 wire w_line2_rd ;
38 wire w_empty ;
39 wire w_prog_full ;
40
41 reg r_1st_line_en ;
42 reg r_2rd_line_en ;
43 reg r_edge_en ;
44 reg [9:0] r_matrix_01 ;
45 reg [9:0] r_matrix_02 ;
46 reg [9:0] r_matrix_11 ;
47 reg [9:0] r_matrix_12 ;
48 reg [9:0] r_matrix_21 ;
49 reg [9:0] r_matrix_22 ;
50
51 assign w_rst_all = i_frame_rst & (~i_sys_rstn);
52 assign w_valid = o_s_stream_ready & i_s_stream_valid;
53 assign w_matrix_00 = i_s_stream_data;
54
55 always@(posedge i_sys_clk)
56 begin
57 r_edge_en <= i_edge_en;
58 end
59 /******************************************************************************\
60 Generate 3 * 3 matrix
61 \******************************************************************************/
62 assign w_line0_rd = w_valid;
63 assign w_line1_rd = w_valid & r_1st_line_en;
64 assign w_line2_rd = w_valid & r_2rd_line_en;
65
66 always@(posedge i_sys_clk)
67 begin
68 if(w_rst_all)
69 begin
70 r_1st_line_en <= 'd0;
71 r_2rd_line_en <= 'd0;
72 end
73 else if(w_valid & w_matrix_00[8])
74 begin
75 r_1st_line_en <= 1'b1;
76 r_2rd_line_en <= r_1st_line_en;
77 end
78 end
79
80 fifo_2048x10 row1_fifo
81 (
82 .clk (i_sys_clk ),
83 .srst (w_rst_all ),
84 .din (w_matrix_00 ),
85 .wr_en (w_line0_rd ),
86 .dout (w_matrix_10T ),
87 .rd_en (w_line1_rd ),
88 .full ( ),
89 .empty ( )
90 );
91 fifo_2048x10 row2_fifo
92 (
93 .clk (i_sys_clk ),
94 .srst (w_rst_all ),
95 .din (w_matrix_10T ),
96 .wr_en (w_line1_rd ),
97 .dout (w_matrix_20T ),
98 .rd_en (w_line2_rd ),
99 .full ( ),
100 .empty ( )
101 );
102 assign w_matrix_10 = w_line1_rd ? w_matrix_10T : w_matrix_00;
103 assign w_matrix_20 = w_line2_rd ? w_matrix_20T : w_matrix_10;
104
105 always@(posedge i_sys_clk)
106 begin
107 if(w_valid)
108 begin
109 r_matrix_01 <= w_matrix_00;
110 r_matrix_11 <= w_matrix_10;
111 r_matrix_21 <= w_matrix_20;
112
113 r_matrix_02 <= r_matrix_01;
114 r_matrix_12 <= r_matrix_11;
115 r_matrix_22 <= r_matrix_21;
116 end
117 end
118 /******************************************************************************\
119 Data processing
120 \******************************************************************************/
121 wire [11:0] w_add_x0 ;
122 wire [11:0] w_add_x2 ;
123 wire [11:0] w_add_y0 ;
124 wire [11:0] w_add_y2 ;
125 wire [11:0] w_abs_x ;
126 wire [11:0] w_abs_y ;
127 wire [12:0] w_abs_add ;
128 wire [9:0] w_fifo_out ;
129 reg [9:0] r_fifo_din ;
130 reg r_fifo_wr ;
131
132 assign w_add_x0 = {1'b0,w_matrix_00} + {r_matrix_01,1'b0} + {1'b0,r_matrix_02}; //First row
133 assign w_add_x2 = {1'b0,w_matrix_20} + {r_matrix_21,1'b0} + {1'b0,r_matrix_22}; //Third row
134 assign w_add_y0 = {1'b0,w_matrix_00} + {w_matrix_10,1'b0} + {1'b0,w_matrix_20}; //First column
135 assign w_add_y2 = {1'b0,r_matrix_02} + {r_matrix_12,1'b0} + {1'b0,r_matrix_22}; //Third column
136
137 assign w_abs_x = w_add_x0 > w_add_x2 ? w_add_x0 - w_add_x2 : w_add_x2 - w_add_x0;
138 assign w_abs_y = w_add_y0 > w_add_y2 ? w_add_y0 - w_add_y2 : w_add_y2 - w_add_y0;
139 assign w_abs_add = w_abs_x + w_abs_y;
140
141 always@(posedge i_sys_clk)
142 begin
143 if(w_rst_all)
144 begin
145 r_fifo_din <= 'd0;
146 r_fifo_wr <= 'd0;
147 end
148 else if(r_edge_en)
149 begin
150 r_fifo_din <= (w_abs_add > THRESHOLD) ? {w_matrix_00[9:8],8'h00} : {w_matrix_00[9:8],8'hff};
151 r_fifo_wr <= w_valid;
152 end
153 else
154 begin
155 r_fifo_din <= w_matrix_00;
156 r_fifo_wr <= w_valid;
157 end
158 end
159
160 fifo_2048x10_f2000 dout_fifo
161 (
162 .clk (i_sys_clk ),
163 .srst (w_rst_all ),
164 .din (r_fifo_din ),
165 .wr_en (r_fifo_wr ),
166 .dout (w_fifo_out ),
167 .rd_en (i_m_stream_ready ),
168 .full ( ),
169 .empty (w_empty ),
170 .prog_full (w_prog_full )
171 );
172 assign o_m_stream_data = {w_fifo_out,w_fifo_out[7:0],w_fifo_out[7:0]};
173 assign o_m_stream_valid = ~w_empty & i_m_stream_ready;
174 assign o_s_stream_ready = ~w_prog_full;
175 endmodule

  笔者的工程是用OV5640的1280*720的分辨率做的实验,所以这里要保证图像数据的完整性,则FIFO的深度必须要大于或者等于一行有效像素(这里为1280)的数值。这里说明下,笔者输入的数据是有RGB转换成YUV的Y通道的8bit数据,其中高2位分别为:每帧图像的第一个像素点,每行像素的最后一点。该代码是可能会有点缺陷,每帧图像的前两行及前两列的数据可能会有一些问题。实际显示可能不是很明显,甚至可以忽略。

  实验结果如下,第一张图为YUV中Y通道的显示结果,第二图为Sobel边缘检测后的结果。

  Y通道数据图像显示:

  Sobel处理后的图像显示:

  实验成功

最新文章

  1. 最实用的IT类网站及工具大集合
  2. 为listview的item添加动画效果
  3. Python的闭包
  4. C# 命令绑定
  5. 水王ID查找
  6. Contest2037 - CSU Monthly 2013 Oct (problem F :ZZY and his little friends)
  7. ocos 信号量
  8. Linux进程通信——管道
  9. Spring装配bean--01组件扫描和自动装配
  10. 用netsh wlan命令行解决“Win10下WLAN不自动登陆”问题
  11. 第四章 MySQL高级查询(二)
  12. win 10 和 CentOS 7 双系统安装
  13. CentOS入门
  14. zabbix3.0使用ss命令对tcp连接数和状态的监控性能优化
  15. Model1与Model2
  16. [转]講講 John Carmack 的快速反平方根演算法
  17. Nutch抓取流程
  18. 5G的作业- 云计算
  19. ida+windbg调试windows
  20. hdu 4370 0 or 1,最短路

热门文章

  1. @Transactional千万不要这样用!!踩坑了你都可能发现不了!!!
  2. CentOS7.6 添加系统自启脚本
  3. word2021自带viso屏幕闪烁、抖动问题解决
  4. No.2.4
  5. 15.网关Gateway
  6. RTFormer: Efficient Design for Real-Time Semantic Segmentation with Transformer概述
  7. Centos7 MyCat2 安装部署
  8. c++ 从编译到执行
  9. R代码
  10. VUE学习-优化过渡