matlab resize_Python Pillow 和 OpenCV 中 resize 的区别

734875f76965284d3d773666f6f3d220.png

这篇文章的起因是之前在测试一个预训练好的动作识别模型时使用 OpenCV 进行 resize 和使用 PIL 的 resize 得到的结果完全不同,按照作者的方法使用 PIL 中双线性插值的 resize 可以得到正确的结果,而用 opencv-python 中双线性插值的 resize 却得到了完全错误的结果,改用 opencv-python 中 INTER_AREA 的 resize 可以得到近似但略差于正确的结果。于是在此比较一下 python 中常用的两个图像处理库 Pillow 和 OpenCV 中 resize 的区别,以及记录一下几个比较坑的地方。

目前来说 PIL 在深度学习里面用到的地方很多,很多项目都是用 PIL 来加载和处理图片,在TorchVision Transforms on PIL Image里就有很多针对 PIL Image 的方法。但对于视频的处理,首选肯定是用 OpenCV 来读取视频,VideoCapture 得到的图像是 numpy.array 的格式,如果先转成 PIL Image 再做 transform ,那样无疑会增加计算开销,如果直接使用 OpenCV 的函数来处理图片,又会造成结果相差很大(基于之前的一些经验)。

首先看下这两个库中 resize 的插值方法有哪些

OpenCV

  • INTER_NEAREST – 最近邻插值
  • INTER_LINEAR – 双线性插值(默认使用)
  • INTER_AREA – 使用像素区域关系进行重采样,对于图片缩小可能是优先使用的方法,因为不会产生有云纹但结果,但对于图片放大,它的作用类似于最近邻。其实这个方法在缩小图像时类似于 CNN 中的 average pooling,具体可以参考 OpenCV里的INTER_AREA究竟是在做啥?,云纹的理解可以参考 MATLAB: Decimation image
  • INTER_CUBIC – 在 4x4 的邻域上进行双立方插值,可以参考 Bicubic Interpolation 解释
  • INTER_LANCZOS4 – 在x,y方向分别对相邻的八个点进行插值,计算加权和

从使用角度来看,INTER_LINEAR 默认选择可以是万金油,但如果想要更好但效果,缩小图像可以选择 INTER_AREA,放大图像可以选择 INTER_CUBIC。Resize 的效果可以看cv2 resize interpolation methods

Pillow:

  • PIL.Image.NEAREST - 最近邻插值(在默认和图片的模式为 “1” 或 “P” 情况下使用)
  • PIL.Image.BILINEAR - 双线性插值(torchvision 默认使用)
  • PIL.Image.BICUBIC - 双立方插值
  • PIL.Image.LANCZOS - 一个高质量的下采样过滤器

进入正题

众所周知,在广大人民群众所喜爱的 PyTorch 框架中,很多开源的模型受官方 torchvision 的影响,在对图像进行处理时往往使用 PIL Image 进行 Resize 和 Random Crop 之类的操作,而在日常使用中,往往会用到 OpenCV 来进行图片处理或者视频抽帧,但是这两者在 Resize 操作上有些许的不同,而最终会在一定程度上影响网络的输出,下面来看一段代码,所有代码均可直接食用。示例图片采用的是dogs-and-cats,也就是封面的这张图

import 

索引 247、167、235 分别是圣伯纳犬、英国猎狐犬和德国牧羊犬,所以某种程度上来说分类结果的大致方向是一样的,但是细节不同,最终可能会影响 top1 的准确率。

实际上用 OpenCV 读取的这张图片,不论使用那种插值方法,最后的结果是一样的,而 Pillow Image 使用不同的 resample 方法,结果会改变,Image.NEAREST 反而和 cv2.INTER_LINEAR 的结果相接近。当然,以上结果换一张图片很可能就不一样了。

对于这种情况,网上也有很多相关的讨论,大致的说法是 cv2 和 pillow 选择的像素点不同,具体可以看`Pillow` vs `cv2` resize,里面有比较详细的图例和解释。

如果也想用 GIF 图来查看结果 ,可以这样

import imageio

pil_img = Image.open('dogs-and-cats.jpg')
cv2_img = cv2.imread('dogs-and-cats.jpg')

pil_img = pil_img.resize((320, 320), Image.BILINEAR)
cv2_img = cv2.resize(cv2_img, (320, 320), cv2.INTER_LINEAR)

gif_images = [pil_img, cv2_img_t]
imageio.mimsave("diff.gif", gif_images, fps=0.5)

9332898a74d96fb1790de184efaa6a3a.gif

个人感觉肉眼只能勉强感受到清晰度上有一些不同,但是输入到网络中还是产生了不小的区别,所以在训练和测试中如果使用了不同的图像处理库,还是应当注意一下这方面的区别。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值