From 4c1c3147d989f5b38ea3417b39d1fab4c8102990 Mon Sep 17 00:00:00 2001 From: catree Date: Wed, 23 May 2018 19:44:27 +0200 Subject: [PATCH] Add Java and Python code for the following imgproc tutorials: Affine Transformations, Histogram Equalization, Histogram Calculation, Histogram Comparison, Back Projection. --- .../back_projection/back_projection.markdown | 251 +++++++++++++------ .../histogram_calculation.markdown | 278 +++++++++++++-------- .../histogram_comparison.markdown | 188 ++++++++------ .../histogram_equalization.markdown | 126 +++++++--- .../imgtrans/warp_affine/warp_affine.markdown | 209 +++++++++++----- .../imgproc/table_of_content_imgproc.markdown | 10 + .../Histograms_Matching/EqualizeHist_Demo.cpp | 62 +++-- .../Histograms_Matching/calcBackProject_Demo1.cpp | 126 +++++----- .../Histograms_Matching/calcBackProject_Demo2.cpp | 99 ++++---- .../Histograms_Matching/calcHist_Demo.cpp | 137 +++++----- .../Histograms_Matching/compareHist_Demo.cpp | 70 +++--- .../ImgTrans/Geometric_Transforms_Demo.cpp | 130 +++++----- .../back_projection/CalcBackProjectDemo1.java | 173 +++++++++++++ .../back_projection/CalcBackProjectDemo2.java | 189 ++++++++++++++ .../histogram_calculation/CalcHistDemo.java | 99 ++++++++ .../histogram_comparison/CompareHistDemo.java | 91 +++++++ .../histogram_equalization/EqualizeHistDemo.java | 49 ++++ .../warp_affine/GeometricTransformsDemo.java | 80 ++++++ .../back_projection/calcBackProject_Demo1.py | 71 ++++++ .../back_projection/calcBackProject_Demo2.py | 79 ++++++ .../histogram_calculation/calcHist_Demo.py | 71 ++++++ .../histogram_comparison/compareHist_Demo.py | 69 +++++ .../histogram_equalization/EqualizeHist_Demo.py | 31 +++ .../warp_affine/Geometric_Transforms_Demo.py | 54 ++++ 24 files changed, 2074 insertions(+), 668 deletions(-) create mode 100644 samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java create mode 100644 samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java create mode 100644 samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java create mode 100644 samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java create mode 100644 samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java create mode 100644 samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java create mode 100644 samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py create mode 100644 samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py create mode 100644 samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py create mode 100644 samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py create mode 100644 samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py create mode 100644 samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py diff --git a/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown b/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown index 8657541..4b67f0b 100644 --- a/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown +++ b/doc/tutorials/imgproc/histograms/back_projection/back_projection.markdown @@ -67,46 +67,104 @@ Code - Calculate the histogram (and update it if the bins change) and the backprojection of the same image. - Display the backprojection and the histogram in windows. -- **Downloadable code**: - -# Click +@add_toggle_cpp +- **Downloadable code**: + - Click [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp) for the basic version (explained in this tutorial). - -# For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the + - For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the skin area) you can check the [improved demo](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp) - -# ...or you can always check out the classical + - ...or you can always check out the classical [camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp) in samples. - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp +@end_toggle + +@add_toggle_java +- **Downloadable code**: + - Click + [here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java) + for the basic version (explained in this tutorial). + - For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the + skin area) you can check the [improved + demo](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java) + - ...or you can always check out the classical + [camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp) + in samples. + +- **Code at glance:** +@include samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java +@end_toggle + +@add_toggle_python +- **Downloadable code**: + - Click + [here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py) + for the basic version (explained in this tutorial). + - For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the + skin area) you can check the [improved + demo](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py) + - ...or you can always check out the classical + [camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp) + in samples. + +- **Code at glance:** +@include samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py +@end_toggle Explanation ----------- --# Declare the matrices to store our images and initialize the number of bins to be used by our - histogram: - @code{.cpp} - Mat src; Mat hsv; Mat hue; - int bins = 25; - @endcode --# Read the input image and transform it to HSV format: - @code{.cpp} - src = imread( argv[1], 1 ); - cvtColor( src, hsv, COLOR_BGR2HSV ); - @endcode --# For this tutorial, we will use only the Hue value for our 1-D histogram (check out the fancier +- Read the input image: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Read the image + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Read the image + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Read the image + @end_toggle + +- Transform it to HSV format: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Transform it to HSV + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Transform it to HSV + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Transform it to HSV + @end_toggle + +- For this tutorial, we will use only the Hue value for our 1-D histogram (check out the fancier code in the links above if you want to use the more standard H-S histogram, which yields better results): - @code{.cpp} - hue.create( hsv.size(), hsv.depth() ); - int ch[] = { 0, 0 }; - mixChannels( &hsv, 1, &hue, 1, ch, 1 ); - @endcode - as you see, we use the function @ref cv::mixChannels to get only the channel 0 (Hue) from - the hsv image. It gets the following parameters: + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Use only the Hue value + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Use only the Hue value + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Use only the Hue value + @end_toggle + +- as you see, we use the function @ref cv::mixChannels to get only the channel 0 (Hue) from + the hsv image. It gets the following parameters: - **&hsv:** The source array from which the channels will be copied - **1:** The number of source arrays - **&hue:** The destination array of the copied channels @@ -115,59 +173,108 @@ Explanation case, the Hue(0) channel of &hsv is being copied to the 0 channel of &hue (1-channel) - **1:** Number of index pairs --# Create a Trackbar for the user to enter the bin values. Any change on the Trackbar means a call +- Create a Trackbar for the user to enter the bin values. Any change on the Trackbar means a call to the **Hist_and_Backproj** callback function. - @code{.cpp} - char* window_image = "Source image"; - namedWindow( window_image, WINDOW_AUTOSIZE ); - createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj ); - Hist_and_Backproj(0, 0); - @endcode --# Show the image and wait for the user to exit the program: - @code{.cpp} - imshow( window_image, src ); - - waitKey(0); - return 0; - @endcode --# **Hist_and_Backproj function:** Initialize the arguments needed for @ref cv::calcHist . The + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Create Trackbar to enter the number of bins + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Create Trackbar to enter the number of bins + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Create Trackbar to enter the number of bins + @end_toggle + +- Show the image and wait for the user to exit the program: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Show the image + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Show the image + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Show the image + @end_toggle + +- **Hist_and_Backproj function:** Initialize the arguments needed for @ref cv::calcHist . The number of bins comes from the Trackbar: - @code{.cpp} - void Hist_and_Backproj(int, void* ) - { - MatND hist; - int histSize = MAX( bins, 2 ); - float hue_range[] = { 0, 180 }; - const float* ranges = { hue_range }; - @endcode --# Calculate the Histogram and normalize it to the range \f$[0,255]\f$ - @code{.cpp} - calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false ); - normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); - @endcode --# Get the Backprojection of the same image by calling the function @ref cv::calcBackProject - @code{.cpp} - MatND backproj; - calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true ); - @endcode - all the arguments are known (the same as used to calculate the histogram), only we add the + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp initialize + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java initialize + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py initialize + @end_toggle + +- Calculate the Histogram and normalize it to the range \f$[0,255]\f$ + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Get the Histogram and normalize it + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Get the Histogram and normalize it + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Get the Histogram and normalize it + @end_toggle + +- Get the Backprojection of the same image by calling the function @ref cv::calcBackProject + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Get Backprojection + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Get Backprojection + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Get Backprojection + @end_toggle + +- all the arguments are known (the same as used to calculate the histogram), only we add the backproj matrix, which will store the backprojection of the source image (&hue) --# Display backproj: - @code{.cpp} - imshow( "BackProj", backproj ); - @endcode --# Draw the 1-D Hue histogram of the image: - @code{.cpp} - int w = 400; int h = 400; - int bin_w = cvRound( (double) w / histSize ); - Mat histImg = Mat::zeros( w, h, CV_8UC3 ); - - for( int i = 0; i < bins; i ++ ) - { rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); } - - imshow( "Histogram", histImg ); - @endcode +- Display backproj: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the backproj + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Draw the backproj + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Draw the backproj + @end_toggle + +- Draw the 1-D Hue histogram of the image: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the histogram + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Draw the histogram + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py Draw the histogram + @end_toggle Results ------- diff --git a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown index 2907bf3..30930cd 100644 --- a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.markdown @@ -17,7 +17,8 @@ histogram called *Image histogram*. Now we will considerate it in its more gener - Histograms are collected *counts* of data organized into a set of predefined *bins* - When we say *data* we are not restricting it to be intensity values (as we saw in the previous - Tutorial). The data collected can be whatever feature you find useful to describe your image. + Tutorial @ref tutorial_histogram_equalization). The data collected can be whatever feature you find + useful to describe your image. - Let's see an example. Imagine that a Matrix contains information of an image (i.e. intensity in the range \f$0-255\f$): @@ -65,122 +66,193 @@ Code - Splits the image into its R, G and B planes using the function @ref cv::split - Calculate the Histogram of each 1-channel plane by calling the function @ref cv::calcHist - Plot the three histograms in a window + +@add_toggle_cpp - **Downloadable code**: Click [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp) + - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp +@end_toggle + +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java +@end_toggle + +@add_toggle_python +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py) + +- **Code at glance:** + @include samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py +@end_toggle Explanation ----------- --# Create the necessary matrices: - @code{.cpp} - Mat src, dst; - @endcode --# Load the source image - @code{.cpp} - src = imread( argv[1], 1 ); +- Load the source image - if( !src.data ) - { return -1; } - @endcode --# Separate the source image in its three R,G and B planes. For this we use the OpenCV function + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Load image + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Load image + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Load image + @end_toggle + +- Separate the source image in its three R,G and B planes. For this we use the OpenCV function @ref cv::split : - @code{.cpp} - vector bgr_planes; - split( src, bgr_planes ); - @endcode + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Separate the image in 3 places ( B, G and R ) + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Separate the image in 3 places ( B, G and R ) + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Separate the image in 3 places ( B, G and R ) + @end_toggle our input is the image to be divided (this case with three channels) and the output is a vector of Mat ) --# Now we are ready to start configuring the **histograms** for each plane. Since we are working +- Now we are ready to start configuring the **histograms** for each plane. Since we are working with the B, G and R planes, we know that our values will range in the interval \f$[0,255]\f$ - -# Establish number of bins (5, 10...): - @code{.cpp} - int histSize = 256; //from 0 to 255 - @endcode - -# Set the range of values (as we said, between 0 and 255 ) - @code{.cpp} - /// Set the ranges ( for B,G,R) ) - float range[] = { 0, 256 } ; //the upper boundary is exclusive - const float* histRange = { range }; - @endcode - -# We want our bins to have the same size (uniform) and to clear the histograms in the - beginning, so: - @code{.cpp} - bool uniform = true; bool accumulate = false; - @endcode - -# Finally, we create the Mat objects to save our histograms. Creating 3 (one for each plane): - @code{.cpp} - Mat b_hist, g_hist, r_hist; - @endcode - -# We proceed to calculate the histograms by using the OpenCV function @ref cv::calcHist : - @code{.cpp} - /// Compute the histograms: - calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); - calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); - calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); - @endcode - where the arguments are: - - - **&bgr_planes[0]:** The source array(s) - - **1**: The number of source arrays (in this case we are using 1. We can enter here also - a list of arrays ) - - **0**: The channel (*dim*) to be measured. In this case it is just the intensity (each - array is single-channel) so we just write 0. - - **Mat()**: A mask to be used on the source array ( zeros indicating pixels to be ignored - ). If not defined it is not used - - **b_hist**: The Mat object where the histogram will be stored - - **1**: The histogram dimensionality. - - **histSize:** The number of bins per each used dimension - - **histRange:** The range of values to be measured per each dimension - - **uniform** and **accumulate**: The bin sizes are the same and the histogram is cleared - at the beginning. - --# Create an image to display the histograms: - @code{.cpp} - // Draw the histograms for R, G and B - int hist_w = 512; int hist_h = 400; - int bin_w = cvRound( (double) hist_w/histSize ); - Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); - @endcode --# Notice that before drawing, we first @ref cv::normalize the histogram so its values fall in the +- Establish the number of bins (5, 10...): + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Establish the number of bins + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Establish the number of bins + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Establish the number of bins + @end_toggle + +- Set the range of values (as we said, between 0 and 255 ) + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Set the ranges ( for B,G,R) ) + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Set the ranges ( for B,G,R) ) + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Set the ranges ( for B,G,R) ) + @end_toggle + +- We want our bins to have the same size (uniform) and to clear the histograms in the + beginning, so: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Set histogram param + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Set histogram param + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Set histogram param + @end_toggle + +- We proceed to calculate the histograms by using the OpenCV function @ref cv::calcHist : + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Compute the histograms + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Compute the histograms + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Compute the histograms + @end_toggle + +- where the arguments are (**C++ code**): + - **&bgr_planes[0]:** The source array(s) + - **1**: The number of source arrays (in this case we are using 1. We can enter here also + a list of arrays ) + - **0**: The channel (*dim*) to be measured. In this case it is just the intensity (each + array is single-channel) so we just write 0. + - **Mat()**: A mask to be used on the source array ( zeros indicating pixels to be ignored + ). If not defined it is not used + - **b_hist**: The Mat object where the histogram will be stored + - **1**: The histogram dimensionality. + - **histSize:** The number of bins per each used dimension + - **histRange:** The range of values to be measured per each dimension + - **uniform** and **accumulate**: The bin sizes are the same and the histogram is cleared + at the beginning. + +- Create an image to display the histograms: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Draw the histograms for B, G and R + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Draw the histograms for B, G and R + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Draw the histograms for B, G and R + @end_toggle + +- Notice that before drawing, we first @ref cv::normalize the histogram so its values fall in the range indicated by the parameters entered: - @code{.cpp} - /// Normalize the result to [ 0, histImage.rows ] - normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - @endcode - this function receives these arguments: + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Normalize the result to ( 0, histImage.rows ) + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Normalize the result to ( 0, histImage.rows ) + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Normalize the result to ( 0, histImage.rows ) + @end_toggle + +- this function receives these arguments (**C++ code**): - **b_hist:** Input array - **b_hist:** Output normalized array (can be the same) - - **0** and\**histImage.rows: For this example, they are the lower and upper limits to - normalize the values ofr_hist*\* + - **0** and **histImage.rows**: For this example, they are the lower and upper limits to + normalize the values of **r_hist** - **NORM_MINMAX:** Argument that indicates the type of normalization (as described above, it adjusts the values between the two limits set before) - **-1:** Implies that the output normalized array will be the same type as the input - **Mat():** Optional mask --# Finally, observe that to access the bin (in this case in this 1D-Histogram): - @code{.cpp} - /// Draw for each channel - for( int i = 1; i < histSize; i++ ) - { - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ), - Scalar( 255, 0, 0), 2, 8, 0 ); - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ), - Scalar( 0, 255, 0), 2, 8, 0 ); - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ), - Scalar( 0, 0, 255), 2, 8, 0 ); - } - @endcode - we use the expression: +- Observe that to access the bin (in this case in this 1D-Histogram): + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Draw for each channel + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Draw for each channel + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Draw for each channel + @end_toggle + we use the expression (**C++ code**): @code{.cpp} b_hist.at(i) @endcode @@ -189,20 +261,24 @@ Explanation b_hist.at( i, j ) @endcode --# Finally we display our histograms and wait for the user to exit: - @code{.cpp} - namedWindow("calcHist Demo", WINDOW_AUTOSIZE ); - imshow("calcHist Demo", histImage ); +- Finally we display our histograms and wait for the user to exit: - waitKey(0); + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Display + @end_toggle - return 0; - @endcode + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Display + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Display + @end_toggle Result ------ --# Using as input argument an image like the shown below: +-# Using as input argument an image like the one shown below: ![](images/Histogram_Calculation_Original_Image.jpg) diff --git a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown index 37ae5ea..23c478a 100644 --- a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.markdown @@ -43,90 +43,118 @@ Code - Compare the histogram of the *base image* with respect to the 2 test histograms, the histogram of the lower half base image and with the same base image histogram. - Display the numerical matching parameters obtained. + +@add_toggle_cpp - **Downloadable code**: Click [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp) + +- **Code at glance:** + @include samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp +@end_toggle + +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java) + - **Code at glance:** + @include samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java +@end_toggle + +@add_toggle_python +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py) -@include cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp +- **Code at glance:** + @include samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py +@end_toggle Explanation ----------- --# Declare variables such as the matrices to store the base image and the two other images to - compare ( BGR and HSV ) - @code{.cpp} - Mat src_base, hsv_base; - Mat src_test1, hsv_test1; - Mat src_test2, hsv_test2; - Mat hsv_half_down; - @endcode --# Load the base image (src_base) and the other two test images: - @code{.cpp} - if( argc < 4 ) - { printf("** Error. Usage: ./compareHist_Demo \n"); - return -1; - } - - src_base = imread( argv[1], 1 ); - src_test1 = imread( argv[2], 1 ); - src_test2 = imread( argv[3], 1 ); - @endcode --# Convert them to HSV format: - @code{.cpp} - cvtColor( src_base, hsv_base, COLOR_BGR2HSV ); - cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV ); - cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV ); - @endcode --# Also, create an image of half the base image (in HSV format): - @code{.cpp} - hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); - @endcode --# Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ). - @code{.cpp} - int h_bins = 50; int s_bins = 60; - int histSize[] = { h_bins, s_bins }; - - float h_ranges[] = { 0, 180 }; - float s_ranges[] = { 0, 256 }; - - const float* ranges[] = { h_ranges, s_ranges }; - - int channels[] = { 0, 1 }; - @endcode --# Create the MatND objects to store the histograms: - @code{.cpp} - MatND hist_base; - MatND hist_half_down; - MatND hist_test1; - MatND hist_test2; - @endcode --# Calculate the Histograms for the base image, the 2 test images and the half-down base image: - @code{.cpp} - calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); - normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); - - calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false ); - normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() ); - - calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false ); - normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() ); - - calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false ); - normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() ); - @endcode --# Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base) +- Load the base image (src_base) and the other two test images: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Load three images with different environment settings + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Load three images with different environment settings + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Load three images with different environment settings + @end_toggle + +- Convert them to HSV format: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Convert to HSV + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Convert to HSV + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV + @end_toggle + +- Also, create an image of half the base image (in HSV format): + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Convert to HSV half + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Convert to HSV half + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV half + @end_toggle + +- Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ). + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Using 50 bins for hue and 60 for saturation + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Using 50 bins for hue and 60 for saturation + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Using 50 bins for hue and 60 for saturation + @end_toggle + +- Calculate the Histograms for the base image, the 2 test images and the half-down base image: + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Calculate the histograms for the HSV images + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Calculate the histograms for the HSV images + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Calculate the histograms for the HSV images + @end_toggle + +- Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base) and the other histograms: - @code{.cpp} - for( int i = 0; i < 4; i++ ) - { int compare_method = i; - double base_base = compareHist( hist_base, hist_base, compare_method ); - double base_half = compareHist( hist_base, hist_half_down, compare_method ); - double base_test1 = compareHist( hist_base, hist_test1, compare_method ); - double base_test2 = compareHist( hist_base, hist_test2, compare_method ); - - printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 ); - } - @endcode + + @add_toggle_cpp + @snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Apply the histogram comparison methods + @end_toggle + + @add_toggle_java + @snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Apply the histogram comparison methods + @end_toggle + + @add_toggle_python + @snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Apply the histogram comparison methods + @end_toggle Results ------- @@ -144,13 +172,13 @@ Results are from the same source. For the other two test images, we can observe that they have very different lighting conditions, so the matching should not be very good: --# Here the numeric results: +-# Here the numeric results we got with OpenCV 3.4.1: *Method* | Base - Base | Base - Half | Base - Test 1 | Base - Test 2 ----------------- | ------------ | ------------ | -------------- | --------------- - *Correlation* | 1.000000 | 0.930766 | 0.182073 | 0.120447 - *Chi-square* | 0.000000 | 4.940466 | 21.184536 | 49.273437 - *Intersection* | 24.391548 | 14.959809 | 3.889029 | 5.775088 - *Bhattacharyya* | 0.000000 | 0.222609 | 0.646576 | 0.801869 + *Correlation* | 1.000000 | 0.880438 | 0.20457 | 0.0664547 + *Chi-square* | 0.000000 | 4.6834 | 2697.98 | 4763.8 + *Intersection* | 18.8947 | 13.022 | 5.44085 | 2.58173 + *Bhattacharyya* | 0.000000 | 0.237887 | 0.679826 | 0.874173 For the *Correlation* and *Intersection* methods, the higher the metric, the more accurate the match. As we can see, the match *base-base* is the highest of all as expected. Also we can observe that the match *base-half* is the second best match (as we predicted). For the other two metrics, diff --git a/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown b/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown index 4fecb15..5a452a7 100644 --- a/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown +++ b/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.markdown @@ -22,7 +22,7 @@ Theory ### What is Histogram Equalization? - It is a method that improves the contrast in an image, in order to stretch out the intensity - range. + range (see also the corresponding Wikipedia entry). - To make it clearer, from the image above, you can see that the pixels seem clustered around the middle of the available range of intensities. What Histogram Equalization does is to *stretch out* this range. Take a look at the figure below: The green circles indicate the @@ -61,53 +61,105 @@ Code - Convert the original image to grayscale - Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist - Display the source and equalized images in a window. + +@add_toggle_cpp - **Downloadable code**: Click [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp) + - **Code at glance:** @include samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp +@end_toggle + +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java +@end_toggle + +@add_toggle_python +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py) + +- **Code at glance:** + @include samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py +@end_toggle Explanation ----------- --# Declare the source and destination images as well as the windows names: - @code{.cpp} - Mat src, dst; - - char* source_window = "Source image"; - char* equalized_window = "Equalized Image"; - @endcode --# Load the source image: - @code{.cpp} - src = imread( argv[1], 1 ); - - if( !src.data ) - { cout<<"Usage: ./Histogram_Demo "< OpenCV 2.0 *Author:* Ana Huamán @@ -173,6 +175,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_histogram_equalization + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán @@ -181,6 +185,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_histogram_calculation + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán @@ -189,6 +195,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_histogram_comparison + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán @@ -197,6 +205,8 @@ In this section you will learn about the image processing (manipulation) functio - @subpage tutorial_back_projection + *Languages:* C++, Java, Python + *Compatibility:* \> OpenCV 2.0 *Author:* Ana Huamán diff --git a/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp index 7c7f4d4..8f5492b 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp @@ -17,37 +17,35 @@ using namespace std; */ int main( int argc, char** argv ) { - Mat src, dst; - - const char* source_window = "Source image"; - const char* equalized_window = "Equalized Image"; - - /// Load image - CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" ); - src = imread( parser.get( "@input" ), IMREAD_COLOR ); - if( src.empty() ) - { - cout << "Could not open or find the image!\n" << endl; - cout << "Usage: " << argv[0] << " " << endl; - return -1; - } - - /// Convert to grayscale - cvtColor( src, src, COLOR_BGR2GRAY ); - - /// Apply Histogram Equalization - equalizeHist( src, dst ); - - /// Display results - namedWindow( source_window, WINDOW_AUTOSIZE ); - namedWindow( equalized_window, WINDOW_AUTOSIZE ); - - imshow( source_window, src ); - imshow( equalized_window, dst ); - - /// Wait until user exits the program - waitKey(0); - - return 0; + //! [Load image] + CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" ); + Mat src = imread( parser.get( "@input" ), IMREAD_COLOR ); + if( src.empty() ) + { + cout << "Could not open or find the image!\n" << endl; + cout << "Usage: " << argv[0] << " " << endl; + return -1; + } + //! [Load image] + + //! [Convert to grayscale] + cvtColor( src, src, COLOR_BGR2GRAY ); + //! [Convert to grayscale] + + //! [Apply Histogram Equalization] + Mat dst; + equalizeHist( src, dst ); + //! [Apply Histogram Equalization] + + //! [Display results] + imshow( "Source image", src ); + imshow( "Equalized Image", dst ); + //! [Display results] + + //! [Wait until user exits the program] + waitKey(); + //! [Wait until user exits the program] + + return 0; } diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp index 1e2fe92..61b6d60 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp @@ -14,79 +14,93 @@ using namespace cv; using namespace std; /// Global Variables -Mat src; Mat hsv; Mat hue; +Mat hue; int bins = 25; /// Function Headers void Hist_and_Backproj(int, void* ); - /** * @function main */ -int main( int, char** argv ) +int main( int argc, char* argv[] ) { - /// Read the image - src = imread( argv[1], IMREAD_COLOR ); - - if( src.empty() ) - { cout<<"Usage: ./calcBackProject_Demo1 "<( "@input" ) ); + if( src.empty() ) + { + cout << "Could not open or find the image!\n" << endl; + cout << "Usage: " << argv[0] << " " << endl; + return -1; } - - /// Transform it to HSV - cvtColor( src, hsv, COLOR_BGR2HSV ); - - /// Use only the Hue value - hue.create( hsv.size(), hsv.depth() ); - int ch[] = { 0, 0 }; - mixChannels( &hsv, 1, &hue, 1, ch, 1 ); - - /// Create Trackbar to enter the number of bins - const char* window_image = "Source image"; - namedWindow( window_image, WINDOW_AUTOSIZE ); - createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj ); - Hist_and_Backproj(0, 0); - - /// Show the image - imshow( window_image, src ); - - /// Wait until user exits the program - waitKey(0); - return 0; + //! [Read the image] + + //! [Transform it to HSV] + Mat hsv; + cvtColor( src, hsv, COLOR_BGR2HSV ); + //! [Transform it to HSV] + + //! [Use only the Hue value] + hue.create(hsv.size(), hsv.depth()); + int ch[] = { 0, 0 }; + mixChannels( &hsv, 1, &hue, 1, ch, 1 ); + //! [Use only the Hue value] + + //! [Create Trackbar to enter the number of bins] + const char* window_image = "Source image"; + namedWindow( window_image ); + createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj ); + Hist_and_Backproj(0, 0); + //! [Create Trackbar to enter the number of bins] + + //! [Show the image] + imshow( window_image, src ); + // Wait until user exits the program + waitKey(); + //! [Show the image] + + return 0; } - /** * @function Hist_and_Backproj * @brief Callback to Trackbar */ void Hist_and_Backproj(int, void* ) { - MatND hist; - int histSize = MAX( bins, 2 ); - float hue_range[] = { 0, 180 }; - const float* ranges = { hue_range }; - - /// Get the Histogram and normalize it - calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false ); - normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); - - /// Get Backprojection - MatND backproj; - calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true ); - - /// Draw the backproj - imshow( "BackProj", backproj ); - - /// Draw the histogram - int w = 400; int h = 400; - int bin_w = cvRound( (double) w / histSize ); - Mat histImg = Mat::zeros( w, h, CV_8UC3 ); - - for( int i = 0; i < bins; i ++ ) - { rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); } - - imshow( "Histogram", histImg ); + //! [initialize] + int histSize = MAX( bins, 2 ); + float hue_range[] = { 0, 180 }; + const float* ranges = { hue_range }; + //! [initialize] + + //! [Get the Histogram and normalize it] + Mat hist; + calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false ); + normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); + //! [Get the Histogram and normalize it] + + //! [Get Backprojection] + Mat backproj; + calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true ); + //! [Get Backprojection] + + //! [Draw the backproj] + imshow( "BackProj", backproj ); + //! [Draw the backproj] + + //! [Draw the histogram] + int w = 400, h = 400; + int bin_w = cvRound( (double) w / histSize ); + Mat histImg = Mat::zeros( h, w, CV_8UC3 ); + + for (int i = 0; i < bins; i++) + { + rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at(i)*h/255.0 ) ), + Scalar( 0, 0, 255 ), FILLED ); + } + imshow( "Histogram", histImg ); + //! [Draw the histogram] } diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp index ecb7737..9c42c0f 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp @@ -14,10 +14,9 @@ using namespace cv; using namespace std; /// Global Variables -Mat src; Mat hsv; -Mat mask; +Mat src, hsv, mask; -int lo = 20; int up = 20; +int low = 20, up = 20; const char* window_image = "Source image"; /// Function Headers @@ -29,23 +28,24 @@ void pickPoint (int event, int x, int y, int, void* ); */ int main( int, char** argv ) { - /// Read the image - src = imread( argv[1], IMREAD_COLOR ); - /// Transform it to HSV - cvtColor( src, hsv, COLOR_BGR2HSV ); - - /// Show the image - namedWindow( window_image, WINDOW_AUTOSIZE ); - imshow( window_image, src ); - - /// Set Trackbars for floodfill thresholds - createTrackbar( "Low thresh", window_image, &lo, 255, 0 ); - createTrackbar( "High thresh", window_image, &up, 255, 0 ); - /// Set a Mouse Callback - setMouseCallback( window_image, pickPoint, 0 ); - - waitKey(0); - return 0; + /// Read the image + src = imread( argv[1] ); + + /// Transform it to HSV + cvtColor( src, hsv, COLOR_BGR2HSV ); + + /// Show the image + namedWindow( window_image ); + imshow( window_image, src ); + + /// Set Trackbars for floodfill thresholds + createTrackbar( "Low thresh", window_image, &low, 255, 0 ); + createTrackbar( "High thresh", window_image, &up, 255, 0 ); + /// Set a Mouse Callback + setMouseCallback( window_image, pickPoint, 0 ); + + waitKey(); + return 0; } /** @@ -53,25 +53,27 @@ int main( int, char** argv ) */ void pickPoint (int event, int x, int y, int, void* ) { - if( event != EVENT_LBUTTONDOWN ) - { return; } + if( event != EVENT_LBUTTONDOWN ) + { + return; + } - // Fill and get the mask - Point seed = Point( x, y ); + // Fill and get the mask + Point seed = Point( x, y ); - int newMaskVal = 255; - Scalar newVal = Scalar( 120, 120, 120 ); + int newMaskVal = 255; + Scalar newVal = Scalar( 120, 120, 120 ); - int connectivity = 8; - int flags = connectivity + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY; + int connectivity = 8; + int flags = connectivity + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY; - Mat mask2 = Mat::zeros( src.rows + 2, src.cols + 2, CV_8UC1 ); - floodFill( src, mask2, seed, newVal, 0, Scalar( lo, lo, lo ), Scalar( up, up, up), flags ); - mask = mask2( Range( 1, mask2.rows - 1 ), Range( 1, mask2.cols - 1 ) ); + Mat mask2 = Mat::zeros( src.rows + 2, src.cols + 2, CV_8U ); + floodFill( src, mask2, seed, newVal, 0, Scalar( low, low, low ), Scalar( up, up, up), flags ); + mask = mask2( Range( 1, mask2.rows - 1 ), Range( 1, mask2.cols - 1 ) ); - imshow( "Mask", mask ); + imshow( "Mask", mask ); - Hist_and_Backproj( ); + Hist_and_Backproj( ); } /** @@ -79,26 +81,25 @@ void pickPoint (int event, int x, int y, int, void* ) */ void Hist_and_Backproj( ) { - MatND hist; - int h_bins = 30; int s_bins = 32; - int histSize[] = { h_bins, s_bins }; - - float h_range[] = { 0, 179 }; - float s_range[] = { 0, 255 }; - const float* ranges[] = { h_range, s_range }; + Mat hist; + int h_bins = 30; int s_bins = 32; + int histSize[] = { h_bins, s_bins }; - int channels[] = { 0, 1 }; + float h_range[] = { 0, 180 }; + float s_range[] = { 0, 256 }; + const float* ranges[] = { h_range, s_range }; - /// Get the Histogram and normalize it - calcHist( &hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false ); + int channels[] = { 0, 1 }; - normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); + /// Get the Histogram and normalize it + calcHist( &hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false ); - /// Get Backprojection - MatND backproj; - calcBackProject( &hsv, 1, channels, hist, backproj, ranges, 1, true ); + normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); - /// Draw the backproj - imshow( "BackProj", backproj ); + /// Get Backprojection + Mat backproj; + calcBackProject( &hsv, 1, channels, hist, backproj, ranges, 1, true ); + /// Draw the backproj + imshow( "BackProj", backproj ); } diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp index 27e21e7..fc45fc2 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp @@ -17,72 +17,73 @@ using namespace cv; */ int main(int argc, char** argv) { - Mat src, dst; - - /// Load image - String imageName( "../data/lena.jpg" ); // by default - - if (argc > 1) - { - imageName = argv[1]; - } - - src = imread( imageName, IMREAD_COLOR ); - - if( src.empty() ) - { return -1; } - - /// Separate the image in 3 places ( B, G and R ) - vector bgr_planes; - split( src, bgr_planes ); - - /// Establish the number of bins - int histSize = 256; - - /// Set the ranges ( for B,G,R) ) - float range[] = { 0, 256 } ; - const float* histRange = { range }; - - bool uniform = true; bool accumulate = false; - - Mat b_hist, g_hist, r_hist; - - /// Compute the histograms: - calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); - calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); - calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); - - // Draw the histograms for B, G and R - int hist_w = 512; int hist_h = 400; - int bin_w = cvRound( (double) hist_w/histSize ); - - Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); - - /// Normalize the result to [ 0, histImage.rows ] - normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); - - /// Draw for each channel - for( int i = 1; i < histSize; i++ ) - { - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ), - Scalar( 255, 0, 0), 2, 8, 0 ); - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ), - Scalar( 0, 255, 0), 2, 8, 0 ); - line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ) , - Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ), - Scalar( 0, 0, 255), 2, 8, 0 ); - } - - /// Display - namedWindow("calcHist Demo", WINDOW_AUTOSIZE ); - imshow("calcHist Demo", histImage ); - - waitKey(0); - - return 0; - + //! [Load image] + CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" ); + Mat src = imread( parser.get( "@input" ), IMREAD_COLOR ); + if( src.empty() ) + { + return -1; + } + //! [Load image] + + //! [Separate the image in 3 places ( B, G and R )] + vector bgr_planes; + split( src, bgr_planes ); + //! [Separate the image in 3 places ( B, G and R )] + + //! [Establish the number of bins] + int histSize = 256; + //! [Establish the number of bins] + + //! [Set the ranges ( for B,G,R) )] + float range[] = { 0, 256 }; //the upper boundary is exclusive + const float* histRange = { range }; + //! [Set the ranges ( for B,G,R) )] + + //! [Set histogram param] + bool uniform = true, accumulate = false; + //! [Set histogram param] + + //! [Compute the histograms] + Mat b_hist, g_hist, r_hist; + calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); + calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); + calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); + //! [Compute the histograms] + + //! [Draw the histograms for B, G and R] + int hist_w = 512, hist_h = 400; + int bin_w = cvRound( (double) hist_w/histSize ); + + Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); + //! [Draw the histograms for B, G and R] + + //! [Normalize the result to ( 0, histImage.rows )] + normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); + normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); + normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); + //! [Normalize the result to ( 0, histImage.rows )] + + //! [Draw for each channel] + for( int i = 1; i < histSize; i++ ) + { + line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ), + Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ), + Scalar( 255, 0, 0), 2, 8, 0 ); + line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ), + Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ), + Scalar( 0, 255, 0), 2, 8, 0 ); + line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ), + Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ), + Scalar( 0, 0, 255), 2, 8, 0 ); + } + //! [Draw for each channel] + + //! [Display] + imshow("Source image", src ); + imshow("calcHist Demo", histImage ); + waitKey(); + //! [Display] + + return 0; } diff --git a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp index 4d0123b..73aa3c9 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp @@ -12,42 +12,43 @@ using namespace std; using namespace cv; +const char* keys = + "{ help h| | Print help message. }" + "{ input1 | | Path to input image 1. }" + "{ input2 | | Path to input image 2. }" + "{ input3 | | Path to input image 3. }"; + /** * @function main */ int main( int argc, char** argv ) { - Mat src_base, hsv_base; - Mat src_test1, hsv_test1; - Mat src_test2, hsv_test2; - Mat hsv_half_down; - - /// Load three images with different environment settings - if( argc < 4 ) + //! [Load three images with different environment settings] + CommandLineParser parser( argc, argv, keys ); + Mat src_base = imread( parser.get("input1") ); + Mat src_test1 = imread( parser.get("input2") ); + Mat src_test2 = imread( parser.get("input3") ); + if( src_base.empty() || src_test1.empty() || src_test2.empty() ) { - printf("** Error. Usage: ./compareHist_Demo \n"); + cout << "Could not open or find the images!\n" << endl; + parser.printMessage(); return -1; } + //! [Load three images with different environment settings] - src_base = imread( argv[1], IMREAD_COLOR ); - src_test1 = imread( argv[2], IMREAD_COLOR ); - src_test2 = imread( argv[3], IMREAD_COLOR ); - - if(src_base.empty() || src_test1.empty() || src_test2.empty()) - { - cout << "Can't read one of the images" << endl; - return -1; - } - - /// Convert to HSV + //! [Convert to HSV] + Mat hsv_base, hsv_test1, hsv_test2; cvtColor( src_base, hsv_base, COLOR_BGR2HSV ); cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV ); cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV ); + //! [Convert to HSV] - hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); + //! [Convert to HSV half] + Mat hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows ), Range( 0, hsv_base.cols ) ); + //! [Convert to HSV half] - /// Using 50 bins for hue and 60 for saturation - int h_bins = 50; int s_bins = 60; + //! [Using 50 bins for hue and 60 for saturation] + int h_bins = 50, s_bins = 60; int histSize[] = { h_bins, s_bins }; // hue varies from 0 to 179, saturation from 0 to 255 @@ -56,17 +57,13 @@ int main( int argc, char** argv ) const float* ranges[] = { h_ranges, s_ranges }; - // Use the o-th and 1-st channels + // Use the 0-th and 1-st channels int channels[] = { 0, 1 }; + //! [Using 50 bins for hue and 60 for saturation] + //! [Calculate the histograms for the HSV images] + Mat hist_base, hist_half_down, hist_test1, hist_test2; - /// Histograms - MatND hist_base; - MatND hist_half_down; - MatND hist_test1; - MatND hist_test2; - - /// Calculate the histograms for the HSV images calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); @@ -78,20 +75,21 @@ int main( int argc, char** argv ) calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false ); normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() ); + //! [Calculate the histograms for the HSV images] - /// Apply the histogram comparison methods - for( int i = 0; i < 4; i++ ) + //! [Apply the histogram comparison methods] + for( int compare_method = 0; compare_method < 4; compare_method++ ) { - int compare_method = i; double base_base = compareHist( hist_base, hist_base, compare_method ); double base_half = compareHist( hist_base, hist_half_down, compare_method ); double base_test1 = compareHist( hist_base, hist_test1, compare_method ); double base_test2 = compareHist( hist_base, hist_test2, compare_method ); - printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 ); + cout << "Method " << compare_method << " Perfect, Base-Half, Base-Test(1), Base-Test(2) : " + << base_base << " / " << base_half << " / " << base_test1 << " / " << base_test2 << endl; } + //! [Apply the histogram comparison methods] - printf( "Done \n" ); - + cout << "Done \n"; return 0; } diff --git a/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp index 93250a5..2e91467 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp @@ -12,77 +12,71 @@ using namespace cv; using namespace std; -/// Global variables -const char* source_window = "Source image"; -const char* warp_window = "Warp"; -const char* warp_rotate_window = "Warp + Rotate"; - /** * @function main */ int main( int argc, char** argv ) { - Point2f srcTri[3]; - Point2f dstTri[3]; - - Mat rot_mat( 2, 3, CV_32FC1 ); - Mat warp_mat( 2, 3, CV_32FC1 ); - Mat src, warp_dst, warp_rotate_dst; - - /// Load the image - CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" ); - src = imread( parser.get( "@input" ), IMREAD_COLOR ); - if( src.empty() ) - { - cout << "Could not open or find the image!\n" << endl; - cout << "Usage: " << argv[0] << " " << endl; - return -1; - } - - /// Set the dst image the same type and size as src - warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); - - /// Set your 3 points to calculate the Affine Transform - srcTri[0] = Point2f( 0,0 ); - srcTri[1] = Point2f( src.cols - 1.f, 0 ); - srcTri[2] = Point2f( 0, src.rows - 1.f ); - - dstTri[0] = Point2f( src.cols*0.0f, src.rows*0.33f ); - dstTri[1] = Point2f( src.cols*0.85f, src.rows*0.25f ); - dstTri[2] = Point2f( src.cols*0.15f, src.rows*0.7f ); - - /// Get the Affine Transform - warp_mat = getAffineTransform( srcTri, dstTri ); - - /// Apply the Affine Transform just found to the src image - warpAffine( src, warp_dst, warp_mat, warp_dst.size() ); - - /** Rotating the image after Warp */ - - /// Compute a rotation matrix with respect to the center of the image - Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); - double angle = -50.0; - double scale = 0.6; - - /// Get the rotation matrix with the specifications above - rot_mat = getRotationMatrix2D( center, angle, scale ); - - /// Rotate the warped image - warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() ); - - - /// Show what you got - namedWindow( source_window, WINDOW_AUTOSIZE ); - imshow( source_window, src ); - - namedWindow( warp_window, WINDOW_AUTOSIZE ); - imshow( warp_window, warp_dst ); - - namedWindow( warp_rotate_window, WINDOW_AUTOSIZE ); - imshow( warp_rotate_window, warp_rotate_dst ); - - /// Wait until user exits the program - waitKey(0); - - return 0; + //! [Load the image] + CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" ); + Mat src = imread( parser.get( "@input" ) ); + if( src.empty() ) + { + cout << "Could not open or find the image!\n" << endl; + cout << "Usage: " << argv[0] << " " << endl; + return -1; + } + //! [Load the image] + + //! [Set your 3 points to calculate the Affine Transform] + Point2f srcTri[3]; + srcTri[0] = Point2f( 0.f, 0.f ); + srcTri[1] = Point2f( src.cols - 1.f, 0.f ); + srcTri[2] = Point2f( 0.f, src.rows - 1.f ); + + Point2f dstTri[3]; + dstTri[0] = Point2f( 0.f, src.rows*0.33f ); + dstTri[1] = Point2f( src.cols*0.85f, src.rows*0.25f ); + dstTri[2] = Point2f( src.cols*0.15f, src.rows*0.7f ); + //! [Set your 3 points to calculate the Affine Transform] + + //! [Get the Affine Transform] + Mat warp_mat = getAffineTransform( srcTri, dstTri ); + //! [Get the Affine Transform] + + //! [Apply the Affine Transform just found to the src image] + /// Set the dst image the same type and size as src + Mat warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); + + warpAffine( src, warp_dst, warp_mat, warp_dst.size() ); + //! [Apply the Affine Transform just found to the src image] + + /** Rotating the image after Warp */ + + //! [Compute a rotation matrix with respect to the center of the image] + Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); + double angle = -50.0; + double scale = 0.6; + //! [Compute a rotation matrix with respect to the center of the image] + + //! [Get the rotation matrix with the specifications above] + Mat rot_mat = getRotationMatrix2D( center, angle, scale ); + //! [Get the rotation matrix with the specifications above] + + //! [Rotate the warped image] + Mat warp_rotate_dst; + warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() ); + //! [Rotate the warped image] + + //! [Show what you got] + imshow( "Source image", src ); + imshow( "Warp", warp_dst ); + imshow( "Warp + Rotate", warp_rotate_dst ); + //! [Show what you got] + + //! [Wait until user exits the program] + waitKey(); + //! [Wait until user exits the program] + + return 0; } diff --git a/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java b/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java new file mode 100644 index 0000000..c5b5f8d --- /dev/null +++ b/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java @@ -0,0 +1,173 @@ +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Image; +import java.util.Arrays; +import java.util.List; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.Point; +import org.opencv.core.Scalar; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class CalcBackProject1 { + private Mat hue; + private Mat histImg = new Mat(); + private JFrame frame; + private JLabel imgLabel; + private JLabel backprojLabel; + private JLabel histImgLabel; + private static final int MAX_SLIDER = 180; + private int bins = 25; + + public CalcBackProject1(String[] args) { + //! [Read the image] + if (args.length != 1) { + System.err.println("You must supply one argument that corresponds to the path to the image."); + System.exit(0); + } + + Mat src = Imgcodecs.imread(args[0]); + if (src.empty()) { + System.err.println("Empty image: " + args[0]); + System.exit(0); + } + //! [Read the image] + + //! [Transform it to HSV] + Mat hsv = new Mat(); + Imgproc.cvtColor(src, hsv, Imgproc.COLOR_BGR2HSV); + //! [Transform it to HSV] + + //! [Use only the Hue value] + hue = new Mat(hsv.size(), hsv.depth()); + Core.mixChannels(Arrays.asList(hsv), Arrays.asList(hue), new MatOfInt(0, 0)); + //! [Use only the Hue value] + + // Create and set up the window. + frame = new JFrame("Back Projection 1 demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + // Set up the content pane. + Image img = HighGui.toBufferedImage(src); + addComponentsToPane(frame.getContentPane(), img); + //! [Show the image] + // Use the content pane's default BorderLayout. No need for + // setLayout(new BorderLayout()); + // Display the window. + frame.pack(); + frame.setVisible(true); + //! [Show the image] + } + + private void addComponentsToPane(Container pane, Image img) { + if (!(pane.getLayout() instanceof BorderLayout)) { + pane.add(new JLabel("Container doesn't use BorderLayout!")); + return; + } + + //! [Create Trackbar to enter the number of bins] + JPanel sliderPanel = new JPanel(); + sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS)); + + sliderPanel.add(new JLabel("* Hue bins: ")); + JSlider slider = new JSlider(0, MAX_SLIDER, bins); + slider.setMajorTickSpacing(25); + slider.setMinorTickSpacing(5); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + JSlider source = (JSlider) e.getSource(); + bins = source.getValue(); + update(); + } + }); + sliderPanel.add(slider); + pane.add(sliderPanel, BorderLayout.PAGE_START); + //! [Create Trackbar to enter the number of bins] + + JPanel imgPanel = new JPanel(); + imgLabel = new JLabel(new ImageIcon(img)); + imgPanel.add(imgLabel); + + backprojLabel = new JLabel(); + imgPanel.add(backprojLabel); + + histImgLabel = new JLabel(); + imgPanel.add(histImgLabel); + pane.add(imgPanel, BorderLayout.CENTER); + } + + private void update() { + //! [initialize] + int histSize = Math.max(bins, 2); + float[] hueRange = {0, 180}; + //! [initialize] + + //! [Get the Histogram and normalize it] + Mat hist = new Mat(); + List hueList = Arrays.asList(hue); + Imgproc.calcHist(hueList, new MatOfInt(0), new Mat(), hist, new MatOfInt(histSize), new MatOfFloat(hueRange), false); + Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX); + //! [Get the Histogram and normalize it] + + //! [Get Backprojection] + Mat backproj = new Mat(); + Imgproc.calcBackProject(hueList, new MatOfInt(0), hist, backproj, new MatOfFloat(hueRange), 1); + //! [Get Backprojection] + + //! [Draw the backproj] + Image backprojImg = HighGui.toBufferedImage(backproj); + backprojLabel.setIcon(new ImageIcon(backprojImg)); + //! [Draw the backproj] + + //! [Draw the histogram] + int w = 400, h = 400; + int binW = (int) Math.round((double) w / histSize); + histImg = Mat.zeros(h, w, CvType.CV_8UC3); + + float[] histData = new float[(int) (hist.total() * hist.channels())]; + hist.get(0, 0, histData); + for (int i = 0; i < bins; i++) { + Imgproc.rectangle(histImg, new Point(i * binW, h), + new Point((i + 1) * binW, h - Math.round(histData[i] * h / 255.0)), new Scalar(0, 0, 255), Core.FILLED); + } + Image histImage = HighGui.toBufferedImage(histImg); + histImgLabel.setIcon(new ImageIcon(histImage)); + //! [Draw the histogram] + + frame.repaint(); + frame.pack(); + } +} + +public class CalcBackProjectDemo1 { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + // Schedule a job for the event dispatch thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + new CalcBackProject1(args); + } + }); + } +} diff --git a/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java b/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java new file mode 100644 index 0000000..a0ab39e --- /dev/null +++ b/samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo2.java @@ -0,0 +1,189 @@ +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Arrays; +import java.util.List; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.Point; +import org.opencv.core.Range; +import org.opencv.core.Rect; +import org.opencv.core.Scalar; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class CalcBackProject2 { + private Mat src; + private Mat hsv = new Mat(); + private Mat mask = new Mat(); + private JFrame frame; + private JLabel imgLabel; + private JLabel backprojLabel; + private JLabel maskImgLabel; + private static final int MAX_SLIDER = 255; + private int low = 20; + private int up = 20; + + public CalcBackProject2(String[] args) { + /// Read the image + if (args.length != 1) { + System.err.println("You must supply one argument that corresponds to the path to the image."); + System.exit(0); + } + + src = Imgcodecs.imread(args[0]); + if (src.empty()) { + System.err.println("Empty image: " + args[0]); + System.exit(0); + } + + /// Transform it to HSV + Imgproc.cvtColor(src, hsv, Imgproc.COLOR_BGR2HSV); + + // Create and set up the window. + frame = new JFrame("Back Projection 2 demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + // Set up the content pane. + Image img = HighGui.toBufferedImage(src); + addComponentsToPane(frame.getContentPane(), img); + // Use the content pane's default BorderLayout. No need for + // setLayout(new BorderLayout()); + // Display the window. + frame.pack(); + frame.setVisible(true); + } + + private void addComponentsToPane(Container pane, Image img) { + if (!(pane.getLayout() instanceof BorderLayout)) { + pane.add(new JLabel("Container doesn't use BorderLayout!")); + return; + } + + /// Set Trackbars for floodfill thresholds + JPanel sliderPanel = new JPanel(); + sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS)); + + sliderPanel.add(new JLabel("Low thresh")); + JSlider slider = new JSlider(0, MAX_SLIDER, low); + slider.setMajorTickSpacing(20); + slider.setMinorTickSpacing(10); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + JSlider source = (JSlider) e.getSource(); + low = source.getValue(); + } + }); + sliderPanel.add(slider); + pane.add(sliderPanel, BorderLayout.PAGE_START); + + sliderPanel.add(new JLabel("High thresh")); + slider = new JSlider(0, MAX_SLIDER, up); + slider.setMajorTickSpacing(20); + slider.setMinorTickSpacing(10); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + JSlider source = (JSlider) e.getSource(); + up = source.getValue(); + } + }); + sliderPanel.add(slider); + pane.add(sliderPanel, BorderLayout.PAGE_START); + + JPanel imgPanel = new JPanel(); + imgLabel = new JLabel(new ImageIcon(img)); + /// Set a Mouse Callback + imgLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + update(e.getX(), e.getY()); + } + }); + imgPanel.add(imgLabel); + + maskImgLabel = new JLabel(); + imgPanel.add(maskImgLabel); + + backprojLabel = new JLabel(); + imgPanel.add(backprojLabel); + + pane.add(imgPanel, BorderLayout.CENTER); + } + + private void update(int x, int y) { + // Fill and get the mask + Point seed = new Point(x, y); + + int newMaskVal = 255; + Scalar newVal = new Scalar(120, 120, 120); + + int connectivity = 8; + int flags = connectivity + (newMaskVal << 8) + Imgproc.FLOODFILL_FIXED_RANGE + Imgproc.FLOODFILL_MASK_ONLY; + + Mat mask2 = Mat.zeros(src.rows() + 2, src.cols() + 2, CvType.CV_8U); + Imgproc.floodFill(src, mask2, seed, newVal, new Rect(), new Scalar(low, low, low), new Scalar(up, up, up), flags); + mask = mask2.submat(new Range(1, mask2.rows() - 1), new Range(1, mask2.cols() - 1)); + + Image maskImg = HighGui.toBufferedImage(mask); + maskImgLabel.setIcon(new ImageIcon(maskImg)); + + int hBins = 30, sBins = 32; + int[] histSize = { hBins, sBins }; + float[] ranges = { 0, 180, 0, 256 }; + int[] channels = { 0, 1 }; + + /// Get the Histogram and normalize it + Mat hist = new Mat(); + List hsvList = Arrays.asList(hsv); + Imgproc.calcHist(hsvList, new MatOfInt(channels), mask, hist, new MatOfInt(histSize), new MatOfFloat(ranges), false ); + + Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX); + + /// Get Backprojection + Mat backproj = new Mat(); + Imgproc.calcBackProject(hsvList, new MatOfInt(channels), hist, backproj, new MatOfFloat(ranges), 1); + + Image backprojImg = HighGui.toBufferedImage(backproj); + backprojLabel.setIcon(new ImageIcon(backprojImg)); + + frame.repaint(); + frame.pack(); + } +} + +public class CalcBackProjectDemo2 { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + // Schedule a job for the event dispatch thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + new CalcBackProject2(args); + } + }); + } +} diff --git a/samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java b/samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java new file mode 100644 index 0000000..16874e7 --- /dev/null +++ b/samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java @@ -0,0 +1,99 @@ +import java.util.ArrayList; +import java.util.List; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.Point; +import org.opencv.core.Scalar; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class CalcHist { + public void run(String[] args) { + //! [Load image] + String filename = args.length > 0 ? args[0] : "../data/lena.jpg"; + Mat src = Imgcodecs.imread(filename); + if (src.empty()) { + System.err.println("Cannot read image: " + filename); + System.exit(0); + } + //! [Load image] + + //! [Separate the image in 3 places ( B, G and R )] + List bgrPlanes = new ArrayList<>(); + Core.split(src, bgrPlanes); + //! [Separate the image in 3 places ( B, G and R )] + + //! [Establish the number of bins] + int histSize = 256; + //! [Establish the number of bins] + + //! [Set the ranges ( for B,G,R) )] + float[] range = {0, 256}; //the upper boundary is exclusive + MatOfFloat histRange = new MatOfFloat(range); + //! [Set the ranges ( for B,G,R) )] + + //! [Set histogram param] + boolean accumulate = false; + //! [Set histogram param] + + //! [Compute the histograms] + Mat bHist = new Mat(), gHist = new Mat(), rHist = new Mat(); + Imgproc.calcHist(bgrPlanes, new MatOfInt(0), new Mat(), bHist, new MatOfInt(histSize), histRange, accumulate); + Imgproc.calcHist(bgrPlanes, new MatOfInt(1), new Mat(), gHist, new MatOfInt(histSize), histRange, accumulate); + Imgproc.calcHist(bgrPlanes, new MatOfInt(2), new Mat(), rHist, new MatOfInt(histSize), histRange, accumulate); + //! [Compute the histograms] + + //! [Draw the histograms for B, G and R] + int histW = 512, histH = 400; + int binW = (int) Math.round((double) histW / histSize); + + Mat histImage = new Mat( histH, histW, CvType.CV_8UC3, new Scalar( 0,0,0) ); + //! [Draw the histograms for B, G and R] + + //! [Normalize the result to ( 0, histImage.rows )] + Core.normalize(bHist, bHist, 0, histImage.rows(), Core.NORM_MINMAX); + Core.normalize(gHist, gHist, 0, histImage.rows(), Core.NORM_MINMAX); + Core.normalize(rHist, rHist, 0, histImage.rows(), Core.NORM_MINMAX); + //! [Normalize the result to ( 0, histImage.rows )] + + //! [Draw for each channel] + float[] bHistData = new float[(int) (bHist.total() * bHist.channels())]; + bHist.get(0, 0, bHistData); + float[] gHistData = new float[(int) (gHist.total() * gHist.channels())]; + gHist.get(0, 0, gHistData); + float[] rHistData = new float[(int) (rHist.total() * rHist.channels())]; + rHist.get(0, 0, rHistData); + + for( int i = 1; i < histSize; i++ ) { + Imgproc.line(histImage, new Point(binW * (i - 1), histH - Math.round(bHistData[i - 1])), + new Point(binW * (i), histH - Math.round(bHistData[i])), new Scalar(255, 0, 0), 2); + Imgproc.line(histImage, new Point(binW * (i - 1), histH - Math.round(gHistData[i - 1])), + new Point(binW * (i), histH - Math.round(gHistData[i])), new Scalar(0, 255, 0), 2); + Imgproc.line(histImage, new Point(binW * (i - 1), histH - Math.round(rHistData[i - 1])), + new Point(binW * (i), histH - Math.round(rHistData[i])), new Scalar(0, 0, 255), 2); + } + //! [Draw for each channel] + + //! [Display] + HighGui.imshow( "Source image", src ); + HighGui.imshow( "calcHist Demo", histImage ); + HighGui.waitKey(0); + //! [Display] + + System.exit(0); + } +} + +public class CalcHistDemo { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + new CalcHist().run(args); + } +} diff --git a/samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java b/samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java new file mode 100644 index 0000000..fb65dc6 --- /dev/null +++ b/samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java @@ -0,0 +1,91 @@ +import java.util.Arrays; +import java.util.List; + +import org.opencv.core.Core; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.Range; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class CompareHist { + public void run(String[] args) { + //! [Load three images with different environment settings] + if (args.length != 3) { + System.err.println("You must supply 3 arguments that correspond to the paths to 3 images."); + System.exit(0); + } + Mat srcBase = Imgcodecs.imread(args[0]); + Mat srcTest1 = Imgcodecs.imread(args[1]); + Mat srcTest2 = Imgcodecs.imread(args[2]); + if (srcBase.empty() || srcTest1.empty() || srcTest2.empty()) { + System.err.println("Cannot read the images"); + System.exit(0); + } + //! [Load three images with different environment settings] + + //! [Convert to HSV] + Mat hsvBase = new Mat(), hsvTest1 = new Mat(), hsvTest2 = new Mat(); + Imgproc.cvtColor( srcBase, hsvBase, Imgproc.COLOR_BGR2HSV ); + Imgproc.cvtColor( srcTest1, hsvTest1, Imgproc.COLOR_BGR2HSV ); + Imgproc.cvtColor( srcTest2, hsvTest2, Imgproc.COLOR_BGR2HSV ); + //! [Convert to HSV] + + //! [Convert to HSV half] + Mat hsvHalfDown = hsvBase.submat( new Range( hsvBase.rows()/2, hsvBase.rows() - 1 ), new Range( 0, hsvBase.cols() - 1 ) ); + //! [Convert to HSV half] + + //! [Using 50 bins for hue and 60 for saturation] + int hBins = 50, sBins = 60; + int[] histSize = { hBins, sBins }; + + // hue varies from 0 to 179, saturation from 0 to 255 + float[] ranges = { 0, 180, 0, 256 }; + + // Use the 0-th and 1-st channels + int[] channels = { 0, 1 }; + //! [Using 50 bins for hue and 60 for saturation] + + //! [Calculate the histograms for the HSV images] + Mat histBase = new Mat(), histHalfDown = new Mat(), histTest1 = new Mat(), histTest2 = new Mat(); + + List hsvBaseList = Arrays.asList(hsvBase); + Imgproc.calcHist(hsvBaseList, new MatOfInt(channels), new Mat(), histBase, new MatOfInt(histSize), new MatOfFloat(ranges), false); + Core.normalize(histBase, histBase, 0, 1, Core.NORM_MINMAX); + + List hsvHalfDownList = Arrays.asList(hsvHalfDown); + Imgproc.calcHist(hsvHalfDownList, new MatOfInt(channels), new Mat(), histHalfDown, new MatOfInt(histSize), new MatOfFloat(ranges), false); + Core.normalize(histHalfDown, histHalfDown, 0, 1, Core.NORM_MINMAX); + + List hsvTest1List = Arrays.asList(hsvTest1); + Imgproc.calcHist(hsvTest1List, new MatOfInt(channels), new Mat(), histTest1, new MatOfInt(histSize), new MatOfFloat(ranges), false); + Core.normalize(histTest1, histTest1, 0, 1, Core.NORM_MINMAX); + + List hsvTest2List = Arrays.asList(hsvTest2); + Imgproc.calcHist(hsvTest2List, new MatOfInt(channels), new Mat(), histTest2, new MatOfInt(histSize), new MatOfFloat(ranges), false); + Core.normalize(histTest2, histTest2, 0, 1, Core.NORM_MINMAX); + //! [Calculate the histograms for the HSV images] + + //! [Apply the histogram comparison methods] + for( int compareMethod = 0; compareMethod < 4; compareMethod++ ) { + double baseBase = Imgproc.compareHist( histBase, histBase, compareMethod ); + double baseHalf = Imgproc.compareHist( histBase, histHalfDown, compareMethod ); + double baseTest1 = Imgproc.compareHist( histBase, histTest1, compareMethod ); + double baseTest2 = Imgproc.compareHist( histBase, histTest2, compareMethod ); + + System.out.println("Method " + compareMethod + " Perfect, Base-Half, Base-Test(1), Base-Test(2) : " + baseBase + " / " + baseHalf + + " / " + baseTest1 + " / " + baseTest2); + } + //! [Apply the histogram comparison methods] + } +} + +public class CompareHistDemo { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + new CompareHist().run(args); + } +} diff --git a/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java b/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java new file mode 100644 index 0000000..0919243 --- /dev/null +++ b/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java @@ -0,0 +1,49 @@ +import org.opencv.core.Core; +import org.opencv.core.Mat; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class EqualizeHist { + public void run(String[] args) { + //! [Load image] + String filename = args.length > 0 ? args[0] : "../data/lena.jpg"; + Mat src = Imgcodecs.imread(filename); + if (src.empty()) { + System.err.println("Cannot read image: " + filename); + System.exit(0); + } + //! [Load image] + + //! [Convert to grayscale] + Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY); + //! [Convert to grayscale] + + //! [Apply Histogram Equalization] + Mat dst = new Mat(); + Imgproc.equalizeHist( src, dst ); + //! [Apply Histogram Equalization] + + //! [Display results] + HighGui.imshow( "Source image", src ); + HighGui.imshow( "Equalized Image", dst ); + //! [Display results] + + //! [Wait until user exits the program] + HighGui.waitKey(0); + //! [Wait until user exits the program] + + System.exit(0); + } +} + +public class EqualizeHistDemo { + + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + new EqualizeHist().run(args); + } + +} diff --git a/samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java b/samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java new file mode 100644 index 0000000..a391930 --- /dev/null +++ b/samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java @@ -0,0 +1,80 @@ +import org.opencv.core.Core; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.Point; +import org.opencv.highgui.HighGui; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; + +class GeometricTransforms { + public void run(String[] args) { + //! [Load the image] + String filename = args.length > 0 ? args[0] : "../data/lena.jpg"; + Mat src = Imgcodecs.imread(filename); + if (src.empty()) { + System.err.println("Cannot read image: " + filename); + System.exit(0); + } + //! [Load the image] + + //! [Set your 3 points to calculate the Affine Transform] + Point[] srcTri = new Point[3]; + srcTri[0] = new Point( 0, 0 ); + srcTri[1] = new Point( src.cols() - 1, 0 ); + srcTri[2] = new Point( 0, src.rows() - 1 ); + + Point[] dstTri = new Point[3]; + dstTri[0] = new Point( 0, src.rows()*0.33 ); + dstTri[1] = new Point( src.cols()*0.85, src.rows()*0.25 ); + dstTri[2] = new Point( src.cols()*0.15, src.rows()*0.7 ); + //! [Set your 3 points to calculate the Affine Transform] + + //! [Get the Affine Transform] + Mat warpMat = Imgproc.getAffineTransform( new MatOfPoint2f(srcTri), new MatOfPoint2f(dstTri) ); + //! [Get the Affine Transform] + + //! [Apply the Affine Transform just found to the src image] + Mat warpDst = Mat.zeros( src.rows(), src.cols(), src.type() ); + + Imgproc.warpAffine( src, warpDst, warpMat, warpDst.size() ); + //! [Apply the Affine Transform just found to the src image] + + /** Rotating the image after Warp */ + + //! [Compute a rotation matrix with respect to the center of the image] + Point center = new Point(warpDst.cols() / 2, warpDst.rows() / 2); + double angle = -50.0; + double scale = 0.6; + //! [Compute a rotation matrix with respect to the center of the image] + + //! [Get the rotation matrix with the specifications above] + Mat rotMat = Imgproc.getRotationMatrix2D( center, angle, scale ); + //! [Get the rotation matrix with the specifications above] + + //! [Rotate the warped image] + Mat warpRotateDst = new Mat(); + Imgproc.warpAffine( warpDst, warpRotateDst, rotMat, warpDst.size() ); + //! [Rotate the warped image] + + //! [Show what you got] + HighGui.imshow( "Source image", src ); + HighGui.imshow( "Warp", warpDst ); + HighGui.imshow( "Warp + Rotate", warpRotateDst ); + //! [Show what you got] + + //! [Wait until user exits the program] + HighGui.waitKey(0); + //! [Wait until user exits the program] + + System.exit(0); + } +} + +public class GeometricTransformsDemo { + public static void main(String[] args) { + // Load the native OpenCV library + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + + new GeometricTransforms().run(args); + } +} diff --git a/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py b/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py new file mode 100644 index 0000000..eb0bdab --- /dev/null +++ b/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py @@ -0,0 +1,71 @@ +from __future__ import print_function +from __future__ import division +import cv2 as cv +import numpy as np +import argparse + +def Hist_and_Backproj(val): + ## [initialize] + bins = val + histSize = max(bins, 2) + ranges = [0, 180] # hue_range + ## [initialize] + + ## [Get the Histogram and normalize it] + hist = cv.calcHist([hue], [0], None, [histSize], ranges, accumulate=False) + cv.normalize(hist, hist, alpha=0, beta=255, norm_type=cv.NORM_MINMAX) + ## [Get the Histogram and normalize it] + + ## [Get Backprojection] + backproj = cv.calcBackProject([hue], [0], hist, ranges, scale=1) + ## [Get Backprojection] + + ## [Draw the backproj] + cv.imshow('BackProj', backproj) + ## [Draw the backproj] + + ## [Draw the histogram] + w = 400 + h = 400 + bin_w = int(round(w / histSize)) + histImg = np.zeros((h, w, 3), dtype=np.uint8) + + for i in range(bins): + cv.rectangle(histImg, (i*bin_w, h), ( (i+1)*bin_w, h - int(round( hist[i]*h/255.0 )) ), (0, 0, 255), cv.FILLED) + + cv.imshow('Histogram', histImg) + ## [Draw the histogram] + +## [Read the image] +parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.') +parser.add_argument('--input', help='Path to input image.') +args = parser.parse_args() + +src = cv.imread(args.input) +if src is None: + print('Could not open or find the image:', args.input) + exit(0) +## [Read the image] + +## [Transform it to HSV] +hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV) +## [Transform it to HSV] + +## [Use only the Hue value] +ch = (0, 0) +hue = np.empty(hsv.shape, hsv.dtype) +cv.mixChannels([hsv], [hue], ch) +## [Use only the Hue value] + +## [Create Trackbar to enter the number of bins] +window_image = 'Source image' +cv.namedWindow(window_image) +bins = 25 +cv.createTrackbar('* Hue bins: ', window_image, bins, 180, Hist_and_Backproj ) +Hist_and_Backproj(bins) +## [Create Trackbar to enter the number of bins] + +## [Show the image] +cv.imshow(window_image, src) +cv.waitKey() +## [Show the image] diff --git a/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py b/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py new file mode 100644 index 0000000..24255a2 --- /dev/null +++ b/samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py @@ -0,0 +1,79 @@ +from __future__ import print_function +import cv2 as cv +import numpy as np +import argparse + +low = 20 +up = 20 + +def callback_low(val): + global low + low = val + +def callback_up(val): + global up + up = val + +def pickPoint(event, x, y, flags, param): + if event != cv.EVENT_LBUTTONDOWN: + return + + # Fill and get the mask + seed = (x, y) + newMaskVal = 255 + newVal = (120, 120, 120) + connectivity = 8 + flags = connectivity + (newMaskVal << 8 ) + cv.FLOODFILL_FIXED_RANGE + cv.FLOODFILL_MASK_ONLY + + mask2 = np.zeros((src.shape[0] + 2, src.shape[1] + 2), dtype=np.uint8) + print('low:', low, 'up:', up) + cv.floodFill(src, mask2, seed, newVal, (low, low, low), (up, up, up), flags) + mask = mask2[1:-1,1:-1] + + cv.imshow('Mask', mask) + Hist_and_Backproj(mask) + +def Hist_and_Backproj(mask): + h_bins = 30 + s_bins = 32 + histSize = [h_bins, s_bins] + h_range = [0, 180] + s_range = [0, 256] + ranges = h_range + s_range # Concat list + channels = [0, 1] + + # Get the Histogram and normalize it + hist = cv.calcHist([hsv], channels, mask, histSize, ranges, accumulate=False) + cv.normalize(hist, hist, alpha=0, beta=255, norm_type=cv.NORM_MINMAX) + + # Get Backprojection + backproj = cv.calcBackProject([hsv], channels, hist, ranges, scale=1) + + # Draw the backproj + cv.imshow('BackProj', backproj) + +# Read the image +parser = argparse.ArgumentParser(description='Code for Back Projection tutorial.') +parser.add_argument('--input', help='Path to input image.') +args = parser.parse_args() + +src = cv.imread(args.input) +if src is None: + print('Could not open or find the image:', args.input) + exit(0) + +# Transform it to HSV +hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV) + +# Show the image +window_image = 'Source image' +cv.namedWindow(window_image) +cv.imshow(window_image, src) + +# Set Trackbars for floodfill thresholds +cv.createTrackbar('Low thresh', window_image, low, 255, callback_low) +cv.createTrackbar('High thresh', window_image, up, 255, callback_up) +# Set a Mouse Callback +cv.setMouseCallback(window_image, pickPoint) + +cv.waitKey() diff --git a/samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py b/samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py new file mode 100644 index 0000000..63302ab --- /dev/null +++ b/samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py @@ -0,0 +1,71 @@ +from __future__ import print_function +from __future__ import division +import cv2 as cv +import numpy as np +import argparse + +## [Load image] +parser = argparse.ArgumentParser(description='Code for Histogram Calculation tutorial.') +parser.add_argument('--input', help='Path to input image.', default='../data/lena.jpg') +args = parser.parse_args() + +src = cv.imread(args.input) +if src is None: + print('Could not open or find the image:', args.input) + exit(0) +## [Load image] + +## [Separate the image in 3 places ( B, G and R )] +bgr_planes = cv.split(src) +## [Separate the image in 3 places ( B, G and R )] + +## [Establish the number of bins] +histSize = 256 +## [Establish the number of bins] + +## [Set the ranges ( for B,G,R) )] +histRange = (0, 256) # the upper boundary is exclusive +## [Set the ranges ( for B,G,R) )] + +## [Set histogram param] +accumulate = False +## [Set histogram param] + +## [Compute the histograms] +b_hist = cv.calcHist(bgr_planes, [0], None, [histSize], histRange, accumulate=accumulate) +g_hist = cv.calcHist(bgr_planes, [1], None, [histSize], histRange, accumulate=accumulate) +r_hist = cv.calcHist(bgr_planes, [2], None, [histSize], histRange, accumulate=accumulate) +## [Compute the histograms] + +## [Draw the histograms for B, G and R] +hist_w = 512 +hist_h = 400 +bin_w = int(round( hist_w/histSize )) + +histImage = np.zeros((hist_h, hist_w, 3), dtype=np.uint8) +## [Draw the histograms for B, G and R] + +## [Normalize the result to ( 0, histImage.rows )] +cv.normalize(b_hist, b_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX) +cv.normalize(g_hist, g_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX) +cv.normalize(r_hist, r_hist, alpha=0, beta=hist_h, norm_type=cv.NORM_MINMAX) +## [Normalize the result to ( 0, histImage.rows )] + +## [Draw for each channel] +for i in range(1, histSize): + cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(b_hist[i-1])) ), + ( bin_w*(i), hist_h - int(round(b_hist[i])) ), + ( 255, 0, 0), thickness=2) + cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(g_hist[i-1])) ), + ( bin_w*(i), hist_h - int(round(g_hist[i])) ), + ( 0, 255, 0), thickness=2) + cv.line(histImage, ( bin_w*(i-1), hist_h - int(round(r_hist[i-1])) ), + ( bin_w*(i), hist_h - int(round(r_hist[i])) ), + ( 0, 0, 255), thickness=2) +## [Draw for each channel] + +## [Display] +cv.imshow('Source image', src) +cv.imshow('calcHist Demo', histImage) +cv.waitKey() +## [Display] diff --git a/samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py b/samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py new file mode 100644 index 0000000..08d0dc3 --- /dev/null +++ b/samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py @@ -0,0 +1,69 @@ +from __future__ import print_function +from __future__ import division +import cv2 as cv +import numpy as np +import argparse + +## [Load three images with different environment settings] +parser = argparse.ArgumentParser(description='Code for Histogram Comparison tutorial.') +parser.add_argument('--input1', help='Path to input image 1.') +parser.add_argument('--input2', help='Path to input image 2.') +parser.add_argument('--input3', help='Path to input image 3.') +args = parser.parse_args() + +src_base = cv.imread(args.input1) +src_test1 = cv.imread(args.input2) +src_test2 = cv.imread(args.input3) +if src_base is None or src_test1 is None or src_test2 is None: + print('Could not open or find the images!') + exit(0) +## [Load three images with different environment settings] + +## [Convert to HSV] +hsv_base = cv.cvtColor(src_base, cv.COLOR_BGR2HSV) +hsv_test1 = cv.cvtColor(src_test1, cv.COLOR_BGR2HSV) +hsv_test2 = cv.cvtColor(src_test2, cv.COLOR_BGR2HSV) +## [Convert to HSV] + +## [Convert to HSV half] +hsv_half_down = hsv_base[hsv_base.shape[0]//2:,:] +## [Convert to HSV half] + +## [Using 50 bins for hue and 60 for saturation] +h_bins = 50 +s_bins = 60 +histSize = [h_bins, s_bins] + +# hue varies from 0 to 179, saturation from 0 to 255 +h_ranges = [0, 180] +s_ranges = [0, 256] +ranges = h_ranges + s_ranges # concat lists + +# Use the 0-th and 1-st channels +channels = [0, 1] +## [Using 50 bins for hue and 60 for saturation] + +## [Calculate the histograms for the HSV images] +hist_base = cv.calcHist([hsv_base], channels, None, histSize, ranges, accumulate=False) +cv.normalize(hist_base, hist_base, alpha=0, beta=1, norm_type=cv.NORM_MINMAX) + +hist_half_down = cv.calcHist([hsv_half_down], channels, None, histSize, ranges, accumulate=False) +cv.normalize(hist_half_down, hist_half_down, alpha=0, beta=1, norm_type=cv.NORM_MINMAX) + +hist_test1 = cv.calcHist([hsv_test1], channels, None, histSize, ranges, accumulate=False) +cv.normalize(hist_test1, hist_test1, alpha=0, beta=1, norm_type=cv.NORM_MINMAX) + +hist_test2 = cv.calcHist([hsv_test2], channels, None, histSize, ranges, accumulate=False) +cv.normalize(hist_test2, hist_test2, alpha=0, beta=1, norm_type=cv.NORM_MINMAX) +## [Calculate the histograms for the HSV images] + +## [Apply the histogram comparison methods] +for compare_method in range(4): + base_base = cv.compareHist(hist_base, hist_base, compare_method) + base_half = cv.compareHist(hist_base, hist_half_down, compare_method) + base_test1 = cv.compareHist(hist_base, hist_test1, compare_method) + base_test2 = cv.compareHist(hist_base, hist_test2, compare_method) + + print('Method:', compare_method, 'Perfect, Base-Half, Base-Test(1), Base-Test(2) :',\ + base_base, '/', base_half, '/', base_test1, '/', base_test2) +## [Apply the histogram comparison methods] diff --git a/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py b/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py new file mode 100644 index 0000000..47caec4 --- /dev/null +++ b/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py @@ -0,0 +1,31 @@ +from __future__ import print_function +import cv2 as cv +import argparse + +## [Load image] +parser = argparse.ArgumentParser(description='Code for Histogram Equalization tutorial.') +parser.add_argument('--input', help='Path to input image.', default='../data/lena.jpg') +args = parser.parse_args() + +src = cv.imread(args.input) +if src is None: + print('Could not open or find the image:', args.input) + exit(0) +## [Load image] + +## [Convert to grayscale] +src = cv.cvtColor(src, cv.COLOR_BGR2GRAY) +## [Convert to grayscale] + +## [Apply Histogram Equalization] +dst = cv.equalizeHist(src); +## [Apply Histogram Equalization] + +## [Display results] +cv.imshow('Source image', src) +cv.imshow('Equalized Image', dst) +## [Display results] + +## [Wait until user exits the program] +cv.waitKey() +## [Wait until user exits the program] diff --git a/samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py b/samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py new file mode 100644 index 0000000..462a412 --- /dev/null +++ b/samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py @@ -0,0 +1,54 @@ +from __future__ import print_function +import cv2 as cv +import numpy as np +import argparse + +## [Load the image] +parser = argparse.ArgumentParser(description='Code for Affine Transformations tutorial.') +parser.add_argument('--input', help='Path to input image.', default='../data/lena.jpg') +args = parser.parse_args() + +src = cv.imread(args.input) +if src is None: + print('Could not open or find the image:', args.input) + exit(0) +## [Load the image] + +## [Set your 3 points to calculate the Affine Transform] +srcTri = np.array( [[0, 0], [src.shape[1] - 1, 0], [0, src.shape[0] - 1]] ).astype(np.float32) +dstTri = np.array( [[0, src.shape[1]*0.33], [src.shape[1]*0.85, src.shape[0]*0.25], [src.shape[1]*0.15, src.shape[0]*0.7]] ).astype(np.float32) +## [Set your 3 points to calculate the Affine Transform] + +## [Get the Affine Transform] +warp_mat = cv.getAffineTransform(srcTri, dstTri) +## [Get the Affine Transform] + +## [Apply the Affine Transform just found to the src image] +warp_dst = cv.warpAffine(src, warp_mat, (src.shape[1], src.shape[0])) +## [Apply the Affine Transform just found to the src image] + +# Rotating the image after Warp + +## [Compute a rotation matrix with respect to the center of the image] +center = (warp_dst.shape[1]//2, warp_dst.shape[0]//2) +angle = -50 +scale = 0.6 +## [Compute a rotation matrix with respect to the center of the image] + +## [Get the rotation matrix with the specifications above] +rot_mat = cv.getRotationMatrix2D( center, angle, scale ) +## [Get the rotation matrix with the specifications above] + +## [Rotate the warped image] +warp_rotate_dst = cv.warpAffine(warp_dst, rot_mat, (warp_dst.shape[1], warp_dst.shape[0])) +## [Rotate the warped image] + +## [Show what you got] +cv.imshow('Source image', src) +cv.imshow('Warp', warp_dst) +cv.imshow('Warp + Rotate', warp_rotate_dst) +## [Show what you got] + +## [Wait until user exits the program] +cv.waitKey() +## [Wait until user exits the program] -- 2.7.4