【OpenCV】不变矩

不变矩

图像矩

在计算图像矩是需要将图像转化为单通道的灰度图,或者进行二值化处理,即目标对象设为1,背景设为0。

图像的矩是将图像像素灰度值进行加权平均,从而反映图像中像素值分布的一种算子。

零阶矩

最简单的图像矩是以1的权重计算的像素灰度值之和,即:
m 00 = ∑ x ∑ y f ( x , y ) \begin{equation} m_{00}=\sum_x \sum_y f(x,y) \end{equation} m00=x∑y∑f(x,y)

如果要计算的是二值化图片中的一个白色对象,比如下图中的字母"S":

通过公式可以知道,零阶矩计算的就是这个字母的像素点的个数和。因此可以推出,零阶矩只能反映图像中对象的面积信息。

至于为什么这个图像矩称为零阶矩,看完下面的空间矩就可知。

空间矩

如果在零阶矩的基础上再加上像素点的位置信息,即行数和列数,则可得到图像的空间矩:
m p q = ∑ x ∑ y x p y q f ( x , y ) \begin{equation} m_{pq}=\sum_x \sum_y x^py^qf(x,y) \end{equation} mpq=x∑y∑xpyqf(x,y)

  • 其中 ( p + q ) (p+q) (p+q)称为矩的
  • 当 p , q = 0 p,q=0 p,q=0时,就可得到 ( 1 ) (1) (1)式中的零阶矩,这也是它为什么被称为零阶矩的原因。

空间矩又称原始矩。由于加入了行数和列数,所以相比于零阶矩,它除了可以反映对象的面积信息,还可以反映图像相对于原点(0行,0列)的位置信息,即离原点越远的灰度值,权重越高。

质心

通过 ( 2 ) (2) (2)式可以计算对象的两个一阶矩:
m 10 = ∑ x ∑ y x f ( x , y ) m_{10}=\sum_x \sum_yxf(x,y) m10=x∑y∑xf(x,y) m 01 = ∑ x ∑ y y f ( x , y ) m_{01}=\sum_x \sum_yyf(x,y) m01=x∑y∑yf(x,y)

这两个一阶矩分别代表了对象中的灰度值在行和列上的分布情况,将它们分别除以零阶矩,就可以得到行和列上的中心位置:
x ˉ = m 10 m 00 , y ˉ = m 01 m 00 \={x}=\frac{m_{10}}{m_{00}}, \={y}=\frac{m_{01}}{m_{00}} xˉ=m00m10,yˉ=m00m01

上式就是对象的质心坐标,代表了对象的中心位置。

中心矩

空间矩包含了对象相对于图像原点的位置信息;如果换成对象相对于其质心的位置信息就变成了中心矩:
μ p q = ∑ x ∑ x ( x − x ˉ ) p ( y − y ˉ ) q f ( x , y ) \begin{equation} \mu_{pq}=\sum_x \sum_x (x-\={x})^p(y-\={y})^qf(x,y) \end{equation} μpq=x∑x∑(x−xˉ)p(y−yˉ)qf(x,y)

由于是相对于对象自身质心的分布,所以中心矩对于对象的平移不敏感,即具有平移不变性

无论对象处于图像中的什么位置,只要形状不变,中心矩就不变。

归一化中心矩

在中心矩的基础上,再将其进行归一化,就得到了归一化的中心矩:
η p q = μ p q ( μ 00 ) γ , γ = ( p + q 2 + 1 ) \eta_{pq}=\frac{\mu_{pq}}{(\mu_{00})^\gamma}, \gamma=\left(\frac{p+q}{2}+1\right) ηpq=(μ00)γμpq,γ=(2p+q+1)

由于经过了归一化,所以该矩对于图像的缩放也不敏感了,即又具有尺度不变性

无论对象被缩放到什么尺寸,只要形状不变,归一化中心矩就不变。

Hu矩

利用归一化后的2阶或3阶中心矩可以构造出7个不变矩(Hu矩):
h u [ 0 ] = η 20 + η 02 h u [ 1 ] = ( η 20 − η 02 ) 2 + 4 η 11 3 h u [ 2 ] = ( η 30 − 3 η 12 ) 2 + ( 3 η 21 − η 03 ) 2 h u [ 3 ] = ( η 30 + η 12 ) 2 + ( η 21 + η 03 ) 2 h u [ 4 ] = ( η 30 − 3 η 12 ) ( η 30 + η 12 ) [ ( η 30 + η 12 ) 2 − 3 ( η 21 + η 03 ) 2 ] + ( 3 η 21 − η 03 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] h u [ 5 ] = ( η 20 − η 02 ) [ ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] + 4 η 11 ( η 30 + η 12 ) ( η 21 + η 03 ) h u [ 6 ] = ( 3 η 21 − η 03 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] − ( η 30 − 3 η 12 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 − ( η 21 + η 03 ) 2 ] {\small \begin{align*} hu[0] & =\eta_{20}+\eta_{02} \\ hu[1] & =(\eta_{20}-\eta_{02})^2+4\eta_{11}^3 \\ hu[2] & =(\eta_{30}-3\eta_{12})^2+(3\eta_{21}-\eta_{03})^2 \\ hu[3] &=(\eta_{30}+\eta_{12})^2+(\eta_{21}+\eta_{03})^2 \\ hu[4] &=(\eta_{30}-3\eta_{12})(\eta_{30}+\eta_{12})[(\eta_{30}+\eta_{12})^2-3(\eta_{21}+\eta_{03})^2]+(3\eta_{21}-\eta_{03})(\eta_{21}+\eta_{03})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2] \\ hu[5] &=(\eta_{20}-\eta_{02})[(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2]+4\eta_{11}(\eta_{30}+\eta_{12})(\eta_{21}+\eta_{03}) \\ hu[6] &=(3\eta_{21}-\eta_{03})(\eta_{21}+\eta_{03})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2]-(\eta_{30}-3\eta_{12})(\eta_{21}+\eta_{03})[3(\eta_{30}+\eta_{12})^2-(\eta_{21}+\eta_{03})^2] \end{align*}} hu[0]hu[1]hu[2]hu[3]hu[4]hu[5]hu[6]=η20+η02=(η20−η02)2+4η113=(η30−3η12)2+(3η21−η03)2=(η30+η12)2+(η21+η03)2=(η30−3η12)(η30+η12)[(η30+η12)2−3(η21+η03)2]+(3η21−η03)(η21+η03)[3(η30+η12)2−(η21+η03)2]=(η20−η02)[(η30+η12)2−(η21+η03)2]+4η11(η30+η12)(η21+η03)=(3η21−η03)(η21+η03)[3(η30+η12)2−(η21+η03)2]−(η30−3η12)(η21+η03)[3(η30+η12)2−(η21+η03)2]

Hu M. K.在其1962年的论文中证明了这些矩具有旋转不变性。无论对象经过多少角度的旋转,只要形状不变,其Hu矩就不变。

但是有个例外,就是 H u [ 6 ] Hu[6] Hu[6],它在经过旋转后,符号会发生改变。

Hu矩不变性的代码体现

以下代码分别对

  • 灰度图
  • 缩小1/2后的图
  • 逆时针旋转5度的图
  • 垂直镜像后的图

计算了Hu矩,代码如下:

python 复制代码
import cv2
import numpy as np
np.set_printoptions(suppress=True)

def my_humoments(img_gray):
    moments = cv2.moments(img_gray)
    humoments = cv2.HuMoments(moments)
    # 取对数
    humoments = np.log(np.abs(humoments))
    print(humoments)
    
if __name__=='__main__':
    fp = 'lena.jpg'
    img = cv2.imread(fp)
    img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    my_humoments(img_gray)
    
    # 缩放
    h,w = img.shape[:2]
    img = cv2.resize(img, (h//2, w//2), cv2.INTER_LINEAR)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("scale.jpg", img_gray)
    my_humoments(img_gray)
    
    # 旋转
    (h, w) = img.shape[:2]
    center = (w//2, h//2)
    M = cv2.getRotationMatrix2D(center, 5, 1.0)
    img =  cv2.warpAffine(img, M, (w, h))
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("rotate.jpg", img_gray)
    my_humoments(img_gray)
    
    # 垂直镜像
    img = cv2.flip(img, 0, dst=None)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("flip.jpg", img_gray)
    my_humoments(img_gray)

输出结果为:

变换形式 H u [ 0 ] Hu[0] Hu[0] H u [ 1 ] Hu[1] Hu[1] H u [ 2 ] Hu[2] Hu[2] H u [ 3 ] Hu[3] Hu[3] H u [ 4 ] Hu[4] Hu[4] H u [ 5 ] Hu[5] Hu[5] H u [ 6 ] Hu[6] Hu[6]
灰度图 -6.62198257 -18.82412227 -27.47557879 -25.20612238 -54.72034032 -34.69525116 -51.54784997
缩放 -6.62296285 -18.82833832 -27.48225177 -25.21085389 -54.77047947 -34.70200431 -51.55821672
旋转 -6.63267923 -18.67986945 -26.87920354 -25.25423734 -54.52139692 -34.62802668 -51.32178852
垂直镜像 -6.63267923 -18.67986945 -26.87920354 -25.25423734 -54.52139692 -34.62802668 -51.32178852

可以看到,虽说Hu矩具有平移不变性、尺度不变性和旋转不变性,但是并不是计算出来的值都相等,只是变化非常小。

Hu矩和中心矩结合OpenCV中的轮廓检测操作可以很好地识别物体、文字的轮廓。

附录

对于二维连续函数 f ( x , y ) f(x,y) f(x,y),其 ( p + q ) (p+q) (p+q)阶的空间矩 定义如下:
m p q = ∫ − ∞ + ∞ ∫ − ∞ + ∞ x p y q f ( x , y ) d x d y , p , q = 0 , 1 , 2 , ⋯ m_{pq}=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}x^py^qf(x,y) \mathrm{d} x \mathrm{d} y, p, q=0, 1,2, \cdots mpq=∫−∞+∞∫−∞+∞xpyqf(x,y)dxdy,p,q=0,1,2,⋯

  • 上式中的 p p p和 q q q可以取所有的自然数,所以 m p q m_{pq} mpq是一个空间矩的集合,且函数 f ( x , y ) f(x,y) f(x,y)只有唯一的矩的集合与之对应。
  • 参数 ( p + q ) (p+q) (p+q)称为矩的阶
  • 当阶 p + q = 0 p+q=0 p+q=0时,得到零阶矩 。零阶矩的几何意义就是对象的面积: m 00 = ∫ − ∞ + ∞ ∫ − ∞ + ∞ f ( x , y ) d x d y m_{00}=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}f(x,y) \mathrm{d} x \mathrm{d} y m00=∫−∞+∞∫−∞+∞f(x,y)dxdy
  • 当 p = 1 , q = 0 p=1, q=0 p=1,q=0时, m 10 m_{10} m10表示对象上所有点的 x x x坐标的总和: m 10 = ∫ − ∞ + ∞ ∫ − ∞ + ∞ x f ( x , y ) d x d y m_{10}=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} xf(x,y)\mathrm{d}x\mathrm{d}y m10=∫−∞+∞∫−∞+∞xf(x,y)dxdy
  • 当 p = 0 , q = 1 p=0,q=1 p=0,q=1时, m 01 m_{01} m01表示对象上所有点的 y y y坐标的总和,: m 01 = ∫ − ∞ + ∞ ∫ − ∞ + ∞ y f ( x , y ) d x d y m_{01}=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} yf(x,y)\mathrm{d}x\mathrm{d}y m01=∫−∞+∞∫−∞+∞yf(x,y)dxdy

中心矩 : μ p q = ∫ − ∞ + ∞ ∫ − ∞ + ∞ ( x − x ˉ ) p ( y − y ˉ ) q f ( x , y ) d x d y \mu_{pq}=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} (x-\={x})^p(y-\={y})^qf(x,y)\mathrm{d}x\mathrm{d}y μpq=∫−∞+∞∫−∞+∞(x−xˉ)p(y−yˉ)qf(x,y)dxdy

参考

  1. 昊虹AI笔记,《什么叫图像或轮廓的空间矩、中心矩、归一化中心矩?并利用OpenCV的类Moments计算轮廓的这几个矩和质心位置》
  2. AI人工智能科学,《矩、中心矩、质心、patch方向》
  3. Ming-Kuei Hu. (1962). Visual pattern recognition by moment invariants. IEEE Transactions on Information Theory, 8(2), 179--187. doi:10.1109/tit.1962.1057692
  4. 暂未成功人士!,《机器学习图像特征提取---Hu矩(Hu不变矩)原理及代码》
  5. 赵卓不凡,《一文弄懂图像的矩和相关应用》
  6. 《深度时间OCR:基于深度学习的文字识别》,机械工业出版社,2020年5月
  7. Mr2021,《Opencv:基于Hu-moments(hu矩)的形状匹配》
相关推荐
西猫雷婶11 分钟前
python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分
开发语言·python·opencv
AI视觉网奇44 分钟前
人脸生成3d模型 Era3D
人工智能·计算机视觉
云空1 小时前
《QT 5.14.1 搭建 opencv 环境全攻略》
开发语言·qt·opencv
编码小哥1 小时前
opencv中的色彩空间
opencv·计算机视觉
吃个糖糖1 小时前
34 Opencv 自定义角点检测
人工智能·opencv·计算机视觉
花花少年1 小时前
【Windows版】opencv 和opencv_contrib配置
opencv·opencv_contrib
YRr YRr1 小时前
解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误
linux·opencv·ubuntu
葡萄爱3 小时前
OpenCV图像分割
人工智能·opencv·计算机视觉
编码小哥5 小时前
通过opencv加载、保存视频
人工智能·opencv
发呆小天才O.oᯅ5 小时前
YOLOv8目标检测——详细记录使用OpenCV的DNN模块进行推理部署C++实现
c++·图像处理·人工智能·opencv·yolo·目标检测·dnn