(penCV+Python)轮廓特征初阶与中阶.docx
图像的矩图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数 据(数据描述量)来描述整个图像,这组数据越简单越有代表性越好。良好的特征 不受光线、噪点、几何形变的干扰,图像识别技术的发展中,不断有新的描述图 像特征提出,而图像不变矩就是其中一个。从图像中计算出来的矩通常描述了图像不同种类的几何特征如:大小、灰度、 方向、形状等,图像矩广泛应用于模式识别、目标分类、目标识别与防伪估计、 图像编码与重构等领域。严格来讲矩是概率与统计中的一个概念,是随机变量的一种数字特征。设 XX为随机变量,C为常数,则量E(x-C)八k称为X关于C点的k阶矩。比较重 要的两种情况如下:c=0,这时a_k=E(XAk)称为X的k阶原点矩。C=E(X),这时.k=E(X-EX)Ak称为X的k阶中心矩。一阶原点矩就是期望,一阶中心矩J=0,二阶中心矩-2就是X的方差 Var(X)o在统计学上,高于4阶的矩极少使出,,3可以去衡量分布是否有偏,-4 可以衡量分布(密度)在均值附近的陡峭程度。针对一幅图像,我们把像素的坐标看成是一个二维随机变量(X,Y),那么一 副灰度图可以用二维灰度图密度函数来表示,因此可以用矩来描述灰度图像的特 征。OpenCV中提供的API用来计算中心矩和Hu矩,下面主要介绍Hu的原理。一幅M×N的数字图像f(i,j),其p+q阶几何矩m_pq和中心矩-pq为:M NZn内=EE巧W)iljlM NMpg = ££ 一 OPu-t 1 J 1i = hooo, j = rQ1m其中f(i,j)为图像在坐标点(i,j)处的灰度值。若将m_00看做图像的灰度质量,贝加-)为图像的质心坐标,那么中心矩 jq反应的是图像灰度相对于其灰度质心的分布情况,可以用几何矩来表示中 心矩03阶中心矩与几何矩的关系如下:"00 = ETI l(i- i)0(j - j)0(i,j) = mool = l %(" i)1(j - j)o(ij) = OMl = P %(一 <)0(j - I)V(W = OMil = 1 fl(i- i)1(j - j)7(i) = mil - tm10"20 =i)2(j-j)0(J)=m20 yn0102 = Efi , l(i i)0(j - 3)2f(iJ) = tq2- ym01"30 =l(i-i)3(j-D(VRJ)=m30 - 2xm2o + 2i2m10l2 = 7l(i- i)1(j 一 j)2(i) = m12 - 2jn11 - xm02 + 22m10 ,21 = 1(i- i)2(j - j)lf(ij) = m21 2xm11 - 9m20 + c2mm 3 = ETl j t(i- i)0(j J)3f(iJ) = m03- 2ym02 + 2y2m01为了消除图像比例变化带来的影响,定义规格化中心矩如下:p + q2,P + g = 2,3,.)利用二阶和三阶规格中心矩可以导出下面7个不变矩组(17),它们在图 像平移、旋转和比例变化时保持不变:42 = (%O-%2产+ 4喑13 = (7te 一 SlJi2)2 + 3(l _ 加3产4 = Oho + )2 + (%1 + )25 = (TbO + 372)(小O + 7h2)(rho + 7Zia)2 3( + )2÷ (3物)(¾ ÷ )3(%o + V12)2 (rh + )2,=Ofeo rto2)(%0 + 7Zn)2 (rfe + )2J + 4小1(小O + )(te + )小7 = (3%1 %3)(%0 + 力2)(如 + 小2)2 - 3(%1 + )2÷÷ (3小2 %o)( + )3(%o + rh2)2 ( + )2OpenCV中提供了 cv2.moments()来计算图像中的中心矩(最高到三阶)。同时 配合函数ContourArea函数计算轮廓面积和arcLength来计算轮廓或曲线长度。我们来看函数原型:cv2.moments (InputArray array, bool binary Image = false)array:输入数组,可以是光栅图像(单通道,8-bit或浮点型二维数组),或者 是一个二维数组,二维数组类型为Point或Point2fobinary Image:默认值是false,如果为true,则所有非零的像素都会按值1 对待,也就是说相当于对图像进行了二值化处理,阈值为1,此参数仅对图像有 效。来看代码:import cv2import numpy as npimg = cv2.imread(pie.png)gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)contour =cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)0cv2.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.destroy AllWindowsO这是我们得到的结果:D:Anaconda3envspytorchpython.exe D:/WII/代码势习/代转级习/labview.py,m,: 55865.8, ,al6,: 14478499.瓦 )l,: 12962615.5, ,n2,: 417898496.5, ,B11,: 335765Process finished with exit code 这是我们得出的所有的矩,现在我们对代码进行改进,计算出对象的重心(质 心): _ MIo _ Moi砧,代码:import cv2import numpy as npimg = c v2. imread( pie .png, )gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)contour =cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)0cv2.drawContours(img,contour,-1,(0,0,255),2)cv2.imshow(res,img)cnt =contour 0 M =cv2.moments(cnt)cx=int(M,ml01M,m00,)cy=int(M,m0M,m00,)print(cx, cy)cv2.waitKey(0)cv2.destroy AllWindowsOD: Anaconda3envspytorchpython.exe D:/合集/代码缥习/代码练习八abvi”.py 259 232Process finished with exit code 可以得出重心坐标。轮廓的面积我们可以使用OPenCV中的函数:cv2.contourArea (InputArray contour,bool oriented = false)contour:是一个向量,二维点。oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个 带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可 以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的 形式返回。我们来看代码:import cv2import numpy as npimg = cv2.imread(pie.png)gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)contour =cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)0cv2.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.destr oyAHWindows()可以看到输出的面积:D:Anaconda3envspytorchpython. e×e D: /合集/代码练习/代码拣习labvie” .py 55865.8Process finished with exit code 事实上,我们也可以使用刚刚讲述的图像的矩来完成,图像的面积等于它的0 阶矩:M,m00,oimport cv2import numpy as npimg = cv2.imread(pie.png)gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)contour =cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)0cv2.drawContours(img,contour,-1,(0,0,255),2)cv2.imshow(res,img)cnt =contour 0 M = cv2.moments(cnt)area =int(M,m001)print(area)cv2.waitKey(0)cv2.destroy AllWindowsOD: Anaconda3evspytorchpytho.e×e D"合集/代码练习/代码练习八abview.py 55865Process finished with exit code 可以看到,效果是一样的。轮廓的周长函数原型:retval = cv.arcLength(curve, closed)第一个参数指代的是输入的二维点的向量。第二个参数代表曲线是否闭合。来看代码:import cv2import numpy as npimg = cv2.imread(pie.png)gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)contour =cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)0cv2.drawContours(img,contour,-1,(0,0,255),2)cv2.imshow(res,img)cnt = contour0C=cv2.arcLength(cnt,True)print(C)cv2.waitKey(0)cv2.destroy AllWindowsO可以直接计算轮廓的周长。OpenCV+Python 轮廓特征中阶本次我们将讨论OPenCV中图像轮廓的另一些特征,它们将非常有用。边界矩形有两类边界矩形。A直边界矩形一个直矩形(就是没有旋转的矩形