【OpenCV学习4】图像金字塔

图像金字塔:

在先前对图像的操作中,我们对图像的处理是停留在二维尺度上的,即没有考虑到图像其实具有第三个维度。而在现实场景中,我们人眼观察到的世界是时刻变化的,即观察近处的图像较大,远处的图像较小的特点。因此对于给定的一帧图像,为了模仿图像离我们远去时在视网膜上的成像,并尽可能的还原图像在不同尺度下的呈现的不同特征,(即图像的纵深),我们引入图像金字塔的概念。试图图在二维图像的基础之上,还原出图像中自然存在的另一个维度:尺度。

图像金字塔(Image Pyramid):

一个图像金字塔由一系列按比例缩放的不同Size的图像组成,最底层的图像的尺寸最大,最上方的图像的尺寸最小,从空间上看就像一个金字塔,因此得名。
在这里插入图片描述

会用到的API:

1.cv::subtract() 计算两个图像之间的每每元素像素差

函数原型:

void cv::subtract(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dst, cv::InputArray mask = noArray(), int dtype = -1)

其中:
src1第一个输入数组或标量。
src2第二个输入数组或标量。
dst输出,大小和通道数与输入数组相同。(若最终dst<0,则dst取0
//mask掩膜;这是一个8位单通道数组,选择感兴趣区域,选定后只能对该区域进行操作。
//dtype输出数组的可选深度,输出图像的深度可以自定义。

类似的减法操作函数:
absdiff(img1,img2,dst)
区别:若dst<0,则dst=|dst|>=0

2.cv::normalize() 归一化函数,将图像像素值归一化到一个范围
该函数分为范围归一化与数据值归一化

函数原型:

void cv::normalize(InputArry src,InputOutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int dtype=-1,InputArray mark=noArry())

其中:
src 输入数组;
dst 输出数组,数组的大小和原数组一致;
alpha 规范范围下限;
beta 规范范围上限;
norm_type 归一化选择的数学公式类型;
//dtype 当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同,不同的地方由dtype决定;
//mark 掩膜。选择感兴趣区域,选定后只能对该区域进行操作

归一化选择的数学公式类型介绍(norm_type):

NORM_MINMAX(常用):
数组的数值被平移或缩放到一个指定的范围,线性归一化。
在这里插入图片描述
其中
max=beta ;
min=alpha

NORM_INF:
分母为L∞范数 ,即矩阵各元素绝对值的最大值(切比雪夫距离)
在这里插入图片描述
NORM_L1:
分母为L1-范数,即矩阵元素的绝对值之和(曼哈顿距离)
在这里插入图片描述
NORM_L2:
分母为L2-范数,即矩阵各元素的欧几里德距离之和
在这里插入图片描述
例:NORM_MINMAX:[0,255]
在这里插入图片描述
input:1,2,3,4,5,6
output:0,28.3333,56.6667,85,113.333,141.667,170,198.333,226.667,255

参考博客:
https://blog.csdn.net/cosmispower/article/details/64457406
https://www.cnblogs.com/huluwa508/p/11356196.html

降采样:

cv::pyrDown()

函数原型:

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

其中:
src: input image.
dst :output image; it has the specified size and the same type as src.
dstsize: size of the output image(没有给就默认M/2×N/2)
borderType: Pixel extrapolation method, see cv::BorderTypes (BORDER_CONSTANT isn’t supported)(像素外推方法)

在源代码中作者也给出了注意事项:
对于输出图像的尺寸:

By default, size of the output image is computed as
Size((src.cols+1)/2, (src.rows+1)/2), but in any case, the
following conditions should be satisfied:
在这里插入图片描述
即2×输出图像的宽/高与原图像宽/高的差值不大于2.(可能和算法有关)

第一步中高斯平滑采用的卷积核,size为5×5:
在这里插入图片描述

代码实现:

void My_pyrdown(int , void*) //降采样(回调函数)
{
    
    
    pyrDown(SRC,DST); //降采样
    SRC=DST.clone();
    imshow("My_pyrdown",SRC);
}
上采样:

cv::pyrUp()和cv::pyrDown()类似。

上采样操作具体操作:
1.将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
2.使用先前同样的内核与放大后的图像卷积, 获得 “新增像素”的近似值(通常使用插值方法)。得到的图像即为放大后的图像,但是与原来的图像相比会比较模糊,因为在缩放的过程中已经丢失了一些信息。

代码实现:

void My_pyrUp(int ,void*) //上采样(回调函数)
{
    
    
    pyrUp(SRC,DST); //上采样
    SRC=DST.clone();
    imshow("My_pyrUp",SRC);
}

效果实现:

降采样:
在这里插入图片描述
上采样:
在这里插入图片描述

高斯金字塔(Gaussian pyramid):

高斯金字塔通过对原图从底部向上,逐层降采样得到,图像的尺度逐层减少。降采样之后的图像大小是原图像Size的1/4,即M×N的图像,降采样得到M/2×N/2.(对原图像删除偶数行与列)
在这里插入图片描述
高斯金字塔的实现过程:
1.对当前层进行高斯模糊(Gaussian Blur)
2.删除所有的偶数行和偶数列,再拼为一个完整的图像,作为高斯金字塔当前层的上一层。

高斯不同(Different of Gaussian)
高斯不同,就是把同一张图像在不同的参数下做高斯模糊之后的结果相减,得到的输出图像,即高斯不同(DOG).这和拉普拉斯金字塔的获取原理有些类似。

高斯不同是图像的内在特征,在灰度图像增强,角点检测中经常用的到。

差分金字塔:
差分金字塔是在高斯金字塔的基础上构建起来的,即在高斯金字塔每一层上再计算高斯不同。DOG金字塔的第1组第1层是由高斯金字塔的第1组第2层减第1组第1层得到的。以此类推,逐组逐层生成每一个差分图像,所有差分图像构成差分金字塔。概括为DOG金字塔的第0组第l层图像是由高斯金字塔的第0组第i+1层减第0组第i层得到的。

每一组在层数上,DOG金字塔比高斯金字塔少一层。像Sift特征点的提取都是在DOG金字塔上进行的。

参考博客:
https://blog.csdn.net/zhu_hongji/article/details/81536820
https://blog.csdn.net/dcrmg/article/details/52561656

代码实现:

void Different_of_Gaussian(int n, void*) //高斯不同
{
    
    
    n=n*2+3;
    Mat temp1,temp2,result;
    GaussianBlur(SRC, temp1, Size(n-2, n-2),2,2);
    GaussianBlur(SRC, temp2, Size(n, n),2,2);
    subtract(temp1,temp2,result); //图像减法操作,temp1-temp2
    normalize(result,result,0,255,NORM_MINMAX); //归一化函数(投影范围:0,255)
    imshow("Different_of_Gaussian",result);
}

第一层高斯金字塔上的高斯差分:
在这里插入图片描述

拉普拉斯金字塔(Laplacian pyramid)

拉普拉斯金字塔可以认为是残差金字塔,用来存储下采样后图片与原始图片的差异。我们知道,如果高斯金字塔中任意一张图Gi(G0为最初的高分辨率图像)先进行下采样得到图Down(Gi),再进行上采样得到图Up(Down(Gi)),得到的Up(Down(Gi))与Gi相比会更模糊,因为下采样过程丢失的信息不能通过上采样来完全恢复,也就是说下采样是不可逆的。

下式是拉普拉斯金字塔第i层的数学定义:
在这里插入图片描述在这里插入图片描述
即:
在这里插入图片描述
参考博客:
https://www.cnblogs.com/sddai/p/10330756.html
https://zhuanlan.zhihu.com/p/94014493

代码实现:

void Laplacian_pyramid(int, void*) //拉普拉斯金字塔
{
    
    
    Mat temp;
    pyrDown(SRC,DST); //降采样
    pyrDown(DST,SRC); //降采样
    pyrUp(SRC,temp); //上采样
    resize(temp,temp,DST.size());
    subtract(DST,temp,SRC);
    normalize(SRC,SRC,0,255,NORM_MINMAX); //归一化函数(投影范围:0,255)
    imshow("Laplacian_pyramid",SRC);
    imwrite("/home/yht/OpenCV/image/test5_pyrdown.png",SRC);
    SRC=DST.clone();
}

拉普拉斯金字塔:

在这里插入图片描述

おすすめ

転載: blog.csdn.net/SESESssss/article/details/106429325
おすすめ