理论
图像金字塔
- 图像金字塔是图像的集合 - 全部来自单个原始图像 - 它们被连续地下采样直到达到某个期望的停止点。
- 有两种常见的图像金字塔:
- 高斯金字塔:用于下采样图像
- 拉普拉斯金字塔:用于从金字塔下方的图像重建上采样图像(分辨率较低)
高斯金字塔
- 想象金字塔是一组图层,图层越高,尺寸越小。
- 每个层从下到上编号,因此层(i + 1)(表示为(Gi + 1)小于层i(Gi))。
- 要在高斯金字塔中生成层(i + 1),我们执行以下操作:
- 使用高斯内核卷积Gi:
- 删除每个偶数行和列。
- 您可以很容易地注意到,生成的图像将是其前一个区域的四分之一。 在输入图像G0(原始图像)上迭代此过程会产生整个金字塔。
- 上述过程对于下采样图像很有用。 如果我们想让它变得更大怎么办?:用零填充列。
- 首先,将图像的尺寸增大到每个尺寸的原始尺寸的两倍,即新的偶数行和
- 使用上面显示的相同内核执行卷积(乘以4)以近似“缺失像素”的值
- 这两个过程(如上所述的下采样和上采样)由OpenCV函数cv :: pyrUp和cv :: pyrDown实现。
代码
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
Mat src, dst, tmp;
const char* window_name = "Pyramids Demo";
int main( void )
{
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" );
src = imread( "../data/chicky_512.png" );
if( src.empty() )
{ printf(" No data! -- Exiting the program \n");
return -1; }
tmp = src;
dst = tmp;
namedWindow( window_name, WINDOW_AUTOSIZE );
imshow( window_name, dst );
for(;;)
{
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;
}
解释
- 加载图像
- 创建一个Mat对象来存储操作的结果(dst),另一个用于保存时间结果(tmp)。
- 创建一个窗口以显示结果
- 执行无限循环等待用户输入。
- 进行上采样(按'u'后):
- 执行下采样(按'd'后):
- 请注意,输入图像可以按两倍(两个维度)进行划分非常重要。 否则,将显示错误。
- 最后,我们用显示的当前图像更新输入图像tmp,以便对其执行后续操作。
效果
原始图像如下所示:
向下采样的效果图
向上采样的效果图