【opencv 450 Image Processing】Image Pyramids图像金字塔

Goal

在本教程中,您将学习如何:

使用 OpenCV 函数 pyrUp()pyrDown() 对给定图像进行下采样或上采样。

Theory

笔记

下面的解释属于 Bradski 和 Kaehler 的《Learning OpenCV》一书。

通常我们需要将图像转换为与原始大小不同的大小。 为此,有两种可能的选择:

  1. Upsize the image (zoom in) or    放大图像(放大)或
  2. Downsize it (zoom out).  缩小它(缩小)。

尽管 OpenCV 中有一个几何变换函数——字面意思——调整图像大小(resize,我们将在以后的教程中展示),但在本节中,我们首先分析Image Pyramids图像金字塔的使用,它广泛应用于各种 视觉应用。

Image Pyramid

图像金字塔是图像的集合——所有图像都来自单个原始图像——这些图像被连续下采样,直到达到某个所需的停止点。

有两种常见的图像金字塔:

Gaussian pyramid:高斯金字塔:用于对图像进行下采样

Laplacian pyramid: 拉普拉斯金字塔:用于从金字塔较低的图像(分辨率较低)重建上采样图像

在本教程中,我们将使用高斯金字塔

Gaussian Pyramid

  1. 将金字塔想象成一组层,其中层越高尺寸越小

 

  1. 每一层都是从下到上编号的,所以第(i+1)层(记为Gi+1)小于第i层(Gi)。
  2. 为了在高斯金字塔中生成第 (i+1) 层,我们执行以下操作:

高斯核卷积 Gi:

 

删除每个偶数行和列

  1. 您可以很容易地注意到,生成的图像将恰好是其前身的四分之一。 在输入图像 G0(原始图像)迭代这个过程会产生整个金字塔。
  2. 上述过程对于对图像进行下采样很有用。 如果我们想让它更大怎么办?:用zeros ( 0)填充列

首先,将图像在每个维度上放大到原始图像的两倍,新的偶数行和.

使用上面显示的相同内核执行卷积(乘以 4)以近似“缺失像素”的值.

  • First, upsize the image to twice the original in each dimension, with the new even rows and
  • Perform a convolution with the same kernel shown above (multiplied by 4) to approximate the values of the "missing pixels"
  1. 两个过程(如上所述的下采样上采样)由 OpenCV 函数 pyrUp() pyrDown() 实现,我们将在下面的代码示例中看到:

笔记

当我们减小图像的大小时,我们实际上是在丢失图像的信息。

Code

本教程代码如下所示。

你也可以从这里下载raw.githubusercontent.com

/**
 * @file Pyramids.cpp
 * @brief Sample code of image pyramids (pyrDown and pyrUp)
 *图像金字塔示例代码(pyrDown和pyrUp)
 * @author OpenCV team
 */
#include "iostream"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

const char* window_name = "Pyramids Demo";

/**
 * @function main
 */
int main( int argc, char** argv )
{
    /// General instructions
    cout << "\n Zoom In-Out demo \n "
            "------------------  \n"
            " * [i] -> Zoom in   \n"
            " * [o] -> Zoom out  \n"
            " * [ESC] -> Close program \n" << endl;

    //![load]
    const char* filename = argc >=2 ? argv[1] : "chicky_512.png";

    // 加载图像
    Mat src = imread( samples::findFile( filename ) );

    // 检查图像是否加载正常
    if(src.empty()){
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default chicky_512.png] \n");
        return EXIT_FAILURE;
    }
    //![load]

    //![loop]
    for(;;)
    {
        //![显示图像]
        imshow( window_name, src );
        //![show_image]
        char c = (char)waitKey(0);

        if( c == 27 )//ESC
        { break; }
        //![pyrup]上采样
        else if( c == 'i' )
        { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );
            printf( "** Zoom In: Image x 2 \n" );
        }
        //![pyrup]
        //![pyrdown]下采样
        else if( c == 'o' )
        { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );
            printf( "** Zoom Out: Image / 2 \n" );
        }
        //![pyrdown]
    }
    //![loop]

    return EXIT_SUCCESS;
}

Explanation

让我们检查一下程序的一般结构:

Load an image

    const char* filename = argc >=2 ? argv[1] : "chicky_512.png";
    // Loads an image
    Mat src = imread( samples::findFile( filename ) );
    // Check if image is loaded fine
    if(src.empty()){
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default chicky_512.png] \n");
        return EXIT_FAILURE;
    }

Create window

imshow( window_name, src );

Loop

 for(;;)
    {
        imshow( window_name, src );
        char c = (char)waitKey(0);
        if( c == 27 )
        { break; }
        else if( c == 'i' )
        { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );
            printf( "** Zoom In: Image x 2 \n" );
        }
        else if( c == 'o' )
        { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );
            printf( "** Zoom Out: Image / 2 \n" );
        }
    }

执行无限循环等待用户输入。 如果用户按下 ESC,我们的程序就会退出。 此外,它有两种选择:

Perform upsampling - Zoom 'i'n (after pressing 'i')

执行上采样 - 缩放“i”(按“i”后)

我们使用带有三个参数的函数 pyrUp():

src:当前和目标图像(显示在屏幕上,应该是输入图像的两倍)

Size( tmp.cols*2, tmp.rows*2 ) :目标大小。 由于我们正在上采样,因此 pyrUp() 期望大小是输入图像(在本例中为 src)的两倍。

        else if( c == 'i' )

        { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );

            printf( "** Zoom In: Image x 2 \n" );

        }

Perform downsampling - Zoom 'o'ut (after pressing 'o')

执行下采样 - 缩小“o”(按“o”后)

我们使用带有三个参数的函数 pyrDown()(类似于 pyrUp()):

src:当前和目标图像(显示在屏幕上,应该是输入图像的一半)

Size(tmp.cols/2, tmp.rows/2):目标大小。 由于我们正在进行下采样,因此 pyrDown() 期望输入图像大小的一半(在本例中为 src)。

        else if( c == 'o' )

        { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );

            printf( "** Zoom Out: Image / 2 \n" );

        }

请注意,输入图像可以除被2整除(在两个维度上)是很重要的。 否则,将显示错误。

Results

该程序默认调用位于 samples/data 文件夹中的图像 chiky_512.png。 请注意,此图像为 512×512,因此下采样不会产生任何错误。 原图如下所示:

 

 

首先,我们通过按“d”应用两个连续的 pyrDown() 操作。 我们的输出是:

 

请注意,由于我们正在减小图像的大小,我们应该会丢失一些分辨率。 这在我们应用 pyrUp() 两次(通过按 'u')后很明显。 我们的输出现在是:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值