【OpenCV】不变矩
不变矩
- 图像矩
- 零阶矩
- 空间矩
- 质心
- 中心矩
- 归一化中心矩
- Hu矩
- Hu矩不变性的代码体现
- 附录
- 参考
图像矩
在计算图像矩是需要将图像转化为单通道的灰度图,或者进行二值化处理,即目标对象设为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矩,代码如下:
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
参考
- 昊虹AI笔记,《什么叫图像或轮廓的空间矩、中心矩、归一化中心矩?并利用OpenCV的类Moments计算轮廓的这几个矩和质心位置》
- AI人工智能科学,《矩、中心矩、质心、patch方向》
- 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
- 暂未成功人士!,《机器学习图像特征提取—Hu矩(Hu不变矩)原理及代码》
- 赵卓不凡,《一文弄懂图像的矩和相关应用》
- 《深度时间OCR:基于深度学习的文字识别》,机械工业出版社,2020年5月
- Mr2021,《Opencv:基于Hu-moments(hu矩)的形状匹配》