前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >计算图像的形心主惯性轴

计算图像的形心主惯性轴

作者头像
用户6021899
发布2023-03-03 09:05:52
4350
发布2023-03-03 09:05:52
举报
文章被收录于专栏:Python编程 pyqt matplotlib
代码语言:javascript
复制
import numpy as np
import math
import numba as nb
from matplotlib import pyplot as plt

# 要求是二值图,前景为1,背景为0
@nb.jit(nb.types.UniTuple(nb.float32, 2)(nb.uint8[:, :]), nopython=True)
def gravity_center(array):
    """计算重心,array的元素都是1或者0,计算1部分的重心"""
    rows, cols = array.shape
    area = 0
    sum_x = 0
    sum_y = 0
    for x in range(rows):
        for y in range(cols):
            if array[x, y] != 0:
                area += 1
                sum_x += x
                sum_y += y
    return sum_x / area, sum_y / area  # x 对应行 , y 对于列!

# 取图像的竖直方向为x方向

@nb.jit(nb.float32(nb.uint8[:, :], nb.float32), nopython=True)
def calc_Ix(array, axis=0.0):  # moments of inertia
    # 计算 对于 y= axis (某列)的惯性矩
    rows, cols = array.shape
    sum = 0
    for x in range(rows):
        for y in range(cols):
            if array[x, y] != 0:
                sum += (y - axis) ** 2
    return sum


@nb.jit(nb.float32(nb.uint8[:, :], nb.float32), nopython=True)
def calc_Iy(array, axis=0.0):  # moments of inertia
    # 计算 对于 x= axis (某行)的惯性矩
    rows, cols = array.shape
    sum = 0
    for x in range(rows):
        for y in range(cols):
            if array[x, y] != 0:
                sum += (x - axis) ** 2
    return sum


@nb.jit(nb.float32(nb.uint8[:, :], nb.float32, nb.float32), nopython=True)
def calc_Ixy(array, axis_x=0.0, axis_y=0.0):  # product of inertia
    # 计算 对于 某行,某列的惯性积
    rows, cols = array.shape
    sum = 0
    for x in range(rows):
        for y in range(cols):
            if array[x, y] != 0:
                sum += (x - axis_x) * (y - axis_y)
    return sum

在依据公式计算两个正交的形心主惯性矩,以及惯性主轴和X轴(图像的竖直方向)的夹角

代码语言:javascript
复制
@nb.jit(nb.types.UniTuple(nb.float32, 3)(nb.float32, nb.float32, nb.float32), nopython=True)
def calc_I1_I2_alpha(Ix, Iy, Ixy):
    temp1 = 0.5 * (Ix + Iy)
    temp2 = 0.5 * math.sqrt((Ix - Iy) ** 2 + 4.0 * Ixy ** 2)
    I1 = temp1 + temp2
    I2 = temp1 - temp2
    if Ix == Iy:
        alpha = math.pi / 2.0
    else:
        alpha = 0.5 * math.atan(-2.0 * Ixy / (Ix - Iy))  # 值域 (-pi/2,+pi/2)
    return I1, I2, alpha

先拿矩形试一试水,

代码语言:javascript
复制
if __name__ == "__main__":
    img2 = np.ones((1000,1200),dtype=np.uint8)

    cx,cy = gravity_center(img2)
    Ix = calc_Ix(img2, axis=cy)
    Iy = calc_Iy(img2, axis=cx)
    Ixy = calc_Ixy(img2, axis_x=cx, axis_y=cy)
    I1, I2, alpha = calc_I1_I2_alpha(Ix, Iy, Ixy)
    print(f"Ix = {Ix}, Iy = {Iy}, Ixy = {Ixy}")
    print(f"I1 = {I1}, I2 = {I2}, alpha = {alpha}, angle ={alpha/math.pi *180} degree")

    plt.imshow(img2, cmap ="gray")
    plt.show()

输出:

代码语言:javascript
复制
Ix = 143999893504.0, Iy = 99999899648.0, Ixy = 0.0
I1 = 143999893504.0, I2 = 99999899648.0, alpha = -0.0, angle =-0.0 degree

理论值是 I1= Ix = 144,000,000,000, I2=Iy=100,000,000,000,alpha=0。计算值与理论值非常接近,误差来自图像的离散(由一个一个像素组成)。

再来实际计算一下下面的猫图

代码语言:javascript
复制
if __name__ == "__main__":
    from PIL import Image
    img = Image.open("cat3.png")
    img = np.array(img)
    img = img[:,:,0]
    img2 = np.zeros(img.shape, dtype = np.uint8)  # reversed
    img2[np.where(img<150)] = 1

    # img2 = np.ones((1000,1200),dtype=np.uint8)
    cx,cy = gravity_center(img2)
    Ix = calc_Ix(img2, axis=cy)
    Iy = calc_Iy(img2, axis=cx)
    Ixy = calc_Ixy(img2, axis_x=cx, axis_y=cy)
    I1, I2, alpha = calc_I1_I2_alpha(Ix, Iy, Ixy)
    print(f"Ix = {Ix}, Iy = {Iy}, Ixy = {Ixy}")
    print(f"I1 = {I1}, I2 = {I2}, alpha = {alpha}, angle ={alpha/math.pi *180} degree")

    plt.imshow(img2, cmap ="gray")
    plt.show()

输出:

代码语言:javascript
复制
Ix = 21522734.0, Iy = 21877528.0, Ixy = 5528713.5
I1 = 27231690.0, I2 = 16168573.0, alpha = 0.7693604230880737, angle =44.081105167346 degree

第一主惯性轴和X方向(竖直方向)的夹角44.08度,看起来没问题。

在某些简单情况下,惯性矩可作为图像的特征,用于图像分类。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档