图像金字塔-百度百科
【OpenCV学习笔记】之图像金字塔(Image Pyramid)
高斯金字塔与拉普拉斯金字塔
数字图像处理(21): 图像金字塔(高斯金字塔 与 拉普拉斯金字塔)
在讲解图像金字塔相关知识的时候,我还是首先考虑一个问题,为什么会出现图像金字塔这个概念。我们在对一张图像进行处理的时候,计算机不像我们人眼一看,一看就知道这里面含有什么物体。所以这时候我们需要把图像中一些重要的信息提取出来,然后在让计算机去理解。就好比我们在教小孩子知识的时候,往往就是让复杂问题简单化,来帮助他更快的理解。因此,要提取图像中有用的信息,就涉及到金字塔中一个重要的概念拉普拉斯金字塔,来得到图像的高频信息。在比如我们人类在看一样东西的时候,只要在人眼可视的范围内,无论这个物体放到多远,我们都能很精确知道这个物体是什么。但是计算机要认识这个物体,你需要把这个物体在远处是什么样子、近处是什么样子,都要清清楚楚的告诉它一边,而从单张图像实现图像的远近,就要用到金字塔中一个重要的概念高斯金字塔。上面列举的例子,只是图像金字塔中的几个可能的应用,它还可以用到很多具体的图像处理中,例如图像融合、光流、SIFT等等,后面有时间的话,我会把概念一一讲解。
尺度变化即实现图像分辨率大小的变化,在OpenCV中使用的函数是resize函数。其中,在对图像缩小处理的时候,一般采用的CV_INTER_AERA(区域插值)的方法。在对图像放大的使用一般采用的是CV_INTER_LINEAR(线性插值)。
图像金字塔实现了多尺度的表达,金字塔的底层为高分辨率的原始图像,高层为了低分辨率图像,而且层越高图像的分辨率越小。主要使用在图像分割、图像压缩、匹配等方向。其中,图像金字塔中比较常见的就是高斯金字塔和拉普拉斯金字塔。
高斯金字塔:用来进行向上/向下采样,是主要的图像金字塔。
拉普拉斯金字塔:在金字塔低层图像重建上层未采样图像,在数字图像处理中用来预测残差,对图像进行最大程度的还原,与高斯金字塔配合使用。
两者的主要区别:高斯金字塔是在原始图像的基础上,对图像进行下采样,图像的分辨率越来越低;拉普拉斯金字塔则是从金字塔的底层向上采样来重建图像。
2.3.1 图像下采样:缩小图像
对图像进行下采样,一般由两步实现:对图像进行高斯卷积核处理(高斯滤波);删除所有的偶数行和列;
根据上图可以看到,图像的分辨率一开始是M X N,经过一次操作后图像的分辨率变为M/2 X N/2,后面以此类推。
注:因为每次在进行下采样的时候,都会减少行列,因此图像的信息不断丢失。
2.3.2 图像下采样OpenCV实现下采样
(1)源代码
#include
using namespace cv;
int main()
{
Mat src, dest1, dest2, show;
src = imread("0.jpg");
//降采样
pyrDown(src, dest1, Size(src.cols / 2, src.rows / 2));
pyrDown(dest1, dest2, Size(dest1.cols / 2, dest1.rows / 2));
namedWindow("image", CV_WINDOW_AUTOSIZE);
show.create(src.rows, src.cols + dest1.cols + dest2.cols, CV_8UC3);
src.copyTo(show(Rect(0, 0, src.cols, src.rows)));
dest1.copyTo(show(Rect(src.cols, 0, dest1.cols, dest1.rows)));
dest2.copyTo(show(Rect(src.cols + dest1.cols, 0, dest2.cols, dest2.rows)));
imshow("image", show);
cvWaitKey();
}
(2)降采样效果图
2.3.3 图像上采样:放大图像
图像进行上采样说白了就是不断的放大图像,每进行一次处理,图像的行和宽都会放大原来的一倍。那么放大的像素怎么来的呢,一般都是在要放大图像中添加新增的行和列,均用0作为填充。
关于行列中填充的实现:
请注意:我们进行的上采样和下采样的过程是不可逆的,其实不说你也可以想到,每次下采样都会丢失数据,所以即使在进行上采样,丢失的数据也不会回来。
2.3.3 图像上采样:OpenCV实现
(1)源代码
#include
using namespace cv;
int main()
{
Mat src, dest1, dest2, show;
src = imread("1.jpg");
//降采样
pyrUp(src, dest1, Size(src.cols * 2, src.rows * 2));
pyrUp(dest1, dest2, Size(dest1.cols * 2, dest1.rows * 2));
namedWindow("image", CV_WINDOW_AUTOSIZE);
show.create(dest2.rows, src.cols + dest1.cols + dest2.cols, CV_8UC3);
src.copyTo(show(Rect(0, 0, src.cols, src.rows)));
dest1.copyTo(show(Rect(src.cols, 0, dest1.cols, dest1.rows)));
dest2.copyTo(show(Rect(src.cols + dest1.cols, 0, dest2.cols, dest2.rows)));
imwrite("./1.jpg", dest2);
imshow("image", show);
cvWaitKey();
}
(2)效果图
2.4.1 基础过程
其实拉普拉斯金字塔是在高斯金字塔的基础上,实现的新金字塔。拉普拉斯金字塔的表达式:
下面我们通过两个流程图来进行分析:
说明:我们可以看到首先对原始图像进行高斯金字塔,然后在最顶层开始,对图像进行上采样。将上采样后的图像与当前层对应的高斯层图像进行做差,来得到图像的轮廓即高频信息。上面这个过程称为“拉普拉斯金字塔”操作。
上面两幅图像,通过将高斯金字塔和拉普拉斯金字塔整合,得到不同的图像。首先还是先对图像进行高斯金字塔处理,之后经过拉普拉斯金字塔得到高频信息,将高频信息与经过高斯上采样来的同层图像来合成一张图像。
2.4.2 拉普拉斯金字塔OpenCV实现
(1)源代码
#include
using namespace cv;
int main()
{
Mat src, dest1, dest2, show;
Mat dest1Up, dest2Up;
Mat laplaceSrc, laplaceDest;
src = imread("0.jpg");
//降采样
pyrDown(src, dest1, Size(src.cols / 2, src.rows / 2));
pyrDown(dest1, dest2, Size(dest1.cols / 2, dest1.rows / 2));
namedWindow("image", CV_WINDOW_AUTOSIZE);
pyrUp(dest2, dest2Up, Size(dest2.cols * 2, dest2.rows * 2));
pyrUp(dest1, dest1Up, Size(dest1.cols * 2, dest1.rows * 2));
show.create(src.rows * 3, src.cols + dest1.cols, CV_8UC3);
laplaceSrc = src - dest1Up;
laplaceDest = dest1 - dest2Up;
src.copyTo(show(Rect(0, 0, src.cols, src.rows)));
dest1Up.copyTo(show(Rect(0, src.rows, dest1Up.cols, dest1Up.rows)));
laplaceSrc.copyTo(show(Rect(0, src.rows + dest1Up.rows, laplaceSrc.cols, laplaceSrc.rows)));
dest1.copyTo(show(Rect(src.cols, 0, dest1.cols, dest1.rows)));
dest2Up.copyTo(show(Rect(src.cols, dest1.rows, dest2Up.cols, dest2Up.rows)));
laplaceDest.copyTo(show(Rect(src.cols, dest1.rows + dest2Up.rows, laplaceDest.cols, laplaceDest.rows)));
imshow("image", show);
cvWaitKey();
}
(2)效果图