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:指定输出目录
相关推荐
零壹AI实验室1 小时前
AI发现潜伏18年的NGINX高危漏洞:CVE-2026-42945完整技术分析
运维·人工智能·nginx
Zy_Yin1231 小时前
拆解如何用anthropic金融agent做投研
人工智能·python·深度学习·金融·github
YueJoy.AI1 小时前
创业团队如何建立客户成功体系
人工智能·ai·语言模型
weixin_468466851 小时前
机器学习数据预处理新手实战指南
人工智能·python·算法·机器学习·编程·数据预处理
zhangfeng11331 小时前
glibc = GNU C Library (GNU C 标准库)CentOS 7 (glibc 2.17) pip支持
c语言·人工智能·神经网络·机器学习·centos·gnu
啦啦啦_99991 小时前
4. 机器翻译任务
人工智能·自然语言处理·机器翻译
Rain5091 小时前
mini-cc 权限安全:给 AI 戴上枷锁
前端·人工智能·安全·架构·node.js·ai编程
春日见1 小时前
自动驾驶数据驱动规控进化之路
运维·服务器·人工智能·深度学习·算法·机器学习·自动驾驶
帅次1 小时前
AI数字营销实战测评:CSDN AI智选主题如何提升技术博客创作效率与质量?
人工智能·深度学习·机器学习·语言模型·自然语言处理·数据挖掘·知识图谱