图像金字塔事图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结果。一幅图像的金字塔事一系列以金字塔形状排列的,分辨率逐步降低且来源于同一张原始图的图像集合,其通过梯次向下采样获得,直到达到某个终止条件才停止采样。底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。
*高斯金字塔(Gaussian pyramid):用来向下采样,主要的图像金字塔。通过高斯平滑(高斯核卷积)和下采样(将所有偶数行和偶数列去掉)获得一系列下采样图像,新的到的图像面积会变成源图像的四分之一。
*拉普拉斯金字塔(Laplacian pyramid):用来从金字塔底层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。先将图像在每个方向上扩大为原来的两倍,新增的行和列以0填充,在使用先前同样的内核(乘以4)与放大后的图像卷积,获得“新增像素”的近似值。
两者简要的区别在于:高斯金字塔用来向下降采样图片,而拉普拉斯金字塔则用来从金字塔底层图像中向上采样,重建一个图像。
图像金字塔向上/向下采样–pyrUp函数/pyrDown函数
向上采样:pyrUp():向上采样并模糊一张图片,即放大一张图片。
void pyrUp(inputArray,outputArray,Size(),int borderType)
*第一个参数,输入图像。
*第二个参数,输出图像。
*第三个参数,输出图像的大小,默认值Size(src.cols x2,src.rows x2)来进行计算。
*第四个参数,一般不用管。
向下采样:pyrDown():向下采样并模糊一张图片,即缩小一张图片。
void pyrDown(inputArray,outputArray,Size(),int borderType)
*第一个参数,输入图像。
*第二个参数,输出图像。
*第三个参数,输出图像的大小,默认值Size((src.cols+1)/2,(src.rows+1)/2)来进行计算。
尺寸调整函数resize()
void resize(inputArray,outputArray,dsize,double fx=0,double fy=0,int interpolation=INTER_LINEAR)
*第一个参数,输入图像。
*第二个参数,输出图像,当其非零时,由dsize的尺寸或者src.size()计算出来。
第三个参数,输出图像的大小,若为0,则dsize=Size(round(fx src.cols),round(fy * src.rows)),其中dsize,fx,fy都不为0。
*第四个参数,沿水平轴的缩放系数,默认值为0,且为0时 fx=(double)dsize.width/src.cols
*第五个参数,沿垂直轴的缩放系数,默认值为0,且为0时 fy=(double)dsize.height/src.rows
*第六个参数,用于指定插值方式,默认为INTER_LINEAR(线性插值)
(1)INTER_NEAREST(最近邻插值)
(2)INTER_LINEAR(线性插值)
(3)INTER_AREA(区域插值,利用像素区域关系的重采样插值)
(4)INTER_CUBIC(三次样条插值,超过4x4像素邻域内的爽三次插值)
(5)INTER_LANCZOS4(Lanczos插值,超过8x8像素邻域的Lanczos插值)
若要缩小图像,一般情况最好用区域插值;若要放大图像,一般情况最好用三次样条插值(效率不高,慢,不推荐使用)或线性插值(效率较高,速度较快,推荐使用)
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
#define WINDOW_NAME "[Procedure Window]"
//全局变量声明
Mat g_srcImage,g_dstImage,g_tmpImage;
//主函数
int main()
{
//载入原图
g_srcImage=imread("/Users/new/Desktop/1.jpg");
if(!g_srcImage.data){printf("读取图片srcImage错误~!\n");return false;}
//创建显示窗口
namedWindow(WINDOW_NAME,WINDOW_AUTOSIZE);
imshow(WINDOW_NAME,g_srcImage);
//参数赋值
g_tmpImage=g_srcImage;
g_dstImage=g_tmpImage;
int key=0;
//轮询获取按键信息
while(1)
{
key=waitKey(9);//读取键值到key变量中
switch(key)
{
//程序退出相关键值处理
case 27://按键ESC
return 0;
break;
case 'q'://按键Q
return 0;
break;
//图片放大相关键值处理
case 'e'://E键按下,调用pyrUp函数
pyrUp(g_tmpImage,g_dstImage,Size(g_tmpImage.cols*2,g_tmpImage.rows*2));
printf("检测到【E】键被按下,开始进行基于【pyrUp】函数的图片放大:图片尺寸x2 \n");
break;
case 'w'://W键按下,调用resize函数
resize(g_tmpImage,g_dstImage,Size(g_tmpImage.cols*2,g_tmpImage.rows*2));
printf("检测到【W】键被按下,开始进行基于【resize】函数的图片放大:图片尺寸x2 \n");
break;
//图片缩小相关键值处理
case 'r'://R键按下,调用pyrDown函数
pyrDown(g_tmpImage,g_dstImage,Size(g_tmpImage.cols/2,g_tmpImage.rows/2));
printf("检测到【R】键被按下,开始进行基于【pyrDown】函数的图片缩小:图片尺寸/2 \n");
break;
case 't'://T键按下,调用resize函数
resize(g_tmpImage,g_dstImage,Size(g_tmpImage.cols/2,g_tmpImage.rows/2));
printf("检测到【T】键被按下,开始进行基于【resize】函数的图片缩小:图片尺寸/2 \n");
break;
}
imshow(WINDOW_NAME,g_dstImage);
//方便下一次循环
g_tmpImage=g_dstImage;
}
return 0;
}
原始图片:
图像金字塔:
操作说明:
Opencv技巧
(1)Size():Size(列,行)和裁剪图片中的顺序一样。
(2)WaitKey():WaitKey(9)=27//按键ESC