图像“金字塔”

图像“金字塔”是通过多个分辨率表示图像的一种有效且简单的结构

一个图像“金字塔”一系列以金字塔排列、分辨率逐步降低的图像集合

图像“金字塔”的底部是待处理图像的高分辨率,顶部是低分辨率的表示

图像“金字塔”种比较著名的两种——高斯“金字塔”和拉普拉斯“金字塔”

高斯金字塔pyrDowm()

高斯“金字塔”的底层为图像的原图,每往上一层就会通过下采样缩小一次图像的尺寸

通常情况下,尺寸会缩小为原来的一半,有特殊需求,缩小的尺寸也可以根据时间情况进行调整

OpenCV4中提供了pyrDowm()函数专门用于图像的下采样计算

pyrDowm()函数原型:

void pyrDowm(InputArray src,
             OutputArray dst,
             const Size& dstsize = Size(),
             int borderType = BORDER_DEFAULT
             )
  • src:输入待下采样的图像
  • dst:输出下采样后的图像,图像的尺寸可以指定,但是数据类型和通道数与src相同
  • dstsize:输出图像尺寸,可以默认
  • borderType:像素边界外推方法的标志

边界外推方法标志

方法标志 简记 作用
BORDER_CONSTANT 0 用特定值填充,如iiiiii\ abcdefgh\ iiiiii
BORDER_REPLICATE 1 两端复制填充,如aaaaaa\ abcdefgh\ bbbbbb
BORDER_REFLECT 2 倒序填充,如fedcba\ abcdefgh\ hgfedcb
BORDER_WRAP 3 正序填充,如cdefgh\ abcdefgh\ abcdefg
BORDER_REFLECT_101 4 不含边界值的倒序填充,如gfedcb\ abcdefgh\ gfedcba
BORDER_TRANSPARENT 5 随机填充,uvwxyz\ abcdefgh\ ijklmno
BORDER_REFLECT101 4 与 BORDER_REFLECT_101 相同
BORDER_DEFAULT 4 与 BORDER_REFLECT_101 相同
BORDER_ISOLATED 16 不关心感兴趣区域之外的部分

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

拉普拉斯“金字塔”pyrUp()

拉普拉斯“金字塔”与高斯“金字塔”正好相反,高斯“金字塔"通过底层图像构建上层图像

而拉普拉斯”金字塔“是通过上层小尺寸的图像构建下层大尺寸的图像

拉普拉斯”金字塔“具有预测残差的作用,需要与高斯”金字塔“联合使用

高斯”金字塔“第i-1层图像的下采样与高斯”金字塔“第i层上采样的差值图像作为拉普拉斯”金字塔“第i层图像

对于上采样操作,OpenCV4中提供pyrUp()函数

pyrUp()函数原型:

void pyrUp(InputArray src,
           OutputArray dst,
           const Szie& dstsize = Szie()
           int borderType = BORDER_DEFAULT
           )
  • src:输入待下采样的图像
  • dst:输出下采样后的图像,图像的尺寸可以指定,但是数据类型和通道数与src相同
  • dstsize:输出图像尺寸,可以默认
  • borderType:像素边界外推方法的标志

完成高斯”金字塔“的构建后,从上到下取出高斯”金字塔“中的每一次图像

如果是高斯”金字塔“中最上面的一层,则先下采样再上采样,将下采样与上采样的差值作为拉普拉斯”金字塔"的最上层一层

如果从高斯”金字塔“取出的第i层不是最上层,则直接对高斯金字塔中第i+1层图像进行上采样,计算与高斯”金字塔“第i层图像差值

将差值图像作为高斯”金字塔“的第i层

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
using namespace std;
using namespace cv;
int main()
{
    Mat img = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg");
    if (img.empty()) {
        cout << "Error" << 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,Size(Gauss[i].rows/2,Gauss[i].cols/2)); //下采样
        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,Size(Gauss[i].rows,Gauss[i].cols));
            lap = Gauss[i] - upGauss;
            Lap.push_back(lap);
        }
        pyrUp(Gauss[i],upGauss,Size(Gauss[i-1].rows,Gauss[i-1].cols));
        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;
}

注意:一定要有相同的尺寸和数据类型

results matching ""

    No results matching ""