opencv中的resize插值方式比较

在做深度学习yolov3目标检测训练时,通常需要对原始图片做resize,把图片的尺寸缩放416x416。然而,opencv提供的resize函数里有多种插值方式,最常见使用的是INTER_LINEAR(双线性插值)和INTER_NEAREST(最近邻插值)。在github上pytorch版本的yolov3的star数量最多的的是https://github.com/ultralytics/yolov3https://github.com/eriklindernoren/PyTorch-YOLOv3这两个,分别打开这两个工程,找到它们的图象预处理resize函数。可以看到,在https://github.com/ultralytics/yolov3工程里,对图片resize是在utils/datasets.py文件的letterbox函数里,代码片段是:

看后面的注释说INTER_AREA是最好的,INTER_LINEAR是最快的,并且letterbox函数的输入参数interp默认是INTER_AREA。而在https://github.com/eriklindernoren/PyTorch-YOLOv3/blob/master/utils/datasets.py工程里,对图片resize依然是在utils/datasets.py文件里,代码片段是:

可以看到,是用pytorch提供的插值函数,插值方式是最近邻插值。查看pytorch提供的关于interpolate的文档,它是由area这个插值方式的,如图所示

而在utils/datasets.py文件里的resize函数里插值方式是固定的,没有作为输入参数传进来。接下来,我们就来比较一下,在opencv提供的resize函数里,INTER_AREA,INTER_LINEAR和INTER_NEAREST这三种插值方式的区别。我们先用手机拍一张图片

手机拍摄的图片都是长方形的,图片高度大于宽度。分别用opencv提供的resize函数的三种插值方式,对原图resize到416x416。python程序如下:

import cv2

if __name__=='__main__':
    imgpath = 'srcimg.jpg'
    img = cv2.imread(imgpath)
    print('srcimg.shape = ', img.shape)
    
    img1 = cv2.resize(img, (416, 416), interpolation=cv2.INTER_AREA)
    img2 = cv2.resize(img, (416, 416), interpolation=cv2.INTER_LINEAR)
    img3 = cv2.resize(img, (416, 416), interpolation=cv2.INTER_NEAREST)

    cv2.imwrite('INTER_AREA.jpg', img1)
    cv2.imwrite('INTER_LINEAR.jpg', img2)
    cv2.imwrite('INTER_NEAREST.jpg', img3)
    cv2.namedWindow('INTER_AREA', cv2.WINDOW_NORMAL)
    cv2.imshow('INTER_AREA', img1)
    cv2.namedWindow('INTER_LINEAR', cv2.WINDOW_NORMAL)
    cv2.imshow('INTER_LINEAR', img2)
    cv2.namedWindow('INTER_NEAREST', cv2.WINDOW_NORMAL)
    cv2.imshow('INTER_NEAREST', img3)

    dif = img1 - img2
    dif = dif.astype(np.float32)
    err = np.mean(np.abs(dif))
    print('INTER_AREA with INTER_LINEAR : mean_error =', err, 'max_error =', np.max(np.abs(dif)), 'min_err =',     np.min(np.abs((dif))))

    dif = img1 - img3
    dif = dif.astype(np.float32)
    err = np.mean(np.abs(dif))
    print('INTER_AREA with INTER_NEAREST : mean_error =', err, 'max_error =', np.max(np.abs(dif)), 'min_err =',
          np.min(np.abs((dif))))

    cv2.waitKey(0)
    cv2.destroyAllWindows()

在Pycharm里运行程序后,得到三种插值的结果图片,INTER_AREA的结果是:

INTER_LINEAR的结果是

INTER_NEAREST的结果是

从图片质量上看,INTER_AREA明显优于INTER_LINEAR和INTER_NEAREST的,在INTER_LINEAR和INTER_NEAREST的图片中有很多瑕疵,纸币中的数字模糊不清。计算resize后的图片像素差异的情况如下:

可以看到INTER_AREA与INTER_LINEAR和INTER_NEAREST的差异还是蛮大的。

INTER_LINEAR和INTER_NEAREST的插值计算原理,在网上可以找到很多文章介绍说明。而INTER_AREA的插值计算原理,在网上能找到的文章很少,知乎上有篇文章介绍INTER_AREA的。链接是https://zhuanlan.zhihu.com/p/38493205

猜你喜欢

转载自blog.csdn.net/nihate/article/details/104531580