本文主要實作對輸入圖像的上采樣和下采樣操作,使用到pyrUP和pyrDown兩個函數來對分别對圖像進行上采樣和下采樣。
圖像金字塔是一系列圖像集合,它們從源圖像連續的進行下采樣,直到需要的位置才停止操作。
兩種常見的圖像金子塔如下所述:
1.高斯金字塔:用于下采樣圖像。
2.拉普拉斯金字塔:用于把下層低分辨率的圖像進行上采樣重建。
本文用到的是高斯金字塔。
1)高斯金字塔圖形如下所示,越往上,圖像的分辨率(大小)越小。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CN1IzM3QTOyQGNzQWMjlTMzYzXzADMygTM4AzLclDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
2)每層的計數從底層開始,即(i+1),注:Gi+1要比Gi層分辨率小!
3)産生i+1層的操作如下所述:
首先,用高斯核和Gi層進行卷積,高斯核大小為16*16;
然後,移走每個偶數行和列。
4)很容易觀測到處理的結果即是前一層的1/4。從G0(原始輸入圖像)遞歸這個處理過程,就可以産生整個金字塔。
5)上面所述的處理過程很适合應用到對圖像的下采樣操作。
如果我們想使圖像變的大一些,怎麼辦呢?
首先,增大圖像的每個次元(一般為高度和寬度)為原來的兩倍。把新的偶數行和列置零。
然後,用上面使用的高斯核進行卷積操作,記得要乘以4,以此來逼近丢失的像素值。
上面所述的兩個處理過程,即對圖像的下采樣和上采樣,本文用pyrUp和pyrDown兩個函數來實作。
具體實作代碼如下所示:
#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;
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" );
//測試圖像必須是2^(n)
src = imread("D:\\lena.bmp");
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 );
//循環操作
for(;;)
{
int c;
c = waitKey(10);
if( (char)c == 27 )//按下鍵盤的"ESC"退出程式
{ break; }
if( (char)c == 'u' )//按下鍵盤的"u"進行上采樣操作
{
//tmp:原圖像 ,dst:輸出圖像,是原圖像的兩倍,
//Size:dst圖像的大小,行和列擴大2倍
pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );
printf( "** Zoom In: Image x 2 \n" );
}
else if( (char)c == 'd' )//按下鍵盤的"d"進行下采樣操作
{
pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );
printf( "** Zoom Out: Image / 2 \n" );
}
//建立輸出顯示視窗
imshow( window_name, dst );
tmp = dst;//更新temp值為了更好的遞歸操作
}
return 0;
}