2014-02-18 19:36:55 Fan0920 阅读数 6208

一、            边缘检测(原理、分类、一阶导、二阶导、模板算子物理含义)

LOG算子、Canny算子 ----步骤(非极大值抑制(局部最大)、双阈值算法(先高后低))边缘的链码表示

图像强度的显著变化有阶跃变化和线条(屋顶)变化两种,边缘则是图像局部强度变化最显著的那些像素的集合。边缘主要存在于目标和目标、目标和背景、区域和区域(包括不同色彩)之间。边缘是一个区域的结束也是另一个区域的开始,利用这个特征可以分割图像。需要说明的是:边缘和物体间的边界并不等同,边缘指的是图像中像素的值有突变的地方,而物体间的边界指的是现实场景中的存在于物体之间的边界。有可能有边缘的地方并非边界,也有可能边界的地方并无边缘,因为现实世界中的物体是三维的,而图像只具有二维信息,从三维到二维的投影成像不可避免的会丢失一部分信息;另外成像过程中的光照和噪声也是不可避免的重要因素。正是因为这些原因,基于边缘的图像分割仍然是当前图像研究中的世界级难题,目前研究者正在试图在边缘提取中加入高层的语义信息。

图像的边缘有方向和幅度两个属性,沿着边缘的方向像素变化平缓,垂直于边缘的方向像素变化剧烈。边缘上的这种变化可以用微分算子来检测,通常用一阶导数(梯度算子)或二阶导数(拉普拉斯算子)来检测边缘。虽然,原理上,可以用更高阶的导数,但是,因为噪声的影响,在纯粹二阶的导数操作中就会出现对噪声的敏感现象,三阶以上的导数信息往往失去了应用价值。二阶导数还可以说明灰度突变的类型。在有些情况下,如灰度变化均匀的图像,只利用一阶导数可能找不到边界,此时二阶导数就能提供很有用的信息。二阶导数对噪声也比较敏感,解决的方法是先对图像进行平滑滤波,消除部分噪声,再进行边缘检测。不过,利用二阶导数信息的算法是基于过零检测的,因此得到的边缘点数比较少,有利于后继的处理和识别工作。

对于阶跃变化情况,一阶导数的幅度峰值一般对应边缘位置,二阶导数的过0点一般对应边缘位置,二阶导数在过0点附近的符号可以确定边缘像素在图像边缘的暗区或明区(大于0表示暗区,小于0表示亮区)。

对于屋顶变化情况,一阶导数过0点可以确定屋顶位置。

    各种算子的存在就是对这种导数分割原理进行的实例化计算,是为了在计算过程中直接使用的一种计算单位。

    Roberts算子:边缘定位准,但是对噪声敏感。适用于边缘明显且噪声较少的图像分割。Roberts边缘检测算子是一种利用局部差分算子寻找边缘的算子,Robert算子图像处理后的结果边缘不是很平滑。经分析,由于Robert算子通常会在图像边缘附近的区域内产生较宽的响应,故采用Roberts算子检测的边缘图像常需做细化处理,边缘定位的精度不是很高。

    Prewitt算子:对噪声有抑制作用,抑制噪声的原理是通过像素平均,但是像素平均相当于对图像的低通滤波,所以Prewitt算子对边缘的定位不如Roberts算子。

Sobel算子:Sobel算子和Prewitt算子都是加权平均,但是Sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。

    Isotropic Sobel算子:加权平均算子,权值反比于邻点与中心点的距离,当沿不同方向检测边缘时梯度幅度一致,就是通常所说的各向同性。

    在边沿检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边沿的;另一个是检测垂直水平边沿的 。Sobel算子另一种形式是各向同性Sobel(Isotropic Sobel)算子,也有两个,一个是检测水平边沿的 ,另一个是检测垂直平边沿的 。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。由于建筑物图像的特殊性,我们可以发现,处理该类型图像轮廓时,并不需要对梯度方向进行运算。由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数,简单有效,因此应用广泛。美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。在观测一幅图像的时候,我们往往首先注意的是图像与背景不同的部分,正是这个部分将主体突出显示,基于该理论,我们可以给出阈值化轮廓提取算法,该算法已在数学上证明当像素点满足正态分布时所求解是最优的。

    上面的算子是利用一阶导数的信息,属于梯度算子范畴。

    Laplacian算子:这是二阶微分算子。其各向同性,即与坐标轴方向无关,坐标轴旋转后梯度结果不变。但是,其对噪声比较敏感,所以,图像一般先经过平滑处理,因为平滑处理也是用模板进行的,所以,通常的分割算法都是把Laplacian算子和平滑算子结合起来生成一个新的模板。

    Laplacian算子一般不以其原始形式用于边缘检测,因为其作为一个二阶导数,Laplacian算子对噪声具有无法接受的敏感性;同时其幅值产生算子边缘,这是复杂的分割不希望有的结果;最后Laplacian算子不能检测边缘的方向;所以Laplacian在分割中所起的作用包括:(1)利用它的零交叉性质进行边缘定位;(2)确定一个像素是在一条边缘暗的一面还是亮的一面;一般使用的是高斯型拉普拉斯算子(Laplacian of a Gaussian,LoG),由于二阶导数是线性运算,利用LoG卷积一幅图像与首先使用高斯型平滑函数卷积改图像,然后计算所得结果的拉普拉斯是一样的。所以在LoG公式中使用高斯函数的目的就是对图像进行平滑处理,使用Laplacian算子的目的是提供一幅用零交叉确定边缘位置的图像;图像的平滑处理减少了噪声的影响并且它的主要作用还是抵消由Laplacian算子的二阶导数引起的逐渐增加的噪声影响。

    微分算子在图像处理中扮演重要的角色,其算法实现简单,而且边缘检测的效果又较好,因此这些基本的微分算子是学习图像处理过程中的必备方法,下面着重讨论几种常见的微分算子。

1.Sobel

 其主要用于边缘检测,在技术上它是以离散型的差分算子,用来运算图像亮度函数的梯度的近似值,缺点是Sobel算子并没有将图像的主题与背景严格地区分开来,换言之就是Sobel算子并没有基于图像灰度进行处理,由于Sobel算子并没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意,算法具体实现很简单,就是3*3的两个不同方向上的模板运算,这里不写出。

2.Robert算子

根据任一相互垂直方向上的差分都用来估计梯度,Robert算子采用对角方向相邻像素之差。梯度计算公式:G[i,j] = |f(x,y)-f(x+1,y+1)|+| f(x+1,y)-f(x,y+1)|

3.Prewitt算子

   该算子与Sobel算子类似,只是权值有所变化,但两者实现起来功能还是有差距的,据经验得知Sobel要比Prewitt更能准确检测图像边缘。

4.Laplacian算子

   拉普拉斯算子是一种二阶微分算子,若只考虑边缘点的位置而不考虑周围的灰度差时可用该算子进行检测。对于阶跃状边缘,其二阶导数在边缘点出现零交叉,并且边缘点两旁的像素的二阶导数异号。

5.LoG算子

首先用高斯函数对图像作平滑滤波处理,然后才使用Laplacian算子检测边缘,因此克服了Laplacian算子抗噪声能力比较差的缺点,但是在抑制噪声的同时也可能将原有的比较尖锐的边缘也平滑掉了,造成这些尖锐边缘无法检被测到。应用LOG算子,高斯函数中方差参数的选择很关键,对图像边缘检测效果有很大的影响。高斯滤波器为低通滤波器,越大,通频带越窄,对较高频率的噪声的抑制作用越大,避免了虚假边缘的检出,同时信号的边缘也被平滑了,造成某些边缘点的丢失。反之,越小,通频带越宽,可以检测到的图像更高频率的细节,但对噪声的抑制能力相对下降,容易出现虚假边缘。因此,应用LOG算子,为取得更佳的效果,对于不同图像应选择不同参数。

6.Canny算子

该算子功能比前面几种都要好,但是它实现起来较为麻烦。Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,其基本原理是 (1)图象边缘检测必须满足两个条件:一能有效地抑制噪声;二必须尽量精确确定边缘的位置。(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny边缘检测算子。(3)类似于 LoG 边缘检测方法,也属于先平滑后求导数的方法。用Canny算子进行边缘检测处理步骤(1) 用高斯滤波器平滑图像(2) 用一阶偏导有限差分计算梯度幅值和方向(3) 对梯度幅值应用非极大值抑制(4) 用双阈值算法检测和连接边缘(取高低两个阈值作用在幅值图得到两个边缘图,高阈值边缘图和低阈值边缘图。连接高阈值边缘图,出现断点时,在低阈值边缘图中的8邻点域搜寻边缘点)

二、            区域增长、Hough变换

区域分割------直接根据事先确定的相似性准则,直接取出若干特征相近或相同像素组成区域。常用方法有:区域增长(生长)、区域分裂-合并

像素集合的区域增长:1.根据图像的不同应用选择一个或者一组种子,它或者是最亮或最暗的点,或者是位于点簇中心的点2.选择一个描述符(条件)3.从该种子开始向外扩张,首先把该种子像素加入结果集合,然后不断将与集合中各个像素连通且满足描述符的像素加入集合4.上一过程进行到不再有满足条件的新结点加入集合为止。(这个算法的关键就是选择一个描述符,即选择合适的生长或相似准则,大部分区域增长准则使用图像的局部性质)【生长方法-先从单个种子象素开始通过不断接纳新象素,最后得到整个区域】

优势:1. 区域生长通常能将具有相同特征的联通区域分割出来。

  2. 区域生长能提供很好的边界信息和分割结果。

  3. 区域生长的思想很简单,只需要若干种子点即可完成。

  4. 在生长过程中的生长准则可以自由的指定。

  5. 可以在同一时刻挑选多个准则。

劣势: 1. 计算代价大。

  2. 噪声和灰度不均一可能会导致空洞和过分割。

  3. 对图像中的阴影效果往往不是很好。

  对噪声问题,通常可以用一些平滑滤波器,或是diffusion滤波器做预处理来解决,所以通常噪声问题并不是很严重。所以实际上,区域生长的最严重的问题就是效率低下。

基于区域灰度差:(1)对图像进行逐行扫描,找出尚没有归属的象素(2)以该象素为中心检查其邻域象素,即将邻域中的象素逐个与它比较,如果灰度差小于预先确定的阈值,将它们合并(3)以新合并的象素为中心,返回到步骤2,检查新象素的邻域,直到区域不能进一步扩张(4)返回到步骤1,继续扫描直到不能发现没有归属的象素,则结束整个生长过程。(这个算法对区域生长起点的选择有较大依赖性,后面是改进算法)(1)设灰度差的阈值为0,用上述方法进行区域扩张,使灰度相同象素合并(2)求出所有邻域区域之间的平均灰度差,并合并具有最小灰度差的邻接区域(3)设定终止准则,通过反复进行上述步骤2中的操作将区域依次合并,直到终止准则满足为止。(这种算法简单,但是也有缺点如下:由于仅考虑了从一个象素到另一个象素的特性是否相似,因此对于有噪声的或复杂的图像,使用这种方法会引起不希望的区域出现;另外,如果两个区域间边缘的灰度变化很平缓,或者对比度弱的两个相交区域,采用这种方法,这两个区域将会合并起来,从而产生错误。后面是进一步改进算法)不用像素的灰度值去和邻域像素的灰度值比较,而用像素所在区域的平均灰度值去和各邻域像素的灰度值进行比较

简单区域增长步骤如下:(1)对格网数据点逐格网单元扫描,当找不到这样的地物点时结束操作;(2)把这个点同周围的8-邻域点比较,若小于阈值,则合并到同一区域,并对合并的地物点赋予该区域的标记;(3)从新合并的地物点开始,反复进行(2)的操作;(4)反复进行(2)、(3)的操作,直到不能合并为止;(5)返回(1)操作,寻找新区域出发点。

基于区域灰度分布统计性质:以灰度分布相似性作为生长准则,通过将一个区域上的统计特性与在该区域的各个部分上所计算出的统计特性进行比较来判断区域的均匀性,如果它们相互接近,那么这个区域可能是均匀的,这种方法对于纹理分割很有用。步骤:(1)把图像分成互不重叠的小区域(2)比较邻接区域的累积灰度直方图,根据灰度分布的相似性进行区域合并(3)设定终止准则,通过反复进行步骤2中的操作将各个区域依次合并,直到终止准则满足

基于区域形状:(1)对图像中灰度级不同的区域,均分为四个子区域(2)如果相邻的子区域所有像素的灰度级相同,则将其合并(3)反复进行上两步操作,直至不再有新的分裂与合并为止

区域分裂-合并:先从整幅图像开始通过不断分裂,得到各个区域(在实际中,先将图像分成任意大小且不重叠的区域)然后再合并或分裂这些区域,以满足分割的要求,在这类方法中,常根据图像的统计特性设定图像区域属性的一致性测度

 

局部连接处理的原理:通过比较梯度值和梯度方向角,如果两个点的梯度值的差小于某一非负的阈值而且这两个点的梯度向量的方向角的差也小于某一角度阈值那么就认为那两个点的梯度值和方向角是相似的,即那两个点具有连接性。处理步骤:(1)设定A、T的阈值大小,确定邻域的大小(2)对图像上每一个像素的邻域点进行分析,判断是否需要连接。(3)记录像素连接的情况,另开一个空间,给不同的边以不同的标记。(4)最后,删除孤立线段,连接断开的线段。

Hough变换是图像处理中从图像中识别几何形状的基本方法之一。Hough变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定的曲线通过曲线表达形式变为参数空间的一个点。这样就把原始图像中给定曲线的检测问题转化为寻找参数空间中的峰值问题。也即把检测整体特性转化为检测局部特性。比如直线、椭圆、圆、弧线等。Hough变换思想为:在原始图像坐标系下的一个点对应了参数坐标系中的一条直线,同样参数坐标系的一条直线对应了原始坐标系下的一个点,然后,原始坐标系下呈现直线的所有点,它们的斜率和截距是相同的,所以它们在参数坐标系下对应于同一个点。这样在将原始坐标系下的各个点投影到参数坐标系下之后,看参数坐标系下有没有聚集点,这样的聚集点就对应了原始坐标系下的直线(在参数平面上相交直线最多的点所对应的xy平面上的直线就是我们的解)。

三、            基于阈值的分割

Otsu(类间方差大、类内方差小)

       一维熵、模糊熵

简单直方图分割:(prewitt提出直方图双峰法)如果灰度级直方图呈明显双峰状,则选取两峰之间的谷底所对应的灰度级作为阈值(只考虑了直方图灰度信息而忽略了图像的空间信息)

最佳阈值:(分割错误最小的阈值)根据灰度级分布概率密度计算出总的错误概率期望,求使其达最小值的灰度即最佳阈值。

类间方差阈值分割:(otsu提出的最大类间方差法,又称大津阈值分割法,在判决分析最小二乘法原理的基础上推到得出的)有三个等价判决准则,其中最简单的是将 “类间方差与总体方差之比的最大值”所对应的灰度值作为阈值。

最大熵阈值分割:(使分割出的两部分的一阶灰度统计的信息量最大)熵函数定义为目标区域的熵与背景区域的熵之和,当熵函数取最大值时对应的灰度值作为阈值(也只考虑了直方图灰度信息而忽略了图像的空间信息)

二维最大熵阈值分割:(使真正代表目标和背景的信息量最大)定义“点灰度-区域灰度均值”二维直方图,找到二维熵函数最大值对应的灰度值作为阈值(点灰度是最基本的特征,但它对噪声敏感,区域灰度特征包含了部分空间信息,且对噪声的敏感程度低于点灰度特征)

模糊熵:描述图像模糊化后其包含的信息量大小,类似确定熵,模糊熵的最大值对应最佳分割门限,模糊熵的大小与隶属度函数的选取形式有关,模糊熵函数的参数相对确定熵更多,求解更为复杂。

四、            形态学处理

腐蚀:结构元

膨胀:结构元先要做反射(与原点对称)

开运算、闭运算

1数学形态学(MM,Mathematical morphology)图像分析基本步骤:

1)提取几何结构特征(模式)

2)根据结构模式选择相应的结构元素

3)用选定的结构元对图像实行击中与否变换(HMT,Hit-Miss Transform),得到比原始图像更显著突出物体特征信息的图像。

结论:经过形态学变换后的图像突出我们所需的信息,从而方便提取信息。HMT是MM图像分析的核心运算。

2选择结构元的基本原则:

1)在几何上比原图简单、且有界

2)结构元必须是凸的

3形态学图像分析的优势:

1)借助先验的几何特征信息,利用形态学算子可以有效滤除噪声,又可保留图像原有信息

2)易于并行处理方法有效实现、硬件实现容易

3)基于MM的边缘信息提取由于基于微分的提取算法,不像微分算法对噪声那样敏感,而且提取的边缘较光滑

4)提取的图像骨架较连续、断点少

4腐蚀运算的实质:在目标图像中标出那些与结构元素相同的子图像原点位置的像素

注意:当结构元素在目标图像上平移时,结构元素中的任何元素不能超出目标图像的范围。 

应用:消除物体之间的粘连。

5膨胀运算的实质:在目标图像中标出那些与反射的结构元素至少有一个非零公共元素的子图像的原点位置的像素。

注意:(1)当结构元素中原点位置的值是0时,仍把它看作是0;而不再把它看作是1。

    (2)当结构元素在目标图像上平移时,允许结构元素中的非原点像素超出目标图像范围。  

应用:将相邻物体粘连起来。填充目标区域的小孔。

6腐蚀和膨胀的对偶性

对目标图像的膨胀运算,相当于对图像背景的腐蚀运算操作(得出的是目标图像膨胀运算结果的背景);对目标图像的腐蚀运算,相当于对图像背景的膨胀运算操作(得出的是目标图像腐蚀运算结果的背景)。

7开运算:先腐蚀再膨胀

8闭运算:先膨胀再腐蚀

9开运算与闭运算的对偶性

用结构元素B对目标图像A的开运算,相当于用结构元素B的反射对目标图像A的背景的闭运算操作(得出的是目标图像开运算结果的背景)。

用结构元素B对目标图像A的闭运算,相当于用结构元素B的反射对目标图像A的背景的开运算操作(得出的是目标图像闭运算结果的背景)。

10灰度形态学

与二值图像腐蚀运算运算的区别:被移动的是输入图像而不是结构元素

灰度腐蚀运算:逐点计算,计算该点局部范围内各点与结构元素中对应点的灰度值之差,并选取其中的最小值作为该点的腐蚀结果。结果:边缘会向灰度值高的区域内部收缩。

灰度膨胀运算:逐点计算,计算该点局部范围内各点与结构元素中对应点的灰度值之和,并选取其中的最大值作为该点的膨胀结果。结果:边缘会向外延伸。

 

五、            图像分割目的和意义

1、  Oversegmentation/undersegmentation/bottom-up/top-down/有监督/无监督

图像分割的发展方向:基于统计理论的图像分割、基于变分模型的图像分割、基于图论的图像分割

2、  K-means与Fuzzy C-means的区别,优劣

K-means聚类需要事先确定聚类的数目、而且初始聚类中心的选取对结果有很大影响。K-means聚类是一种硬划分(Hard Clustering),非此即彼。

优点:简单快速,易于实现

缺点:需要知道K,对异常值很敏感

很少应用于像素分割

FCM基于划分,思想是使得被划分到同一簇的对象之间相似度最大,使得不同簇之间的相似度最小。FCM是一种柔性的模糊划分,用隶属度表示某个样本属于某个簇的程度。

         相似性传播聚类(AP,Affinity Propagation cluttering)(不确定考不考):

Responsibilities(吸引度):描述点K适合作为数据点i的聚类中心的程度

Availabilities(归属度):描述点i选择点K作为其聚类中心的适合程度

输入:N个数据点的相似度,组成N*N的相似度矩阵S(S矩阵对角线上数值成为参考度P)

AP算法通过迭代过程不断更新每一个点的吸引度和归属度值(responsibilities & availabilities ),直到产生m个高质量的exemplar,同时将其余的数据点分配到相应的聚类中。

3、  分水岭的基本思想

分水岭:将灰度图像看做地形图,假设在每个区域最小值位置打个洞,让水从洞里以均匀的速度上升,从低到高淹没整个地形。当处在不同的汇聚盆地中的水将要聚合在一起时,修建大坝组织聚合,最后得到的水坝边界就是分水岭的分割线。(分水岭算法的目标是找出分割线;分水岭算法的处理对象是梯度图而不是原始图)

原始图à梯度图à梯度图的分水岭à最终轮廓

缺点:由于噪声或者梯度的局部不规则而引起“过度分割”

分水岭算法的改进:a在分割前对图像进行预处理b在分割时添加约束c在分割后对图像进行再处理                      如:标记约束分水岭算法(限定区域最低点的数量);等级分割(用分水岭算法得到初始的分割图片后再次用分水岭算法得出下一级分割图);简单的技巧(使用高斯或中值滤波减少区域数量)

优点:快、用于分级分割特别好

缺点:对于复杂的分割不容易得出不同的区域;没有top-down信息

应用:多用于分级分割

Mean-shift segmentation 基本思想、优点、缺点

理论:什么是Mean Shift?密度估计方法?非参数核密度估计?Mean Shift起源和性能?

应用:聚类、不连续保持平滑(既平滑了噪声又保留了边界)、目标轮廓检测、目标跟踪

优点:应用独立工具,适合于实时数据分析,在数据聚类上不假设任何先验外形,可以处理任意的特征空间,只选择一个参数,h(窗大小)有物理意义,不像K均值

缺点:窗大小(带宽选择)很重要,不合适的窗大小可能导致模式合并或产生另外的“阴影”模式—>使用自适应窗大小

分割的使用:

效率、更好的特征、需要分割目标

K均值、分水岭、均值漂移分割:

均值漂移分割:一般目的的好的分割方法、一般的有用的聚类、跟踪技术

分水岭分割:利于分层分割,结合边缘预测一起用

4、  N-cut为什么可以用图论方法?为拉普拉斯矩阵、谱聚类

六、            SIFT 步骤 DOG

SIFT(Scale Invarient Feature Transform,尺度不变特征变换)匹配算法:将一幅图像映射(变换)为一个局部特征向量集,特征向量具有平移、缩放、旋转不变性,同时对光照变化、仿射及投影变换也有一定不变性。思想:SIFT算法是一种提取局部特征的算法,在尺度空间寻找极值点,提取位置,尺度,旋转不变量。

特点:SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变换保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性。独特性好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配。多量性,即使少数的几个物体也可以产生大量的SIFT特征向量。高速性,经过优化的SIFT算法可以满足一定的速度需求。可扩展性,可很方便的与其他形式的特征向量进行联合。

实质:在不同尺度空间上查找特征点(关键点)的问题。三大工序:1提取特征点,2对关键点附加详细信息(局部特征),即所谓的描述器,3通过两方特征点的两两比较找出相互匹配的若干对特征点,也就是建立景物之间的联系(关键点,在不同尺度空间的图像下检测出的具有方向信息的局部极值点)

 SIFT算法步骤:

1) 检测尺度空间极值点

2) 精确定位极值点

3) 为每个关键点指定方向参数

4) 关键点描述子的生成

DOG算子计算简单,是尺度归一化的LoG算子的近似。

七、            HOG特征

方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的方向梯度直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。将归一化之后的块描述符(向量)称为HOG描述符.

1)主要思想:

       在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)。

2)具体的实现方法是:

       首先将图像分成小的连通区域,我们把它叫细胞单元。然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。

3)提高性能:

       把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能对光照变化和阴影获得更好的效果。

4)优点:

       与其他的特征描述方法相比,HOG有很多优点。首先,由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。其次,在粗的空域抽样、精细的方向抽样以及较强的局部光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。因此HOG特征是特别适合于做图像中的人体检测的。

大概过程:

HOG特征提取方法就是将一个image(你要检测的目标或者扫描窗口):

1)灰度化(将图像看做一个x,y,z(灰度)的三维图像);

2)采用Gamma校正法对输入图像进行颜色空间的标准化(归一化);目的是调节图像的对比度,降低图像局部的阴影和光照变化所造成的影响,同时可以抑制噪音的干扰;

3)计算图像每个像素的梯度(包括大小和方向);主要是为了捕获轮廓信息,同时进一步弱化光照的干扰。

4)将图像划分成小cells(例如6*6像素/cell);

5)统计每个cell的梯度直方图(不同梯度的个数),即可形成每个cell的descriptor;

6)将每几个cell组成一个block(例如3*3个cell/block),一个block内所有cell的特征descriptor串联起来便得到该block的HOG特征descriptor。

7)将图像image内的所有block的HOG特征descriptor串联起来就可以得到该image(你要检测的目标)的HOG特征descriptor了。这个就是最终的可供分类使用的特征向量了。

八、            Adaboost分类器

Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。使用adaboost分类器可以排除一些不必要的训练数据特徵,并将关键放在关键的训练数据上面。

目前,对Adaboost算法的研究以及应用大多集中于分类问题,同时近年也出现了一些在回归问题上的应用。

Adaboost(AdaptiveBoosting)算法
  对于boosting算法,存在两个问题:
  1.如何调整训练集,使得在训练集上训练的弱分类器得以进行;
  2.如何将训练得到的各个弱分类器联合起来形成强分类器。
  针对以上两个问题,adaboost算法进行了调整:
  1.使用加权后选取的训练数据代替随机选取的训练样本,这样将训练的焦点集中在比较难分的训练数据样本上;
  2.将弱分类器联合起来,使用加权的投票机制代替平均投票机制。让分类效果好的弱分类器具有较大的权重,而分类效果差的分类器具有较小的权重。

Adaboost算法是Freund和Schapire根据在线分配算法提出的,他们详细分析了Adaboost算法错误率的上界,以及为了使强分类器 达到错误率,算法所需要的最多迭代次数等相关问题。与Boosting算法不同的是,adaboost算法不需要预先知道弱学习算法学习正确率的下限即弱分类器的误差,并且最后得到的强分类器的分类精度依赖于所有弱分类器的分类精度,这样可以深入挖掘弱分类器算法的能力。
  Adaboost算法中不同的训练集是通过调整每个样本对应的权重来实现的。开始时,每个样本对应的权重是相同的,即其中 n为样本个数,在此样本分布下训练出一弱分类器。对于分类错误的样本,加大其对应的权重;而对于分类正确的样本,降低其权重,这样分错的样本就被突出出来,从而得到一个新的样本分布。在新的样本分布下,再次对弱分类器进行训练,得到弱分类器。依次类推,经过T 次循环,得到T 个弱分类器,把这T个弱分类器按一定的权重叠加(boost)起来,得到最终想要的强分类器。
  1.给定训练样本集S,其中X和Y分别对应于正例样本和负例样本;T为训练的最大循环次数;

  2.初始化样本权重为1/n,即为训练样本的初始概率分布;

  3.第一次迭代:

  (1)训练样本的概率分布相当下,训练弱分类器:

  (2)计算弱分类器的错误率:

  (3)选取合适阈值,使得错误率最小

  (4)更新样本权重:

  (5)最终得到的强分类器:

 

每轮循环后,权值应做多大的调整呢?这个答案依赖于当前分类器的总体误差。明确地说,如果e代表分类器在加权数据上的误差率(在0和1之间的一个小数),那么对于正确分类的实例,权值更新为

权值=权值*e/(1-e)

对于错误分类的实例,权值保持不变。当然,这并没有如前所述,增加被错误分类的实例的权值。然而,在更新了所有实例的权值后,要进行正常化处理,使它们的权值总和与原来的相同。每个实例的权值都要除以新权值总和再乘以原来的权值总和。这样便自动增加了每个错误分类实例的权值,同时减小了每个正确分类实例的权值。

每当在加权的训练数据集上的误差率大于等于0.5时,提升程序将删除当前的分类器并不再继续进行循环。当误差率等于0时,也同样处理,因为这时所有实例的权值都为0。

为了做出一个预测,使用一个加了权的投票来组合它们的输出。要决定这些权值,性能表现好的分类器(e接近于0)应当获得一个高的权值,而性能表现差的分类器(e接近于0.5)则应获得一个较低的权值。更具体地说

权值=-log(e/(1-e))

这是一个0和无穷大之间的正数。为了做出预测,将投给某个具体类的所有分类器的权值相加,选择相加总和最大的那个类别。
  Adaboost算法是经过调整的Boosting算法,其能够对弱学习得到的弱分类器的错误进行适应性调整。上述算法中迭代了T次的主循环,每一次循环根据当前的权重分布对样本x定一个分布P,然后对这个分布下的样本使用若学习算法得到一个错误率为e的弱分类器,对于这个算法定义的弱学习算法的错误率的上限并不需要事先知道,实际上。每一次迭代,都要对权重进行更新。更新的规则是:减小弱分类器分类效果较好的数据的概率,增大弱分类器分类效果较差的数据的概率。最终的分类器是个弱分类器的加权平均。

 

目标识别的步骤

1获取训练数据2提取特征3训练分类器4利用分类器进行检测

2019-07-24 18:22:16 qq_37935516 阅读数 137

边缘是指图像中像素灰度有阶跃变化或屋顶变化的像素的集合,存在于目标与背景、目标与目标、区域与区域之间,勾画出了目标物体的轮廓,使人们能对某种目标一目了然。

 

边缘一般分为:

  • 阶跃边缘:两边像素的灰度明显不同,呈现出阶梯状
  • 屋顶边缘:两边像素的灰度从逐步增加向逐步减少转变

常用的边缘检测算子有:

  • 梯度算子
  • Roberts算子
  • Prewitt算子
  • Sobel算子
  • Kirsch算子
  • Laplacian算子
  • Marr算子

 

梯度算子

特点:仅计算相邻像素的灰度差,对噪声比较敏感,无法抑制噪声的影响。

Roberts算子

与梯度算子相似,但是计算方向不同,Roberts算子计算的是45°方向的梯度。

可以看出,其效果比梯度算子略好一点,也同样对噪声敏感,对边缘定位不准确,提取边缘线条较粗。

Prewitt算子

与梯度算子不同的是,Prewitt算子采用3×3大小,顾及了局部的整体情况的同时抑制了噪声的影响,边缘检测结果在水平方向和垂直方向均比Robert算子更加明显。

Sobel算子

与Prewitt算子类似,在四领域的权重为2,而其他像素的权值为1。Sobel算子在Prewitt算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。

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

其能够进一步抑制噪声,但是检测的边缘较宽。

Kirsch算子(方向算子)

利用一组模板对图像中的同一像素求卷积,选取最大值最为该像素的边缘强度,对应的方向则为边缘方向。

特点:在计算边缘强度的同时可以得到边缘方向,各方向间的夹角为45°。

Nevitia算子

与Kirsch算子不同的是,它由12个模板,且各方向间的夹角为30°而不是45°。

拉普拉斯算子

拉普拉斯(Laplacian)算子是n维欧几里德空间中的一个二阶微分算子,常用于图像增强领域和边缘提取。它通过灰度差分计算邻域内的像素,基本流程是:判断图像中心像素灰度值与它周围其他像素的灰度值,如果中心像素的灰度更高,则提升中心像素的灰度;反之降低中心像素的灰度,从而实现图像锐化操作。在算法实现过程中,Laplacian算子通过对邻域中心像素的四方向或八方向求梯度,再将梯度相加起来判断中心像素灰度与邻域内其他像素灰度的关系,最后通过梯度运算的结果对像素灰度进行调整。

通过模板可以发现,当邻域内像素灰度相同时,模板的卷积运算结果为0;当中心像素灰度高于邻域内其他像素的平均灰度时,模板的卷积运算结果为正数;当中心像素的灰度低于邻域内其他像素的平均灰度时,模板的卷积为负数。对卷积运算的结果用适当的衰弱因子处理并加在原中心像素上,就可以实现图像的锐化处理。
 

由于梯度算子和拉普拉斯算子都对噪声敏感,因此一般用他们检测边缘之前要先对图像进行平滑。

特点:

优点:

  1. 各向同性、线性和位移不变的
  2. 对细线和孤立点检测效果较好

缺点:

  1. 对噪声敏感,对噪声有双倍加强的作用
  2. 不能检测出边的方向
  3. 常产生双像素的边缘

Marr算子

由于拉普拉斯算子在检测前需要平滑,于是在拉普拉斯基础上发展了Marr算子,平滑函数采用正态分布的高斯函数。

参考资料:

[Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子

2018-08-20 23:08:45 lujiaqi3847 阅读数 384

1、实验目的

图像信息量巨大,而边缘信息是图像的一种描述,是图像最基本的特征,所包含的也是图像中用于识别的有用信息。所谓边缘是指其周围像素灰度有阶跃变化或屋顶变化的那些像素的集合,边缘存在于目标、背景和区域之间,所以,它是图像分割所依赖的最重要的依据。由于边缘是位置的标志,对灰度的变化不敏感,,因此,边缘也是图像匹配的重要的特征。图像边缘为人们描述或识别目标以及解释图像提供了一个有价值的和重要的特征参数,其算法的优劣直接影响着所研制系统的性能。

2、实验内容

1)Linux平台:

(1)硬件结构图:

(2)程序流程图:

(3)核心代码与关键技术:

 ARM 端源代码与视频采集回放实验完全一致。

package.xdc:该文件中定义了该 codec 包的静态属性,如 codec 名称和关联包。 如下面代码定义了 该 codec 包 的 名 称 为 codecs.vidsobeledge , 包 含 了 1 个 简 单 的 算 法 叫VIDSOBELEDGE。

package codecs.vidsobeledge {module VIDSOBELEDGE;}

VIDSOBELEDGE.xs:该文件内容是模块的实现,文件名称 VIDSOBELEDGE 必须和 package.xdc 文件中定义的模块名称一致。文件中包含了 VIDSOBELEDGE.xdc 中声明的方法的实现。

videnc_copy.c:该文件包含了 codec 的 xDM 接口的 8 个接口函数实现。该文件和前两个实验中codec/videnc_copy 中提供的函数实现基本一致,process 函数有区别,前两个实验中只是将输入的视频数据进行了一下空间的搬移,而在本实验中进行了边缘检测处理。

XDAS_Int32 VIDENCCOPY_TI_process(IVIDENC_Handle h, XDM_BufDesc *inBufs, XDM_BufDesc  *outBufs,  IVIDENC_InArgs  *inArgs,  IVIDENC_OutArgs *outArgs){    …

UYVY_to_YUY2(inBufs->bufs[curBuf],tmp1);IMG_sobel(tmp1,tmp2,720,576);YUY2_to_UYVY(tmp2,outBufs->bufs[curBuf]);  …

边缘检测算法函数使用了img64x.lib中提供的 sobel 算子算法。

void IMG_sobel(const unsigned char *in_data, /*

Input image data */unsigned char *out_data, /*

Output image data */short cols, short rows /*

Image dimensions */);

2)CCS平台:

(1)硬件结构图:

(2)程序流程图:

(3)核心代码与关键技术:

边缘检测是基于对图像灰度差异运算实现的,所以如果输入的是RGB彩色图像,需要先进行灰度图的转换。

RGB转换成灰度图像的一个常用公式是:

Gray = R*0.299 + G*0.587 + B*0.114

//******************灰度转换函数*************************  

//第一个参数image输入的彩色RGB图像;  

//第二个参数imageGray是转换后输出的灰度图像;  

//*************************************************************  

void ConvertRGB2GRAY(const Mat &image,Mat &imageGray)  

{   if(!image.data||image.channels()!=3)   {  return ;  }  

    imageGray=Mat::zeros(image.size(),CV_8UC1); uchar *pointImage=image.data;  uchar *pointImageGray=imageGray.data; int stepImage=image.step; int stepImageGray=imageGray.step;  

for(int i=0;i<imageGray.rows;i++)  { for(int j=0;j<imageGray.cols;j++)  {pointImageGray[i*stepImageGray+j]=0.114*pointImage[i*stepImage+3*j]+0.587*pointImage[i*stepImage+3*j+1]+0.299*pointImage[i*stepImage+3*j+2];}}  

//******Sobel卷积因子计算X、Y方向梯度和梯度方向角*****  

//第一个参数imageSourc原始灰度图像;  

//第二个参数imageSobelX是X方向梯度图像;  

//第三个参数imageSobelY是Y方向梯度图像;  

//第四个参数pointDrection是梯度方向角数组指针  

//*************************************************************  

void SobelGradDirction(const Mat imageSource,Mat &imageSobelX,Mat &imageSobelY,double *&pointDrection)  

{  

    pointDrection=new double[(imageSource.rows-1)*(imageSource.cols-1)];  

    for(int i=0;i<(imageSource.rows-1)*(imageSource.cols-1);i++)  

    {  

        pointDrection[i]=0;  

    }  

    imageSobelX=Mat::zeros(imageSource.size(),CV_32SC1);  

    imageSobelY=Mat::zeros(imageSource.size(),CV_32SC1);  

    uchar *P=imageSource.data;  uchar *PX=imageSobelX.data; uchar *PY=imageSobelY.data;    

  

    int step=imageSource.step;    

    int stepXY=imageSobelX.step;   int k=0;   int m=0;   int n=0;  

    for(int i=1;i<(imageSource.rows-1);i++)    

    {    

        for(int j=1;j<(imageSource.cols-1);j++)    

        {  //通过指针遍历图像上每一个像素   

double gradY=P[(i-1)*step+j+1]+P[i*step+j+1]*2+P[(i+1)*step+j+1]-P[(i-1)*step+j-1]-P[i*step+j-1]*2-P[(i+1)*step+j-1];  

PY[i*stepXY+j*(stepXY/step)]=abs(gradY);  

            double gradX=P[(i+1)*step+j-1]+P[(i+1)*step+j]*2+P[(i+1)*step+j+1]-P[(i-1)*step+j-1]-P[(i-1)*step+j]*2-P[(i-1)*step+j+1];  

            PX[i*stepXY+j*(stepXY/step)]=abs(gradX);  

            if(gradX==0)  

            {  gradX=0.00000000000000001;  /*防止除数为0异常*/  }  

            pointDrection[k]=atan(gradY/gradX)*57.3;//弧度转换为度  

            pointDrection[k]+=90;  

            k++;  }  }   

    convertScaleAbs(imageSobelX,imageSobelX);  

    convertScaleAbs(imageSobelY,imageSobelY);  

}  

3、实验步骤

1)实验准备:

(1)配置好串口终端(具体操作参考 4.2 节) ;

(2)用串口线一端连接 PC 机串口, 另一端连接 SEED-DTK6446 实验箱 RS232 串口 J3;

(3)使用网线将 SEED-DTK6446 实验箱和 linux 开发主机都连接到局域网上;

(4)将摄像头连接到视频输入口 J27;

(5)将视频显示设备连接到视频输出口 J13。

2)Linux平台操作步骤:

(1)在 linux 主机上打开终端,进入实验程序 codec 算法包所在目录

Host # cd /opt/dvevm_1_20/seed_exp/05.videosobel/codecs/vidsobeledge

(2)重新编译 codec 算法包

Host # make clean

Host # make

(3)进入实验程序 ARM 端所在目录

Host # cd /opt/dvevm_1_20/seed_exp/05.videosobel/video_sobel_app

(4)重新编译应用程序。

Host # make clean

Host # make

(5)复制编译生成的可执行文件到 NFS 根文件系统中

Host # cp release/video_sobel_app /opt/nfs/opt/seed_exp

(6)进入实验程序 DSP 端所在目录

Host # cd /opt/dvevm_1_20/seed_exp/05.videosobel/servers/vidsobeledge

(7)重新编译 DSP Server。

Host # make clean

Host # make

(8)复制编译生成的. x64P 文件到 NFS 根文件系统中

Host # cp vidsobeledge.x64P /opt/nfs/opt/seed_exp

(9)将系统配置为从 NFS 根文件系统启动

(10)启动系统后,登陆系统,进入可执行文件所在目录

root @ xxx.xxx.xxx.xxx:~#cd /opt/seed_exp

(11)加载 cmemk.ko 和 dsplinkk.ko 模块

root @ xxx.xxx.xxx.xxx:/opt/seed_exp#./loadmodules.sh

(12)执行应用程序

root @ xxx.xxx.xxx.xxx:/opt/seed_exp#./video_sobel_app

视频显示设备上将实时的显示采集的经算法处理的图像。

3)CCS平台操作:

(1)打开 CCS5.3 并导入现有工程到软件中,点击 File,选择 File-->Import,在弹出的对话框中选中 sobel 添加该工程文件;

(2)设置编译与连接选项;

(3)设置目标配置文件,点击 File,选择 File → New → Target Configuration File;

(4)配置 ARM 端;

(5)编译工程, 点击 Project →Build Project, 对工程进行编译, 如正确则生成 .out 文件;

(6)使用 Run→Load→Load Program 菜单命令,装载 composite_loop.out 文件,进行调试,.out 文件一般存放在程序文件夹的 debug 文件夹中;

(7)运行程序,可在视频 LCD 上看到前端实时处理的边缘检测图像。

 

4、实验结果与分析

(详细的实验结果,图//文相结合,并对实验结果及实验中遇到的问题进行较全面的对比分析,阐述解决方案,通过测试或实验分析其有效性)

1)实验结果及分析

(1)Linux平台结果:                (2)CCS平台结果:

              

(3)结果分析:根据实验结果,我们发现css平台下和linux平台下都实现了边缘检测。由实验结果分析,边沿还是比较模糊,证明算法中sobel算子在进行阈值分割时的阈值不太合适,导致边沿虽然能勾画出物体轮廓,但不能很有效清晰的绘制出边缘图像。因此,该sobel算子还有可以改进的空间,例如,根据图像的特点可以采用动态阈值的方法进行分割监测,但是缺点是运算量会大大增加。下一步会进行动态阈值分割算法的改进。

  • 资源分享

链接:12-2018.01-数字信号处理《基于CCS和Linux平台的图像边缘检测算法开发及图像处理》 密码:k77w

2018-12-11 10:37:29 weixin_42346564 阅读数 1977

 

canny要工作:推导了最优边缘检测算子

      图像的边缘检测是:图像最基本特征,边缘点指的是图像中周围像素灰度有阶跃变化或屋顶变化的那些像素点,即:灰度值导数极大的地方。

      边缘检测的目的是:标识数字图像中亮度变化的明显的点。之前介绍过增强边缘的图像锐化的方法,本节文章主要介绍一种专门用于边缘检测的canny算子。

PPT下载:https://download.csdn.net/download/weixin_42346564/10846987


      本节的重点是分割方法,是基于检测急剧的,局部的强度变化。我们感兴趣的三种图像特征是孤立的线边缘

      边缘像素是图像强度突然变化的像素,边缘(或边缘段)是一组连通的边缘像素;

      线可以被看作是(通常)较细的边缘段,其中线两侧背景的强度要么比线像素的强度高得多,要么比线像素的强度低得多。线条产生了所谓的“屋顶边缘”。最后,一个孤立的点可以看作是被背景(前景)像素包围的前景(背景)像素。局部平均平滑图像。考虑到平均值类似于积分,很明显,利用导数可以检测到强度的突变和局部变化。由于很快就会证明的原因,一阶和二阶导数特别适合于这个目的。数字函数的导数是用有限差分定义的。有很多种方法来计算这些差异,但是。正如3.6节所解释的

我们要求:

(1)一阶导数的任何近似在等强度区域必须为零

(2)在强度阶跃或斜坡开始时必须非零;

(3)在强度斜坡上的点必须非零。


Canny边缘检测基本特征如下:

  • 须满足条件:①抑制噪声②精确定位边缘

 

  • l边缘检测算子应满足以下3个判断准则:

  • 从数学上表达了三个准则[信噪比准则(低错误率)、定位精度准则、单边缘响应准则],并寻找表达式的最佳解。

  •     (1)信噪比准则SRN(低误判率),即尽可能少地把边缘点误认为是非边缘点,目的是找出Hx,y); SNR越大,误判率越低。

  •     (2)定位精确度准则即准确地把边缘点定位在灰度变化最大的像素上;
  •     (3)单边缘响应准则,抑制虚假边缘。

 

Canny边缘检测算法步骤:

步骤1:用高斯滤波平滑处理原图像; 
步骤2:用一阶偏导的有限差分进行计算梯度的幅值方向; 
步骤3:对梯度幅值进行非极大值抑制; 
步骤4:用双阈值算法检测和连接边缘。


步骤详解

先看一下Canny算子的效果:

步骤1:用高斯滤波器平滑处理原图像

令f(x,y)表示数据(输入源数据),G(x,y)表示二维高斯函数(卷积操作数),fs(x,y)f(x,y)表示数据(输入源数据),G(x,y)表示二维高斯函数(卷积操作数),fs(x,y)为卷积平滑后的图像。

实现步骤有四个子过程:

第一步首先用二维高斯函数的一阶导数对图像进行平滑,对原图像进行高斯平滑处理,得到处理后的图像如下:

 

对原图像f(x,y) 进行高斯平滑处理,得到处理后的图像g(x,y) 如下: 

使用平滑滤波的原因从根本上来说是边缘检测算子中的导数计算。导数计算对噪声十分敏感,如果不提前使用滤波器加以改善,则在导数计算后,噪声将会被放大,使得检测出来的虚假边缘变多,不利于边缘的提取。

平滑滤波和边缘检测是一对矛盾的概念。一方面,平滑滤波能够有效的抑制噪声,而在此过程中会使得图像边缘模糊,增加了边缘定位的不确定性。另一方面,平滑滤波能够除去对边缘检测中导数运算敏感的噪声,有效的抑制了虚假边缘的产生。实际工程经验表明,高斯滤波器可以在抗噪声干扰和边缘检测精确定位之间提供一个较好的折中方案。

 

 


步骤2:用一阶偏导的有限差分进行计算梯度的幅值和方向; 

 

第二步用2×2 邻域一阶偏导的有限方差来计算平滑后的数据阵列I(x,y) 梯度幅值和梯度方向

注:其中,I是图像像素的值(亮度值)(i,j)为像素的坐标。梯度是方向导数分别在x,y轴的投影(dx(i,j)dy(i,j)).梯度的模就是方向导数的值,用勾股定理求得。已知x,y方向上的偏导, 再通过反正切, 就可以求出具体的角度(x轴的夹角), 即梯度的方向.

 

补充:求变化率时,对于一元函数,即求导;对于二元函数,求偏导。

 

数字图像处理中,用一阶有限差分近似求取灰度值的梯度值(变化率)。

(即:使差商(Δf/Δx)近似取代微商(∂f/∂x)。求灰度的变化率,分别取x和y方向上相邻像素做差,代替求取x和y(Δf/Δx)近似取代微商(∂f/∂x)。求灰度的变化率,分别取x和y方向上相邻像素做差,代替求取x和y方向一阶偏导)

 

例:计算一点x方向和yx方向和y方向的梯度幅值和方向;

 

上图中显示一段直的边缘线段放大后一部分,每个方块代表一个像素点,用一个方框强调点处边缘的幅值和方向。令灰色像素值为0,白色像素值为1。

根据x方向和y方向的卷积模板,可知,在3×3邻域中从底部一行像素值减去顶部一行的像素,得到x方向的偏导数(梯度);同样,从右边一列像素值减去左边一列的像素,得到y方向的偏导数。

x方向的梯度:gx=∂f/∂x=(0−0)+(0−1)+(0−1)=−2

y方向的梯度:gy=∂f/∂x=(1−0)+(1−0)+(0−0)= 2

由此,可以得到该点梯度的幅值和方向:

 

图像的边缘有方向和幅度两个属性,沿边缘方向像素变化平缓,垂直于边缘方向像素变化剧烈,边缘上的这种变化可以用微分算子检测出来,通常用一阶或二阶导数来检测边缘.

一阶导数可以用于检测图像中的一个点是否是边缘点(也就是判断一个点是否在斜坡上)。同样,二阶导数的符号可以用于判断一个边缘像素是否在亮的一边还是暗的一边。 

用一阶偏导的有限差分来计算梯度的幅值和方向。  

for y = 1:(Ay-1)
    for x = 1:(Ax-1)
        gx =  src(y, x) + src(y+1, x) - src(y, x+1)  - src(y+1, x+1);
        gy = -src(y, x) + src(y+1, x) - src(y, x+1) + src(y+1, x+1);
        m(y,x) = (gx^2+gy^2)^0.5 ;
        %--------------------------------
        theta(y,x) = atand(gx/gy)  ;
        tem = theta(y,x);
        %--------------------------------
        if (tem<67.5)&&(tem>22.5)
            sector(y,x) =  0;    
        elseif (tem<22.5)&&(tem>-22.5)
            sector(y,x) =  3;    
        elseif (tem<-22.5)&&(tem>-67.5)
            sector(y,x) =   2;    
        else
            sector(y,x) =   1;    
        end
        %--------------------------------        
    end    
end

其中,直角坐标系中坐标与幅值和方位角之间得关系如公式:其中,M(x,y)代表幅值,反映了图像的边缘强度;θ(x,y)代表方位角反映了梯度方向。当M(x,y)取得局部最大值时,其对应的梯度方向θ(x,y)反映了边缘方向(边缘方向与梯度方向垂直)。 

 

步骤3:对梯度幅值进行非极大值抑制; 

 

第三步,为了精确定位边缘,必须细化梯度幅值图像M(i, j) 中的屋脊带,只保留幅值局部变化最大的点,这一过程称为非极大值抑制 ,在每一点上,领域中心 x 与沿着其对应的梯度方向的两个像素相比,若中心像素为最大值,则保留,否则中心置0,这样可以抑制非极大值,保留局部梯度最大的点,以得到细化的边缘。

       仅仅得到全局的梯度并不足以确定边缘。因此,为了确定边缘,必须保留局部梯度最大的点,而且要抑制非极大值(NMS)。

图像梯度幅值矩阵中的元素值越大,说明图像中该点的梯度值越大,单着并不是能够说明该点就是边缘(这仅仅是属于图像增强的过程)。在canny算法中,非极大值抑制,是进行边缘检测的重要步骤,通俗意义上是指寻找像素点局部最大值,将非极大值点所对应的灰度值为0,这样可以剔除掉一大部分的非边缘的点。

解决这个问题的方法就需要利用梯度的方向,与邻域像素的梯度幅值进行比较,从而抑制非极大值。

 判断像素点为中心分成四个扇区,代表梯度方向近似的四个可能角度(0°, 45°, 90°,135°),将梯度角离散为圆周的四个扇区之一,以便使用3x3的窗口做抑制运算。四个扇区的标号从0-3,对应于3x3的8邻域空间四种可能组合。

对每一个像素点的梯度进行非极大值抑制,首先将判断像素梯度值M(x,y)与沿着梯度方向的2个8邻域像素的梯度M(x±1,y±1)进行比较。如果该像素点位置的梯度幅值没有沿着梯度方向的两个相邻像素的梯度值大,则说明该点的梯度值不是局部最大值需被抑制,令M(x,y)=0,即该点不是边缘点。用此方法进行抑制全局梯度值中的非极大值。

这一步骤将会排除非边缘的像素,仅仅保留一些细的线条,即就是候选的边缘。

%matlab
%-------------------------
%非极大值抑制
%------> x
%   2 1 0
%   3 X 3
%y  0 1 2
for y = 2:(Ay-1)
    for x = 2:(Ax-1)        
        if 0 == sector(y,x) %右上 - 左下
            if ( m(y,x)>m(y-1,x+1) )&&( m(y,x)>m(y+1,x-1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 1 == sector(y,x) %竖直方向
            if ( m(y,x)>m(y-1,x) )&&( m(y,x)>m(y+1,x)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 2 == sector(y,x) %左上 - 右下
            if ( m(y,x)>m(y-1,x-1) )&&( m(y,x)>m(y+1,x+1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 3 == sector(y,x) %横方向
            if ( m(y,x)>m(y,x+1) )&&( m(y,x)>m(y,x-1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        end        
    end%end for x
end%end for y

步骤4:用双阈值算法检测和连接边缘。

最后在第四步,对经过非极大值抑制的数据阵列N(i, j) 分别使用高、低2 个阈值τh τl分割图像,得到两个阈值边缘图像。

阈值τ太低和阴影à假边缘;

阈值τ取得太高à部分轮廊丢失.

选用两个阈值: 更有效的阈值方案.

具体做法

n 1 取高低两个阈值作用在幅值图;

n 2 得到两个边缘图,高阈值低阈值边缘图;

n 3 连接高阈值边缘图,出现断点时,在低阈值边缘图中的8邻点域搜寻边缘点。

n 4 取阈值,检测边缘,将低于阈值的所有值赋零值,得到图像的边缘阵列.

对非极大值抑制之后的图像与高阈值和低阈值进行判断,根据判断的情况分为以下三种情况:

  1. 如果某一像素位置的梯度幅值超过高阈值,则该像素被保留为边缘像素;
  2. 如果某一像素位置的梯度幅值小于低阈值,则该像素被排除;
  3. 如果某一像素位置的梯度幅值介于高、低阈值之间,则判断该像素8邻域空间的像素是否存在高于高阈值的像素。如果存在,则该像素将被保留。
%matlab
%---------------------------------
%双阈值检测
ratio = 2;
for y = 2:(Ay-1)
    for x = 2:(Ax-1)        
        if canny1(y,x)<lowTh %低阈值处理
            canny2(y,x) = 0;
            bin(y,x) = 0;
            continue;
        elseif canny1(y,x)>ratio*lowTh %高阈值处理
            canny2(y,x) = canny1(y,x);
            bin(y,x) = 1;
            continue;
        else %介于之间的看其8邻域有没有高于高阈值的,有则可以为边缘
            tem =[canny1(y-1,x-1), canny1(y-1,x), canny1(y-1,x+1);
                       canny1(y,x-1),    canny1(y,x),   canny1(y,x+1);
                       canny1(y+1,x-1), canny1(y+1,x), canny1(y+1,x+1)];
            temMax = max(tem);
            if temMax(1) > ratio*lowTh
                canny2(y,x) = temMax(1);
                bin(y,x) = 1;
                continue;
            else
                canny2(y,x) = 0;
                bin(y,x) = 0;
                continue;
            end
        end
    end%end for x
end%end for y
  1. 选取高阈值TH和低阈值TL,比率为2:1或3:1。(一般取TH=0.3/0.2,TL=0.1TH和低阈值TL,比率为2:1或3:1。(一般取TH=0.3/0.2,TL=0.1)
  2. 取出非极大值抑制后的图像中的最大梯度幅值,重新定义高低阈值。即:TH×Max,TL×MaxTH×Max,TL×Max。(当然可以自己给定)
  3. 将小于TL的点抛弃,赋0;将大于TH的点立即标记(这些点就是边缘点),赋1。将小于TL的点抛弃,赋0;将大于TH的点立即标记(这些点就是边缘点),赋1。
  4. 将大于TL,小于TH的点使用8连通区域确定(即:只有与TH像素连接时才会被接受,成为边缘点,赋1)将大于TL,小于TH的点使用8连通区域确定(即:只有与TH像素连接时才会被接受,成为边缘点,赋1)。

注意:双阈值做法是将候选像素点拼接成轮廓,轮廓的形成时对这些像素运用滞后性阈值。

 Eg:示例

Canny算子的检测比较优越,可以减少小模板检测中边缘中断,有利于得到较完整的边缘。

MATLAB程序:

I = imread(‘1.jpg');

imshow(I);

BW5 = edge(I,‘ canny’);

figure,imshow(BW5,[]);


咦,为什么canny会产生双边缘的结果呢, 

我们来看一下    BW5 = edge(I,‘ canny’);  的edge的这个function的解释:

不难看出,因为阈值的不同,所产生的边缘检测的结果也略有差异,则thresh阈值设置需要手动修改一下,

当thresh=0.3,会产生这样的结果 : BW5 = edge(I,‘ canny’,0.3

当thresh=0.7,会产生这样的结果 : BW5 = edge(I,‘ canny’,0.7

最后的最后,如果您觉得此篇文章对您有帮助,扫码支持或点个赞呗,家里的喵儿想吃小鱼干了~

2019-03-24 22:31:58 weixin_42683993 阅读数 719

LOG算子和CANNY算子边缘提取

  1. 边缘的含义:
    在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变、纹理结构的突变、颜色的突变等。尽管图像的边缘点产生的原因各不相同,但他们都是图形上灰度不连续或灰度急剧变化的点,图像边缘分为阶跃状、斜坡状和屋顶状。

  2. 一般图像边缘检测方法主要有如下四个步骤:
     图像滤波:传统边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数的计算对噪声很敏感,因此必须使用滤波器来改善与噪声有关的边缘检测器的性能。需要指出的是,大多数滤波器在降低噪声的同时也造成了边缘强度的损失,因此,在增强边缘和降低噪声之间需要一个折衷的选择。
     图像增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将邻域(或局部)强度值有显著变化的点突显出来。边缘增强一般是通过计算梯度的幅值来完成的。
     图像检测:在图像中有许多点的梯度幅值比较大,而这些点在特定的应用领域中并不都是边缘,所以应该用某种方法来确定哪些点是边缘点。最简单的边缘检测判断依据是梯度幅值。
     图像定位:如果某一应用场合要求确定边缘位置,则边缘的位置可在子像素分辨率上来估计,边缘的方位也可以被估计出来。

  3. LOG边缘检测算子
    在20世纪70年代,Marr理论根据神经生理学实验得出了以下结论:物体的边界是将亮度图像与其解释连接起来的最重要线索。边缘检测技术在当时是基于很小邻域的卷积,只对特殊图像效果好。这些边缘检测子的主要缺点是它们依赖物体的大小且对噪声敏感。
    基于二阶导数过零点的边缘检测技术探究了阶跃边缘对应于图像函数陡峭的变化这一事实。图像函数的一阶导数在对应于图像边缘的位置上应该取得极值,因此二阶导数在同一位置应该为0;而寻找过零点位置比起极值来得更容易和更准确。关键的问题是如何稳定地计算二阶导数,一种可能性是首先平滑图像(减小噪声),再计算二阶导数。在选择平滑滤波器时,需要满足两个标准:
     滤波器应该是平滑的且在邻域中大致上是有限带宽的,以便减少会导致函数变化的可能频率数。
     空间定位的约束要求滤波器的响应来自于图像中邻近的点。这两个标准矛盾的,但是可以通过使用高斯分布同时得到优化。在实践中,需要准确地考虑优化的含义。
    选择Laplacian算子的基础有两个基本概念。第一,算子的高斯部分会模糊图像,从而在尺寸上将结构的灰度(包括噪声)降低到远小于σ的程度,而且高斯函数能在空间和频率两个域平滑图像,因而在原图像中引入不存在的人为干扰(如振铃)的可能性很小。第二,拉普拉斯有各向同性(旋转不变)的重要优点,符合人的视觉系统特性,而且对任何模板方向的灰度变化有相等的响应,从而避免了使用多个模板去计算图像中任何点处的最强响应。
    LOG算法步骤如下:
     取样得到的高斯低通滤波器对输入图像滤波。
     计算第一步得到图像的拉普拉斯。
     找到步骤2所得图像的零交叉。

  4. Canny边缘检测算子介绍
    1986年,JOHN CANNY 提出一个很好的边缘检测算法,被称为Canny边缘检测器,
    Canny方法基于三个基本的目标:
     检测标准: 低错误率。所有的边缘都应该被找到,并且没有假边缘。
     行为标准: 边缘点应被很好的定位。测到的边缘点与真实边缘的中心之间距离应该最小。
     单响应标准: 单一的边缘点效应。对于真实的边缘点,检测器应该仅仅返回一个点。也就是真实边缘的局部最大数应该是最小的。意味着仅存在单一边缘点的位置,检测器不应指出多个边缘像素。
    Canny边缘检测算法由一下基本步骤组成:
     用一个高斯滤波器平滑输入图像。
     计算梯度幅值图像和角度图像。
     对梯度幅值图像应用非最大抑制。
     用双阈值处理和连接分析来检测并连接边缘。

  5. 比较分析
     相同尺度下的LOG算子总是能比Canny算子检测出更多的细节,Canny算子能对真正比较显著地边缘给出检测。LOG算子容易受尺度的影响,不同尺度下的边缘点要用不同尺度的LOG算子检测,Canny 算子受尺度的影响不太明显,不同尺度下,边缘点的位置都有偏差,但几乎相同;
     从对噪声的敏感程度来看,LOG边缘检测子是采用二阶导数过零点的检测方法,故对噪声更敏感一些,因此从抑制噪声方面来讲,Canny边缘检测子不容易受到噪声的干扰,而相同尺度下LOG算子却容易受到噪声的干扰,抑制噪声的能力要弱一些。LOG算子对噪声的抑制能力随着尺度的增加而增加,相同尺度下的Canny算子比LOG算子的抗噪声能力强,而LOG算子比Canny算子的边缘点准确;
     对于弱边缘,由于Canny边缘检测子采用两种不同的阈值分别检测强边缘和弱边缘,并且当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中,故而Canny算子更能检测出真正的弱边缘,但是Canny边缘检测子检测出的边缘的位置会有一定范围的误差,
     对于假边缘,LOG边缘检测子相对比较容易受到噪声干扰,会检测出更多的细节,也容易检测出一些由于噪声引起的假边缘,但是LOG边缘检测子对边缘位置的检测还是很准确的。

  6. 参考文献
    [1] D.Marr and E. Hildreth, Theory of Edge Detection, Proc. R. Soc. Lond. B207:187-217.
    [2] John Canny, A Computational Approach to Edge Detection, IEEE Trans. PAMI, 8(6):679-698.
    [3] James J. Clark, Authenticating Edges Produced by Zero-crossing Algorithms, IEEE T. PAMI, 11(1), 1989, pp.43-57.

附录:实验代码

code:独立加性高斯白噪声

function [distImg,endtImg] = add_noise(origImg,u)
origImg = im2double(origImg);
distImg = imnoise(origImg, 'gaussian', 0, u);
endtImg = distImg.*255;
end

code:对图像进行高斯滤波

function g=my_gaussian(src,n,k)  
n1=(n+1)/2;                                         
[m,l]=size(src);  
b=zeros(n,n);                                      
I=zeros(m,l);  
g=zeros(m,l);  
img=zeros(m,l);  
[Ay, Ax ,dim ] = size(src);
if dim>1
    src = rgb2gray(src);
end
for i=1:n  
    for j=1:n  
          b(i,j)=(exp(-((i-n1)^2 +(j-n1)^2)/(2*k)))/(2*pi*k);  
    end  
end  
b = b/sum(b(:));        
I=double(src);  
img=conv2(I,b,'same');              
g=uint8(img);    
end

code:LOG算子实现图像处理以及结果展示

function [thrr] =log_img(noise,n,k,thr)
[filename, pathname] = uigetfile({'*.jpg'; '*.bmp'; '*.gif'}, '选择图片');
if filename == 0
    return;
end
imgsrc = imread([pathname, filename]);
[y, x, dim] = size(imgsrc);  %转换为灰度图像
if dim>1
    imgsrc = rgb2gray(imgsrc);
end
if (x~=256 && y~=256)  %转换为8bit 256*256图像
    imgsrc = im2uint8(imgsrc);
    imgsrc=imresize(imgsrc,[256,256]);
end
[showing_noise, img_noise]= add_noise(imgsrc,noise);
img= my_gaussian(img_noise,n,k); 
[img_log,thrr]=edge(img,'log',thr);
figure(1)    
        imshow(imgsrc);%原图
figure(2)  
        imshow(showing_noise);
figure(3)  
        imshow(img);%高斯滤波后
figure(4)  
        imshow(img_log);
end  

code:CANNY算子实现

function [ m, theta, sector, canny1,  canny2, bin] = canny_step( src,  lowTh)
[Ay, Ax, dim ] = size(src);
if dim>1
    src = rgb2gray(src);
end
src = double(src);
m = zeros(Ay, Ax); 
theta = zeros(Ay, Ax);
sector = zeros(Ay, Ax);
canny1 = zeros(Ay, Ax);
canny2 = zeros(Ay, Ax);
bin = zeros(Ay, Ax);
 
%梯度计算
for y = 1:(Ay-1)
    for x = 1:(Ax-1)
        gx =  src(y, x) + src(y+1, x) - src(y, x+1)  - src(y+1, x+1);
        gy = -src(y, x) + src(y+1, x) - src(y, x+1) + src(y+1, x+1);
        m(y,x) = (gx^2+gy^2)^0.5 ;
        theta(y,x) = atand(gx/gy)  ;
        tem = theta(y,x); 
        if (tem<67.5)&&(tem>22.5)
            sector(y,x) =  0;    
        elseif (tem<22.5)&&(tem>-22.5)
            sector(y,x) =  3;    
        elseif (tem<-22.5)&&(tem>-67.5)
            sector(y,x) =   2;    
        else
            sector(y,x) =   1;    
        end
            
    end    
end

%非极大值抑制
for y = 2:(Ay-1)
    for x = 2:(Ax-1)        
        if 0 == sector(y,x) %右上 - 左下
            if ( m(y,x)>m(y-1,x+1) )&&( m(y,x)>m(y+1,x-1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 1 == sector(y,x) %竖直方向
            if ( m(y,x)>m(y-1,x) )&&( m(y,x)>m(y+1,x)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 2 == sector(y,x) %左上 - 右下
            if ( m(y,x)>m(y-1,x-1) )&&( m(y,x)>m(y+1,x+1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        elseif 3 == sector(y,x) %横方向
            if ( m(y,x)>m(y,x+1) )&&( m(y,x)>m(y,x-1)  )
                canny1(y,x) = m(y,x);
            else
                canny1(y,x) = 0;
            end
        end        
    end
end

%双阈值检测
ratio = 2;
for y = 2:(Ay-1)
    for x = 2:(Ax-1)        
        if canny1(y,x)<lowTh 
            canny2(y,x) = 0;
            bin(y,x) = 0;
            continue;
        elseif canny1(y,x)>ratio*lowTh 
            canny2(y,x) = canny1(y,x);
            bin(y,x) = 1;
            continue;
        else 
            tem =[canny1(y-1,x-1), canny1(y-1,x), canny1(y-1,x+1);
                       canny1(y,x-1),    canny1(y,x),   canny1(y,x+1);
                       canny1(y+1,x-1), canny1(y+1,x), canny1(y+1,x+1)];
            temMax = max(tem);
            if temMax(1) > ratio*lowTh
                canny2(y,x) = temMax(1);
                bin(y,x) = 1;
                continue;
            else
                canny2(y,x) = 0;
                bin(y,x) = 0;
                continue;
            end
        end
    end
end
end

code:CANNY图像处理及结果展示

function  canny_plotimg(noise,n,thr,k)
[filename, pathname] = uigetfile({'*.jpg'; '*.bmp'; '*.gif'}, '选择图片');
if filename == 0
    return;
end
imgsrc = imread([pathname, filename]);
[y, x, dim] = size(imgsrc);
if dim>1
    imgsrc = rgb2gray(imgsrc);
end
if (x~=256 && y~=256)   %转换为8bit 256*256图像
    imgsrc = im2uint8(imgsrc);
    imgsrc=imresize(imgsrc,[256,256]);
end 
[showing_noise, img_noise]= add_noise(imgsrc,noise);
img= my_gaussian(img_noise,n,k); 
[m theta sector canny1  canny2 bin] = canny1step(img, thr);
figure(1)    
        imshow(imgsrc);%原图
figure(2)  
        imshow(showing_noise);
figure(3)  
        imshow(img);%高斯滤波后
figure(4)  
        imshow(uint8(m));%导数
figure(5)  
        imshow(uint8(canny1));%非极大值抑制
figure(6)  
        imshow(uint8(canny2));%双阈值
没有更多推荐了,返回首页