双线性源码:https://blog.csdn.net/love_image_xie/article/details/87969405
五个都有的:https://blog.csdn.net/carson2005/article/details/22417587
opencv自带的函数:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR)
interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
使用注意事项:
1、dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像
resize(img, imgDst, Size(30,30));
要么你就让dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
2、至于最后的插值方法,正常情况下使用默认的双线性插值就够用了。
几种常用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值;
但是效率和效果成反比,所以根据自己的情况酌情使用。
3、正常情况下,在使用之前dst图像的大小和类型都是不知道的,类型从src图像继承而来,大小也是从原图像根据参数计算出来。但是如果你事先已经指定好dst图像的大小,那么你可以通过下面这种方式来调用函数:
resize(src, dst, dst.size(), 0, 0, interpolation);
#include
#include
#include
//
#include
//
using namespace cv;
using namespace std;
//实现双线性插值
void BilinearInterpolation(Mat &src, Mat &dst) {
int srcRows = src.rows;
int srcCols = src.cols;
//定义目标函数
int dstRows = dst.rows;
int dstCols = dst.cols;
//缩放因子(除法有小数的问题)
double sx = (double)src.cols / dst.cols;
double sy = (double)src.rows / dst.rows;
cout << sx << endl;
用的公式,f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
for(int i = 0; i < dst.rows; i++) {
//求目标图像像素对应原图的坐标,为了使得目标图像中心与原图像中心对齐,使用下面的公式
double index_i = (i + 0.5) * sy - 0.5;浮点行
//判断是否越界
if(index_i < 0) {
index_i = 0;
}
if(index_i > src.rows - 1) {
index_i = src.rows - 1;
}
int i1 = cvFloor(index_i);//向下取整
int i2 = cvCeil(index_i);//即向上取整
double v = index_i - i1;
for(int j = 0; j < dst.cols; j++) {
double index_j = (j + 0.5) * sx - 0.5;浮点列
if(index_j < 0) {
index_j = 0;
}
if(index_j > src.cols - 1) {
index_j = src.cols - 1;
}
int j1 = cvFloor(index_j);
int j2 = cvCeil(index_j);
double u = index_j - j1;
if(src.channels() == 1) {
dst.at<uchar>(i, j) = cvFloor((1 - u) * (1 - v) * src.at<uchar>(i1, j1) + (1 - u) * v * src.at<uchar>(i2, j1) + u * (1 - v) * src.at<uchar>(i1, j2) + u * v * src.at<uchar>(i2, j2));
} else {
dst.at<Vec3b>(i, j)[0] = cvFloor((1 - u) * (1 - v) * src.at<Vec3b>(i1, j1)[0] + (1 - u) * v * src.at<Vec3b>(i2, j1)[0] + u * (1 - v) * src.at<Vec3b>(i1, j2)[0] + u * v * src.at<Vec3b>(i2, j2)[0]);
dst.at<Vec3b>(i, j)[1] = cvFloor((1 - u) * (1 - v) * src.at<Vec3b>(i1, j1)[1] + (1 - u) * v * src.at<Vec3b>(i2, j1)[1] + u * (1 - v) * src.at<Vec3b>(i1, j2)[1] + u * v * src.at<Vec3b>(i2, j2)[1]);
dst.at<Vec3b>(i, j)[2] = cvFloor((1 - u) * (1 - v) * src.at<Vec3b>(i1, j1)[2] + (1 - u) * v * src.at<Vec3b>(i2, j1)[2] + u * (1 - v) * src.at<Vec3b>(i1, j2)[2] + u * v * src.at<Vec3b>(i2, j2)[2]);
}
}
}
}
int main() {
//1、读图
Mat src;
src = imread("../data/1.jpg");
cvtColor(src, src, COLOR_BGR2GRAY);
imshow("src", src);
//插值
Mat dst;
dst = Mat(Size(src.rows * 2, src.cols * 2), CV_8UC1, Scalar::all(0));
BilinearInterpolation(src, dst);
imshow("dst", dst);
---------opencv自带的插值函数------------------------------
// Mat dst2;
// cv::resize(src, dst2, dst1.size(), 0, 0, 1);//双线性
// //cv::resize(src, dst2, dst1.size(), 0, 0, 2);//双三次
// cv::imwrite("../save/3cvlinear2.jpg", dst2);
// imshow("cvdst2", dst2);
---------------------------------------------------
cout << dst.size << endl;
waitKey(0);
}