Pytorch机器学习(六)——YOLOV5中的自适应图片缩放letterbox

Pytorch机器学习(六)——YOLOV5中的自适应图片缩放letterbox

目录

Pytorch机器学习(六)——YOLOV5中的自适应图片缩放letterbox

前言

一、letterbox自适应图片缩放技术

一,计算收缩比

二,计算收缩后图片的长宽

三,计算需要填充的像素

四,最后resize图片并填充像素

二、代码总和

二、使用步骤

1.引入库

2.读入数据

总结


前言

YOLOV5中相比于之前的版本,有很多小trick,导致其性能和应用比较好。本文先讲讲在将图片输入网络前,对图片进行预处理的letterbox的自适应图片缩放技术


一、letterbox自适应图片缩放技术

在目标检测中,输入的图片尺寸有大有小,根据前人的实验结果,输入网络的尺寸统一缩放到同一个尺寸时,检测效果会更好(train中放入的图片并不经过letterbox,而是检测的时候使用letterbox

但这时就有个问题,如果是简单的使用resize,就会造成图片的失真,所以提出了letterbox自适应图片缩放技术。

下图即是经过letterbox处理的图片,图片被resize到640*640,且通过的是灰边来补齐缺边,很好的保留了图片的特征。

 而其实letterbox的实现也十分简单,以下将结合代码讲解步骤(下面所有的例子都以缩放到640*640为例。

一,计算收缩比

shape = im.shape[:2]  # current shape [height, width]
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])

这里的收缩比取的是长宽方向上变化范围最小的一个。

二,计算收缩后图片的长宽

new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))

三,计算需要填充的像素

这里其实就是在计算那个需要收缩比大的那一边需要填充的像素

# 计算需要填充的边的像素
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  
# stride表示的即是模型下采样次数的2的次方,这个涉及感受野的问题,在YOLOV5中下采样次数为5
# 则stride为32
dw, dh = np.mod(dw, stride), np.mod(dh, stride)  
dw /= 2  # 除以2即最终每边填充的像素
dh /= 2

四,最后resize图片并填充像素

if shape[::-1] != new_unpad:  # resize
    im = cv.resize(im, new_unpad, interpolation=cv.INTER_LINEAR)
# round(dw,dh - 0.1)直接让小于1的为0
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
# 添加灰边
im = cv.copyMakeBorder(im, top, bottom, left, right, cv.BORDER_CONSTANT, value=color) 

二、代码总和

def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, stride=32):
    # Resize and pad image while meeting stride-multiple constraints
    shape = im.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)
   
    # Scale ratio (new / old)
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])

    # Compute padding
    ratio = r, r  # width, height ratios
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
    if auto:  # minimum rectangle
        dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding

    dw /= 2  # divide padding into 2 sides
    dh /= 2
    print(dw, dh)
    if shape[::-1] != new_unpad:  # resize
        im = cv.resize(im, new_unpad, interpolation=cv.INTER_LINEAR)
    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    im = cv.copyMakeBorder(im, top, bottom, left, right, cv.BORDER_CONSTANT, value=color)  # add border
    return im, ratio, (dw, dh)

おすすめ

転載: blog.csdn.net/lzzzzzzm/article/details/120067557