文章目录

一、插值算法

由于图片存储的时候其实就是一个矩阵,所以在对图像进行缩放操作的时候,也就是在对矩阵进行操作。如果想要将图片放大,这里我们就需要用到过采样算法来扩大矩阵,利用欠采样来缩小图像。

opencv 官网关于插值算法介绍:InterpolationFlags

​https://docs.opencv.org/master/d7/da8/tutorial_table_of_content_imgproc.html​

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_#include

最近邻插值(Nearest Interpolation)

黑色的×表示需要插入的值,它会选择距离它最近的 OpenCV + CPP 系列(十三)插值算法 与 图像缩放_插值_02的值来作为它的值。当插入的值距离四个点都相等时,会选择距离最近的左上角的值。

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_线性插值_03

线性插值(Linear interpolation)

这里的线性插值其实是指双线性插值,这种插值算法也是resize函数中默认使用的插值算法。
假设我们已知坐标 OpenCV + CPP 系列(十三)插值算法 与 图像缩放_opencv_04OpenCV + CPP 系列(十三)插值算法 与 图像缩放_opencv_05,我们想要得到在区间 OpenCV + CPP 系列(十三)插值算法 与 图像缩放_opencv_06

其实 P 点的值等于周围四个点(OpenCV + CPP 系列(十三)插值算法 与 图像缩放_#include_07)与P点所构成的四个对角矩形面积的加权平均。

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_插值_08

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_opencv_09

双三次插值(Bicubic interpolation)

双三次插值是一种更加复杂的插值算法,是二维空间中最常用的插值算法,相对双线性插值的图像边缘更加平滑,函数 OpenCV + CPP 系列(十三)插值算法 与 图像缩放_#include_10 在点 OpenCV + CPP 系列(十三)插值算法 与 图像缩放_插值_11的值可以通过矩形网格中最近的十六个采样点的加权平均得到,这里需要使用两个多项式插值三次函数,每个方向使用一个。

双三次插值常用的BiCubic函数如下图

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_插值_12

区域插值(Area interpolation)

区域插值算法主要分两种情况,缩小图像和放大图像的工作原理并不相同。

  • 缩小图像
    如果图像缩小的比例是整数倍,在调用INTER_LINEAR_EXACT插值算法时,
    如果图像的宽和高的缩小比例都是2,而且图像的通道数不是2,实际上会调用INTER_AREA。在调用INTER_LINEAR时,如果图像的宽和高的缩小比例都是2,实际上是会调用INTER_AREA。
    INTER_AREA实际上是个box filter,类似于均值滤波器。
  • 放大图像
    如果放大图像的比例是整数倍,与最近邻插值相似。
    如果放大的比例不是整数倍,则会采用线性插值。

Lanczos插值

Lanczos插值属于一种模板算法,需要通过计算模板中的权重信息来计算 x对应的值。

对于一维信息,假如我们输入的点集为 X,那么,Lanczos对应有个窗口模板Window,窗口中每个位置的权重计算如下:

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_插值_13

插值算法耗时比较

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_#include_14

二、图像缩放

头文件 ​​quick_opencv.h​​:声明类与公共函数

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;

class QuickDemo {
public:
...
void resize_Demo(Mat& image);
};

主函数调用该类的公共成员函数

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;


int main(int argc, char** argv) {
Mat src = imread("D:\\Desktop\\pandas.jpg");
if (src.empty()) {
printf("Could not load images...\n");
return -1;
}
namedWindow("input", WINDOW_NORMAL);
imshow("input", src);

QuickDemo qk;

...
//qk.polyline_drawing_Demo();
qk.resize_Demo(src);
waitKey(0);
destroyAllWindows();
return 0;
}

源文件 ​​quick_demo.cpp​​:实现类与公共函数

void QuickDemo::resize_Demo(Mat& image) {
Mat zoomin , zoomout;
int h = image.rows;
int w = image.cols;
resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR); //缩小1倍
resize(image, zoomout, Size(w * 1.5, h * 1.5), 0, 0, INTER_LINEAR); //放大1.5倍
imshow("zoomin", zoomin);
imshow("zoomout", zoomout);
}

从左至右:缩小、原图、放大

OpenCV + CPP 系列(十三)插值算法 与 图像缩放_opencv_15