OpenCV 图像缩放实验

OpenCV 图像缩放实验报告

一、实验目的

  1. 完成 OpenCV 在本地(WSL2 + VSCode)的部署。
  2. 利用 OpenCV 对手机拍摄图像进行尺寸变换,掌握 cv2.resize 的基本用法。
  3. 分析直接缩放导致的几何失真问题,实现等比缩放 + 黑边填充(letterbox)方案,使图像在指定画布中无失真居中显示。

二、实验环境

项目 配置
操作系统 Windows 11 + WSL2 (Ubuntu 22.04)
Python 3.11 (conda 虚拟环境 cv_env)
OpenCV 4.10.0 (opencv-python + opencv-contrib-python)
编辑器 VS Code + WSL Remote 扩展
其他依赖 NumPy ≥ 1.26

部署命令摘要:

bash 复制代码
conda create -n cv_env python=3.11 -y
conda activate cv_env
pip install opencv-python opencv-contrib-python numpy

三、原理分析

3.1 直接缩放(任务 2)

直接调用 cv2.resize(img, (W_dst, H_dst))独立对水平和垂直方向做线性映射:

x′=x⋅WdstWsrc,y′=y⋅HdstHsrc x' = x \cdot \frac{W_{dst}}{W_{src}}, \quad y' = y \cdot \frac{H_{dst}}{H_{src}} x′=x⋅WsrcWdst,y′=y⋅HsrcHdst

当 WdstWsrc≠HdstHsrc\frac{W_{dst}}{W_{src}} \neq \frac{H_{dst}}{H_{src}}WsrcWdst=HsrcHdst 时,两方向缩放比不同,图像几何形状被改变 ------ 圆变椭圆,正方形变矩形。手机照片常见长宽比为 4:3 或 16:9,直接缩放到 1:1 必然发生这种失真。

3.2 等比缩放 + 黑边填充(任务 3,Letterbox)

为保持原图几何比例不变,水平和垂直方向必须使用同一缩放比

s=min⁡(WdstWsrc, HdstHsrc) s = \min\left(\frac{W_{dst}}{W_{src}},\ \frac{H_{dst}}{H_{src}}\right) s=min(WsrcWdst, HsrcHdst)

取较小者,保证缩放后图像两个方向都不超过目标画布。缩放后图像尺寸为:

Wnew=⌊Wsrc⋅s⌉,Hnew=⌊Hsrc⋅s⌉ W_{new} = \lfloor W_{src} \cdot s \rceil, \quad H_{new} = \lfloor H_{src} \cdot s \rceil Wnew=⌊Wsrc⋅s⌉,Hnew=⌊Hsrc⋅s⌉

然后在 Wdst×HdstW_{dst} \times H_{dst}Wdst×Hdst 的黑色画布上居中粘贴,左上角偏移:

top=⌊Hdst−Hnew2⌋,left=⌊Wdst−Wnew2⌋ \text{top} = \left\lfloor \frac{H_{dst} - H_{new}}{2} \right\rfloor, \quad \text{left} = \left\lfloor \frac{W_{dst} - W_{new}}{2} \right\rfloor top=⌊2Hdst−Hnew⌋,left=⌊2Wdst−Wnew⌋

这种方法在深度学习目标检测(YOLO、SSD 等)中是标准的输入预处理方式,因为变形会显著影响检测精度。

3.3 插值方法选择

OpenCV resizeinterpolation 参数对结果有影响:

缩放方向 推荐方法 原因
缩小 (scale < 1) cv2.INTER_AREA 基于像素区域加权平均,抗锯齿、保留细节
放大 (scale > 1) cv2.INTER_CUBICINTER_LINEAR 三次插值更平滑,线性更快

本实验中两个函数都根据缩放方向自动选择插值方法。

四、核心代码

完整代码见附件 opencv_homework.py,关键函数如下。

4.1 直接缩放

python 复制代码
def resize_direct(img: np.ndarray, target_size: int = 1024) -> np.ndarray:
    h, w = img.shape[:2]
    interp = cv2.INTER_AREA if target_size < max(h, w) else cv2.INTER_CUBIC
    return cv2.resize(img, (target_size, target_size), interpolation=interp)

4.2 Letterbox 等比缩放

python 复制代码
def resize_letterbox(img, target_size=1024, pad_color=(0, 0, 0)):
    h, w = img.shape[:2]
    # 1) 计算等比缩放比
    scale = min(target_size / h, target_size / w)
    new_w, new_h = int(round(w * scale)), int(round(h * scale))
    # 2) 缩放
    interp = cv2.INTER_AREA if scale < 1 else cv2.INTER_CUBIC
    resized = cv2.resize(img, (new_w, new_h), interpolation=interp)
    # 3) 居中粘贴到目标画布
    canvas = np.full((target_size, target_size, 3), pad_color, dtype=np.uint8)
    top  = (target_size - new_h) // 2
    left = (target_size - new_w) // 2
    canvas[top:top + new_h, left:left + new_w] = resized
    return canvas

五、实验结果

5.1 输入

测试图像为模拟手机照片,尺寸 4032 × 3024 ,长宽比 4:3 ≈ 1.333,含网格线、同心圆、四角彩色方块用于直观判断变形情况。

5.2 输出三联对比

(左:原图缩略;中:直接缩放;右:letterbox 等比缩放)

5.3 定量与定性分析

指标 直接缩放 Letterbox 等比缩放
输出尺寸 1024 × 1024 ✅ 1024 × 1024 ✅
横向缩放比 1024/4032 ≈ 0.254 1024/4032 ≈ 0.254
纵向缩放比 1024/3024 ≈ 0.339 1024/4032 ≈ 0.254
圆是否仍为圆 ❌ 变成椭圆(垂直拉伸 ≈ 33%) ✅ 保持圆形
正方形是否仍为正方形 ❌ 变成矩形 ✅ 保持正方形
文字是否变形 ❌ 字符竖向变胖 ✅ 不变形
有效图像占比 100%(但形变) 1024×768 / 1024² ≈ 75%
填充区域 上下各 128 像素黑边

直接缩放横纵比相差 33.3%,对应中心圆的垂直直径被拉长约 1/3,肉眼极易察觉。Letterbox 方案以损失 25% 画布面积(变为黑色填充)为代价,换得完整保留原图几何信息。

5.4 控制台输出

复制代码
[输入] sample_photo.jpg  尺寸: 4032 x 3024  长宽比: 1.3333
[任务2] 直接缩放 -> output/02_direct_1024x1024.jpg  尺寸: 1024x1024 (已变形)
[任务3] 等比缩放 -> output/03_letterbox_1024x1024.jpg  尺寸: 1024x1024 (无变形)
[对比图] -> output/04_compare.jpg

六、讨论与扩展

  1. 填充颜色的选择 :本实验用纯黑 (0,0,0)。若用于神经网络输入,常用 (114,114,114) 灰色(YOLOv5 默认),原因是灰色更接近自然图像的均值,引入的偏差小。
  2. 舍入误差int(round(w*scale)) 可能让 new_w 比目标少 1 像素,导致左右黑边不完全对称。生产环境可对最右/最下一行单独 pad 一像素。
  3. 逆变换 :若后续要把检测框坐标映射回原图,需要保留 scale, top, left 三个参数,按 x_orig = (x_pad - left) / scale 反推。这是检测/分割任务后处理的常见步骤。
  4. 替代方案 :除了黑边填充,还可以用 center crop (中心裁剪)或 reflect padding(镜像填充),各有适用场景;本实验按作业要求使用黑边填充。

七、结论

  1. 成功在 WSL2 + VSCode 环境部署了 OpenCV 4.10。
  2. 验证了 cv2.resize 直接缩放在长宽比不匹配时会引入几何失真。
  3. 通过 letterbox 算法(等比缩放 + 中心粘贴 + 黑边填充)实现了无失真的 1024×1024 输出,代码可作为后续 CV 项目的通用预处理工具。

附录:完整运行方式

bash 复制代码
# 激活环境
conda activate cv_env

# 运行(输入你的手机照片路径)
python opencv_homework.py /path/to/your_photo.jpg -o ./output

# 默认输出目录 ./output/ 下包含:
#   02_direct_1024x1024.jpg     - 任务 2 结果
#   03_letterbox_1024x1024.jpg  - 任务 3 结果
#   04_compare.jpg              - 三联对比图

可选参数:

  • --size 512:改为缩放到其他边长
  • -o ./out:指定输出目录
相关推荐
神奇霸王龙3 分钟前
2026旗舰六阶段MCP流水线实战指南
人工智能·ai·ai作画·prompt·aigc·mcp
山河不见老5 分钟前
【Cursor 、Qoder安装问题】Cursor 、Qoder安装卡在“正在准备安装”问题排查及解决
人工智能·windows·编辑器
新知图书5 分钟前
2.3 开发工作流
人工智能·agent·ai agent·智能体
tuanxiang8 分钟前
用免费 AI 改写工具处理批量文案的踩坑记录,附完整降噪脚本
人工智能
小邓的技术笔记8 分钟前
DeepSeek 大模型落地应用与场景实战指南
大数据·人工智能
石榴14 分钟前
从 Codex + Obsidian 到本地 RAG:我的私人知识库实践
人工智能
QZSJTR19 分钟前
技术解析|从SEO到GEO:生成式搜索时代实体企业数字化适配方案
人工智能
安逸sgr20 分钟前
如何减少 Prompt 引起的幻觉和答非所问?
人工智能·ai·大模型·prompt·agent·智能体
Vince的修炼之路20 分钟前
大模型 Skills 技术深度分析
人工智能·架构
小码哥哥22 分钟前
企业级AI知识库:高效安全的知识管理新范式
人工智能·安全