数字图像处理之双线性插值

数字图像中实现缩放的方法有很多种,其中一种就是双线性插值,在实现图像缩放时,有两种方法来确定缩放后的图像的像素值,第一种是根据原图像中的的像素找到对应的缩放后的图像中的像素,第二种是根据缩放后的图像找到对应的原图像中的像素,如下图

                

但是第一种方法有缺点,因为小图中的像素点到大图中的像素点不是满射,因此大图中的点不能完全有像素值,第二种方法也有缺点,大图中的点逆映射为小图中的点时,得到的像素坐标值可能不是整数,一种办法是采用最近邻方法,即将得到的坐标值与相邻的原图像中的像素坐标值比较,取离得最近的坐标值对应的像素值作为缩放后的图像对应的坐标值的像素值,这种办法可能导致图像失真,因此采用双线性差值的办法来进行计算相应的像素值。

                

右侧是最一般的双线性插值,下面举一个实际的例子来说明双线性插值在图像缩放中的应用。

假设一个图像的大小是485x647,放大分别放大1.3倍和1.7倍,即485x1.3=630.5,647x1.7=1099.9,根据四舍五入的原则确定放大后的图像为631x1100,接下来就是计算放大后图像各个位置的像素值,例如计算放大后图像位于(136,345)位置的像素值,则136/1.3=104.615,345/1.7=202.941,这里由于示例的原因取小数点后三位,则原图像中相邻的四个位置分别是(104,202),(104,203),(105,202),(105,203)这四个点,

如图我画出了这个点对应的周围的四个点,203.941-203=0.941

所以f(R1)=(1-0.941)xf(104,203)+0.941xf(104,204),

f(R2)=(1-0.941)xf(105,203)+0.941xf(105,204),

104.615-104=0.615

所以f(P)=(1-0.615)xf(R1)+0.615xf(R2),

其中f表示的那一点的像素值,这样就计算出了f(P),实际上就是放大后图像(136,345)处对应的像素值。

下面还是先看Mat的存储形式。Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。

单通道灰度图数据存放格式:

多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:

注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。

下面介绍两种访问mat中像素值的方法

第一种:

uchar* p = I.ptr<uchar>(i);//获得第i行的指针

p[j]得到的就是第i行第j个像素,注意j指的是从前往后数第j个元素,不是上图标的column j,例如j=4,则表示上图的column 1的绿色值。

第二种

I.at<Vec3b>(i,j)[k],表示的是第i行第j列的第k个值,例如i=0,j=1,k=1表示上图中的row 0,column 1的绿色值。

介绍完这些,下面是我写的缩放的源代码了

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int x, y;
void scale(Mat &srcmat, Mat &desmat, double sx, double sy);
int main(int argc ,char** argv){
    Mat srcimg = imread("opencv.jpg", IMREAD_COLOR);// Read the file
    if (!srcimg.data) // Check for invalid input
    {
        cout << "Could not open or find the image" << std::endl;
        return -1;
    }
    double sx = 0, sy = 0;
    cout << "please input scale x and scale y" << endl;
    cin >> sx >> sy;
    namedWindow("source img",WINDOW_AUTOSIZE);
    imshow("source img", srcimg);
     y = int(srcimg.cols*sy), x = int(srcimg.rows*sx);
    Mat scaimg(x, y, CV_8UC3, Scalar::all(0));
    scale(srcimg, scaimg, sx, sy);
    imshow("scaled img", scaimg);
    waitKey();
    return 0;
}
void scale(Mat &srcmat, Mat &desmat, double sx, double sy){
    int nc = x, nl = y,srccol=0,srcrow=0;
    double alph = 0.0, beta = 0.0;
    for (int i = 0; i < nc; i++){
        uchar* desdata = desmat.ptr<uchar>(i);
        for (int j = 0; j < nl; j++){
            srcrow = int(i / sx);
            //下面的的几个if是判断放大后图像对应到原图像的坐标是否越界的
            if (srcrow >= srcmat.rows-1){
                srcrow = srcmat.rows - 2;
            }
            alph = i / sx - srcrow;
            if (alph >= 1)
                alph = 1;
            srccol = int(j / sy);
            if (srccol >= srcmat.cols-1)
                srccol = srcmat.cols-2;
            beta = j / sy - srccol;
            if (beta >= 1)
                beta=1;
            for (int k = 0; k < 3; k++){
                double kk=srcmat.at<Vec3b>(srcrow, srccol)[k] +
                    beta*(srcmat.at<Vec3b>(srcrow, srccol+1)[k] - srcmat.at<Vec3b>(srcrow, srccol)[k]);
                double jj = srcmat.at<Vec3b>(srcrow+1, srccol)[k] +
                    beta*(srcmat.at<Vec3b>(srcrow+1, srccol + 1)[k] - srcmat.at<Vec3b>(srcrow+1, srccol)[k]);
                desdata[j*3+k] = kk + alph*(jj - kk);
            }
        }
    }
}

结果如下:

参考:http://en.wikipedia.org/wiki/Bilinear_interpolation

   http://blog.csdn.net/xiaowei_cqu/article/details/7771760

时间: 2024-10-12 22:04:46

数字图像处理之双线性插值的相关文章

【数字图像处理】六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解

本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行讲解,主要通过MFC单文档视图实现显示BMP图片空间几何变换,包括图像平移.图形旋转.图像反转倒置镜像和图像缩放的知识.同时文章比较详细基础,没有采用GDI+获取矩阵,而是通过读取BMP图片信息头和矩阵像素实现变换,希望该篇文章对你有所帮助,尤其是初学者和学习图像处理的学生. [数字图像处理]一.MFC详解显示BMP格式图片 [数字图像处理]二.MFC单文档分割窗口显示图片 [数字图像处

《数字图像处理原理与实践(MATLAB版)》一书之代码Part9

本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part9,辑录该书第431至第438页之代码,供有需要读者下载研究使用.至此全书代码发布已经接近尾声,希望这些源码能够对有需要的读者有所帮助.代码执行结果请参见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MATLAB版)>一书代码发布的说明 http://blog.csdn.net/baimafujinji/article/details/40987807 首先给出的是原书P438所列之程序源

《数字图像处理原理与实践(MATLAB版)》一书之代码Part8

本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part8,辑录该书第375至第415页之代码,供有需要读者下载研究使用.至此全书代码发布已经接近尾声,希望这些源码能够对有需要的读者有所帮助.代码执行结果请参见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MATLAB版)>一书代码发布的说明 http://blog.csdn.net/baimafujinji/article/details/40987807 P385-1 function y

数字图像处理作业使用OpenCV - 使用笔记

数字图像处理作业的输入图像全部都是灰度图像,所以汇总一下自己遇到的问题答案. OCV的图像容器是Mat<typename>,可以用imread(filename)读取图像,filename是c string,char*和const char*都行.灰度图像的typename是uchar,RGB图像的typename是Vec3b. Mat容器如果直接使用操作符赋值,只会复制一份信息头而不会复制包含数据的矩阵,由此而降低内存的浪费和速度,所以这样得到的多个Mat对象都指向同一个数据矩阵,换句话说,

数字图像处理1 、2基本原理

数字图像处理matlab版 冈萨雷斯 图书笔记系列,是个人读书笔记,写的不会太详细,具体内容要看课本(有例子和程序),这里只是罗列些基本的和重要的概念,方便复习,记忆和理解,弄点例子和练习. 什么东西都那么详细,是不现实的,大脑记不住,也太没效率.厚书可以慢看,但不能厚重的回忆,要把书读薄. 第一章 绪言和第二章 基本原理.对应课本,第1,2章. 解释了图像处理的含义,以及低,中,高级处理的对应内容. 数字图像是二维的,用函数表示为f(x, y),x行,y列,也可用二维矩阵表示. 注: Matl

初始----python数字图像处理--:环境安装与配置

一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因此,我们这里使用python这个脚本语言来进行数字图像处理. 要使用python,必须先安装python,一般是2.7版本以上,不管是在windows系统,还是linux系统,安装都是非常简单的. 要使用python进行各种开发和科学计算,还需要安装对应的包.这和matlab非常相似,只是matla

OpenCV-跟我一起学数字图像处理之直方图均衡化

从这篇博文开始,小生正式从一个毫不相干专业转投数字图像处理.废话不多说了,talk is cheap. show me the code. 直方图均衡化目的 由于一些图像灰度的分布过于集中,这样会导致图像的层次不够分明,直方图均衡化就是为了让图像的灰度分布更均匀,图像的层次感更强. 数学原理 基于连续灰度分布的结论推导 直方图均衡化属于数字图像处理中灰度变换(intensity transformation)的内容,灰度变换的目的就是找到一个合适的映射函数s=T(r).将原图像的灰度值映射到新的

《数字图像处理原理与实践(MATLAB版)》一书之代码Part5

本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part5,辑录该书第225至第280页之代码(此处应部分读者之需求调整了代码发布的顺序--详细说明请见下面的文章链接),供有需要读者下载研究使用.代码执行结果请参见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MATLAB版)>一书代码发布的说明 http://blog.csdn.net/baimafujinji/article/details/40987807 P245 I = imread(

《数字图像处理原理与实践(MATLAB版)》一书之代码Part6

本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part6,辑录该书第281至第374页之代码,供有需要读者下载研究使用.代码执行结果请参见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MATLAB版)>一书代码发布的说明 http://blog.csdn.net/baimafujinji/article/details/40987807 P338 i=double(imread('vase.tif'));[C,S]=wavedec2(i,2,