diff --git a/doc/tutorials/imgproc/pyramids/pyramids.markdown b/doc/tutorials/imgproc/pyramids/pyramids.markdown index 5210ec007d..b832b22fb8 100644 --- a/doc/tutorials/imgproc/pyramids/pyramids.markdown +++ b/doc/tutorials/imgproc/pyramids/pyramids.markdown @@ -1,12 +1,15 @@ Image Pyramids {#tutorial_pyramids} ============== +@prev_tutorial{tutorial_morph_lines_detection} +@next_tutorial{tutorial_threshold} + Goal ---- 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. Theory @@ -19,7 +22,7 @@ Theory -# *Upsize* the image (zoom in) or -# *Downsize* it (zoom out). - 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 applications. @@ -52,12 +55,12 @@ Theory predecessor. Iterating this process on the input image \f$G_{0}\f$ (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 (\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 - Perform a convolution with the same kernel shown above (multiplied by 4) to approximate the values of the "missing pixels" - 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: @note When we reduce the size of an image, we are actually *losing* information of the image. @@ -65,76 +68,134 @@ Theory Code ---- -This tutorial code's is shown lines below. You can also download it from -[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp) +This tutorial code's is shown lines below. + +@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 ----------- 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 - as an argument) - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp load +#### Load an image + +@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 - results (*tmp*). - @code{.cpp} - Mat src, dst, tmp; - /* ... */ - tmp = src; - dst = tmp; - @endcode +#### Loop -- Create a window to display the result - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp create_window +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp loop +@end_toggle -- Perform an infinite loop waiting for user input. - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp infinite_loop +@add_toggle_java +@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')** - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrup - We use the function @ref cv::pyrUp with three arguments: +Perform an infinite loop waiting for user input. +Our program exits if the user presses **ESC**. Besides, it has two options: - - *tmp*: The current image, it is initialized with the *src* original image. - - *dst*: The destination image (to be shown on screen, supposedly the double of the +- **Perform upsampling - Zoom 'i'n (after pressing 'i')** + + 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) - - *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*). - - **Perform downsampling (after pressing 'd')** - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp pyrdown - Similarly as with @ref cv::pyrUp , we use the function @ref cv::pyrDown with three arguments: - - - *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 - image) - - *Size( tmp.cols/2, tmp.rows/2 )* : The destination size. Since we are upsampling, - @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 - both dimensions). Otherwise, an error will be shown. - - Finally, we update the input image **tmp** with the current image displayed, so the - subsequent operations are performed on it. - @snippet cpp/tutorial_code/ImgProc/Pyramids.cpp update_tmp + - *Size( tmp.cols*2, tmp.rows\*2 )* : The destination size. Since we are upsampling, + **pyrUp()** expects a size double than the input image (in this case *src*). + +@add_toggle_cpp +@snippet cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp pyrup +@end_toggle + +@add_toggle_java +@snippet java/tutorial_code/ImgProc/Pyramids/Pyramids.java pyrup +@end_toggle + +@add_toggle_python +@snippet python/tutorial_code/imgProc/Pyramids/pyramids.py pyrup +@end_toggle + +- **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 ------- -- After compiling the code above we can test it. The program calls an image **chicky_512.jpg** - that comes in the *samples/data* folder. Notice that this image is \f$512 \times 512\f$, +- 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$, 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) -- 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) - 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: ![](images/Pyramids_Tutorial_PyrUp_Result.jpg) diff --git a/doc/tutorials/imgproc/table_of_content_imgproc.markdown b/doc/tutorials/imgproc/table_of_content_imgproc.markdown index f4c57cdd62..d25502369a 100644 --- a/doc/tutorials/imgproc/table_of_content_imgproc.markdown +++ b/doc/tutorials/imgproc/table_of_content_imgproc.markdown @@ -51,6 +51,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_pyramids + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán diff --git a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp b/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp deleted file mode 100644 index 62c2fe5c01..0000000000 --- a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @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; -} diff --git a/samples/cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp b/samples/cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp new file mode 100644 index 0000000000..1cc7bf2edc --- /dev/null +++ b/samples/cpp/tutorial_code/ImgProc/Pyramids/Pyramids.cpp @@ -0,0 +1,69 @@ +/** + * @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; +} diff --git a/samples/java/tutorial_code/ImgProc/Pyramids/Pyramids.java b/samples/java/tutorial_code/ImgProc/Pyramids/Pyramids.java new file mode 100644 index 0000000000..b4ada166b2 --- /dev/null +++ b/samples/java/tutorial_code/ImgProc/Pyramids/Pyramids.java @@ -0,0 +1,67 @@ +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); + } +} diff --git a/samples/python/tutorial_code/imgProc/Pyramids/pyramids.py b/samples/python/tutorial_code/imgProc/Pyramids/pyramids.py new file mode 100644 index 0000000000..127345a6e0 --- /dev/null +++ b/samples/python/tutorial_code/imgProc/Pyramids/pyramids.py @@ -0,0 +1,51 @@ +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:])