索贝尔算子(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处理后的图像显示:

  实验成功

基于Sobel算子的图像边缘检测的更多相关文章

  1. 每天进步一点点------Sobel算子(3)基于彩色图像边缘差分的运动目标检测算法

    摘  要: 针对目前常用的运动目标提取易受到噪声影响.易出现阴影和误检漏检等情况,提出了一种基于Sobel算子的彩色边缘图像检测和帧差分相结合的检测方法.首先用Sobel算子提取视频流中连续4帧图像的 ...

  2. EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子

    在上篇文章中我们了解了PlateLocate的过程中的所有步骤.在本篇文章中我们对前3个步骤,分别是高斯模糊.灰度化和Sobel算子进行分析. 一.高斯模糊 1.目标 对图像去噪,为边缘检测算法做准备 ...

  3. 扩展的Sobel 算子

    Custom Extended Sobel Filters  https://arxiv.org/pdf/1910.00138.pdf sobel算子是进行边缘检测的一个重要算子.它通常是一个3x3的 ...

  4. 图像边缘检测——Sobel算子

    边缘是图像最基本的特征,其在计算机视觉.图像分析等应用中起着重要的作用,这是因为图像的边缘包含了用于识别的有用信息,是图像分析和模式识别的主要特征提取手段. 1.何为“图像边缘”? 在图像中,“边缘” ...

  5. Sobel算子取代:基于特定点方向的canny边缘检测

    前言: Canny边缘检测使用了Sobel算子,计算dx和dy两个方向,对于特定方向的边缘检测,可以作少量修改. 代码: 计算特定方向上的边缘 void CannyOrient( cv::Mat &a ...

  6. 图像边缘检测——几种图像边缘检测算子的学习及python 实现

    本文学习利用python学习边缘检测的滤波器,首先读入的图片代码如下: import cv2 from pylab import * saber = cv2.imread("construc ...

  7. [OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    http://blog.csdn.net/poem_qianmo/article/details/25560901 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog ...

  8. 学习 opencv---(11)OpenC 边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器

    本篇文章中,我们将一起学习OpenCV中边缘检测的各种算子和滤波器——Canny算子,Sobel算子,Laplace算子以及Scharr滤波器.文章中包含了五个浅墨为大家准备的详细注释的博文配套源代码 ...

  9. 边缘检测:Canny算子,Sobel算子,Laplace算子

    1.canny算子 Canny边缘检测算子是John F.Canny于 1986 年开发出来的一个多级边缘检测算法.更为重要的是 Canny 创立了边缘检测计算理论(Computational the ...

  10. 数字集成电路设计-8-一个简单sobel图像边缘检测加速器的设计,实现,仿真与综合

    引言 图像视频处理等多媒体领域是FPGA应用的最主要的方面之一,边缘检测是图像处理和计算机视觉中的基本问题,所以也是最常用的,随着数据量的不断增加以及对实时性的要求,一般软件已经不能满足实际需要,这时 ...

随机推荐

  1. 在真实世界中观察目标治疗策略实施1年对初诊RA患者的影响

    在真实世界中观察目标治疗策略实施1年对初诊RA患者的影响 Tan AL, et al. Rheumatology 2016.Present ID: 083. 背景:制订目标治疗(T2T)建议是要将获得 ...

  2. Python实战项目1-开发流程需求分析/基础环境搭建

    软件开发流程 # 真正的企业里软件从立项到交付整个过程 -立项:确定公司要开发这个软件 公司高层 -软件来源 -产品经理设计出来的---->互联网项目 互联网公司 -用户(医院,政府部门,企业. ...

  3. vue中使用xlsx 导出表格

         <t-table v-show="false" id="exportTab" row-key="index" :data=& ...

  4. npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree

    VScode报错:npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree 不能解析依赖树 ,需要先修复上面 ...

  5. java学习日记20230227-java学习方法/转义字符/注释

    Java学习方法 学习java基本原理和基本语法 快速入门(基本程序 CRUD) 研究技术的注意事项,使用细节,使用规范,如何优化 JAVA转义字符 \t : 一个制表位,实现对齐的功能 \n:换行符 ...

  6. gitlab中CI/CD过程中的坑

    先上观点,azure的pipeline比gitlab ce版好用,gitlab收费版没有用过. 在.gitlab-ci.yml中的特殊字符处理: 解决方法: cmd="[$var1] &am ...

  7. 解决windows下使用vscode没有函数提示的问题

    vscode支持非常多的扩展,包括支持protobuf语法,非常方便. 笔者近期在使用vscode打开工程(文件夹)情况下,困扰于没有函数提示,例如不同路径的头文件中的函数不提示,库函数不提示,试尽各 ...

  8. Oracle 验证身份证号

    --验证身份证号是否正确CREATE OR REPLACE FUNCTION fn_checkidcard (p_idcard IN VARCHAR2) RETURN INT IS v_regstr ...

  9. npm 局部安装 jbrowse

    #此处不要加 -g参数 , -g 是全局安装 npm install @jbrowse/cli #用npx 才能使用这个包,无法按照官方文档直接使用 npx jbrowse --version

  10. CentOS7安裝 Nginx + php7 + php-fpm

    原文 : https://ivanagyro.medium.com/於centos7安裝-nginx-php7-php-fpm-laravel5-6-df8631681acf安装nginx 1/ 用y ...