图像金字塔是图像中多尺度表达的一种,也是很常见的,最主要用于图像的分割。opencv中给出了图像金字塔的一些列函数,再谈openv之前先介绍下高斯金字塔和拉普拉斯金字塔
1 高斯金字塔和拉普拉斯金字塔
(1)高斯金字塔是通过高斯平滑和亚采样获得一些列下采样图像,也就是说第K层高斯金字塔通过平滑、亚采样就可以获得K+1层高斯图像,高斯金字塔包含了一系列低通滤波器,其截至频率从上一层到下一层是以因子2逐渐增加,所以高斯金字塔可以跨越很大的频率范围。金字塔的图像如下:
高斯金字塔 拉普拉斯金字塔
(2)拉普拉斯金字塔包含了一些列的带通滤波器,其具体过程如下:
可以看出,拉普拉丝图像的形成过程大致为对原图像进行低通滤波和降采样得到一个粗尺度的近似图像, 即分解得到的低通近似图像, 把这个近似图像经过插值、滤波, 再计算它和原图像的差值, 就得到分解的带通分量。下一级分解是在得到的低通近似图像上进行, 迭代完成多尺度分解。可以看出拉普拉斯金字塔的分解过程(如图1所示)包括四个步骤: 1低通滤波;2降采样(缩小尺寸); 3内插(放大尺寸); 4带通滤波(图像相减) 。拉普拉斯图像突出图像中的高频分量,注意的是拉普拉斯金字塔的最后一层是低通滤波图像,不是带通滤波图像。
(3)源图像的重建
源图像的重建是构建拉普拉斯金字塔的逆过程,首先将第K层的高斯图像 插值放大一倍,然后和第K-1层拉普拉斯金字塔相加就可以得到第K-1层的高斯金字塔图像。以此类推,就可以得到源图像。
2.opencv函数
(1)PyrDown 构建高斯金字塔
cvPyrDown函数
PyrDown
图像的下采样
void cvPyrDown( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 );
src 输入图像.
dst 输出图像, 宽度和高度应是输入图像的一半 ,传入前必须已经完成初始化
filter 卷积滤波器的类型,目前仅支持 CV_GAUSSIAN_5x5
函数 cvPyrDown 使用 Gaussian 金字塔分解对输入图像向下采样。首先它对输入图像用指定滤波器进行卷积,然后通过拒绝偶数的行与列来下采样图像。
(2)PyrUp(获取的不是高斯金字塔的图像哦)
cvPyrUp
void cvPyrUp( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 );
src 输入图像.
dst 输出图像, 宽度和高度应是输入图像的2倍
filter 卷积滤波器的类型,目前仅支持 CV_GAUSSIAN_5x5
函数 cvPyrUp 使用Gaussian 金字塔分解对输入图像向上采样。首先通过在图像中插入 0 偶数行和偶数列,然后对得到的图像用指定的滤波器进行高斯卷积,
其中滤波器乘以4做插值。所以输出图像是输入图像的 4 倍大小
PyrUp处理结果
PyrDown和PyrUp过程并不是逆过程,opencv中PyrDown可以构建高斯金字塔,但是PyrUp函数得到的并不是拉普拉斯图像,《learning opencv》中解释说PyrUp函数实现的函数为: 实际上,我利用这个函数得到的图像是一个经过低通滤波的图像,可以看下图:dst明显是src图像的一个高斯滤波。而并不是带通图像。也就是说PyrUp函数其实只是实现了 过程,查看源代码确实如此。
构建拉普拉斯金字塔就可以将高斯金字塔减去响应的PyrUp处理结果即可,我写了一个例子验证这个结果:
构建拉普拉斯金字塔
cvNamedWindow("G0");
cvNamedWindow("G1");
cvNamedWindow("G1*g(5*5)");
cvNamedWindow("L0");
IplImage *img=cvLoadImage("Miss.bmp");
IplImage *img2 = cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,1);
IplImage *img3 = cvCreateImage(cvSize(img->width/2,img->height/2),IPL_DEPTH_8U,1);
IplImage *img4 = cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,1);
cvCvtColor(img,img2,CV_BGR2GRAY);
cvShowImage("G0",img2); //G0
cvPyrDown(img2,img3);
cvShowImage("G1",img3); //G1
cvPyrUp(img3,img4);
cvShowImage("G1*g(5*5)",img4); //对G1插值,然后使用高斯滤波(cvPyrUp过程)
cvSub(img2,img4,img4); //G0减去G1插值后的图像获得L0
cvShowImage("L0",img4);
cvDestroyWindow("G0");
cvDestroyWindow("G1");
cvDestroyWindow("G1*g(5*5)");
cvDestroyWindow("L0");
cvReleaseImage(&img2);
处理过程图像以及结果
L0中包含很明显的高频信息,并不是低通结果,L金字塔剩下的构建以此类推。
关于金字塔的分割回头和其他的分割算法一起学习吧