在做深度学习yolov3目标检测训练时,通常需要对原始图片做resize,把图片的尺寸缩放416x416。然而,opencv提供的resize函数里有多种插值方式,最常见使用的是INTER_LINEAR(双线性插值)和INTER_NEAREST(最近邻插值)。在github上pytorch版本的yolov3的star数量最多的的是https://github.com/ultralytics/yolov3和https://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