OpenCV8-图像金字塔

OpenCV8-图像金字塔


1.图像金字塔

图像"金字塔"是通过多个分辨率表示图像的一种有效且简单的结构。一个图像"金字塔"是一系列以金字塔形状排列、分辨率逐步降低的图像集合。图像"金字塔"的底部是待处理图像的高分辨率表示,顶部是低分辨率表示。本文中将介绍图像"金字塔"中比较著名的两种:高斯"金字塔"和拉普拉斯"金字塔"。

2.高斯金字塔

高斯"金字塔"是指通过下采样不断地将图像的尺寸缩小,进而在图像"金字塔"中包含多个尺寸的图像。一般情况下,高斯"金字塔"的底层为图像的原图,每往上一层就会通过下采样缩小一次图像的尺寸,通常情况下,尺寸会缩小为原来的一半,但是如果有特俗需求,缩小的尺寸也可以根据实际情况进行调整。由于每次图像的尺寸都缩小为原来的一半,图像尺寸缩小的速度非常快,因此常见的高斯"金字塔"的层数为3~6层。

OpenCV中提供了pyrDown函数专门用于图像的下采样计算,以便构建图像的高斯"金字塔":

cpp 复制代码
void pyrDown(
    InputArray src,  // 输入待下采样的图像
    OutputArray dst, // 输出下采样后的图像
    const Size& dstsize = Size(),  // 输出图像尺寸,可以默认
    int borderType = BORDER_DEFAULT // 像素边界外推方法的标志,图像几何变换一文中-仿射变换有说明
);

该函数用于实现图像模糊并对其进行下采样,默认标志下,函数输出图像的尺寸为输入图像尺寸的一半,但是也可以通过dstsize参数来设置输出图像的大小,需要注意的是,无论输出尺寸为多少,应该满足下面公式的条件:
{ ∣ d s t s i z e . w i d t h 2 − s r c . c o l s ∣ ≤ 2 ∣ d s t s i z e . h e i g h t 2 − s r c . r o l s ∣ ≤ 2 \left\{ \begin{matrix} | dstsize.width2 - src.cols | \leq 2 \\ | dstsize.height2 - src.rols | \leq 2 \\ \end{matrix} \right. {∣dstsize.width2−src.cols∣≤2∣dstsize.height2−src.rols∣≤2

该函数首先将原始图像与内核矩阵进行卷积,之后通过不适用偶数行和列的方式对图像进行下采样,最终实现尺寸缩小的下采样,内核矩阵如下:
k = 1 256 [ 1 4 6 4 1 4 6 24 6 4 6 24 36 24 6 4 16 24 16 4 1 4 6 4 1 ] k = \frac{1}{256} \begin{bmatrix} 1 & 4 & 6 & 4 & 1 \\ 4 & 6 & 24 & 6 & 4 \\ 6 & 24 & 36 & 24 & 6 \\ 4 & 16 & 24 & 16 & 4 \\ 1 & 4 & 6 & 4 & 1 \\ \end{bmatrix} k=2561 14641462416462436246462416414641

该函数的功能与resize函数将图像尺寸缩小一样,但是使用的内部算法不同。

3.拉普拉斯金字塔

拉普拉斯"金字塔"是通过上层小尺寸的图像构建下层大尺寸的图像。拉普拉斯"金字塔"具有预测残差的作用,需要与高斯"金字塔"一起使用。

假设我们有了一个高斯图像"金字塔",对于其中的第i层图像(高斯"金字塔"最下面为第0层),首先通过下采样得到一个尺寸缩小一半图像,即高斯"金字塔"中的第i+1层或者不在高斯"金字塔"中,之后对这福图像进行上采样,将图像尺寸恢复到第i层图像的大小,最后求取高斯"金字塔"第i层图像与经过上采样后的图像的残差图像,这个残差图像就是拉普拉斯"金字塔"的第i层图像。

对于上采样操作OpenCV提供了pyrUp函数:

cpp 复制代码
void pyrUp(
    InputArray src, 
    OutputArray dst,
    const Size& dstsize = Size(), 
    int borderType = BORDER_DEFAULT 
);
// 函数参数同pyrDown

4.Demo

cpp 复制代码
#include <opencv2\opencv.hpp>
#include <opencv2/core/utils/logger.hpp> // debug no log
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	Mat img = imread("lena.png");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	vector<Mat> Gauss, Lap;  //高斯金字塔和拉普拉斯金字塔
	int level = 3;  //高斯金字塔下采样次数
	Gauss.push_back(img);  //将原图作为高斯金字塔的第0层
	//构建高斯金字塔
	for (int i = 0; i < level; i++)
	{
		Mat gauss;
		pyrDown(Gauss[i], gauss);  //下采样
		Gauss.push_back(gauss);
	}
	//构建拉普拉斯金字塔
	for (int i = Gauss.size() - 1; i > 0; i--)
	{
		Mat lap, upGauss;
		if (i == Gauss.size() - 1)  //如果是高斯金字塔中的最上面一层图像
		{
			Mat down;
			pyrDown(Gauss[i], down);  //上采样
			pyrUp(down, upGauss);
			lap = Gauss[i] - upGauss;
			Lap.push_back(lap);
		}
		pyrUp(Gauss[i], upGauss);
		lap = Gauss[i - 1] - upGauss;
		Lap.push_back(lap);
	}
	//查看两个金字塔中的图像
	for (int i = 0; i < Gauss.size(); i++)
	{
		string name = to_string(i);
		imshow("G" + name, Gauss[i]);
		imshow("L" + name, Lap[i]);
	}

	waitKey(0);
	return 0;
}
相关推荐
李元豪3 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
UestcXiye4 小时前
《TCP/IP网络编程》学习笔记 | Chapter 9:套接字的多种可选项
c++·计算机网络·ip·tcp
埃菲尔铁塔_CV算法4 小时前
图像算法之 OCR 识别算法:原理与应用场景
图像处理·python·计算机视觉
一丝晨光4 小时前
编译器、IDE对C/C++新标准的支持
c语言·开发语言·c++·ide·msvc·visual studio·gcc
丶Darling.5 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯
奶味少女酱~5 小时前
常用的c++特性-->day02
开发语言·c++·算法
思通数据6 小时前
AI与OCR:数字档案馆图像扫描与文字识别技术实现与项目案例
大数据·人工智能·目标检测·计算机视觉·自然语言处理·数据挖掘·ocr
我是哈哈hh6 小时前
专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结
c++·算法·动态规划
_小柏_7 小时前
C/C++基础知识复习(15)
c语言·c++
_oP_i7 小时前
cmake could not find a package configuration file provided by “Microsoft.GSL“
c++