最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python可視化實戰(zhàn)從矩陣乘法到圖像仿射變換的線性代數(shù)之旅

 更新時間:2026年02月14日 14:22:45   作者:灝瀚星空  
這篇文章主要介紹了Python可視化實戰(zhàn)從矩陣乘法到圖像仿射變換,線性代數(shù)是理解空間變換和數(shù)據(jù)結(jié)構(gòu)的核心數(shù)學工具,其意義往往隱藏在抽象的矩陣運算背后,隨著計算機圖形學和人工智能的發(fā)展,將線性代數(shù)概念轉(zhuǎn)化為可視化形式成為揭示其本質(zhì)的關(guān)鍵手段,需要的朋友可以參考下

前言

線性代數(shù)是理解空間變換和數(shù)據(jù)結(jié)構(gòu)的核心數(shù)學工具,其幾何意義往往隱藏在抽象的矩陣運算背后。隨著計算機圖形學和人工智能的發(fā)展,將線性代數(shù)概念轉(zhuǎn)化為可視化形式成為揭示其本質(zhì)的關(guān)鍵手段。本文通過Python代碼實現(xiàn)一系列可視化工具,涵蓋矩陣變換、特征向量分析和圖像仿射變換,旨在以直觀的方式展現(xiàn)線性代數(shù)在幾何變換、數(shù)據(jù)降維和計算機視覺中的應(yīng)用,幫助讀者建立“代數(shù)運算-幾何直觀-工程應(yīng)用”的完整認知鏈條。

一、基本概念回顧

1. 矩陣變換的幾何本質(zhì)

矩陣是線性變換的數(shù)值載體,每個2x2矩陣對應(yīng)二維平面上的一種線性變換:

旋轉(zhuǎn)矩陣:

將向量繞原點旋轉(zhuǎn)θ\thetaθ角度。

縮放矩陣:

沿x軸和y軸分別縮放Sx倍和Sy?倍。

剪切矩陣:

沿x軸方向剪切kkk個單位。這些變換可通過矩陣乘法復合,實現(xiàn)復雜的空間形變。

2. 特征向量與特征值

對于矩陣AAA,若存在非零向量v\mathbf{v}v和標量λ\lambdaλ使得Av=λvA\mathbf{v} = \lambda\mathbf{v}Av=λv,則v\mathbf{v}v稱為特征向量,λ\lambdaλ為特征值。幾何上,特征向量是變換中僅發(fā)生縮放而不改變方向的特殊向量,特征值表示縮放比例。對稱矩陣的特征向量互相正交,可張成整個空間(如主成分分析PCA的理論基礎(chǔ))。

3. 仿射變換與圖像映射

仿射變換是線性變換與平移的復合,表達式為y=Ax+b\mathbf{y} = A\mathbf{x} + \mathbfy=Ax+b。在計算機視覺中,圖像仿射變換通過矩陣AAA實現(xiàn)旋轉(zhuǎn)、縮放、剪切等操作,需通過反向映射(逆矩陣運算)將變換后的像素坐標映射回原始圖像采樣,避免像素丟失或重疊。

二、矩陣變換可視化工具

1. 向量與形狀變換演示

# 向量旋轉(zhuǎn)示例(90度旋轉(zhuǎn)矩陣)
v = [1, 2]
M_rotation = np.array([[0, -1], [1, 0]])
plot_vector_transformation(v, M_rotation, "vector_rotation.png")

可視化效果:藍色箭頭為原始向量,紅色箭頭為變換后向量,坐標系自動適配向量范圍,矩陣以文本形式顯示于右上角。

2. 多種變換效果對比

plot_matrix_effects("matrix_effects.png")

四宮格展示:

  • 旋轉(zhuǎn):保持形狀不變,僅改變方向;
  • 縮放:x軸拉長1.5倍,y軸壓縮0.7倍;
  • 剪切:底邊固定,頂部沿x軸偏移0.8個單位;
  • 投影:y坐標清零,形狀坍塌為x軸上的線段。

三、特征向量幾何意義演示

靜態(tài)可視化:單位圓到橢圓的變換

A = np.array([[3, 1], [1, 2]])  # 對稱矩陣,特征向量正交
plot_eigenvectors(A, "eigenvectors_symmetric.png")

關(guān)鍵元素:

  • 藍色單位圓經(jīng)矩陣AAA變換為紅色橢圓;
  • 綠色和品紅色箭頭為特征向量,變換后方向不變,長度由特征值(λ1=3.30\lambda_1=3.30λ1?=3.30, λ2=1.70\lambda_2=1.70λ2?=1.70)決定;
  • 特征向量方向?qū)?yīng)橢圓的長軸和短軸。

動態(tài)演示:插值變換過程

create_eigenvector_animation(A, "eigenvector_animation.gif")

動畫邏輯:從單位矩陣(無變換)逐漸插值到目標矩陣AAA,觀察單位圓如何逐步變形為橢圓,特征向量始終保持方向不變,直觀展現(xiàn)“特征向量是變換的主方向”這一本質(zhì)。

四、計算機視覺案例:圖像仿射變換

1. 靜態(tài)變換:縮放與旋轉(zhuǎn)復合

# 30度旋轉(zhuǎn)+0.8倍縮放矩陣
theta = np.pi/6
M_scale_rotate = np.array([
    [0.8*np.cos(theta), -0.8*np.sin(theta)],
    [0.8*np.sin(theta), 0.8*np.cos(theta)]
])
plot_image_affine_transform("sample_image.jpg", M_scale_rotate, "image_affine_transform.png")

實現(xiàn)細節(jié):

  • 反向映射:通過逆矩陣將變換后坐標映射回原始圖像采樣;
  • 網(wǎng)格線對比:紅色網(wǎng)格為原始圖像坐標,藍色網(wǎng)格為變換后坐標,展示空間形變。

2. 動態(tài)旋轉(zhuǎn)動畫

create_image_rotation_animation("sample_image.jpg", "image_rotation.gif")

技術(shù)要點:

  • 每幀計算旋轉(zhuǎn)矩陣并更新圖像坐標;
  • 自動計算旋轉(zhuǎn)后圖像邊界,避免黑邊拉伸;
  • 近鄰插值保持像素完整性(可擴展為雙線性插值提升畫質(zhì))。

五、生成圖像說明

向量變換圖 (vector_rotation.png):

展示向量在矩陣變換前后的變化

藍色箭頭表示原始向量

紅色箭頭表示變換后向量

包含變換矩陣的數(shù)學表示

形狀變換圖 (triangle_shear.png):

展示三角形在剪切變換下的形變

藍色輪廓表示原始形狀

紅色虛線輪廓表示變換后形狀

直觀展示矩陣變換對幾何形狀的影響

矩陣變換效果圖 (matrix_effects.png):

四宮格對比不同矩陣變換效果

包含旋轉(zhuǎn)、縮放、剪切和投影

每個子圖顯示對應(yīng)的變換矩陣

特征向量圖 (eigenvectors_symmetric.png):

藍色圓表示單位圓

紅色橢圓表示矩陣變換后的結(jié)果

綠色和品紅色箭頭表示特征向量

展示特征向量在變換后保持方向不變

特征向量動畫 (eigenvector_animation.gif):

動態(tài)展示單位圓到橢圓的變換過程

特征向量在變換過程中保持方向

特征值表示特征向量的縮放比例

圖像仿射變換圖 (image_affine_transform.png):

并排顯示原始圖像和變換后圖像

網(wǎng)格線展示變換的空間映射關(guān)系

包含變換矩陣的數(shù)學表示

圖像旋轉(zhuǎn)動畫 (image_rotation.gif):

展示圖像在二維平面中的旋轉(zhuǎn)過程

演示仿射變換在計算機視覺中的應(yīng)用

展示線性變換對像素位置的映射

六、教學要點

矩陣變換幾何解釋:

  • 矩陣作為線性變換的數(shù)學表示
  • 旋轉(zhuǎn)、縮放、剪切和投影的矩陣形式
  • 矩陣乘法與向量變換的關(guān)系

特征值與特征向量:

  • 特征向量在變換中保持方向不變
  • 特征值表示特征向量的縮放因子
  • 特征分解的幾何意義

計算機視覺應(yīng)用:

  • 仿射變換的圖像處理應(yīng)用
  • 圖像旋轉(zhuǎn)、縮放和剪切的實現(xiàn)
  • 反向映射與圖像重采樣技術(shù)

編程實現(xiàn)技巧:

  • 使用NumPy進行矩陣運算
  • Matplotlib幾何形狀繪制
  • 圖像處理與坐標映射
  • 動態(tài)變換的動畫實現(xiàn)

本節(jié)代碼提供了強大的線性代數(shù)可視化工具,從基礎(chǔ)的向量變換到復雜的圖像仿射變換,直觀展示了線性代數(shù)的核心概念。特征向量動畫和圖像變換案例揭示了數(shù)學在計算機視覺中的實際應(yīng)用價值。

總結(jié)

本文通過可視化工具將線性代數(shù)的抽象概念轉(zhuǎn)化為直觀圖像,從向量變換的幾何直觀,到特征向量的物理意義,再到圖像仿射變換的工程實現(xiàn),構(gòu)建了“理論-代碼-應(yīng)用”的完整學習路徑。讀者可通過調(diào)整代碼中的矩陣參數(shù),觀察不同變換效果,深入理解線性代數(shù)在計算機圖形學、機器學習等領(lǐng)域的基礎(chǔ)作用。

完整代碼

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.animation import FuncAnimation
from matplotlib import patches
from PIL import Image
import os
# ---------------------- 全局配置 ----------------------
plt.rcParams["font.sans-serif"] = ["SimHei"]  # 設(shè)置中文字體為黑體
plt.rcParams["axes.unicode_minus"] = False  # 正確顯示負號
plt.rcParams["mathtext.fontset"] = "cm"  # 設(shè)置數(shù)學字體為Computer Modern
# ====================== 矩陣變換可視化工具 ======================
def plot_vector_transformation(v, M, output_path="vector_transformation.png"):
    """
    可視化向量經(jīng)過矩陣變換后的效果
    參數(shù):
    v: 原始向量 [x, y]
    M: 2x2變換矩陣
    output_path: 輸出文件路徑
    """
    plt.figure(figsize=(10, 8), dpi=130)
    ax = plt.gca()
    # 原始向量
    origin = np.array([0, 0])
    v = np.array(v)
    ax.quiver(
        *origin,
        *v,
        scale=1,
        scale_units="xy",
        angles="xy",
        color="b",
        width=0.01,
        label=f"原始向量: ({v[0]}, {v[1]})",
    )
    # 變換后的向量
    v_transformed = M @ v
    ax.quiver(
        *origin,
        *v_transformed,
        scale=1,
        scale_units="xy",
        angles="xy",
        color="r",
        width=0.01,
        label=f"變換后: ({v_transformed[0]:.2f}, {v_transformed[1]:.2f})",
    )
    # 設(shè)置坐標系
    max_val = max(np.abs(v).max(), np.abs(v_transformed).max()) * 1.2
    ax.set_xlim(-max_val, max_val)
    ax.set_ylim(-max_val, max_val)
    # 添加網(wǎng)格和樣式
    ax.grid(True, linestyle="--", alpha=0.6)
    ax.set_aspect("equal")
    ax.spines["left"].set_position("zero")
    ax.spines["bottom"].set_position("zero")
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    # 使用簡單的文本表示矩陣
    matrix_text = (
        f"變換矩陣:\n" f"[{M[0,0]:.2f}, {M[0,1]:.2f}]\n" f"[{M[1,0]:.2f}, {M[1,1]:.2f}]"
    )
    plt.text(
        0.05,
        0.95,
        matrix_text,
        transform=ax.transAxes,
        fontsize=14,
        bbox=dict(facecolor="white", alpha=0.8),
    )
    # 設(shè)置標題和圖例
    plt.title("向量矩陣變換", fontsize=16, pad=20)
    plt.legend(loc="best", fontsize=12)
    # 保存圖像
    plt.savefig(output_path, bbox_inches="tight")
    plt.close()
    print(f"向量變換圖已保存至: {output_path}")
def plot_shape_transformation(vertices, M, output_path="shape_transformation.png"):
    """
    可視化形狀經(jīng)過矩陣變換后的效果
    參數(shù):
    vertices: 形狀頂點列表 [[x1,y1], [x2,y2], ...]
    M: 2x2變換矩陣
    output_path: 輸出文件路徑
    """
    plt.figure(figsize=(10, 8), dpi=130)
    ax = plt.gca()
    # 原始形狀
    shape_original = Polygon(
        vertices,
        closed=True,
        fill=False,
        edgecolor="b",
        linewidth=2.5,
        label="原始形狀",
    )
    ax.add_patch(shape_original)
    # 變換后的形狀
    vertices_transformed = np.array(vertices) @ M.T
    shape_transformed = Polygon(
        vertices_transformed,
        closed=True,
        fill=False,
        edgecolor="r",
        linewidth=2.5,
        linestyle="--",
        label="變換后形狀",
    )
    ax.add_patch(shape_transformed)
    # 設(shè)置坐標系
    all_points = np.vstack([vertices, vertices_transformed])
    max_val = np.abs(all_points).max() * 1.2
    ax.set_xlim(-max_val, max_val)
    ax.set_ylim(-max_val, max_val)
    # 添加網(wǎng)格和樣式
    ax.grid(True, linestyle="--", alpha=0.6)
    ax.set_aspect("equal")
    ax.spines["left"].set_position("zero")
    ax.spines["bottom"].set_position("zero")
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    # 使用簡單的文本表示矩陣
    matrix_text = (
        f"變換矩陣:\n" f"[{M[0,0]:.2f}, {M[0,1]:.2f}]\n" f"[{M[1,0]:.2f}, {M[1,1]:.2f}]"
    )
    plt.text(
        0.05,
        0.95,
        matrix_text,
        transform=ax.transAxes,
        fontsize=14,
        bbox=dict(facecolor="white", alpha=0.8),
    )
    # 設(shè)置標題和圖例
    plt.title("形狀矩陣變換", fontsize=16, pad=20)
    plt.legend(loc="best", fontsize=12)
    # 保存圖像
    plt.savefig(output_path, bbox_inches="tight")
    plt.close()
    print(f"形狀變換圖已保存至: {output_path}")
def plot_matrix_effects(output_path="matrix_effects.png"):
    """
    可視化不同矩陣變換效果:旋轉(zhuǎn)、縮放、剪切、投影
    """
    # 創(chuàng)建基本形狀 (三角形)
    vertices = np.array([[0, 0], [1, 0], [0.5, 1], [0, 0]])
    # 定義變換矩陣
    transformations = {
        "旋轉(zhuǎn)": np.array(
            [
                [np.cos(np.pi / 4), -np.sin(np.pi / 4)],
                [np.sin(np.pi / 4), np.cos(np.pi / 4)],
            ]
        ),
        "縮放": np.array([[1.5, 0], [0, 0.7]]),
        "剪切": np.array([[1, 0.8], [0, 1]]),
        "投影": np.array([[1, 0], [0, 0]]),  # 投影到x軸
    }
    fig, axs = plt.subplots(2, 2, figsize=(14, 12), dpi=130)
    fig.suptitle("基本矩陣變換效果", fontsize=20, y=0.95)
    for ax, (title, M) in zip(axs.flat, transformations.items()):
        # 原始形狀
        shape_original = Polygon(
            vertices, closed=True, fill=False, edgecolor="b", linewidth=2, alpha=0.7
        )
        ax.add_patch(shape_original)
        # 變換后的形狀
        vertices_transformed = vertices @ M.T
        shape_transformed = Polygon(
            vertices_transformed, closed=True, fill=False, edgecolor="r", linewidth=2.5
        )
        ax.add_patch(shape_transformed)
        # 設(shè)置坐標系
        all_points = np.vstack([vertices, vertices_transformed])
        max_val = np.abs(all_points).max() * 1.2
        ax.set_xlim(-max_val, max_val)
        ax.set_ylim(-max_val, max_val)
        # 添加網(wǎng)格和樣式
        ax.grid(True, linestyle="--", alpha=0.5)
        ax.set_aspect("equal")
        ax.spines["left"].set_position("zero")
        ax.spines["bottom"].set_position("zero")
        ax.spines["right"].set_visible(False)
        ax.spines["top"].set_visible(False)
        # 使用簡單的文本表示矩陣
        matrix_text = f"[{M[0,0]:.2f}, {M[0,1]:.2f}]\n[{M[1,0]:.2f}, {M[1,1]:.2f}]"
        ax.set_title(f"{title}\n{matrix_text}", fontsize=14)
    plt.tight_layout(pad=3.0)
    plt.savefig(output_path, bbox_inches="tight")
    plt.close()
    print(f"矩陣變換效果圖已保存至: {output_path}")
# ====================== 特征向量幾何意義演示 ======================
def plot_eigenvectors(A, output_path="eigenvectors.png"):
    """
    可視化矩陣的特征向量和特征值
    參數(shù):
    A: 2x2矩陣
    output_path: 輸出文件路徑
    """
    # 計算特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(A)
    plt.figure(figsize=(10, 8), dpi=130)
    ax = plt.gca()
    # 創(chuàng)建單位圓
    theta = np.linspace(0, 2 * np.pi, 100)
    circle_x = np.cos(theta)
    circle_y = np.sin(theta)
    ax.plot(circle_x, circle_y, "b-", alpha=0.5, label="單位圓")
    # 變換后的橢圓
    ellipse_points = np.column_stack([circle_x, circle_y]) @ A.T
    ax.plot(ellipse_points[:, 0], ellipse_points[:, 1], "r-", label="變換后橢圓")
    # 繪制特征向量
    colors = ["g", "m"]
    for i, (eigenvalue, eigenvector) in enumerate(zip(eigenvalues, eigenvectors.T)):
        # 原始特征向量
        ax.quiver(
            0,
            0,
            *eigenvector,
            scale=1,
            scale_units="xy",
            angles="xy",
            color=colors[i],
            width=0.015,
            label=f"特征向量 {i+1}: ({eigenvector[0]:.2f}, {eigenvector[1]:.2f})",
        )
        # 變換后的特征向量
        transformed_vector = A @ eigenvector
        ax.quiver(
            0,
            0,
            *transformed_vector,
            scale=1,
            scale_units="xy",
            angles="xy",
            color=colors[i],
            width=0.015,
            alpha=0.5,
            linestyle="--",
        )
        # 標記特征值
        ax.text(
            transformed_vector[0] * 1.1,
            transformed_vector[1] * 1.1,
            f"λ={eigenvalue:.2f}",
            color=colors[i],
            fontsize=12,
        )
    # 設(shè)置坐標系
    max_val = max(np.abs(ellipse_points).max(), 1.5)
    ax.set_xlim(-max_val, max_val)
    ax.set_ylim(-max_val, max_val)
    # 添加網(wǎng)格和樣式
    ax.grid(True, linestyle="--", alpha=0.6)
    ax.set_aspect("equal")
    ax.spines["left"].set_position("zero")
    ax.spines["bottom"].set_position("zero")
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    # 使用簡單的文本表示矩陣
    matrix_text = (
        f"矩陣:\n"
        f"[{A[0,0]:.2f}, {A[0,1]:.2f}]\n"
        f"[{A[1,0]:.2f}, {A[1,1]:.2f}]\n\n"
        f"特征值: {eigenvalues[0]:.2f}, {eigenvalues[1]:.2f}"
    )
    plt.text(
        0.05,
        0.95,
        matrix_text,
        transform=ax.transAxes,
        fontsize=14,
        bbox=dict(facecolor="white", alpha=0.8),
    )
    # 設(shè)置標題和圖例
    plt.title("特征向量與特征值幾何意義", fontsize=16, pad=20)
    plt.legend(loc="best", fontsize=11)
    # 保存圖像
    plt.savefig(output_path, bbox_inches="tight")
    plt.close()
    print(f"特征向量圖已保存至: {output_path}")
def create_eigenvector_animation(A, output_path="eigenvector_animation.gif"):
    """
    創(chuàng)建特征向量動畫:展示單位圓到橢圓的變換過程
    """
    fig, ax = plt.subplots(figsize=(8, 8), dpi=120)
    # 計算特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(A)
    # 單位圓
    theta = np.linspace(0, 2 * np.pi, 100)
    circle_points = np.column_stack([np.cos(theta), np.sin(theta)])
    # 創(chuàng)建初始圖形
    (circle,) = ax.plot(circle_points[:, 0], circle_points[:, 1], "b-", alpha=0.7)
    (ellipse,) = ax.plot([], [], "r-", linewidth=2)
    # 特征向量線
    vec_lines = []
    for i, eigenvector in enumerate(eigenvectors.T):
        color = "g" if i == 0 else "m"
        (line,) = ax.plot([], [], color=color, linewidth=2.5, label=f"特征向量 {i+1}")
        vec_lines.append(line)
    # 設(shè)置坐標系
    max_val = max(np.abs(circle_points).max(), np.abs(eigenvectors).max()) * 1.5
    ax.set_xlim(-max_val, max_val)
    ax.set_ylim(-max_val, max_val)
    # 添加網(wǎng)格和樣式
    ax.grid(True, linestyle="--", alpha=0.5)
    ax.set_aspect("equal")
    ax.spines["left"].set_position("zero")
    ax.spines["bottom"].set_position("zero")
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    # 使用簡單的文本表示矩陣
    matrix_text = (
        f"矩陣 A:\n" f"[{A[0,0]:.2f}, {A[0,1]:.2f}]\n" f"[{A[1,0]:.2f}, {A[1,1]:.2f}]"
    )
    text = ax.text(
        0.05,
        0.95,
        matrix_text,
        transform=ax.transAxes,
        fontsize=12,
        bbox=dict(facecolor="white", alpha=0.8),
    )
    # 設(shè)置標題和圖例
    plt.title("特征向量變換動畫", fontsize=14, pad=15)
    plt.legend(loc="best")
    # 動畫更新函數(shù)
    def update(t):
        # 插值矩陣: 從單位矩陣到目標矩陣
        M = np.eye(2) * (1 - t) + A * t
        # 變換圓點
        transformed_points = circle_points @ M.T
        ellipse.set_data(transformed_points[:, 0], transformed_points[:, 1])
        # 更新特征向量線
        for i, eigenvector in enumerate(eigenvectors.T):
            vec_transformed = M @ eigenvector
            vec_lines[i].set_data([0, vec_transformed[0]], [0, vec_transformed[1]])
        # 更新插值值
        text.set_text(f"{matrix_text}\n\n插值: {t:.2f}")
        return ellipse, *vec_lines, text
    # 創(chuàng)建動畫
    anim = FuncAnimation(
        fig, update, frames=np.linspace(0, 1, 50), interval=100, blit=True
    )
    # 保存GIF
    anim.save(output_path, writer="pillow", fps=10)
    plt.close()
    print(f"特征向量動畫已保存至: {output_path}")
# ====================== 計算機視覺案例 ======================
def plot_image_affine_transform(
    image_path, transform_matrix, output_path="image_transform.png"
):
    """
    應(yīng)用仿射變換到圖像并可視化結(jié)果
    參數(shù):
    image_path: 圖像文件路徑
    transform_matrix: 2x2變換矩陣
    output_path: 輸出文件路徑
    """
    # 加載圖像
    img = Image.open(image_path).convert("RGB")
    img_array = np.array(img)
    # 創(chuàng)建圖像網(wǎng)格
    height, width = img_array.shape[:2]
    x = np.linspace(0, width, 10)
    y = np.linspace(0, height, 10)
    X, Y = np.meshgrid(x, y)
    # 創(chuàng)建繪圖
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8), dpi=130)
    fig.suptitle("圖像仿射變換", fontsize=20, y=0.98)
    # 原始圖像
    ax1.imshow(img_array)
    ax1.set_title("原始圖像", fontsize=16)
    ax1.axis("off")
    # 創(chuàng)建網(wǎng)格點
    points = np.column_stack([X.ravel(), Y.ravel()])
    # 應(yīng)用變換
    transformed_points = points @ transform_matrix.T
    # 變換后圖像
    # 由于變換可能改變圖像范圍,我們需要調(diào)整坐標
    min_x, min_y = transformed_points.min(axis=0)
    max_x, max_y = transformed_points.max(axis=0)
    # 創(chuàng)建新圖像網(wǎng)格
    new_width = int(max_x - min_x)
    new_height = int(max_y - min_y)
    # 創(chuàng)建新圖像數(shù)組
    new_img = np.zeros((new_height, new_width, 3), dtype=np.uint8)
    # 反向映射: 對于新圖像的每個點,找到原始圖像中的對應(yīng)點
    inv_matrix = np.linalg.inv(transform_matrix)
    for y_new in range(new_height):
        for x_new in range(new_width):
            # 將新圖像坐標轉(zhuǎn)換回原始圖像坐標
            orig_x, orig_y = np.array([x_new + min_x, y_new + min_y]) @ inv_matrix.T
            # 如果坐標在原始圖像范圍內(nèi),則采樣顏色
            if 0 <= orig_x < width and 0 <= orig_y < height:
                # 簡單最近鄰插值
                orig_x_int = int(orig_x)
                orig_y_int = int(orig_y)
                new_img[y_new, x_new] = img_array[orig_y_int, orig_x_int]
    # 顯示變換后圖像
    ax2.imshow(new_img, extent=[min_x, max_x, max_y, min_y])
    ax2.set_title("變換后圖像", fontsize=16)
    # 添加變換網(wǎng)格
    for i in range(len(y)):
        ax1.plot(x, [y[i]] * len(x), "r-", alpha=0.3)
    for j in range(len(x)):
        ax1.plot([x[j]] * len(y), y, "r-", alpha=0.3)
    # 繪制變換后的網(wǎng)格
    T_grid = transformed_points.reshape(X.shape[0], X.shape[1], 2)
    for i in range(len(y)):
        ax2.plot(T_grid[i, :, 0], T_grid[i, :, 1], "b-", alpha=0.5)
    for j in range(len(x)):
        ax2.plot(T_grid[:, j, 0], T_grid[:, j, 1], "b-", alpha=0.5)
    ax2.axis("off")
    # 使用簡單的文本表示矩陣
    matrix_text = (
        f"變換矩陣:\n"
        f"[{transform_matrix[0,0]:.2f}, {transform_matrix[0,1]:.2f}]\n"
        f"[{transform_matrix[1,0]:.2f}, {transform_matrix[1,1]:.2f}]"
    )
    plt.figtext(
        0.5,
        0.02,
        matrix_text,
        ha="center",
        fontsize=14,
        bbox=dict(facecolor="white", alpha=0.8),
    )
    plt.tight_layout(pad=3.0)
    plt.savefig(output_path, bbox_inches="tight")
    plt.close()
    print(f"圖像變換圖已保存至: {output_path}")
def create_image_rotation_animation(image_path, output_path="image_rotation.gif"):
    """
    創(chuàng)建圖像旋轉(zhuǎn)動畫
    """
    # 加載圖像
    img = Image.open(image_path).convert("RGB")
    img_array = np.array(img)
    height, width = img_array.shape[:2]
    # 創(chuàng)建圖形
    fig = plt.figure(figsize=(8, 8), dpi=120)
    ax = fig.add_subplot(111)
    ax.set_title("圖像旋轉(zhuǎn)動畫", fontsize=14)
    ax.axis("off")
    # 顯示原始圖像
    im = ax.imshow(img_array)
    # 動畫更新函數(shù)
    def update(frame):
        # 計算旋轉(zhuǎn)角度 (0到360度)
        angle = np.radians(frame * 7.2)  # 每幀旋轉(zhuǎn)7.2度,50幀完成360度
        # 創(chuàng)建旋轉(zhuǎn)矩陣
        rotation_matrix = np.array(
            [[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]]
        )
        # 計算旋轉(zhuǎn)后的圖像尺寸
        corners = np.array([[0, 0], [width, 0], [width, height], [0, height]])
        rotated_corners = corners @ rotation_matrix.T
        min_x, min_y = rotated_corners.min(axis=0)
        max_x, max_y = rotated_corners.max(axis=0)
        new_width = int(max_x - min_x)
        new_height = int(max_y - min_y)
        # 創(chuàng)建新圖像數(shù)組
        new_img = np.zeros((new_height, new_width, 3), dtype=np.uint8)
        # 反向映射
        inv_matrix = np.linalg.inv(rotation_matrix)
        for y_new in range(new_height):
            for x_new in range(new_width):
                # 將新圖像坐標轉(zhuǎn)換回原始圖像坐標
                orig_x, orig_y = np.array([x_new + min_x, y_new + min_y]) @ inv_matrix.T
                # 如果坐標在原始圖像范圍內(nèi),則采樣顏色
                if 0 <= orig_x < width and 0 <= orig_y < height:
                    orig_x_int = int(orig_x)
                    orig_y_int = int(orig_y)
                    new_img[y_new, x_new] = img_array[orig_y_int, orig_x_int]
        im.set_array(new_img)
        im.set_extent([min_x, max_x, max_y, min_y])
        return (im,)
    # 創(chuàng)建動畫
    anim = FuncAnimation(fig, update, frames=50, interval=100, blit=True)
    # 保存GIF
    anim.save(output_path, writer="pillow", fps=10)
    plt.close()
    print(f"圖像旋轉(zhuǎn)動畫已保存至: {output_path}")
# ====================== 使用示例 ======================
if __name__ == "__main__":
    # 清理舊文件
    for f in [
        "vector_rotation.png",
        "triangle_shear.png",
        "matrix_effects.png",
        "eigenvectors_symmetric.png",
        "eigenvector_animation.gif",
        "image_affine_transform.png",
        "image_rotation.gif",
        "temp_image.jpg",
    ]:
        if os.path.exists(f):
            os.remove(f)
    # 1. 向量變換示例(90度旋轉(zhuǎn))
    v = [1, 2]
    M_rotation = np.array([[0, -1], [1, 0]])
    plot_vector_transformation(v, M_rotation, "vector_rotation.png")
    # 2. 形狀變換示例(剪切變換)
    triangle = [[0, 0], [1, 0], [0.5, 1], [0, 0]]
    M_shear = np.array([[1, 0.5], [0, 1]])
    plot_shape_transformation(triangle, M_shear, "triangle_shear.png")
    # 3. 矩陣變換效果對比
    plot_matrix_effects("matrix_effects.png")
    # 4. 特征向量可視化(對稱矩陣)
    A = np.array([[3, 1], [1, 2]])
    plot_eigenvectors(A, "eigenvectors_symmetric.png")
    create_eigenvector_animation(A, "eigenvector_animation.gif")
    # 5. 圖像仿射變換(自動生成臨時圖像)
    image_path = "sample_image.jpg"
    if not os.path.exists(image_path):
        # 創(chuàng)建100x100藍色方塊圖像
        img_array = np.zeros((100, 100, 3), dtype=np.uint8)
        img_array[20:80, 20:80] = np.array([0, 128, 255], dtype=np.uint8)
        Image.fromarray(img_array).save("temp_image.jpg")
        image_path = "temp_image.jpg"
    # 縮放+旋轉(zhuǎn)矩陣(30度縮放0.8倍)
    theta = np.pi / 6
    M_scale_rotate = np.array(
        [
            [0.8 * np.cos(theta), -0.8 * np.sin(theta)],
            [0.8 * np.sin(theta), 0.8 * np.cos(theta)],
        ]
    )
    plot_image_affine_transform(
        image_path, M_scale_rotate, "image_affine_transform.png"
    )
    create_image_rotation_animation(image_path, "image_rotation.gif")
    print("\n所有可視化結(jié)果已生成,文件列表:")
    for f in os.listdir():
        if any(f.endswith(ext) for ext in [".png", ".gif"]):
            print(f"- {f}")

以上就是Python可視化實戰(zhàn)從矩陣乘法到圖像仿射變換的線性代數(shù)之旅的詳細內(nèi)容,更多關(guān)于Python線性代數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

中江县| 临猗县| 德格县| 甘肃省| 南城县| 梨树县| 永吉县| 乌拉特后旗| 古交市| 靖州| 彩票| 汝城县| 漳浦县| 柳河县| 萨嘎县| 泗水县| 呈贡县| 大邑县| 沙田区| 罗定市| 河北省| 宜川县| 桐柏县| 镇安县| 绍兴县| 九龙坡区| 吉林市| 盐边县| 和林格尔县| 布尔津县| 枣阳市| 永胜县| 牙克石市| 天等县| 洱源县| 全南县| 广丰县| 余姚市| 长兴县| 常山县| 平乡县|