numpy和pandas应用案例

 

1.图像卷积

image

 

import numpy as np
import matplotlib.pyplot as plt
import imageio.v2 as imageio  # 使用新版API避免警告
import os

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']  # Windows系统中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# ===================== 1. 定义数据 =====================
# 5*5 原始图像
img = np.array([
    [10, 20, 30, 40, 50],
    [15, 25, 35, 45, 55],
    [20, 30, 40, 50, 60],
    [25, 35, 45, 55, 65],
    [30, 40, 50, 60, 70]
])

# 3*3 卷积核(垂直边缘检测)
kernel = np.array([
    [1, 0, -1],
    [1, 0, -1],
    [1, 0, -1]
])

img_h, img_w = img.shape
k_h, k_w = kernel.shape
out_h = img_h - k_h + 1
out_w = img_w - k_w + 1

# 存储每一帧画面
frames = []

# ===================== 2. 逐滑动窗口绘制帧 =====================
for y in range(out_h):
    for x in range(out_w):
        # 截取当前卷积窗口
        window = img[y:y+k_h, x:x+k_w]
        # 卷积计算:对应相乘求和
        conv_val = np.sum(window * kernel)

        # 创建画布
        fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4))
        fig.suptitle("卷积运算滑动过程", fontsize=14)

        # 左图:原始图像 + 框选当前窗口
        ax1.imshow(img, cmap="gray", vmin=0, vmax=80)
        ax1.set_title("原始图像 (5×5)")
        # 绘制红色框标记卷积区域
        rect = plt.Rectangle((x-0.5, y-0.5), k_w, k_h,
                             fill=False, color="red", linewidth=3)
        ax1.add_patch(rect)
        ax1.set_xticks([])
        ax1.set_yticks([])

        # 中图:当前3×3图像块 + 卷积核
        ax2.imshow(window, cmap="gray", vmin=0, vmax=80)
        ax2.set_title(f"当前图像块 (3×3)\n卷积值 = {conv_val}")
        ax2.set_xticks([])
        ax2.set_yticks([])

        # 右图:卷积核(特征矩阵)
        ax3.imshow(kernel, cmap="gray")
        ax3.set_title("卷积核(特征矩阵) (3×3)")
        ax3.set_xticks([])
        ax3.set_yticks([])

        plt.tight_layout()
        # 保存单帧为临时图片
        temp_path = "temp_frame.png"
        plt.savefig(temp_path, dpi=100, bbox_inches="tight")
        plt.close(fig)

        # 读取帧并加入列表
        frames.append(imageio.imread(temp_path))

# ===================== 3. 合成GIF动图 =====================
gif_path = "conv_process.gif"
imageio.mimsave(gif_path, frames, duration=1.2)  # 每帧停留1.2秒
# 删除临时文件
os.remove("temp_frame.png")

print(f"✅ 卷积过程GIF已生成:{os.path.abspath(gif_path)}")

conv_process

 

2.实际图像

import numpy as np
import matplotlib.pyplot as plt
import imageio.v2 as imageio  # 使用新版API避免警告
import os
from PIL import Image

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']  # Windows系统中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# ===================== 配置项(自行修改这里)=====================
# 1. 替换为你的肖像图片路径
IMG_PATH = "portrait.jpg"
# 2. 统一缩放到 200x200(方便观察滑动,可按需改)
RESIZE_W, RESIZE_H = 200, 200
# 3. 卷积核 3×3 垂直边缘检测(特征矩阵)
kernel = np.array([
    [1, 0, -1],
    [1, 0, -1],
    [1, 0, -1]
])
k_h, k_w = kernel.shape
# 每帧停留时长(秒)
FRAME_DURATION = 0.8
# 每隔多少像素滑动一次(步长),越大GIF帧数越少、播放越快
STRIDE = 5
# =================================================================

# 1. 加载图片 → 灰度图 → 转numpy数组
img = Image.open(IMG_PATH).convert("L")
img = img.resize((RESIZE_W, RESIZE_H))
img = np.array(img, dtype=np.float32)
img_h, img_w = img.shape

# 计算输出特征图尺寸
out_h = (img_h - k_h) // STRIDE + 1
out_w = (img_w - k_w) // STRIDE + 1

frames = []
temp_file = "temp_frame.png"

# 2. 逐窗口滑动、绘图、保存帧
print("开始生成GIF帧...")
for y in range(0, img_h - k_h + 1, STRIDE):
    for x in range(0, img_w - k_w + 1, STRIDE):
        # 截取当前 3×3 图像块
        window = img[y:y+k_h, x:x+k_w]
        # 卷积计算
        conv_val = np.sum(window * kernel)

        # 绘图布局:原图 | 当前图像块 | 卷积核
        fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(14, 5))
        fig.suptitle("真实肖像图 + 卷积滑动过程", fontsize=15)

        # 左:整张肖像图 + 红色框标记当前卷积区域
        ax1.imshow(img, cmap="gray")
        rect = plt.Rectangle((x-0.5, y-0.5), k_w, k_h,
                             fill=False, color="red", linewidth=2.5)
        ax1.add_patch(rect)
        ax1.set_title("原始肖像图")
        ax1.set_xticks([])
        ax1.set_yticks([])

        # 中:当前 3×3 图像块
        ax2.imshow(window, cmap="gray")
        ax2.set_title(f"当前 3×3 图像块\n卷积输出值: {conv_val:.2f}")
        ax2.set_xticks([])
        ax2.set_yticks([])

        # 右:卷积核(特征矩阵)
        ax3.imshow(kernel, cmap="gray")
        ax3.set_title("3×3 卷积核(特征矩阵)")
        ax3.set_xticks([])
        ax3.set_yticks([])

        plt.tight_layout()
        plt.savefig(temp_file, dpi=100, bbox_inches="tight")
        plt.close(fig)  # 及时关闭图形以释放内存

        # 加入帧列表
        frames.append(imageio.imread(temp_file))
        
        # 显示进度
        total_frames = ((img_h - k_h) // STRIDE + 1) * ((img_w - k_w) // STRIDE + 1)
        current_frame = len(frames)
        if current_frame % 10 == 0:  # 每10帧显示一次进度
            print(f"已生成 {current_frame}/{total_frames} 帧")

# 3. 合成GIF动图
gif_save_path = "portrait_conv.gif"
imageio.mimsave(gif_save_path, frames, duration=FRAME_DURATION)

# 删除临时文件
if os.path.exists(temp_file):
    os.remove(temp_file)

print(f"✅ 肖像图卷积演示GIF生成完成!\n路径:{os.path.abspath(gif_save_path)}")

portrait

image

 

posted @ 2026-05-28 21:19  szmtjs10  阅读(8)  评论(0)    收藏  举报