zoukankan      html  css  js  c++  java
  • OpenCVPython系列之轮廓特征初阶

    在上一个教程中,我们讲到了轮廓的查找以及绘制,但是只掌握这些还是远远不够的,我们经常需要一些更加复杂的操作,本次教程我们将谈谈关于轮廓的特征。

    图像的矩

    图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(数据描述量)来描述整个图像,这组数据月简单越有代表性越好。良好的特征不受光线、噪点、几何形变的干扰,图像识别技术的发展中,不断有新的描述图像特征提出,而图像不变矩就是其中一个。

    从图像中计算出来的矩通常描述了图像不同种类的几何特征如:大小、灰度、方向、形状等,图像矩广泛应用于模式识别、目标分类、目标识别与防伪估计、图像编码与重构等领域。

    严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设 xx 为随机变量,C为常数,则量E[(x−c)^k]称为X关于C点的k阶矩。比较重要的两种情况如下:

    1.c=0,这时a_k=E(X^k)称为X的k阶原点矩;

    2.c=E(X),这时μ_k=E[(X−EX)^k]称为X的k阶中心矩

    一阶原点矩就是期望,一阶中心矩μ_1=0,二阶中心矩μ_2就是X的方差Var(X)。在统计学上,高于4阶的矩极少使用,μ_3可以去衡量分布是否有偏,μ_4可以衡量分布(密度)在均值拘谨的陡峭程度。

    针对一幅图像,我们把像素的坐标看成是一个二维随机变量(X, Y),那么一副灰度图可以用二维灰度图密度函数来表示,因此可以用矩来描述灰度图像的特征。

    OpenCV中提供的API用来计算中心矩和Hu矩,下面主要介绍Hu的原理。

    一幅M×N的数字图像f(i,j),其p+q阶几何矩m_pq和中心矩μ_pq为:

    image.png

    image.png

    其中f(i,j)为图像在坐标点(i,j)处的灰度值。

    若将m_00看做图像的灰度质量,则(i¯,j¯)为图像的质心坐标,那么难中心矩μ_pq反应的是图像灰度相对于其灰度质心的分布情况,可以用几何矩来表示中心矩0~3阶中心矩与几何矩的关系如下:

    image.png

    为了消除图像比例变化带来的影响,定义规格化中心矩如下:

    image.png

    利用二阶和三阶规格中心矩可以导出下面7个不变矩组(Φ1 Φ7),它们在图像平移、旋转和比例变化时保持不变:

    image.png

    OpenCV中提供了cv2.moments()来计算图像中的中心矩(最高到三阶)。同时配合函数contourArea函数计算轮廓面积和arcLength来计算轮廓或曲线长度。

    我们来看函数原型:

    cv2.moments (InputArray array,bool binaryImage = false)  

    array:输入数组,可以是光栅图像(单通道,8-bit或浮点型二维数组),或者是一个二维数组,二维数组类型为Point或Point2f

    binaryImage:默认值是false,如果为true,则所有非零的像素都会按值1对待,也

    就是说相当于对图像进行了二值化处理,阈值为1,此参数仅对图像有效。

    来看代码:

    import cv2
    import numpy as np
    
    img = cv2.imread("pie.png")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(img,contour,-1,(0,0,255),2)
    cv2.imshow("res",img)
    cnt = contour[0]
    M = cv2.moments(cnt)
    print(M)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    image.png

    这是我们得到的结果:

    image.png

    这是我们得出的所有的矩,现在我们对代码进行改进,计算出对象的重心(质心):

    image.png

    代码:

    import cv2
    import numpy as np
    
    img = cv2.imread("pie.png")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(img,contour,-1,(0,0,255),2)
    cv2.imshow("res",img)
    cnt = contour[0]
    M = cv2.moments(cnt)
    cx=int(M['m10']/M['m00'])
    cy=int(M['m01']/M['m00'])
    print(cx,cy)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    image.png

    可以得出重心坐标。

    轮廓的面积

    我们可以使用OpenCV中的函数:

    cv2.contourArea  (   InputArray  contour,bool    oriented = false )  

    contour:是一个向量,二维点、

    oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的形式返回。

    我们来看代码:

    import cv2
    import numpy as np
    
    img = cv2.imread("pie.png")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(img,contour,-1,(0,0,255),2)
    cv2.imshow("res",img)
    cnt = contour[0]
    M = cv2.moments(cnt)
    area=cv2.contourArea(cnt)
    print(area)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    image.png

    可以看到输出的面积:

    image.png

    事实上,我们也可以使用刚刚讲述的图像的矩来完成,图像的面积等于它的0阶矩:M['m00']

    import cv2
    import numpy as np
    
    img = cv2.imread("pie.png")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(img,contour,-1,(0,0,255),2)
    cv2.imshow("res",img)
    cnt = contour[0]
    M = cv2.moments(cnt)
    area = int(M['m00'])
    print(area)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    image.png

    可以看到,效果是一样的。

    轮廓的周长

    函数原型:

    retval   =     cv.arcLength(     curve, closed      )

    第一个参数指代的是输入的二维点的向量;

    第二个参数代表曲线是否闭合。

    来看代码:

    import cv2
    import numpy as np
    
    img = cv2.imread("pie.png")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0]
    cv2.drawContours(img,contour,-1,(0,0,255),2)
    cv2.imshow("res",img)
    cnt = contour[0]
    C= cv2.arcLength(cnt,True)
    print(C)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    image.png

    image.png

    可以直接计算轮廓的周长。

    本次教程我们简介轮廓的一些基本特征,但是轮廓仍然有很多的特征,我们将在下次细述。

  • 相关阅读:
    Python安装mysql-python错误提示python setup.py egg_info
    修改svn默认端口
    python pip下载速度慢的解决方法
    使用mysql自带工具mysqldump进行全库备份以及source命令恢复数据库
    pycharm 中自动补全代码提示前符号 p,m ,c,v, f 是什么意思
    Mysql按条件计数的几种方法
    linux shell 之if-------用if做判断
    在Centos7 上安装SVN
    Nginx配置文件详细说明
    设置文件上传的最大大小
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/15656445.html
Copyright © 2011-2022 走看看