10.2高斯金字塔-向上取样

实验原理

在OpenCV中,高斯金字塔(Gaussian Pyramid)和上采样(Upsampling)是图像处理中的常见技术,它们经常用于图像的多分辨率分析。高斯金字塔主要用于图像的多尺度表示,而上采样则是将图像放大到更高分辨率的过程。以下是如何在OpenCV C++中实现高斯金字塔及其上采样的详细步骤和示例代码。

高斯金字塔
高斯金字塔是通过对图像进行连续的下采样和模糊处理来构建的。高斯金字塔是一种图像的多分辨率表示方法,它通过对图像进行下采样(降低分辨率)来形成一系列不同分辨率的图像集合。每个下采样层都比上一层分辨率更低,而这个过程通常通过高斯滤波器完成。具体步骤如下:

1.初始化:从原始图像开始。
2.高斯模糊:对当前层的图像进行高斯模糊处理,以减少高频噪声。
3.下采样:将模糊后的图像尺寸减半,通常是通过丢弃每隔一个像素来实现的。
4.重复:对得到的新图层重复上述过程,直到达到所需的层次数。

向上取样(上采样)
向上取样是指将低分辨率的图像恢复到较高分辨率的过程。通常是在高斯金字塔的上下文中进行的,以便在构建拉普拉斯金字塔时能够恢复图像的细节信息(向上取样通常用于重建图像的细节)。上采样的步骤如下:

1.上采样:将图像尺寸增加一倍,通常是通过插入零值像素来实现的。
2.高斯滤波:对上采样后的图像进行高斯滤波,以去除插值产生的高频噪声。

pyrDown函数

pyrDown 是 OpenCV 中用于构建高斯金字塔的一个函数。该函数通过下采样(通常是指图像尺寸减半)来生成较小的图像,常用于图像金字塔的构建中。下面是对 pyrDown 函数的详细解释以及一个示例代码。

函数原型

void pyrDown(InputArray src, OutputArray dst, const Size &dstsize=Size(), 
            int borderType=BORDER_DEFAULT);
参数说明
src: 输入图像,可以是单通道或多通道图像。
dst: 输出图像,是经过下采样处理后的图像。输出图像的类型应与输入图像相同。
dstsize: 可选参数,默认情况下,如果未指定,则输出图像的尺寸将是输入图像尺寸的一半。
borderType: 可选参数,默认值为 BORDER_DEFAULT。当输入图像的尺寸不是输出图像尺寸的两倍时,此参数决定了如何处理边缘像素。常用的边界类型有 BORDER_REFLECT、BORDER_CONSTANT 等。

下采样过程
pyrDown 函数通常包括以下步骤:

1.高斯模糊:对输入图像进行高斯模糊,以减少高频噪声,避免下采样过程中出现伪影。
2.下采样:将高斯模糊后的图像尺寸减半,通常是通过丢弃每隔一个像素来实现的。

示例代码

下面是一个使用 pyrDown 构建高斯金字塔的示例代码:

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

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	// 读取图像
	Mat img = imread("04.jpg", IMREAD_COLOR);
	if (img.empty())
	{
		cout << "Error: Image cannot be loaded!" << endl;
		return -1;
	}

	int levels = 3;  // 定义金字塔层数
	vector<Mat> pyr(levels);

	// 创建高斯金字塔
	pyr[0] = img;
	for (int i = 1; i < levels; ++i)
	{
		pyrDown(pyr[i - 1], pyr[i]);
	}

	// 显示每一层
	for (int i = 0; i < levels; ++i)
	{
		namedWindow("Level " + to_string(i), WINDOW_NORMAL);
		imshow("Level " + to_string(i), pyr[i]);
	}

	waitKey(0);  // 等待按键退出
	return 0;
}


说明:
1.读取图像:读取一个图像文件,并检查是否成功加载。
2.创建高斯金字塔:使用 pyrDown 函数逐层创建高斯金字塔。这里假设每层都是前一层尺寸的一半。
3.显示图像:使用 imshow 函数显示高斯金字塔的每一层。

注意事项
如果输入图像的宽度或高度不是2的幂次方,那么在下采样过程中可能会出现尺寸不匹配的情况。这时可以通过调整 dstsize 参数或者在调用 pyrDown 之前调整输入图像的尺寸来解决。
pyrDown 使用了一个默认的高斯核进行模糊处理。如果你需要自定义高斯核,可以先手动对图像进行高斯模糊,然后再进行下采样。

运行结果

pyrUp函数

pyrUp 是 OpenCV 提供的一个函数,用于从较小的图像生成较大的图像,即上采样操作。这个函数通常用于图像金字塔的构建中,与 pyrDown 函数相对应。下面是对 pyrUp 函数的详细解释以及一个示例代码。

函数原型

void pyrUp(InputArray src, OutputArray dst, const Size &dsize=Size(), 
            int borderType=BORDER_DEFAULT);
参数说明
src: 输入图像,可以是单通道或多通道图像。
dst: 输出图像,是经过上采样处理后的图像。输出图像的类型应与输入图像相同。
dsize: 可选参数,默认情况下,如果未指定,则输出图像的尺寸将是输入图像尺寸的两倍。你可以指定不同的尺寸来改变输出图像的大小。
borderType: 可选参数,默认值为 BORDER_DEFAULT。当输入图像放大到目标尺寸时,此参数决定了如何处理边缘像素。常用的边界类型有 BORDER_REFLECT、BORDER_CONSTANT 等。

上采样过程
pyrUp 函数通常包括以下步骤:

1.高斯模糊:尽管 pyrUp 主要用于上采样,但它也会使用一个高斯核来平滑图像,这有助于避免放大过程中可能出现的高频噪声。
2.上采样:将图像尺寸放大,通常是通过插值算法来估计新增像素的值。

示例代码

下面是一个使用 pyrUp 构建拉普拉斯金字塔的示例代码:

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

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // 读取图像
    Mat img = imread("path/to/your/image.jpg", IMREAD_COLOR);
    if (img.empty())
    {
        cout << "Error: Image cannot be loaded!" << endl;
        return -1;
    }

    // 创建一个小的图像
    Mat smallImg;
    pyrDown(img, smallImg);

    // 将小图像上采样回原尺寸
    Mat upsampledImg;
    pyrUp(smallImg, upsampledImg, img.size());

    // 显示原始图像和上采样的图像
    namedWindow("Original Image", WINDOW_NORMAL);
    imshow("Original Image", img);

    namedWindow("Upsampled Image", WINDOW_NORMAL);
    imshow("Upsampled Image", upsampledImg);

    waitKey(0);  // 等待按键退出
    return 0;
}

说明:
1.读取图像:读取一个图像文件,并检查是否成功加载。
2.创建小图像:使用 pyrDown 函数创建一个较小的图像。
3.上采样图像:使用 pyrUp 函数将小图像上采样回原图像的尺寸。
4.显示图像:使用 imshow 函数显示原始图像和上采样后的图像。
注意事项
在使用 pyrUp 时,通常会将图像放大到特定的尺寸,通常是原始尺寸的两倍。但是,也可以指定不同的尺寸来适应不同的需求。
上采样过程中,图像质量可能会有所损失,因为从较小的图像中恢复丢失的信息是有限的。因此,在进行图像放大时,可能会观察到一些模糊效果。

运行结果

示例代码1

下面是一个使用OpenCV C++构建高斯金字塔并执行上采样的示例代码:

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

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // 读取图像
    Mat img = imread("path/to/your/image.jpg", IMREAD_COLOR);
    if (img.empty())
    {
        cout << "Error: Image cannot be loaded!" << endl;
        return -1;
    }

    int levels = 3;  // 定义金字塔层数
    vector<Mat> pyr(levels);

    // 创建高斯金字塔
    pyr[0] = img;
    for (int i = 1; i < levels; ++i)
    {
        pyrDown(pyr[i-1], pyr[i]);
    }

    // 上采样并显示每一层
    Mat upsampled;
    for (int i = levels - 1; i >= 0; --i)
    {
        if (i < levels - 1)
        {
            // 上采样当前层
            pyrUp(pyr[i], upsampled, pyr[i-1].size());
            imshow("Upsampled Level " + to_string(i), upsampled);
        }
        else
        {
            imshow("Original Level " + to_string(i), pyr[i]);
        }
    }

    waitKey(0);  // 等待按键退出
    return 0;
}

说明:
读取图像:读取一个图像文件,并检查是否成功加载。
创建高斯金字塔:使用 pyrDown 函数逐层创建高斯金字塔。
上采样并显示:从最底层开始,使用 pyrUp 函数上采样每一层,并显示结果。
注意事项:
在上采样过程中,pyrUp 函数要求输出图像的大小必须指定。这是因为上采样不仅仅是简单地插入零值,还需要根据目标大小进行插值。
pyrDown 和 pyrUp 函数默认使用了特定的高斯核来进行模糊处理和插值。

运行结果1

此代码会报错尚未处理!

示例代码2

以下是一个C++示例,展示了如何使用OpenCV构建高斯金字塔,并演示如何从高斯金字塔的一层向上取样回到原图分辨率:

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

using namespace std;
using namespace cv;

void buildGaussianPyramid(const Mat &src, vector<Mat>& gaussianPyramid, int levels) {
	// 初始化高斯金字塔的第一层
	gaussianPyramid.push_back(src.clone());

	// 构建剩余的高斯金字塔层
	for (int i = 0; i < levels - 1; ++i) {
		Mat nextLevel;
		pyrDown(gaussianPyramid[i], nextLevel);
		gaussianPyramid.push_back(nextLevel);
	}
}

void upSampleFromGaussian(const vector<Mat>& gaussianPyramid, vector<Mat>& upsampledLayers) {
	// 初始化向上取样后的第一层为原图
	upsampledLayers.push_back(gaussianPyramid.front().clone());

	// 从第二层开始向上取样
	for (size_t i = 1; i < gaussianPyramid.size(); ++i) {
		Mat expanded;
		pyrUp(gaussianPyramid[i], expanded, gaussianPyramid[i - 1].size());
		upsampledLayers.push_back(expanded);
	}
}

int main(int argc, char** argv) {


	// 加载图像
	Mat img = imread("07.jpg", IMREAD_GRAYSCALE);
	if (!img.data) {
		cout << "Error opening image" << endl;
		return -1;
	}

	// 设置金字塔的层数
	int levels = 5;

	// 构建高斯金字塔
	vector<Mat> gaussianPyramid;
	buildGaussianPyramid(img, gaussianPyramid, levels);

	// 从高斯金字塔向上取样
	vector<Mat> upsampledLayers;
	upSampleFromGaussian(gaussianPyramid, upsampledLayers);

	// 显示高斯金字塔的每一层
	for (size_t i = 0; i < gaussianPyramid.size(); ++i)
	{
		cv::namedWindow("Gaussian Level " + to_string(i), cv::WINDOW_NORMAL);
		imshow("Gaussian Level " + to_string(i), gaussianPyramid[i]);
		waitKey(0);
	}

	// 显示向上取样后的每一层
	for (size_t i = 0; i < upsampledLayers.size(); ++i) 
	{
		cv::namedWindow("Upsampled Level " + to_string(i), cv::WINDOW_NORMAL);
		imshow("Upsampled Level " + to_string(i), upsampledLayers[i]);
		waitKey(0);
	}

	return 0;
}


代码解释
1. buildGaussianPyramid 函数用于构建高斯金字塔。它接受原始图像和金字塔的层数,然后使用 pyrDown 函数逐层下采样。
2. upSampleFromGaussian 函数用于从高斯金字塔向上取样。它接受高斯金字塔的所有层,并使用 pyrUp 函数将每一层恢复到其上一层的大小。
3. 主函数中加载图像,并设置金字塔的层数。
4. 构建高斯金字塔并显示每一层。
5. 从高斯金字塔向上取样并显示每一层的结果。

运行结果2

实验代码3

#include "pch.h"
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;
using namespace std;
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 

int main()
{
	Mat img, r1, r2 ;
	img = imread("9.jpeg", IMREAD_COLOR); 	//读取原始图像
	if (img.empty())
	{
		cout << "图像读取错误!" << endl;
	}
	pyrDown(img, r1);  	//图像向下取样
	pyrUp(r1, r2);
 
	namedWindow("original", WINDOW_NORMAL);
	imshow("original", img);  	//显示图像
	namedWindow("PyrDown1", WINDOW_NORMAL);
	imshow("PyrDown1", r1);
	namedWindow("PyrUp", WINDOW_NORMAL);
	imshow("PyrUp", r2);

	waitKey(0);
	destroyAllWindows(); //销毁所有窗口
}

运行结果3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值