opencv-实现双线性插值

双线性源码: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);
}






你可能感兴趣的:(opencv)