CNN--不同的filter对图片进行卷积

import os
import numpy as np
from PIL import Image, ImageDraw
import matplotlib.pyplot as plt

# ============== 1) 使用你的图片 ==============
CUSTOM_PATH = "apple.png"

def load_or_make_image():
    if CUSTOM_PATH and os.path.exists(CUSTOM_PATH):
        img = Image.open(CUSTOM_PATH).convert("L")
        title = f"Original ({os.path.basename(CUSTOM_PATH)})"
    else:
        # 备用: 生成一张灰度示例图
        H, W = 128, 128
        img = Image.new("L", (W, H), color=220)
        draw = ImageDraw.Draw(img)
        draw.rectangle([20, 20, 100, 60], fill=40)
        draw.ellipse([60, 70, 110, 120], fill=255)
        draw.line([0, 0, 127, 127], fill=90, width=3)
        title = "Original (synthetic)"
    return img, title

img, orig_title = load_or_make_image()
img_np = np.array(img, dtype=np.float32)

# ============== 2) 多个 3×3 卷积核 ==============
kernels = {
    "Sobel X": np.array([[1, 0, -1],
                         [1, 0, -1],
                         [1, 0, -1]], dtype=np.float32),
    "Sobel Y": np.array([[ 1,  1,  1],
                         [ 0,  0,  0],
                         [-1, -1, -1]], dtype=np.float32),
    "Laplacian": np.array([[0, -1,  0],
                           [-1, 4, -1],
                           [0, -1,  0]], dtype=np.float32),
    "Sharpen": np.array([[0, -1,  0],
                         [-1, 5, -1],
                         [0, -1,  0]], dtype=np.float32),
    "Box Blur": (1/9.0) * np.ones((3,3), dtype=np.float32),
    "Emboss": np.array([[-2, -1, 0],
                        [-1,  1, 1],
                        [ 0,  1, 2]], dtype=np.float32),
    "Outline": np.array([[-1, -1, -1],
                         [-1,  8, -1],
                         [-1, -1, -1]], dtype=np.float32),
}

# ============== 3) 卷积函数 ==============
def conv2d_same(image: np.ndarray, kernel: np.ndarray) -> np.ndarray:
    kh, kw = kernel.shape
    pad_h, pad_w = kh//2, kw//2
    padded = np.pad(image, ((pad_h, pad_h), (pad_w, pad_w)), mode='constant')
    out = np.zeros_like(image, dtype=np.float32)
    for i in range(out.shape[0]):
        for j in range(out.shape[1]):
            region = padded[i:i+kh, j:j+kw]
            out[i, j] = float(np.sum(region * kernel))
    return out

def to_uint8_for_display(arr: np.ndarray) -> np.ndarray:
    a_min, a_max = float(arr.min()), float(arr.max())
    if a_max - a_min < 1e-6:
        return np.zeros_like(arr, dtype=np.uint8)
    norm = (arr - a_min) / (a_max - a_min) * 255.0
    return norm.astype(np.uint8)

# ============== 4) 卷积 + 展示 ==============
results = {"Original": img_np}
for name, k in kernels.items():
    conv = conv2d_same(img_np, k)
    results[name] = to_uint8_for_display(conv)

# 展示:所有图像在一行或两行
n = len(results)
cols = 4  # 每行展示 4 张图,可以改成 3 或 5
rows = int(np.ceil(n / cols))

plt.figure(figsize=(4*cols, 4*rows))
for idx, (name, arr) in enumerate(results.items(), 1):
    plt.subplot(rows, cols, idx)
    plt.imshow(arr, cmap="gray")
    plt.title(name)
    plt.axis("off")

plt.tight_layout()
plt.show()

苹果原图
image
不同的filter卷积之后展示的图片效果

image

posted @ 2025-10-22 09:58  方子敬  阅读(5)  评论(0)    收藏  举报