本文记录《机器视觉》 第三章第二节 —— 简单几何性质,一些学习笔记和个人理解,其中核心内容为二值图的转动惯量求解。
我们已经有了一组二值图,我们可以根据二值图来确定其表示物体的简单几何性质。
二值图的特征函数 b(x, y)比较简单,当[x, y]处有物体时值为1,否则为0
可以认为是二值图的 0 阶矩的物理意义。
空间位置按照密度加权平均即是质心的位置 (\bar{x}, \bar{y}) :
可以认为是二值图的 1 阶矩(静力矩)物理意义。
我们已经确定该轴经过一个确定的点 (\bar{x}, \bar{y}) 了,仅需要再确定直线倾角即可。
其中,我们定义平移后的二值图I’上点的坐标为 ({x’}, {y’}) 。
从式\eqref{15}开始,事实上我们要解的就是一个带约束的优化方程组,可以使用拉格朗日乘数法求解:
可以将\eqref{19}看作是一个二次型优化问题,原带约束的方程可以写成:
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
from numpy.lib.function_base import iterable
def vvd_round(num):
if iterable(num):
return np.round(np.array(num)).astype('int32').tolist()
return int(round(num))
def show_image(image):
plt.imshow(image.astype('uint8'))
plt.show()
pass
def gravity_center(mask):
Ys, Xs = mask.nonzero()
A = (mask > 0).sum()
C_X = (Xs).sum() / A
C_Y = (Ys).sum() / A
return C_X, C_Y
def load_gray_image(image_path):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = (image == 0).astype('uint8') * 255
return image
def moment_of_inertia(mask, center):
temp_image = mask.copy().astype('uint8') * 128
C_X, C_Y = center
Ys, Xs = mask.nonzero()
Ys = (Ys - C_Y) / 100
Xs = (Xs - C_X) / 100
a = (Xs * Xs).sum()
b = 2 * (Xs * Ys).sum()
c = (Ys * Ys).sum()
if b == 0:
theta = 0
elif a == c:
theta = - np.pi * 0.5 * 0.5
else:
theta = - math.atan(b / (a - c)) / 2
point_1 = vvd_round([C_X + math.cos(theta) * 200, C_Y - math.sin(theta) * 200])
point_2 = vvd_round([C_X - math.cos(theta) * 200, C_Y + math.sin(theta) * 200])
temp_image = cv2.line(temp_image.astype('uint8'), point_1, point_2, 255, 2)
point_1 = vvd_round([C_X + math.cos(theta + 0.5 * np.pi) * 200, C_Y - math.sin(theta + 0.5 * np.pi) * 200])
point_2 = vvd_round([C_X - math.cos(theta + 0.5 * np.pi) * 200, C_Y + math.sin(theta + 0.5 * np.pi) * 200])
temp_image = cv2.line(temp_image.astype('uint8'), point_1, point_2, 200, 2)
theta_1 = theta
theta_2 = theta + 0.5 * np.pi
E_1 =(math.sin(theta_1)) ** 2 * a - b * math.sin(theta_1) * math.cos(theta_1) + c * (math.cos(theta_1)) ** 2
E_2 =(math.sin(theta_2)) ** 2 * a - b * math.sin(theta_2) * math.cos(theta_2) + c * (math.cos(theta_2)) ** 2
return temp_image, min(E_2, E_1) / max(E_2, E_1, 1)
if __name__ == '__main__':
image_path = 'test.png'
image = load_gray_image(image_path)
center = gravity_center(image)
temp_image, rate = moment_of_inertia(image, center)
show_image(temp_image)
pass