美文网首页
OpenCV的resize方法与双线性插值

OpenCV的resize方法与双线性插值

作者: Aspirinrin | 来源:发表于2018-02-08 16:35 被阅读2835次

    训练Object Detection模型SSD完毕之后进入test阶段,每张图像在进入输入层之前需要进行resize操作,以满足CNN模型对输入层size的要求。本文首先介绍了Caffe实现的SSD模型对输入图像的变换规定,引出了OpenCV中的resize方法,最后介绍该方法中的插值参数cv.INTER_LINEAR和该插值方法的原理。

    caffe_ssd

    caffe_ssd在test阶段,对图像的变换设置如下:

    test_transform_param = {
            'mean_value': [104, 117, 123],
            'force_color': True,
            'resize_param': {
                    'prob': 1,
                    'resize_mode': P.Resize.WARP,
                    'height': resize_height,
                    'width': resize_width,
                    'interp_mode': [P.Resize.LINEAR],
                    },
            }
    

    以上设定来自ssd_coco.py

    • 'mean_value': [104, 117, 123]是ImageNet图像BGR三个通道的均值。每张图像分别需要减去相应通道的均值,实现中心化。
    • 'force_color': True强制采用彩色BGR图像模式,防止灰度图像维度与SSD模型输入层维度不一致。
    • resize_param属性在caffe.proto的ResizeParameter中有说明
      // Message that stores parameters used by data transformer for resize policy
      message ResizeParameter {
        //Probability of using this resize policy
        optional float prob = 1 [default = 1];
      
        enum Resize_mode {
          WARP = 1;
          FIT_SMALL_SIZE = 2;
          FIT_LARGE_SIZE_AND_PAD = 3;
        }
        optional Resize_mode resize_mode = 2 [default = WARP];
        optional uint32 height = 3 [default = 0];
        optional uint32 width = 4 [default = 0];
        // A parameter used to update bbox in FIT_SMALL_SIZE mode.
        optional uint32 height_scale = 8 [default = 0];
        optional uint32 width_scale = 9 [default = 0];
      
        enum Pad_mode {
          CONSTANT = 1;
          MIRRORED = 2;
          REPEAT_NEAREST = 3;
        }
        // Padding mode for BE_SMALL_SIZE_AND_PAD mode and object centering
        optional Pad_mode pad_mode = 5 [default = CONSTANT];
        // if specified can be repeated once (would fill all the channels)
        // or can be repeated the same number of times as channels
        // (would use it them to the corresponding channel)
        repeated float pad_value = 6;
      
        enum Interp_mode { //Same as in OpenCV
          LINEAR = 1;
          AREA = 2;
          NEAREST = 3;
          CUBIC = 4;
          LANCZOS4 = 5;
        }
        //interpolation for for resizing
        repeated Interp_mode interp_mode = 7;
      }
      
      其中的interp_mode采用LINEAR模式对图像进行Resize操作,与Opencv中的resize一致。

    接下来,我们具体介绍一下OpenCV中的resize方法。

    resize方法的签名

    C++:   
    void cv::resize (InputArray src,
        OutputArray             dst,
        Size                      dsize,
        double                  fx = 0,
        double                  fy = 0,
        int                       interpolation = INTER_LINEAR
    )       
    Python:   
    dst =   cv.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
    

    参数说明:

    src 输入图像.
    dst 输出图像; 其size为dsize,或由src.size()、fx与fy计算而得; dst类型与src保持一致.   
    dsize 输出图像的size; 如果设为0,或(0, 0), 计算方式为:
        𝚍𝚜𝚒𝚣𝚎 = 𝚂𝚒𝚣𝚎(𝚛𝚘𝚞𝚗𝚍(𝚏𝚡*𝚜𝚛𝚌.𝚌𝚘𝚕𝚜), 𝚛𝚘𝚞𝚗𝚍(𝚏𝚢*𝚜𝚛𝚌.𝚛𝚘𝚠𝚜))
    dsize和(fx, fy)必须有一组不为0. 如果都为0,无法确定被resize后的图像大小
    fx  水平轴缩放因子; 等于0时,计算方式为:
        (𝚍𝚘𝚞𝚋𝚕𝚎)𝚍𝚜𝚒𝚣𝚎.𝚠𝚒𝚍𝚝𝚑/𝚜𝚛𝚌.𝚌𝚘𝚕𝚜
    fy  竖直轴缩放因子; 等于0时,计算方式为:
        (𝚍𝚘𝚞𝚋𝚕𝚎)𝚍𝚜𝚒𝚣𝚎.𝚑𝚎𝚒𝚐𝚑𝚝/𝚜𝚛𝚌.𝚛𝚘𝚠𝚜
    interpolation   差值方法, 方法见InterpolationFlags
    

    InterpolationFlags
    缩小图像时,一般INTER_AREA插值效果较好。放大图像时, INTER_CUBIC (slow)更好些,或INTER_LINEAR (faster but still looks OK)。

    Resize Image Example

    import cv2 as cv
    img = cv.imread('./lena.jpg')
    h, w = img.shape[:2]
    # 缩小图像到原来一半大小,方法一,设置dsize
    dst = cv.resize(img, (h//2, w//2), None, 0, 0, cv.INTER_LINEAR)
    cv.imwrite('./lena1.jpg', dst)
    # 缩小图像到原来一半大小,方法二,设置fx和fy
    dst = cv.resize(src=img, dsize=None, fx=0.5, fy=0.5, interpolation=cv.INTER_LINEAR)
    cv.imwrite('./lena2.jpg', dst)
    

    cv.INTER_LINEAR的原理

    resize方法提供了9种插值参数,Caffe中支持的5种分别是

    • 最近邻插值法 cv.INTER_NEAREST
    • 双线性插值法 cv.INTER_LINEAR
    • 双三次插值法 cv.INTER_CUBIC
    • 区域插值法 cv.INTER_AREA
    • 兰索斯插值法 cv.INTER_LANCZOS4

    下面具体介绍一下双线性插值法,这种插值方法最易于理解,也应用最多。

    首先,在x轴方向进行线性插值:蓝色点得到绿色点 x轴方向线性插值 然后,在y轴方向进行线性插值:绿色点得到橙色点 y轴方向线性插值 最后,简化为矩阵变换的形式: 双线性插值的矩阵变换表达

    相关文章

      网友评论

          本文标题:OpenCV的resize方法与双线性插值

          本文链接:https://www.haomeiwen.com/subject/csbttftx.html