学习OpenCV范例(十三)——图像金字塔

来源:互联网 发布:linux c 删除非空目录 编辑:程序博客网 时间:2024/05/17 02:24

以多个分辨率来表示图像的一种有效且概念简单的结构是图像金字塔,一个图像金字塔是一系列以金子塔形状排列的、分辨率逐渐降低的图像集合。——《数字图像处理》。

图像金字塔可用于图像的缩小和放大,在后期的讲解中还会涉及到利用图像金字塔对图像进行分割。

1、原理

一个图像金字塔是一系列图像的集合 - 所有图像来源于同一张原始图像 - 通过梯次向下采样获得,直到达到某个终止条件才停止采样。
有两种类型的图像金字塔常常出现在文献和应用中:
高斯金字塔(Gaussian pyramid): 用来向下采样,主要的图像金字塔
拉普拉斯金字塔(Laplacian pyramid): 用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。

高斯金字塔

想想金字塔为一层一层的图像,层级越高,图像越小,分辨率越低。

Pyramid figure

每一层都按从下到上的次序编号, 层级 G(i+1) (表示为 G(i+1) 尺寸小于第i层G(i))。

为了获取层级为 G(i+1) 的金字塔图像,我们采用如下方法:

①、对图像G(i)进行高斯内核卷积

②、将所有偶数行和列去除

得到的图像即为G(i+1)的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G(i)(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。

以上就是对图像的向下取样操作,缩小图像,如果想放大图像,则需要通过向上取样操作得到,具体做法如下:

①、将图像在每个方向扩大为原来的两倍,新增的行和列以0填充

②、使用先前同样的内核(乘以4)与放大后的图像卷积,获得 “新增像素” 的近似值

得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,那么就需要用到拉普拉斯金字塔。

拉普拉斯金字塔

拉普拉斯金字塔第i层的数学定义为:


UP()操作是对源图像进行向上取样,符号叉表示卷积,G为高斯内核。也即是说拉普拉斯金字塔是通过源图像减去缩小后再放大的图像。

整个过程可以由下图看出:


          图1、高斯金字塔及其逆形式—拉普拉斯金子塔(图片来自学习OpenCV)

2、代码实现

#include "stdafx.h"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <math.h>#include <stdlib.h>#include <stdio.h>using namespace cv;/// 全局变量Mat src, dst, tmp;char* window_name = "Pyramids Demo";/** * @函数 main */int main( int argc, char** argv ){  /// 指示说明  printf( "\n Zoom In-Out demo  \n " );  printf( "------------------ \n" );  printf( " * [u] -> Zoom in  \n" );  printf( " * [d] -> Zoom out \n" );  printf( " * [ESC] -> Close program \n \n" );  /// 测试图像 - 尺寸必须能被 2^{n} 整除  src = imread( "chicky_512.png" );  if( !src.data )    { printf(" No data! -- Exiting the program \n");      return -1; }  tmp = src;  dst = tmp;  /// 创建显示窗口  namedWindow( window_name, CV_WINDOW_AUTOSIZE );  imshow( window_name, dst );  /// 循环  while( true )  {    int c;    c = waitKey(10);    if( (char)c == 27 )      { break; }    if( (char)c == 'u' )      { pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );        printf( "** Zoom In: Image x 2 \n" );      }    else if( (char)c == 'd' )     { pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );       printf( "** Zoom Out: Image / 2 \n" );     }    imshow( window_name, dst );    tmp = dst;  }  return 0;}

3、运行结果


                             图2、原图


图3、缩小


                         图4、放大

4、用到的类和函数

pyrDown:

功能:图像的下采样

结构:

void pyrDown(InputArray src, OutputArray dst, const Size& dstsize=Size())
src :源图像
dst :目标图像,和源图像有同样的size和type
dstsize :目标图像的Size,默认为Size((src.cols+1)/2, (src.rows+1)/2),但在任何情况下,下面的条件必须满足:

\begin{array}{l}| \texttt{dstsize.width} *2-src.cols| \leq  2  \\ | \texttt{dstsize.height} *2-src.rows| \leq  2 \end{array}
高斯内核结构为:

\frac{1}{256} \begin{bmatrix} 1 & 4 & 6 & 4 & 1  \\ 4 & 16 & 24 & 16 & 4  \\ 6 & 24 & 36 & 24 & 6  \\ 4 & 16 & 24 & 16 & 4  \\ 1 & 4 & 6 & 4 & 1 \end{bmatrix}

首先它对输入图像用指定滤波器进行卷积,然后通过拒绝偶数的行与列来下采样图像。

pyrUp:

功能:图像的上采样

结构:

void pyrUp(InputArray src, OutputArray dst, const Size& dstsize=Size())
src :源图像
dst :目标图像,和源图像有同样的size和type
dstsize :目标图像的Size,默认为
Size(src.cols*2, (src.rows*2),但在任何情况下,下面的条件必须满足:
\begin{array}{l}| \texttt{dstsize.width} -src.cols*2| \leq  ( \texttt{dstsize.width}   \mod  2)  \\ | \texttt{dstsize.height} -src.rows*2| \leq  ( \texttt{dstsize.height}   \mod  2) \end{array}

首先通过在图像中插入 0 偶数行和偶数列,然后对得到的图像用指定的滤波器进行高斯卷积,其中滤波器乘以4做插值。所以输出图像是输入图像的 4 倍大小。

0 0
原创粉丝点击