双线性插值简介及C++代码实现

这篇具有很好参考价值的文章主要介绍了双线性插值简介及C++代码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

双线性插值是指现在某个方向进行两次线性插值,之后在另外一个方向对插值的结果再进行一次线性插值。以下图为例,已知 Q 11 Q_{11} Q11 Q 12 Q_{12} Q12 Q 21 Q_{21} Q21 Q 22 Q_{22} Q22四个点的坐标和像素值、 P P P点的坐标,求 P P P点的像素值。双线性插值的做法是首先在 x x x方向上做两次线性插值获得 R 1 R_{1} R1点和 R 2 R_{2} R2点的像素值,之后在 y y y方向上做一次线性插值获得 P P P点的像素值。

c++双线性插值,c++,算法,opencv

代码实现

在实际处理的过程中,依次遍历目标 M a t Mat Mat所有像素点 ( x , y ) (x,y) (x,y),找到像素点 ( x , y ) (x,y) (x,y)在原 M a t Mat Mat上的对应点 ( s x , s y ) (s_{x},s_{y}) (sx,sy)。由于 s x s_{x} sx s y s_{y} sy的值可能不是整数,所以取最接近的四个点进行双线性插值。话不多说,直接来看c++代码。

Mat sxxcz1(Mat img, int h, int w) {
    Mat img2(h, w,  CV_8UC3, Scalar::all(0));
    float ori_h = img.rows;
    float ori_w = img.cols;
    float rate_h = ori_h / h;
    float rate_w = ori_w / w;
    for (int i = 0; i < h; i++) {
        float f_h = i * rate_h;
        int s_h = cvFloor(f_h);
        f_h -= s_h;
        
        if (s_h < 0) {
            f_h = 0, s_h = 0;
        } 
        if (s_h >= ori_h - 1) {
            f_h = 1, s_h = ori_h - 2;
        }

        for (int j = 0; j < w; j++) {
            
            float f_w = j * rate_w;
            int s_w = cvFloor(f_w);
            f_w -= s_w;
            
            if (s_w < 0) {
                f_w = 0, s_w = 0;
            } 
            if (s_w >= ori_w - 1) {
                f_w = 1, s_w = ori_w - 2;
            }

            for (int k = 0; k < img.channels(); k++) {
                img2.at<Vec3b>(i, j)[k] = (1 - f_h) * (1 - f_w) * img.at<Vec3b>(s_h, s_w)[k] 
                                        + (1 - f_h) * f_w * img.at<Vec3b>(s_h, s_w + 1)[k]
                                        + f_h * (1 - f_w) * img.at<Vec3b>(s_h + 1, s_w)[k] 
                                        + f_h * f_w * img.at<Vec3b>(s_h + 1, s_w + 1)[k];
            }
        }
    }
    return img2;
}

效果展示如下:
c++双线性插值,c++,算法,opencv

c++双线性插值,c++,算法,opencv
但是在使用上面的代码处理比较简单的图像时,放大后的图像会有明显的违和感。
c++双线性插值,c++,算法,opencvc++双线性插值,c++,算法,opencv
针对这个问题,查阅了一下官方代码的源码,发现在计算周围四个点的权重时,官方使用的代码更合理,于是对自己的代码进行了修改。修改后的代码如下:

Mat sxxcz2(Mat img, int h, int w) {
    Mat img2(h, w,  CV_8UC3, Scalar::all(0));
    float ori_h = img.rows;
    float ori_w = img.cols;
    float rate_h = ori_h / h;
    float rate_w = ori_w / w;
    for (int i = 0; i < h; i++) {
        float f_h = ((i + 0.5) * rate_h - 0.5);
        int s_h = cvFloor(f_h);
        f_h -= s_h;
        
        if (s_h < 0) {
            f_h = 0, s_h = 0;
        } 
        if (s_h >= ori_h - 1) {
            f_h = 1, s_h = ori_h - 2;
        }  

        short cbufh[2];
		cbufh[0] = cv::saturate_cast<short>((1.f - f_h) * 2048);
		cbufh[1] = 2048 - cbufh[0];
        for (int j = 0; j < w; j++) {
            
            float f_w = ((j + 0.5) * rate_w - 0.5);
            int s_w = cvFloor(f_w);
            f_w -= s_w;
            
            if (s_w < 0) {
                f_w = 0, s_w = 0;
            }
            if (s_w >= ori_w - 1) {
                f_w = 1, s_w = ori_w - 2;
            }

            short cbufw[2];
			cbufw[0] = cv::saturate_cast<short>((1.f - f_w) * 2048);
			cbufw[1] = 2048 - cbufw[0];

            for (int k = 0; k < img.channels(); k++) {
                cout << (1 - f_w) * img.at<Vec3b>(s_h, s_w)[k] << endl;;
                img2.at<Vec3b>(i, j)[k] = (cbufh[0] * cbufw[0] * img.at<Vec3b>(s_h, s_w)[k] 
                                        + cbufh[0] * cbufw[1] * img.at<Vec3b>(s_h, s_w + 1)[k]
                                        + cbufh[1] * cbufw[0] * img.at<Vec3b>(s_h + 1, s_w)[k] 
                                        + cbufh[1] * cbufw[1] * img.at<Vec3b>(s_h + 1, s_w + 1)[k]) >> 22;
            }
        }
    }
    return img2;
}

运行修改后的代码,图像质量明显提升。
c++双线性插值,c++,算法,opencv

总结

通过本文的撰写,自己对双线性插值算法有了更加深刻的理解。在复现代码的过程中,发现自己还是不够关注运行效率等细节上的问题,在今后的工作和生活中还是需要多加锻炼。文章来源地址https://www.toymoban.com/news/detail-723328.html

到了这里,关于双线性插值简介及C++代码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度学习基础知识 最近邻插值法、双线性插值法、双三次插值算法

    最邻近插值:将每个目标像素找到距离它最近的原图像素点,然后将该像素的值直接赋值给目标像素 优点 :实现简单,计算速度快 缺点 :插值结果缺乏连续性,可能会产生锯齿状的边缘,对于图像质量影响较大,因此当处理精度要求较高的图像时,通常会采用更加精细的插

    2024年02月03日
    浏览(53)
  • 数字图像处理(十三)图像放大及双线性插值算法

    图像放大是日常学习中经常要用到的两个算法,我们首先讨论缩放的流程以及放大时如何优化双线性插值算法。 采用国际标准测试图像Lena,为了方便,我们将读入的彩色图转为灰度图进行缩放。 和图像缩小不同,图像放大是小数据量到大数据量的处理过程,因此需要对许多

    2024年02月05日
    浏览(48)
  • 九.图像处理与光学之图像几何变换算法(双线性插值)

    ​ 图像几何变换是图像处理中非常基础实用的技能,主要包括图片位移、缩放、镜像、剪切、放射变换等,在对图像进行空间变换的过程中,典型的情况是在对图像进行放大,旋转处理的时候,图像会出现失真的现象。这是由于在变换之后的图像中,存在着一些变换之前的图

    2024年02月13日
    浏览(46)
  • 在 FPGA 上如何实现双线性插值的计算?

    作者 | 殷庆瑜  责编 | 胡巍巍 目录 一、概述 二、What?什么是双线性插值? 二、Why?为什么需要双线性插值? 三、How?怎么实现双线性插值? 关键点1 像素点选择 关键点2 权重计算 升级1 通过查表减少计算量 升级2 通过数据锁存减少取数周期 升级3 通过换数信号兼容更多分

    2024年02月08日
    浏览(39)
  • 霍夫变换直线检测算法实现OpenCV(C++)

    一、原理 对于霍夫变换的原理这里就不进行描述啦,感兴趣的可以自行搜索。也可以看知乎上面的这篇贴文通俗易懂理解——霍夫变换原理。 二、算法代码 三、效果测试 测试代码 上述代码中的drawLine()函数是《OpenCV4快速入门》一书的代码清单 7-2中的原函数,只用于画线。

    2024年02月05日
    浏览(45)
  • 传统图片超分算法——双三次插值 (Bicubic)、附C++源码

    呼,花了一个下午,终于是写完加调试完了所有的代码。 双三次插值介绍 之前我写的这篇博客中讲了什么是超分,并实现了单线性插值算法和双线性插值算法。在这里将再介绍一种插值算法——双三次插值算法。 首先,双三次插值法需要参考16个点(4x4),因此插值效果会

    2024年02月07日
    浏览(39)
  • OpenCV - C++实战(01) — OpenCV简介

    目录 第1章  OpenCV简介 1.1 简介         1.1.1 OpencV 库简介   1.1.2 命名空间 1.2 OpenCV模块 1.3 装载、显示和存储图像 1.3.1 创建图像 1.3.2 读取图像 1.3.3 定义窗口与显示图像 1.3.4 图像翻转 1.3.5 保存图像 1.3.6 图像的复制 1.3.7 创建数组和向量 1.3.8 完整代码  1.4 深入了解cv::Mat 1

    2024年02月13日
    浏览(27)
  • 【数值分析】拉格朗日插值法与牛顿插值法的C++实现

    设函数 y = f ( x ) displaystylecolor{red}y=f(x) y = f ( x ) 在区间 [ a , b ] displaystylecolor{red}[a,b] [ a , b ] 上有定义,且 a ≤ x 0 x 1 ⋯ x n ≤ b displaystylecolor{red}a ≤x_0x_1dotsx_n ≤b a ≤ x 0 ​ x 1 ​ ⋯ x n ​ ≤ b ,已知在 x 0 … x n displaystylecolor{red}x_0dots x_n x 0 ​ … x n ​ 点处的值分别为

    2024年02月06日
    浏览(50)
  • Android studio配置OpenCV的JNI接口,实现C++代码编程

    目录 一、下载OpenCV-android-sdk 二、新建项目 三、导入OpenCV包  四、配置OpenCV的JNI接口,拷贝OpenCV所需的头文件和库文件 五、修改Cmake文件  六、配置app的build.gradle文件  七、测试 OpenCV官网地址:https://opencv.org/  点击Library--Releases,下载Android版本,解压得到 OpenCV-android-sdk文件

    2024年02月10日
    浏览(45)
  • 二分查找算法讲解及其C++代码实现

    二分查找算法是一种常用的查找算法,也被称为折半查找。它可以在有序的数组或列表中快速查找需要的元素。 算法描述: 首先确定数组的中间位置mid=(left+right)/2; 然后将要查找的值key与中间位置的值进行比较; 如果key等于中间位置的值,则查找成功,返回mid; 如果key小

    2024年02月01日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包