opencv#25 拉普拉斯图像金字塔

高斯图像金字塔是一个将原图像进行不断下采样,或者称为不断模糊的这样一个金字塔,我们称之为模糊类型的图像金字塔。那么这种将图像进行模糊,在如果我对它进行上采用,也就是还原过程,那么这个经过模糊又还原之后的图像,与原始图像相差多少,就构成了拉普拉斯图像金字塔(残差图像金字塔)。

假设我们有一种高斯图像金字塔中的高斯图像,那么将它去除,如果想计算下一层的高斯图像金字塔,那么就可以对它进行下采样,所谓的高斯模糊就是我们下采样的过程,这里我们假设下采样将尺寸缩小为原来的一半,之后可以得到我们的高斯图像,将这张得到的高斯图像再次进行上采样,上采样必然伴随着差值这样的操作,通过上采样后,图像的尺寸又回到了与原图像的尺寸相同的图像,将两者进行运算,得到的结果就是第k层的拉普拉斯图像。

假如第k层的高斯图像是一个n*n的图像,那么经过下采样后,它的图像变成了n/2*n/2,所以第k+1的高斯图像,它的尺寸就是n/2*n/2,将这张图像进行上采样后,得到一张n*n的图像,这张图像与第k层的高斯图像进行运算,也就是第k层的高斯图像减去这种通过下采样又上采样后的图像,得到的差值,我们称之为第k层的拉普拉斯图像,通过这种方式,我们就可以构建出拉普拉斯图像,这个图像与高斯图像结合就可以较好的去描述一张图像,经过拉伸变化可以得到什么样的效果。

在opencv中提供了与下采样相对应的上采样的函数

拉普拉斯图像金字塔实现

pyrUp()

void cv::pyrUp(InputArray      src,
               OutputArray     dst,
               const Size &    dstsize = Size(),
               int             borderType = BORDER_DEFAULT
              )

·src:输入待上采样的图像。

·dst:输出上采样后的图像,图像尺寸可以指定,但是数据类型和通道数与src相同。

·dstsize:输出图像尺寸,可以缺省。

·borderType:像素边界外推方法的标志

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv; //opencv的命名空间
using namespace std;

int main()
{
	Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenac.png");
    
	vector<Mat> Guass; //存放高斯金字塔的向量
	int level = 3;//定义金字塔的层数

	Guass.push_back(img); //将高斯金字塔的第0层设置为原图像


	for (int i = 0; i < level; i++)  //对高斯金字塔的第0层进行循环采样
	{
		Mat guass; //存放采样后图像
		pyrDown(Guass[i], guass);
		Guass.push_back(guass);//将采样后的图像存入向量中
	}

	//通过上面的程序我们得到了高斯图像金字塔,后面读取高斯图像金字塔中的图片,每读取一张就计算一个拉普拉斯金字塔中的图片
	vector<Mat> Lap;//存放拉普拉斯图像金字塔的向量
	
	for (int i = Guass.size() - 1; i > 0 ; i--)//从图像最上面一层开始读(上节运行展示过高斯图像金字塔,是尺寸最小的图像在最上层,下面依次增大)
	{
		Mat lap,upGuass;

		if (i == Guass.size() - 1)//这里需要注意,当第一次读取高斯图像金字塔中图像时,在高斯图像金字塔中没有一个图像比这张图像更小了,所以需要人为的对图像进行缩小再放大
		{                         //所以要进行一个判断,先下采样,再上采样
			Mat down;
			pyrDown(Guass[i], down);
			pyrUp(down, upGuass);
			lap = Guass[i] - upGuass;
		/*	Lap.push_back(lap);*/
		}
		//如果读取的高斯图像金字塔中的图像不是最上面的层,那么比它尺寸还小的图像就是它id+1的图像,因此我们可以直接从高斯图像金字塔获取
		pyrUp(Guass[i], upGuass);
		lap = Guass[i - 1] - upGuass;
		Lap.push_back(lap);

	}
	//读取高斯金字塔中图像,由于读取图像时,高斯图像金字塔是最大的图像在底部,而拉普拉斯图像金字塔是最小的图像在底部,因此我们要反序读出,从而实现尺寸的对应
	for (int i = 0; i < Guass.size(); i++)
	{
		string name = to_string(i);
		
		Mat guass, lap;//这样操作才可通过image watch形式查看
		guass = Guass[i];
		lap = Lap[Guass.size() - 1 - i];

		imshow("G" + name, Guass[i]);
		imshow("L" + name, Lap[Guass.size() - 1 - i]);

	}



	//由于我们的一系列图像是放置在向量中的,因此即使我们用Image watch查看也没有办法查看到每一张图像,因此我们再通过for循环,将里面的每一张图像读取出来
	for (int i = 0; i < level; i++)
	{
		//我们希望在循环过程中直接显示图像,因此我们需要设置不同的名称
		string name = to_string(i); //存放用于标识每一张图像的序号
		//依次读取图像
		imshow(name, Guass[i]);//name时图像的序号名称
	}

	waitKey(0);
	return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值