• 视频处理之Sobel【附源码】


    欲观原文,请君移步

    边缘检测是检测图像中的一些像素点,它们周围的像素点的灰度发生了急剧的变化,我们认为在这过程中,图像中的物体不同导致了这一变化,因此可以将这些像素点作为一个集合,可以用来标注图像中不同物体的边界。边缘区域的灰度剖面可以看作是一个阶跃,即图像的灰度在一个很小的区域内变化到另一个相差十分明显的区域。边缘是图像中的重要的结构性特征,边缘往往存在于目标和背景之间,不同的区域之间,因此它可以作为图像分割的重要依据。在边缘检测中,它提取的是图像中不连续部分的特征,将闭合的边缘提取出来便可以作为一个区域。与区域划分相比,边缘检测不需要逐个的对像素进行比较,比较适合大图像的处理.

    图像边缘是图像最基本的特征,所谓边缘(Edge) 是指图像局部特性的不连续性。灰度或结构等信息的突变处称之为边缘。例如,灰度级的突变、颜色的突变,、纹理结构的突变等。这些突变会导致梯度很大。图像的梯度可以用一阶导数和二阶偏导数来求解。但是图像以矩阵的形式存储的,不能像数学理论中对直线或者曲线求导一样,对一幅图像的求导相当于对一个平面、曲面求导。对图像的操作,我们采用模板对原图像进行卷积运算,从而达到我们想要的效果。而获取一幅图像的梯度就转化为:模板(Roberts、Prewitt、Sobel、Lapacian算子)对原图像进行卷积。本文主要描述Sobel算子的实现原理和实现过程。

    Sobel算子简介

    Sobel算子 是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导。该算子用于计算图像明暗程度近似值,根据图像边缘旁边明暗程度把该区域内超过某个数的特定点记为边缘。Sobel算子在Prewitt算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。

    Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。Sobel算子的边缘定位更准确,常用于噪声较多、灰度渐变的图像。

    Sober算法基础

    其算法模板如下面的公式所示,其中dx表示水平方向,dy表示垂直方向。

    用数学公式表示如下

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

    FPGA实现

    硬件框图如下

    如下图所示,首先需要缓存两行图像用于计算(第三行可以用寄存器存储一个像素即可计算)。

    然后加入sobel算子模块将所得到的9个像素按照sobel算子进行运算。

    接着把输出的Gx和Gy做平方,所以需要一个乘法器模块。

    然后将Gx,Gy和Gxy(分别为水平梯度,垂直梯度,水平和垂直梯度)做平方根输出。

    最后再用一个输出模块来整合整个视频流,可以选择阈值和边缘模式。

    缓存模块

    小编是一个懒人,能不写代码就尽量不写代码,既然要缓存了,首先看看有没有IP,查看了一下based shift register 这个IP,发现最大深度只有1088,所以没办法,小编只能自己写了。

    为了考虑后期还会继续使用这种缓存的应用场景,小编在这个模块使用RAM的原语进行设计,因为是基于视频的应用,所以设置的缓存深度为1行,如果需要缓存多行,把这个模块级联即可。

    仿真结果如下图

    梯度计算模块


    按照sobel算子给出源码如下

    // GX = (A13+2 *A23 + A33 ) - (A11 +2 *A21 + A31 )
    
    // GY = (A31+2* A32 + A33 ) - (A11 +2* A12 + A13 )
    
    // | G | =(GX^2+ GY^2)^1/2
    
    	always @ (posedge clk) begin
    		if(pixel_en_d3)begin
    			GX_right 	<=(A13+2 *A23 + A33 ) ;
    			GX_left 	<=(A11 +2 *A21 + A31);
    		end
    		if(pixel_en_d3)begin
    			GY_up 		<=(A31+2* A32 + A33 );
    			GY_down 	<=(A11 +2* A12 + A13 );
    		end
    		add_en<=pixel_en_d3;
    	end	
    	always @ (posedge clk) begin
    		if(add_en)begin
    			if(GX_right>GX_left)	GX<=GX_right-GX_left;
    			else 					GX<=GX_left-GX_right;
    
    			if(GY_up>GY_down) 		GY<=GY_up-GY_down;
    			else 					GY<=GY_down-GY_up;
    		end
    		GX_GY_valid	<=	add_en;
    	end
    

    乘法器模块

    使用Multiplier IP:输入两个乘法因子为无符号数8bit

    配置其latency为3 clock cycle(便于时序收敛)

    平方根模块

    计算平方根,这里用到了Cordic IP,如下图所示选择实现功能为:Square Root

    选择Data Fomat为unsigned interger,输入的值限制到(0,2^n)

    选择输入位宽为24bit。

    实现结果

    仿真程序层次图

    仿真结果

    实现结果

    调节阈值视频链接
    调节阈值
    https://v.qq.com/x/page/g0969ko1uts.html

    参考链接

    https://www.jianshu.com/p/bed4ffe996a1

    https://blog.csdn.net/zaishuiyifangxym/article/details/89840396

    资料获取

  • 相关阅读:
    [LeetCode] Same Tree, Solution
    图搜索
    1 sec on Large Judge (java): https://github.com/l...
    [LeetCode] Path Sum, Solution
    嗯哪
    海量数据处理总结
    [LeetCode] Unique Binary Search Trees II, Solution
    [Interview] Serialize and Deserialize a tree
    设计题
    [LeetCode] Convert Sorted Array to Binary Search Tree, Solution
  • 原文地址:https://www.cnblogs.com/xiguazai/p/13047762.html
Copyright © 2020-2023  润新知