Goal
学习使用pyrUp()和pyrDown()对图像进行上采样和下采样。
Theory
理论来源于《Learning OpenCV》!- Usually we need to convert an image to a size different than its original. For this, there are two possible options:
- Upsize the image (zoom in) or
- Downsize it (zoom out).
有两种可能:放大以及缩小
Although there is a geometric transformation function in OpenCV that -literally- resize an image (resize , which we will show in a future tutorial), in this section we analyze first the use of Image Pyramids, which are widely applied in a huge range of vision applications.
尽管OpenCV中已经有了一个函数resize(),不过这个函数将会在以后的教程中介绍。这里介绍类图像金字塔。
Image Pyramid
- An image pyramid is a collection of images - all arising from a single original image - that are successively downsampled until some desired stopping point is reached.
- There are two common kinds of image pyramids:
- Gaussian pyramid: Used to downsample images
- Laplacian pyramid: Used to reconstruct an upsampled image from an image lower in the pyramid (with less resolution)
图像金字塔是一系列的图片。全部来源于原始图片,连续向下采样知道满足一定的条件。
通常有两种图像金字塔
高斯金字塔:通常下采样
拉普拉斯金字塔:通常用于图像的重建(图片的分辨率通常低!)
Gaussian Pyramid
-
Imagine the pyramid as a set of layers in which the higher the layer, the smaller the size.
设想金字塔是好多层,随着层数高,尺寸越小。
Every layer is numbered from bottom to top, so layer (i+1) (denoted as Gi+1 is smaller than layer i ( Gi).
从下到上一次层数变大,但尺寸也越来小。
-
To produce layer (i+1) in the Gaussian pyramid, we do the following:
- Convolve Gi with a Gaussian kernel:
116⎡⎣⎢⎢⎢⎢⎢⎢1464141624164624362464162416414641⎤⎦⎥⎥⎥⎥⎥⎥- Remove every even-numbered row and column.
生成上一层,这样做:
1.使用高斯卷积核(模糊) 2.删除偶数行和偶数列
You can easily notice that the resulting image will be exactly one-quarter the area of its predecessor. Iterating this process on the input image G0 (original image) produces the entire pyramid.
可以看到新生成的图片是原图片的四分之一。迭代这个过程到停止。
The procedure above was useful to downsample an image. What if we want to make it bigger?: columns filled with zeros ( 0)
- First, upsize the image to twice the original in each dimension, wit 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.扩展原始图片为两倍
2.进行卷积使用上面的核,计算缺失的像素值。
- Note
When we reduce the size of an image, we are actually losing information of the image.
当减小图片尺寸的时候,其实已经丧失了图片的部分有用信息。
Code
#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] : "lena.jpg";
// Loads an image
Mat src = imread( filename );
// Check if image is loaded fine
if(src.empty()){
printf(" Error opening image\n");
printf(" Program Arguments: [image_name -- default ../data/chicky_512.png] \n");
return -1;
}
//![load]`
//![loop]
for(;;)
{
//![show_image]
imshow( window_name, src );
//![show_image]
char c = (char)waitKey(0);
if( c == 27 )
{ 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 0;
}
代码较为简单,注释较为清楚,这里不再解释。
CMakeLists.txt文件如下
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin)
结果如下: