Commit 08515281 authored by tribta's avatar tribta

Tutorial Image Pyramids

parent f7d85bfe
Image Pyramids {#tutorial_pyramids} Image Pyramids {#tutorial_pyramids}
============== ==============
@prev_tutorial{tutorial_morph_lines_detection}
@next_tutorial{tutorial_threshold}
Goal Goal
---- ----
In this tutorial you will learn how to: In this tutorial you will learn how to:
- Use the OpenCV functions @ref cv::pyrUp and @ref cv::pyrDown to downsample or upsample a given - Use the OpenCV functions **pyrUp()** and **pyrDown()** to downsample or upsample a given
image. image.
Theory Theory
...@@ -19,7 +22,7 @@ Theory ...@@ -19,7 +22,7 @@ Theory
-# *Upsize* the image (zoom in) or -# *Upsize* the image (zoom in) or
-# *Downsize* it (zoom out). -# *Downsize* it (zoom out).
- Although there is a *geometric transformation* function in OpenCV that -literally- resize an - Although there is a *geometric transformation* function in OpenCV that -literally- resize an
image (@ref cv::resize , which we will show in a future tutorial), in this section we analyze 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 first the use of **Image Pyramids**, which are widely applied in a huge range of vision
applications. applications.
...@@ -52,12 +55,12 @@ Theory ...@@ -52,12 +55,12 @@ Theory
predecessor. Iterating this process on the input image \f$G_{0}\f$ (original image) produces the predecessor. Iterating this process on the input image \f$G_{0}\f$ (original image) produces the
entire pyramid. entire pyramid.
- The procedure above was useful to downsample an image. What if we want to make it bigger?: - The procedure above was useful to downsample an image. What if we want to make it bigger?:
columns filled with zeros (\f$0\f$) columns filled with zeros (\f$0 \f$)
- First, upsize the image to twice the original in each dimension, wit the new even rows and - 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 - Perform a convolution with the same kernel shown above (multiplied by 4) to approximate the
values of the "missing pixels" values of the "missing pixels"
- These two procedures (downsampling and upsampling as explained above) are implemented by the - These two procedures (downsampling and upsampling as explained above) are implemented by the
OpenCV functions @ref cv::pyrUp and @ref cv::pyrDown , as we will see in an example with the OpenCV functions **pyrUp()** and **pyrDown()** , as we will see in an example with the
code below: code below:
@note When we reduce the size of an image, we are actually *losing* information of the image. @note When we reduce the size of an image, we are actually *losing* information of the image.
...@@ -65,76 +68,134 @@ Theory ...@@ -65,76 +68,134 @@ Theory
Code Code
---- ----
This tutorial code's is shown lines below. You can also download it from This tutorial code's is shown lines below.
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp)
@add_toggle_cpp
You can also download it from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp)
@include samples/cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp
@end_toggle
@add_toggle_java
You can also download it from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgProc/Pyramids/Pyramids.java)
@include samples/java/tutorial_code/ImgProc/Pyramids/Pyramids.java
@end_toggle
@include samples/cpp/tutorial_code/ImgProc/Pyramids.cpp @add_toggle_python
You can also download it from
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/imgProc/Pyramids/pyramids.py)
@include samples/python/tutorial_code/imgProc/Pyramids/pyramids.py
@end_toggle
Explanation Explanation
----------- -----------
Let's check the general structure of the program: Let's check the general structure of the program:
- Load an image (in this case it is defined in the program, the user does not have to enter it #### Load an image
as an argument)
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp load @add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp load
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java load
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/imgProc/Pyramids/pyramids.py load
@end_toggle
#### Create window
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp show_image
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java show_image
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/imgProc/Pyramids/pyramids.py show_image
@end_toggle
- Create a Mat object to store the result of the operations (*dst*) and one to save temporal #### Loop
results (*tmp*).
@code{.cpp}
Mat src, dst, tmp;
/* ... */
tmp = src;
dst = tmp;
@endcode
- Create a window to display the result @add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp create_window @snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp loop
@end_toggle
- Perform an infinite loop waiting for user input. @add_toggle_java
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp infinite_loop @snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java loop
@end_toggle
Our program exits if the user presses *ESC*. Besides, it has two options: @add_toggle_python
@snippet python/tutorial_code/imgProc/Pyramids/pyramids.py loop
@end_toggle
- **Perform upsampling (after pressing 'u')** Perform an infinite loop waiting for user input.
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrup Our program exits if the user presses **ESC**. Besides, it has two options:
We use the function @ref cv::pyrUp with three arguments:
- *tmp*: The current image, it is initialized with the *src* original image. - **Perform upsampling - Zoom 'i'n (after pressing 'i')**
- *dst*: The destination image (to be shown on screen, supposedly the double of the
We use the function **pyrUp()** with three arguments:
- *src*: The current and destination image (to be shown on screen, supposedly the double of the
input image) input image)
- *Size( tmp.cols*2, tmp.rows\*2 )\* : The destination size. Since we are upsampling, - *Size( tmp.cols*2, tmp.rows\*2 )* : The destination size. Since we are upsampling,
@ref cv::pyrUp expects a size double than the input image (in this case *tmp*). **pyrUp()** expects a size double than the input image (in this case *src*).
- **Perform downsampling (after pressing 'd')**
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrdown @add_toggle_cpp
Similarly as with @ref cv::pyrUp , we use the function @ref cv::pyrDown with three arguments: @snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp pyrup
@end_toggle
- *tmp*: The current image, it is initialized with the *src* original image.
- *dst*: The destination image (to be shown on screen, supposedly half the input @add_toggle_java
image) @snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java pyrup
- *Size( tmp.cols/2, tmp.rows/2 )* : The destination size. Since we are upsampling, @end_toggle
@ref cv::pyrDown expects half the size the input image (in this case *tmp*).
- Notice that it is important that the input image can be divided by a factor of two (in @add_toggle_python
both dimensions). Otherwise, an error will be shown. @snippet python/tutorial_code/imgProc/Pyramids/pyramids.py pyrup
- Finally, we update the input image **tmp** with the current image displayed, so the @end_toggle
subsequent operations are performed on it.
@snippet cpp/tutorial_code/ImgProc/Pyramids.cpp update_tmp - **Perform downsampling - Zoom 'o'ut (after pressing 'o')**
We use the function **pyrDown()** with three arguments (similarly to **pyrUp()**):
- *src*: The current and destination image (to be shown on screen, supposedly half the input
image)
- *Size( tmp.cols/2, tmp.rows/2 )* : The destination size. Since we are upsampling,
**pyrDown()** expects half the size the input image (in this case *src*).
@add_toggle_cpp
@snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp pyrdown
@end_toggle
@add_toggle_java
@snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java pyrdown
@end_toggle
@add_toggle_python
@snippet python/tutorial_code/imgProc/Pyramids/pyramids.py pyrdown
@end_toggle
Notice that it is important that the input image can be divided by a factor of two (in both dimensions).
Otherwise, an error will be shown.
Results Results
------- -------
- After compiling the code above we can test it. The program calls an image **chicky_512.jpg** - The program calls by default an image [chicky_512.png](https://raw.githubusercontent.com/opencv/opencv/master/samples/data/chicky_512.png)
that comes in the *samples/data* folder. Notice that this image is \f$512 \times 512\f$, that comes in the `samples/data` folder. Notice that this image is \f$512 \times 512\f$,
hence a downsample won't generate any error (\f$512 = 2^{9}\f$). The original image is shown below: hence a downsample won't generate any error (\f$512 = 2^{9}\f$). The original image is shown below:
![](images/Pyramids_Tutorial_Original_Image.jpg) ![](images/Pyramids_Tutorial_Original_Image.jpg)
- First we apply two successive @ref cv::pyrDown operations by pressing 'd'. Our output is: - First we apply two successive **pyrDown()** operations by pressing 'd'. Our output is:
![](images/Pyramids_Tutorial_PyrDown_Result.jpg) ![](images/Pyramids_Tutorial_PyrDown_Result.jpg)
- Note that we should have lost some resolution due to the fact that we are diminishing the size - Note that we should have lost some resolution due to the fact that we are diminishing the size
of the image. This is evident after we apply @ref cv::pyrUp twice (by pressing 'u'). Our output of the image. This is evident after we apply **pyrUp()** twice (by pressing 'u'). Our output
is now: is now:
![](images/Pyramids_Tutorial_PyrUp_Result.jpg) ![](images/Pyramids_Tutorial_PyrUp_Result.jpg)
...@@ -51,6 +51,8 @@ In this section you will learn about the image processing (manipulation) functio ...@@ -51,6 +51,8 @@ In this section you will learn about the image processing (manipulation) functio
- @subpage tutorial_pyramids - @subpage tutorial_pyramids
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0 *Compatibility:* \> OpenCV 2.0
*Author:* Ana Huamán *Author:* Ana Huamán
......
/**
* @file Pyramids.cpp
* @brief Sample code of image pyramids (pyrDown and pyrUp)
* @author OpenCV team
*/
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
/// Global variables
Mat src, dst, tmp;
const char* window_name = "Pyramids Demo";
/**
* @function main
*/
int main( void )
{
/// General instructions
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" );
//![load]
src = imread( "../data/chicky_512.png" ); // Loads the test image
if( src.empty() )
{ printf(" No data! -- Exiting the program \n");
return -1; }
//![load]
tmp = src;
dst = tmp;
//![create_window]
imshow( window_name, dst );
//![create_window]
//![infinite_loop]
for(;;)
{
char c = (char)waitKey(0);
if( c == 27 )
{ break; }
//![pyrup]
if( c == 'u' )
{ pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );
printf( "** Zoom In: Image x 2 \n" );
}
//![pyrup]
//![pyrdown]
else if( c == 'd' )
{ pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );
printf( "** Zoom Out: Image / 2 \n" );
}
//![pyrdown]
imshow( window_name, dst );
//![update_tmp]
tmp = dst;
//![update_tmp]
}
//![infinite_loop]
return 0;
}
/**
* @file Pyramids.cpp
* @brief Sample code of image pyramids (pyrDown and 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] : "../data/chicky_512.png";
// 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;
}
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
class PyramidsRun {
String window_name = "Pyramids Demo";
public void run(String[] args) {
/// General instructions
System.out.println("\n" +
" Zoom In-Out demo \n" +
"------------------ \n" +
" * [i] -> Zoom [i]n \n" +
" * [o] -> Zoom [o]ut \n" +
" * [ESC] -> Close program \n");
//! [load]
String filename = ((args.length > 0) ? args[0] : "../data/chicky_512.png");
// Load the image
Mat src = Imgcodecs.imread(filename);
// Check if image is loaded fine
if( src.empty() ) {
System.out.println("Error opening image!");
System.out.println("Program Arguments: [image_name -- default ../data/chicky_512.png] \n");
System.exit(-1);
}
//! [load]
//! [loop]
while (true){
//! [show_image]
HighGui.imshow( window_name, src );
//! [show_image]
char c = (char) HighGui.waitKey(0);
c = Character.toLowerCase(c);
if( c == 27 ){
break;
//![pyrup]
}else if( c == 'i'){
Imgproc.pyrUp( src, src, new Size( src.cols()*2, src.rows()*2 ) );
System.out.println( "** Zoom In: Image x 2" );
//![pyrup]
//![pyrdown]
}else if( c == 'o'){
Imgproc.pyrDown( src, src, new Size( src.cols()/2, src.rows()/2 ) );
System.out.println( "** Zoom Out: Image / 2" );
//![pyrdown]
}
}
//! [loop]
System.exit(0);
}
}
public class Pyramids {
public static void main(String[] args) {
// Load the native library.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new PyramidsRun().run(args);
}
}
import sys
import cv2
def main(argv):
print("""
Zoom In-Out demo
------------------
* [i] -> Zoom [i]n
* [o] -> Zoom [o]ut
* [ESC] -> Close program
""")
## [load]
filename = argv[0] if len(argv) > 0 else "../data/chicky_512.png"
# Load the image
src = cv2.imread(filename)
# Check if image is loaded fine
if src is None:
print ('Error opening image!')
print ('Usage: pyramids.py [image_name -- default ../data/chicky_512.png] \n')
return -1
## [load]
## [loop]
while 1:
rows, cols, _channels = map(int, src.shape)
## [show_image]
cv2.imshow('Pyramids Demo', src)
## [show_image]
k = cv2.waitKey(0)
if k == 27:
break
## [pyrup]
elif chr(k) == 'i':
src = cv2.pyrUp(src, dstsize=(2 * cols, 2 * rows))
print ('** Zoom In: Image x 2')
## [pyrup]
## [pyrdown]
elif chr(k) == 'o':
src = cv2.pyrDown(src, dstsize=(cols // 2, rows // 2))
print ('** Zoom Out: Image / 2')
## [pyrdown]
## [loop]
cv2.destroyAllWindows()
return 0
if __name__ == "__main__":
main(sys.argv[1:])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment