五种矩阵变换

Figure_1


import numpy as np
import matplotlib.pyplot as plt

# 全局中文设置
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 生成基础网格
x = np.linspace(-1, 2, 10)
y = np.linspace(-1, 2, 10)
X, Y = np.meshgrid(x, y)
pts = np.vstack([X.ravel(), Y.ravel()])

# 5类线性变换,优化反射变换
transform_list = [
    {
        "name": "1. 轴向缩放变换\n两个正交特征方向,仅拉伸压缩",
        "mat": np.array([[2, 0], [0, 0.5]]),
        "color": "#dd3333"
    },
    {
        "name": "2. 旋转变换\n无实特征向量,实数域不可对角化",
        "mat": np.array([[np.cos(np.pi/6), -np.sin(np.pi/6)],
                         [np.sin(np.pi/6), np.cos(np.pi/6)]]),
        "color": "#3366dd"
    },
    {
        "name": "3. 反射变换(沿x轴镜像)\nx轴方向不变,y轴方向反向翻转",
        "mat": np.array([[1, 0], [0, -1]]),
        "color": "#9933dd",
        "draw_sym": True  # 绘制对称轴
    },
    {
        "name": "4. 斜向拉伸(可对角化)\n表观剪切,换基可消除斜向形变",
        "mat": np.array([[2, 1], [1, 2]]),
        "color": "#ff7722"
    },
    {
        "name": "5. 原生剪切变换\n仅1个实特征方向,无法对角化",
        "mat": np.array([[1, 1.2], [0, 1]]),
        "color": "#ddaa00"
    }
]

# 布局:2行3列,隐藏最后一张空白子图
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
axes = axes.flatten()
axes[5].axis('off')

for idx, info in enumerate(transform_list):
    ax = axes[idx]
    A = info["mat"]
    color = info["color"]
    title = info["name"]
    draw_sym = info.get("draw_sym", False)

    # 原始网格
    ax.plot(X, Y, c="gray", lw=0.6, alpha=0.4)
    ax.plot(X.T, Y.T, c="gray", lw=0.6, alpha=0.4)
    ax.scatter(pts[0], pts[1], s=14, c="gray", alpha=0.6, label="原始点")

    # 矩阵变换
    pts_trans = A @ pts
    Xt = pts_trans[0].reshape(X.shape)
    Yt = pts_trans[1].reshape(Y.shape)

    # 变换后网格+带黑边散点
    ax.plot(Xt, Yt, c=color, lw=0.7, alpha=0.5)
    ax.plot(Xt.T, Yt.T, c=color, lw=0.7, alpha=0.5)
    ax.scatter(pts_trans[0], pts_trans[1], s=16, c=color, alpha=0.8,
               edgecolors="black", linewidth=0.2, label="变换后点")

    # 反射变换绘制对称轴
    if draw_sym:
        ax.axhline(y=0, color='red', linestyle='--', lw=2, alpha=0.7, label='镜像对称轴(x轴)')

    # 绘制实特征向量
    eigvals, eigvecs = np.linalg.eig(A)
    for i in range(2):
        val = eigvals[i]
        vec = eigvecs[:, i]
        if np.isreal(val):
            ax.arrow(0, 0, vec[0]*3, vec[1]*3, head_width=0.08, lw=2, color="blue", alpha=0.7)

    ax.set_title(title, fontsize=11)
    ax.set_aspect("equal")
    ax.grid(alpha=0.3)
    ax.legend(fontsize=8)

plt.tight_layout()
plt.show()

# 输出特征值
for info in transform_list:
    vals = np.linalg.eigvals(info["mat"])
    print(f"{info['name'].splitlines()[0]} 特征值:{vals.round(3)}")
posted @ 2026-06-27 14:53  redufa  阅读(3)  评论(0)    收藏  举报