永兴的笔记-OpenCV-9 图像轮廓

在这里插入图片描述

一、什么是图像轮廓?

1、轮廓的基本概念:
构成图形或物体的外缘的线条。
2、轮廓检测:
轮廓检测指在包含目标和背景的数字图像中,忽略背景和目标内部的纹理以及噪声干扰的影响,采用一定的技术和方法来实现目标轮廓提取的过程。它是目标检测、形状分析、目标识别和目标跟踪等技术的重要基础。
3、图像中的信号:
图像中的低频信号和高频信号也叫做低频分量和高频分量。 简单一点说,图像中的高频分量,指的是图像强度(亮度/灰度)变化剧烈的地方,也就是我们常说的边缘(轮廓);图像中的低频分量,指的是图像强度(亮度/灰度)变换平缓的地方,也就是大片色块的地方。 人眼对图像中的高频信号更为敏感,举个例子,在一张白纸上有一行字,那么我们肯定直接聚焦在文字上,而不会太在意白纸本身,这里文字就是高频信号,而白纸就是低频信号。
4、边缘和轮廓的区别:
边缘检测是检测图像的边缘 也就是图像差异比较大的地方
轮廓提取是提取出你想要得到的轮廓 轮廓可能是边缘的一部分
5、边缘和边界的区别:
在图像合成中单一物体的轮廓叫做边缘,画布的大小叫边界.

二、图像轮廓的作用:

1、轮廓检测通常过程:
求取图像(灰度或彩色)中物体轮廓的过程主要有四个步骤。

  • 首先对输入图像做预处理,通用的方法是采用较小的二维高斯模板做平滑滤波处理,去除图像噪声。(采用小尺度的模板是为了保证后续轮廓定位的准确性,因为大尺度平滑往往会导致平滑过渡,从而模糊边缘,大大影响后续的边缘检测。)
  • 其次对平滑后的图像做边缘检测处理,得到初步的边缘响应图像。(其中通常会涉及到亮度、颜色等可以区分物体与背景的可用梯度特征信息。)
  • 然后再对边缘响应做进一步处理,得到更好的边缘响应图像。这个过程通常会涉及到判据,即对轮廓点和非轮廓点做出不同处理或用相同的程式因作用结果的不同而达到区分轮廓点和非轮廓点的效果,从而得到可以作为轮廓的边缘图像。(若是此步骤之前得到的轮廓响应非常好时,该步骤往往是不用再考虑的。然而在实际应用过程中,上一步骤得到的结果往往是不尽人意的。)
    因此,此过程往往起着至关重要的作用,最后对轮廓进行精确定位处理,这个过程通常又分成两个过程。
    • 第一步先对边缘响应图像做细化处理,得到单像素边缘图像。这个过程普遍采用的是非最大值抑制方法(局部极大搜索)。非最大值抑制可以非常有效地细化梯度幅值图像中的屋脊带,从而只保留局部变化最大的点。本文的研究均采用此方法做细化处理。
    • 第二步为在此基础上做基于滞后门限的二值化处理,滞后门限利用递归跟踪算法可以保证最后的轮廓图像是连续的。这一个过程往往在与标准轮廓(比如图像数据库中人为勾画的轮廓)做比较时才考虑,也就是说一个完整的轮廓检测算法往往是不包括该过程的。获取轮廓信息的另一种通用方法就是先对图像做分割,图像分割处理好后,直接将分割区域的边界作为轮廓。该方法最终的结果直接依赖于图像分割的效果,因此实际中多归于分割问题。

2、轮廓检测的分类(了解)

  • 静态图像轮廓检测编
    早期轮廓检测的方法通过局部的测量计算来量化一个给定图像位置的边界是否存在。Roberts算子,Sobel算子和Prewitt算子通过灰度图像和局部导数滤波器卷积进行边缘检测。Mary和Hildreth使用拉普拉斯算子的零交叉高斯算子。丰富的特征描述子可以通过对不同尺度的图像和多方向的滤波器的响应获得。

    • 目前,很多对于静态图像的目标轮廓提取,在检测过程中主要通过外观线索判断像素是否属于目标的轮廓,根据图像局部特征并基于学习策略进行轮廓判断。Arbelaez等利用一种叫做“双半圆盘”算子的梯度算子计算亮度、色彩、纹理多种外观线索的方向梯度特征,通过梯度上升得到各种外观线索的优化组合,生成的局部边缘检测器能有效去除目标内部纹理的虚假边缘。除此以外,他们还建立了一个具有轮廓和分割手工标记的图像轮廓和分割数据集作为自然场景轮廓和分割方法的统一标准。Dollar等以亮度、色彩线索为判定标准利用集成分类器对图像块分类,获取到图像块内的结构边缘信息,提升了处理效率。
      同时,深度线索作为特殊的外观线索,可以辅助判断目标轮廓,Kinect深度相机得到的场景深度图像对光照变化和背景中颜色相近的物体的干扰具有鲁棒性。Leordeanu等结合图像的像素级表达和区域块表达,将不同类型边缘结构的局部定位应用于深度图像。徐玉华等采用活动轮廓对人体目标建模,提出一种新的水平集框架下自适应融合RGB-D图像的颜色和深度信息的人体轮廓跟踪方法。
    • 静态图像轮廓检测对外观相似的目标和背景不具有识别力,背景的局部边缘干扰会导致目标的伪轮廓。因此越来越多的轮廓检测研究基于运动视频获取运动信息来区分外观一致的目标和背景,并激励运动目标的强边缘。
  • 视频轮廓检测:

    • 在运动视频中,运动线索是判断运动目标轮廓的关键。相关研究己实验表明了运动线索在轮廓检测、目标识别等视觉任务中的重要性。格式塔(Gestalt)原则中的“common fate"理论,指出相似运动的点被认为是连贯一致的整体,运动线索作为几乎所有视觉类别所共有的信息,在生物学视觉系统中也一直强调其重要性。相比于亮度、色彩和立体视差这些外观线索,运动线索更有助于区分不同的运动目标。在增加了额外时间维度的视频数据中,相机的运动或场景的变化使得我们可以挖掘运动目标边界与背景间的相对运动信息并用于推断目标轮廓,即运动轮廓。
    • 视频轮廓检测中的运动线索主要由数据驱动得到,分为两大类方法。第一类利用光流法获取运动线索。光流法基于时空梯度模型计算物体的亮度随时间和空间的变化场。光流计算像素点的瞬时变化速率,其原理是假设像素点从一个位置移动到其他位置,其灰度值保持不变,因此根据光流估计可以计算出某一像素点运动瞬时变化速率。Stein等在超像素图上建立区域光流场,结合外观特征,利用adaboost学习方法建立轮廓检测的总体框架,并且建立了具有轮廓手工标记的视频轮廓数据库用于训练学习。He等在建立光流场后基于SVD(Singular ValueDecomposition,奇异值分解)因子分解方法建立伪深度图,将运动线索转化为深度线索用于轮廓检测。
      • 光流法的优点在于无需对场景的背景建模,就能够检测到运动目标,因此在动态场景中经常利用光流法来检测运动目标。然而,光流法基于亮度守恒假设条件,在复杂自然场景中,由于遮挡性、多光源、透明性和噪声等原因,使得光流的可靠性估计较差,获取到的运动信息误差较大。
      • 第二类利用帧差法获取运动线索。帧差法也是运动目标检测中常见的方法之一。其基本原理非常简单,先计算前后两帧相减的像素差,利用固定闭值进行二值化处理,得到前景运动目标。如果目标没有运动,那么两帧相减的像素差为零;若目标有明显的运动,那么两帧相减的像素差大于闭值,二值化处理可得到视频帧中的运动目标位置。Sundberg等利用关键帧及其前后帧的帧间差异作为运动线索之一,同时依据Arbelaez等的静态轮廓检测结果作为初始分割图建立光流场,通过支持向量机(Support Vector Machine, SVM)学习特征权重,线性加权各个特征得到轮廓概率值。
      • 由于帧差法利用相邻帧相减,具有很强的适应性,能够快速适应环境的变化,因此能得到较好的效果。但是正是由于这个原因,目标静止或运动幅度很小时前后两帧变化不大,从而导致无法检测出来;而且当目标表面单一时,前后帧运动目标区域大部分像素值相似,从而会产生空洞现象。此外,帧差法主要是依据关键帧及其前后帧的帧间差异建模,仅获取了三帧之间的运动信息,缺少三帧之外的运动信息,容易造成部分运动信息的缺失。

三、OpenCV的图像轮廓检测:

一般过程:
灰度模式 – 高斯平滑 – 边缘检测 – 二值化 – 轮廓检测
1、图像轮廓的查找:
dst,countours, hierarchy = cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None)

  • 参数 :
    • image: 原图像
    • mode:
mode 详解
cv2.RETR_EXTERNAL 只检测外轮廓
cv2.RETR_LIST 检测的轮廓不建立等级关系
cv2.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息
cv2.RETR_TREE 建立一个等级树结构的轮廓
    • method :
method 描述
cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2), abs(y2-y1))<=1。
cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个 矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1 和 cv2.CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法
  • 返回值 :
    • dst : 返回的图像
    • countours : 使用teh-Chinl chain 近似算法。
    • hieratchy : 每条轮廓对应的属性
import cv2
img = cv2.imread("first.jpg",0) #以灰度图像读取图像
GauImg = cv2.GaussianBlur(img,(3,3),1) #高斯模糊
Canny_GauImg = cv2.Canny(GauImg,100,200) #边缘检测
thresh,thdDst= cv2.threshold(Canny_GauImg,172,255,cv2.THRESH_BINARY) #二值化图像
binary , contours , hierarchu = cv2.findContours(thdDst,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cv2.imshow("img",img)
cv2.imshow("binart",binary)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
2、轮廓绘制:
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

  • 参数:
    • image: 原图像
    • contours: 绘制的轮廓
    • contourldx: 指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。
    • color: BGR颜色
import cv2
BGRimg = cv2.imread("first.jpg") #以灰度图像读取图像
GRAYimg = cv2.cvtColor(BGRimg,cv2.COLOR_BGR2GRAY) #颜色空间转化
GauImg = cv2.GaussianBlur(GRAYimg,(3,3),1) #高斯模糊
Canny_GauImg = cv2.Canny(GauImg,100,200) #边缘检测
thresh,thdDst= cv2.threshold(Canny_GauImg,172,255,cv2.THRESH_BINARY) #二值化
binary , contours , hierarchu = cv2.findContours(thdDst,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #检测轮廓
contoursImg = cv2.drawContours(BGRimg,contours,-1,(255,0,0)) #绘制轮廓
cv2.imshow("img",BGRimg)
cv2.imshow("binart",binary)
cv2.imshow("contours",contoursImg)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

3、轮廓的特征:

练习题 9:
描绘出喜欢人物头部的轮廓,并绘制在原图上。

评论出你的答案

发布了45 篇原创文章 · 获赞 28 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_43505377/article/details/103820457
今日推荐