mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -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 );
|
||||
- Display backproj:
|
||||
|
||||
for( int i = 0; i < bins; i ++ )
|
||||
{ rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); }
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the backproj
|
||||
@end_toggle
|
||||
|
||||
imshow( "Histogram", histImg );
|
||||
@endcode
|
||||
@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
|
||||
-------
|
||||
|
||||
+175
-99
@@ -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<Mat> 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.
|
||||
- Establish the number of bins (5, 10...):
|
||||
|
||||
-# 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 );
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Establish the number of bins
|
||||
@end_toggle
|
||||
|
||||
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
|
||||
@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<float>(i-1)) ) ,
|
||||
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
|
||||
Scalar( 255, 0, 0), 2, 8, 0 );
|
||||
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
|
||||
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
|
||||
Scalar( 0, 255, 0), 2, 8, 0 );
|
||||
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
|
||||
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(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<float>(i)
|
||||
@endcode
|
||||
@@ -189,20 +261,24 @@ Explanation
|
||||
b_hist.at<float>( 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:
|
||||
|
||||

|
||||
|
||||
|
||||
+101
-73
@@ -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 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)
|
||||
|
||||
- **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 <image_settings0> <image_setting1> <image_settings2>\n");
|
||||
return -1;
|
||||
}
|
||||
- Load the base image (src_base) and the other two test images:
|
||||
|
||||
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 };
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Load three images with different environment settings
|
||||
@end_toggle
|
||||
|
||||
float h_ranges[] = { 0, 180 };
|
||||
float s_ranges[] = { 0, 256 };
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Load three images with different environment settings
|
||||
@end_toggle
|
||||
|
||||
const float* ranges[] = { h_ranges, s_ranges };
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Load three images with different environment settings
|
||||
@end_toggle
|
||||
|
||||
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() );
|
||||
- Convert them to HSV format:
|
||||
|
||||
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() );
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Convert to HSV
|
||||
@end_toggle
|
||||
|
||||
calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
|
||||
normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_comparison/CompareHistDemo.java Convert to HSV
|
||||
@end_toggle
|
||||
|
||||
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)
|
||||
@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,
|
||||
|
||||
+86
-34
@@ -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 <a href="https://en.wikipedia.org/wiki/Histogram_equalization">Wikipedia entry</a>).
|
||||
- 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;
|
||||
- Load the source image:
|
||||
|
||||
char* source_window = "Source image";
|
||||
char* equalized_window = "Equalized Image";
|
||||
@endcode
|
||||
-# Load the source image:
|
||||
@code{.cpp}
|
||||
src = imread( argv[1], 1 );
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Load image
|
||||
@end_toggle
|
||||
|
||||
if( !src.data )
|
||||
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
|
||||
return -1;}
|
||||
@endcode
|
||||
-# Convert it to grayscale:
|
||||
@code{.cpp}
|
||||
cvtColor( src, src, COLOR_BGR2GRAY );
|
||||
@endcode
|
||||
-# Apply histogram equalization with the function @ref cv::equalizeHist :
|
||||
@code{.cpp}
|
||||
equalizeHist( src, dst );
|
||||
@endcode
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Load image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Load image
|
||||
@end_toggle
|
||||
|
||||
- Convert it to grayscale:
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Convert to grayscale
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Convert to grayscale
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Convert to grayscale
|
||||
@end_toggle
|
||||
|
||||
- Apply histogram equalization with the function @ref cv::equalizeHist :
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Apply Histogram Equalization
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Apply Histogram Equalization
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Apply Histogram Equalization
|
||||
@end_toggle
|
||||
As it can be easily seen, the only arguments are the original image and the output (equalized)
|
||||
image.
|
||||
|
||||
-# Display both images (original and equalized) :
|
||||
@code{.cpp}
|
||||
namedWindow( source_window, WINDOW_AUTOSIZE );
|
||||
namedWindow( equalized_window, WINDOW_AUTOSIZE );
|
||||
- Display both images (original and equalized):
|
||||
|
||||
imshow( source_window, src );
|
||||
imshow( equalized_window, dst );
|
||||
@endcode
|
||||
-# Wait until user exists the program
|
||||
@code{.cpp}
|
||||
waitKey(0);
|
||||
return 0;
|
||||
@endcode
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Display results
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Display results
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Display results
|
||||
@end_toggle
|
||||
|
||||
- Wait until user exists the program
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
Results
|
||||
-------
|
||||
|
||||
@@ -80,7 +80,7 @@ Theory
|
||||
Code
|
||||
----
|
||||
|
||||
-# **What does this program do?**
|
||||
- **What does this program do?**
|
||||
- Loads an image
|
||||
- Applies an Affine Transform to the image. This transform is obtained from the relation
|
||||
between three points. We use the function @ref cv::warpAffine for that purpose.
|
||||
@@ -88,57 +88,88 @@ Code
|
||||
the image center
|
||||
- Waits until the user exits the program
|
||||
|
||||
-# The tutorial's code is shown below. You can also download it here
|
||||
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp)
|
||||
@add_toggle_cpp
|
||||
- The tutorial's code is shown below. You can also download it
|
||||
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
|
||||
@include samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
- The tutorial's code is shown below. You can also download it
|
||||
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/Smoothing/Smoothing.cpp)
|
||||
@include samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
- The tutorial's code is shown below. You can also download it
|
||||
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py)
|
||||
@include samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py
|
||||
@end_toggle
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
-# Declare some variables we will use, such as the matrices to store our results and 2 arrays of
|
||||
points to store the 2D points that define our Affine Transform.
|
||||
@code{.cpp}
|
||||
Point2f srcTri[3];
|
||||
Point2f dstTri[3];
|
||||
- Load an image:
|
||||
|
||||
Mat rot_mat( 2, 3, CV_32FC1 );
|
||||
Mat warp_mat( 2, 3, CV_32FC1 );
|
||||
Mat src, warp_dst, warp_rotate_dst;
|
||||
@endcode
|
||||
-# Load an image:
|
||||
@code{.cpp}
|
||||
src = imread( argv[1], 1 );
|
||||
@endcode
|
||||
-# Initialize the destination image as having the same size and type as the source:
|
||||
@code{.cpp}
|
||||
warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
|
||||
@endcode
|
||||
-# **Affine Transform:** As we explained in lines above, we need two sets of 3 points to derive the
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Load the image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Load the image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Load the image
|
||||
@end_toggle
|
||||
|
||||
- **Affine Transform:** As we explained in lines above, we need two sets of 3 points to derive the
|
||||
affine transform relation. Have a look:
|
||||
@code{.cpp}
|
||||
srcTri[0] = Point2f( 0, 0 );
|
||||
srcTri[1] = Point2f( src.cols - 1, 0 );
|
||||
srcTri[2] = Point2f( 0, src.rows - 1 );
|
||||
|
||||
dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );
|
||||
dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );
|
||||
dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );
|
||||
@endcode
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Set your 3 points to calculate the Affine Transform
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Set your 3 points to calculate the Affine Transform
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Set your 3 points to calculate the Affine Transform
|
||||
@end_toggle
|
||||
You may want to draw these points to get a better idea on how they change. Their locations are
|
||||
approximately the same as the ones depicted in the example figure (in the Theory section). You
|
||||
may note that the size and orientation of the triangle defined by the 3 points change.
|
||||
|
||||
-# Armed with both sets of points, we calculate the Affine Transform by using OpenCV function @ref
|
||||
- Armed with both sets of points, we calculate the Affine Transform by using OpenCV function @ref
|
||||
cv::getAffineTransform :
|
||||
@code{.cpp}
|
||||
warp_mat = getAffineTransform( srcTri, dstTri );
|
||||
@endcode
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Get the Affine Transform
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Get the Affine Transform
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Get the Affine Transform
|
||||
@end_toggle
|
||||
We get a \f$2 \times 3\f$ matrix as an output (in this case **warp_mat**)
|
||||
|
||||
-# We then apply the Affine Transform just found to the src image
|
||||
@code{.cpp}
|
||||
warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
|
||||
@endcode
|
||||
- We then apply the Affine Transform just found to the src image
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Apply the Affine Transform just found to the src image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Apply the Affine Transform just found to the src image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Apply the Affine Transform just found to the src image
|
||||
@end_toggle
|
||||
with the following arguments:
|
||||
|
||||
- **src**: Input image
|
||||
@@ -149,47 +180,87 @@ Explanation
|
||||
We just got our first transformed image! We will display it in one bit. Before that, we also
|
||||
want to rotate it...
|
||||
|
||||
-# **Rotate:** To rotate an image, we need to know two things:
|
||||
- **Rotate:** To rotate an image, we need to know two things:
|
||||
|
||||
-# The center with respect to which the image will rotate
|
||||
-# The angle to be rotated. In OpenCV a positive angle is counter-clockwise
|
||||
-# *Optional:* A scale factor
|
||||
|
||||
We define these parameters with the following snippet:
|
||||
@code{.cpp}
|
||||
Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
|
||||
double angle = -50.0;
|
||||
double scale = 0.6;
|
||||
@endcode
|
||||
-# We generate the rotation matrix with the OpenCV function @ref cv::getRotationMatrix2D , which
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Compute a rotation matrix with respect to the center of the image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Compute a rotation matrix with respect to the center of the image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Compute a rotation matrix with respect to the center of the image
|
||||
@end_toggle
|
||||
|
||||
- We generate the rotation matrix with the OpenCV function @ref cv::getRotationMatrix2D , which
|
||||
returns a \f$2 \times 3\f$ matrix (in this case *rot_mat*)
|
||||
@code{.cpp}
|
||||
rot_mat = getRotationMatrix2D( center, angle, scale );
|
||||
@endcode
|
||||
-# We now apply the found rotation to the output of our previous Transformation.
|
||||
@code{.cpp}
|
||||
warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
|
||||
@endcode
|
||||
-# Finally, we display our results in two windows plus the original image for good measure:
|
||||
@code{.cpp}
|
||||
namedWindow( source_window, WINDOW_AUTOSIZE );
|
||||
imshow( source_window, src );
|
||||
|
||||
namedWindow( warp_window, WINDOW_AUTOSIZE );
|
||||
imshow( warp_window, warp_dst );
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Get the rotation matrix with the specifications above
|
||||
@end_toggle
|
||||
|
||||
namedWindow( warp_rotate_window, WINDOW_AUTOSIZE );
|
||||
imshow( warp_rotate_window, warp_rotate_dst );
|
||||
@endcode
|
||||
-# We just have to wait until the user exits the program
|
||||
@code{.cpp}
|
||||
waitKey(0);
|
||||
@endcode
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Get the rotation matrix with the specifications above
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Get the rotation matrix with the specifications above
|
||||
@end_toggle
|
||||
|
||||
- We now apply the found rotation to the output of our previous Transformation:
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Rotate the warped image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Rotate the warped image
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Rotate the warped image
|
||||
@end_toggle
|
||||
|
||||
- Finally, we display our results in two windows plus the original image for good measure:
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Show what you got
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Show what you got
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Show what you got
|
||||
@end_toggle
|
||||
|
||||
- We just have to wait until the user exits the program
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_java
|
||||
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Wait until user exits the program
|
||||
@end_toggle
|
||||
|
||||
Result
|
||||
------
|
||||
|
||||
-# After compiling the code above, we can give it the path of an image as argument. For instance,
|
||||
- After compiling the code above, we can give it the path of an image as argument. For instance,
|
||||
for a picture like:
|
||||
|
||||

|
||||
|
||||
@@ -165,6 +165,8 @@ In this section you will learn about the image processing (manipulation) functio
|
||||
|
||||
- @subpage tutorial_warp_affine
|
||||
|
||||
*Languages:* C++, Java, Python
|
||||
|
||||
*Compatibility:* \> 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
|
||||
|
||||
Reference in New Issue
Block a user