文章目录
一、插值算法
由于图片存储的时候其实就是一个矩阵,所以在对图像进行缩放操作的时候,也就是在对矩阵进行操作。如果想要将图片放大,这里我们就需要用到过采样算法来扩大矩阵,利用欠采样来缩小图像。
opencv 官网关于插值算法介绍:InterpolationFlags
https://docs.opencv.org/master/d7/da8/tutorial_table_of_content_imgproc.html
最近邻插值(Nearest Interpolation)
黑色的×表示需要插入的值,它会选择距离它最近的 P ( x + 1 , y ) P_{(x+1,y)} P(x+1,y)的值来作为它的值。当插入的值距离四个点都相等时,会选择距离最近的左上角的值。
线性插值(Linear interpolation)
这里的线性插值其实是指双线性插值,这种插值算法也是resize函数中默认使用的插值算法。
假设我们已知坐标
(
x
0
,
y
0
)
(x_0 , y_0)
(x0,y0) 与
(
x
1
,
y
1
)
( x_1 , y_1 )
(x1,y1),我们想要得到在区间
[
x
0
,
x
1
]
[x_0,x_1]
[x0,x1] 上任意位置 x 所对应y的值,如下图所示
其实 P 点的值等于周围四个点(
Q
12
,
Q
22
,
Q
11
,
Q
21
Q_{12}, Q_{22}, Q_{11}, Q_{21}
Q12,Q22,Q11,Q21)与P点所构成的四个对角矩形面积的加权平均。
双三次插值(Bicubic interpolation)
双三次插值是一种更加复杂的插值算法,是二维空间中最常用的插值算法,相对双线性插值的图像边缘更加平滑,函数 f f f 在点 ( x , y ) (x,y) (x,y)的值可以通过矩形网格中最近的十六个采样点的加权平均得到,这里需要使用两个多项式插值三次函数,每个方向使用一个。
双三次插值常用的BiCubic函数如下图
区域插值(Area interpolation)
区域插值算法主要分两种情况,缩小图像和放大图像的工作原理并不相同。
- 缩小图像
如果图像缩小的比例是整数倍,在调用INTER_LINEAR_EXACT插值算法时,
如果图像的宽和高的缩小比例都是2,而且图像的通道数不是2,实际上会调用INTER_AREA。在调用INTER_LINEAR时,如果图像的宽和高的缩小比例都是2,实际上是会调用INTER_AREA。
INTER_AREA实际上是个box filter,类似于均值滤波器。 - 放大图像
如果放大图像的比例是整数倍,与最近邻插值相似。
如果放大的比例不是整数倍,则会采用线性插值。
Lanczos插值
Lanczos插值属于一种模板算法,需要通过计算模板中的权重信息来计算 x对应的值。
对于一维信息,假如我们输入的点集为 X,那么,Lanczos对应有个窗口模板Window,窗口中每个位置的权重计算如下:
插值算法耗时比较
二、图像缩放
头文件 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);
}
从左至右:缩小、原图、放大