图片 Patch 划分与可视化工具
图片 Patch 划分与可视化工具 该工具可将图片划分为规则的 patch 网格,支持两种划分方式:按 patch 像素尺寸或行列数划分。主要功能包括: 将图片裁剪为多个 patch 并保存 生成带网格线的可视化图片 可选高亮特定 patch 工具基于 Python 开发,依赖 Pillow 和 OpenCV 库。使用前需创建虚拟环境并安装依赖项。通过命令行参数可灵活配置 patch 大小、保留边
图片 Patch 划分与可视化工具
本工具用于将图片划分为规则的 patch 网格,并生成带网格叠加的可视化效果图(支持高亮某一块 patch),效果类似典型的 Vision Transformer 输入可视化。
- 脚本文件:
image_patcher.py - 主要依赖:
Pillow,opencv-python,numpy
1. 环境准备
在项目根目录 /home/xxx/tool 下创建并使用虚拟环境(推荐):
cd /home/xxx/tool
# 创建虚拟环境
python3 -m venv .venv
# 激活虚拟环境(Linux)
source .venv/bin/activate
# 安装依赖
pip install --upgrade pip
pip install pillow opencv-python
如果你已经按照上述步骤创建过
.venv并安装过依赖,可以直接激活虚拟环境开始使用。
2. 脚本功能概览
脚本支持两种划分方式:
- 按 patch 像素尺寸划分:指定
--patch_w和--patch_h - 按行列数划分:指定
--rows和--cols,脚本会根据图片宽高自动计算合适的 patch 尺寸
并且可以:
- 将所有 patch 裁剪并保存到
out_dir/patches目录 - 生成一张带网格线的可视化图片
out_dir/grid_visualization.png - 可选高亮某一块 patch(通过行列索引指定)
脚本代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
图片 patch 划分与可视化工具
功能:
1. 将图片按给定 patch 大小裁剪保存。
2. 生成一张带网格叠加的可视化图。
3. 可选择高亮某一个 patch(行、列索引,从 0 开始)。
"""
import argparse
from pathlib import Path
import cv2
from PIL import Image
def make_dirs(path: Path) -> None:
"""创建目录(若不存在)。"""
path.mkdir(parents=True, exist_ok=True)
def split_into_patches(
image_path: Path,
out_dir: Path,
patch_w: int,
patch_h: int,
drop_last: bool = True,
) -> None:
"""
将图片切成 patch 并保存到 out_dir/patches 下。
drop_last=True 时,不足一整块的边缘会被舍弃。
"""
img = Image.open(image_path).convert("RGB")
w, h = img.size
patches_dir = out_dir / "patches"
make_dirs(patches_dir)
patch_id = 0
for y in range(0, h, patch_h):
if drop_last and y + patch_h > h:
break
for x in range(0, w, patch_w):
if drop_last and x + patch_w > w:
break
box = (x, y, x + patch_w, y + patch_h)
patch = img.crop(box)
patch_file = patches_dir / f"patch_{patch_id:04d}_r{y//patch_h}_c{x//patch_w}.png"
patch.save(patch_file)
patch_id += 1
print(f"共保存 {patch_id} 个 patch 到 {patches_dir}")
def draw_grid_and_highlight(
image_path: Path,
out_path: Path,
patch_w: int,
patch_h: int,
line_color=(255, 255, 255),
line_thickness: int = 1,
highlight_row: int | None = None,
highlight_col: int | None = None,
highlight_color_outer=(255, 215, 0),
highlight_color_inner=(0, 160, 220),
highlight_thickness_outer: int = 4,
highlight_thickness_inner: int = 4,
) -> None:
"""
在图片上画网格线,并可选高亮某一格 patch。
highlight_row / highlight_col 为 patch 的行列索引(从 0 开始)。
"""
img = cv2.imread(str(image_path))
if img is None:
raise FileNotFoundError(f"Cannot read image: {image_path}")
h, w, _ = img.shape
# 画竖线
for x in range(0, w, patch_w):
cv2.line(img, (x, 0), (x, h), line_color, line_thickness)
# 画横线
for y in range(0, h, patch_h):
cv2.line(img, (0, y), (w, y), line_color, line_thickness)
# 高亮某个 patch
if highlight_row is not None and highlight_col is not None:
x1 = highlight_col * patch_w
y1 = highlight_row * patch_h
x2 = min(x1 + patch_w, w)
y2 = min(y1 + patch_h, h)
# 外层框
cv2.rectangle(
img,
(x1, y1),
(x2, y2),
highlight_color_outer,
thickness=highlight_thickness_outer,
)
# 内层框,稍微缩进一点,形成两层效果
offset = highlight_thickness_outer + 2
cv2.rectangle(
img,
(x1 + offset, y1 + offset),
(x2 - offset, y2 - offset),
highlight_color_inner,
thickness=highlight_thickness_inner,
)
cv2.imwrite(str(out_path), img)
print(f"网格可视化保存到: {out_path}")
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="图片 patch 划分工具")
parser.add_argument("--image", type=str, required=True, help="输入图片路径")
# 两种指定方式:1)给出 patch 像素大小;2)给出行列数
parser.add_argument("--patch_w", type=int, help="patch 宽度(像素)")
parser.add_argument("--patch_h", type=int, help="patch 高度(像素)")
parser.add_argument("--rows", type=int, help="按行数自动划分(例如 9 表示 9 行)")
parser.add_argument("--cols", type=int, help="按列数自动划分(例如 9 表示 9 列)")
parser.add_argument("--out_dir", type=str, required=True, help="输出目录(将自动创建)")
parser.add_argument(
"--keep_edge",
action="store_true",
help="默认丢弃不能整除的边缘;加上该参数则保留(仅影响网格线是否画到边缘)",
)
parser.add_argument(
"--no_split",
action="store_true",
help="只画网格,不切 patch",
)
parser.add_argument(
"--draw_grid",
action="store_true",
help="是否生成带网格叠加的图片",
)
parser.add_argument(
"--highlight_row",
type=int,
default=None,
help="要高亮 patch 的行索引(从 0 开始)",
)
parser.add_argument(
"--highlight_col",
type=int,
default=None,
help="要高亮 patch 的列索引(从 0 开始)",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
image_path = Path(args.image)
out_dir = Path(args.out_dir)
make_dirs(out_dir)
# 根据参数决定 patch 大小:
# - 若给定 patch_w/patch_h,则直接使用;
# - 否则若给定 rows/cols,则根据图片尺寸自动计算;
# - 其他情况视为参数错误。
img = Image.open(image_path)
img_w, img_h = img.size
if args.patch_w and args.patch_h:
patch_w = args.patch_w
patch_h = args.patch_h
elif args.rows and args.cols:
patch_w = img_w // args.cols
patch_h = img_h // args.rows
print(f"按 {args.rows}x{args.cols} 网格自动计算 patch 大小: {patch_w}x{patch_h}")
else:
raise ValueError(
"参数错误:需要二选一\n"
"1) 指定 --patch_w 和 --patch_h\n"
"2) 或者指定 --rows 和 --cols(例如 --rows 9 --cols 9)"
)
drop_last = not args.keep_edge
# 1. 切 patch
if not args.no_split:
split_into_patches(
image_path=image_path,
out_dir=out_dir,
patch_w=patch_w,
patch_h=patch_h,
drop_last=drop_last,
)
# 2. 生成带网格/高亮 patch 的可视化
if args.draw_grid:
grid_out_path = out_dir / "grid_visualization.png"
draw_grid_and_highlight(
image_path=image_path,
out_path=grid_out_path,
patch_w=patch_w,
patch_h=patch_h,
highlight_row=args.highlight_row,
highlight_col=args.highlight_col,
)
if __name__ == "__main__":
main()
3. 基本用法
激活虚拟环境后,在项目目录下运行:
cd /home/xxx/tool
source .venv/bin/activate
3.1 帮助信息
python image_patcher.py -h
可以看到主要参数(摘要):
- 必选
--image: 输入图片路径--out_dir: 输出目录(会自动创建)
- 划分方式(二选一)
--patch_w: patch 宽度(像素)--patch_h: patch 高度(像素)--rows: 按行数自动划分(例如 9 表示 9 行)--cols: 按列数自动划分(例如 9 表示 9 列)
- 可选功能
--draw_grid: 生成带网格叠加的图片--no_split: 只画网格,不实际裁剪 patch--keep_edge: 默认丢弃不能整除的边缘;加上该参数则网格线会画到图片最边缘--highlight_row: 需要高亮的 patch 行索引(从 0 开始)--highlight_col: 需要高亮的 patch 列索引(从 0 开始)
注意:需要二选一
- 要么指定
--patch_w和--patch_h- 要么指定
--rows和--cols
否则脚本会报参数错误。
4. 按像素大小划分示例
将图片按 32 x 32 像素 patch 切分,并生成带网格的可视化图:
python image_patcher.py \
--image '/home/xxx/tool/喜鹊.jpg' \
--patch_w 32 --patch_h 32 \
--out_dir /home/xxx/tool/output_xique_32 \
--draw_grid
运行后:
- 所有 patch 会保存在
output_xique_32/patches目录下 - 网格可视化图为
output_xique_32/grid_visualization.png
可以额外高亮某一块 patch(例如第 0 行第 1 列):
python image_patcher.py \
--image '/home/xxx/tool/喜鹊.jpg' \
--patch_w 32 --patch_h 32 \
--out_dir /home/xxx/tool/output_xique_32_hl \
--draw_grid \
--highlight_row 0 --highlight_col 1
5. 按行列数划分示例(9×9 网格)
如果你更习惯指定“网格行数 × 网格列数”,可以使用 --rows 和 --cols,脚本会根据图片尺寸自动算出每个 patch 的宽高。
以 喜鹊.jpg 为例,将其划分为 9×9 网格:
python image_patcher.py \
--image '/home/xxx/tool/喜鹊.jpg' \
--rows 9 --cols 9 \
--out_dir /home/xxx/tool/output_xique_9x9 \
--draw_grid
脚本会输出类似日志:
按 9x9 网格自动计算 patch 大小: 26x23
共保存 81 个 patch 到 /home/xxx/tool/output_xique_9x9/patches
网格可视化保存到: /home/xxx/tool/output_xique_9x9/grid_visualization.png
- 一共会得到 (9 \times 9 = 81) 个 patch
- 所有 patch 文件在
output_xique_9x9/patches目录中 - 网格可视化图是
output_xique_9x9/grid_visualization.png,上面能看到 9×9 的白色网格
5.1 高亮某一块 patch
例如高亮第 2 行第 3 列(索引从 0 开始)的 patch:
python image_patcher.py \
--image '/home/xxx/tool/喜鹊.jpg' \
--rows 9 --cols 9 \
--out_dir /home/xxx/tool/output_xique_9x9_hl \
--draw_grid \
--highlight_row 1 --highlight_col 2
生成的 grid_visualization.png 中,对应的 patch 会被金黄色和蓝色双层矩形框高亮,类似示例图片中的效果。
5.2 生成目录结构示例
以本仓库为例,分别运行 32×32 像素划分和 9×9 行列划分后,目录结构大致如下(省略部分 patch 文件):
/home/xxx/tool
├── image_patcher.py
├── README.md
├── 喜鹊.jpg
├── .venv/ # Python 虚拟环境(可选)
├── output_xique_32/ # 32x32 像素划分输出示例
│ ├── grid_visualization.png # 带 32x32 网格的整体可视化
│ └── patches/
│ ├── patch_0000_r0_c0.png
│ ├── patch_0001_r0_c1.png
│ ├── patch_0002_r0_c2.png
│ ├── ... # 其它 patch,命名中包含行列索引
├── output_xique_9x9/ # 9x9 行列划分输出示例
│ ├── grid_visualization.png # 带 9x9 网格的整体可视化
│ └── patches/
│ ├── patch_0000_r0_c0.png
│ ├── patch_0001_r0_c1.png
│ ├── patch_0002_r0_c2.png
│ ├── ... # 一共 81 个 patch
└── ...
每个 patch 文件名中都包含:
- 顺序编号:例如
patch_0007 - 行列索引:例如
_r2_c3表示第 3 行、第 4 列(索引从 0 开始)
这样在做调试或可视化时,可以很方便地根据文件名定位到原图中的具体位置。
5.3 可视化效果示例
如果你用自己的 Markdown 查看器或在 IDE 中打开本仓库,可以直接看到如下示意图(以下路径均相对于仓库根目录):
- 9×9 网格整体效果:

- 左上角 patch 示例(
patch_0000_r0_c0.png,对应第 0 行第 0 列):

- 如果你按 32×32 像素划分并生成了
output_xique_32目录,也可以类似地查看:
output_xique_32/grid_visualization.png
output_xique_32/patches/patch_0000_r0_c0.png
在大部分支持图片预览的 Markdown 工具(例如 VS Code、Cursor、Typora)中,这些路径会自动渲染为图片,从而直观展示脚本运行结果。
6. 参数说明小结
--image: 需要处理的图片路径(支持中文路径)--out_dir: 输出目录,若不存在会自动创建--patch_w/--patch_h: patch 的宽高(像素);与--rows/--cols不能混用--rows/--cols: 网格的行数和列数,用于自动计算 patch 大小--draw_grid: 是否生成带网格的可视化图--no_split: 若只想看网格,不想实际保存 patch,可以加上该参数--keep_edge: 默认会丢弃不能整除的边缘区域;加上该参数可以让网格线画到整张图的边缘(注意:当前裁剪逻辑仍按整块 patch 保存)--highlight_row/--highlight_col: 指定要高亮的 patch 的行、列索引(从 0 开始计数)
更多推荐
所有评论(0)