mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 09:25:45 +08:00
Add Java and Python code for the following imgproc tutorials: Affine Transformations, Histogram Equalization, Histogram Calculation, Histogram Comparison, Back Projection.
This commit is contained in:
parent
3654fb10d7
commit
4c1c3147d9
@ -67,46 +67,104 @@ Code
|
|||||||
- Calculate the histogram (and update it if the bins change) and the backprojection of the
|
- Calculate the histogram (and update it if the bins change) and the backprojection of the
|
||||||
same image.
|
same image.
|
||||||
- Display the backprojection and the histogram in windows.
|
- 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)
|
[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 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
|
skin area) you can check the [improved
|
||||||
demo](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp)
|
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)
|
[camshiftdemo](https://github.com/opencv/opencv/tree/master/samples/cpp/camshiftdemo.cpp)
|
||||||
in samples.
|
in samples.
|
||||||
|
|
||||||
- **Code at glance:**
|
- **Code at glance:**
|
||||||
@include samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp
|
@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
|
Explanation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
-# Declare the matrices to store our images and initialize the number of bins to be used by our
|
- Read the input image:
|
||||||
histogram:
|
|
||||||
@code{.cpp}
|
@add_toggle_cpp
|
||||||
Mat src; Mat hsv; Mat hue;
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Read the image
|
||||||
int bins = 25;
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Read the input image and transform it to HSV format:
|
@add_toggle_java
|
||||||
@code{.cpp}
|
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java Read the image
|
||||||
src = imread( argv[1], 1 );
|
@end_toggle
|
||||||
cvtColor( src, hsv, COLOR_BGR2HSV );
|
|
||||||
@endcode
|
@add_toggle_python
|
||||||
-# For this tutorial, we will use only the Hue value for our 1-D histogram (check out the fancier
|
@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
|
code in the links above if you want to use the more standard H-S histogram, which yields better
|
||||||
results):
|
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
|
- **&hsv:** The source array from which the channels will be copied
|
||||||
- **1:** The number of source arrays
|
- **1:** The number of source arrays
|
||||||
- **&hue:** The destination array of the copied channels
|
- **&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)
|
case, the Hue(0) channel of &hsv is being copied to the 0 channel of &hue (1-channel)
|
||||||
- **1:** Number of index pairs
|
- **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.
|
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);
|
@add_toggle_cpp
|
||||||
return 0;
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Create Trackbar to enter the number of bins
|
||||||
@endcode
|
@end_toggle
|
||||||
-# **Hist_and_Backproj function:** Initialize the arguments needed for @ref cv::calcHist . The
|
|
||||||
|
@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:
|
number of bins comes from the Trackbar:
|
||||||
@code{.cpp}
|
|
||||||
void Hist_and_Backproj(int, void* )
|
@add_toggle_cpp
|
||||||
{
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp initialize
|
||||||
MatND hist;
|
@end_toggle
|
||||||
int histSize = MAX( bins, 2 );
|
|
||||||
float hue_range[] = { 0, 180 };
|
@add_toggle_java
|
||||||
const float* ranges = { hue_range };
|
@snippet samples/java/tutorial_code/Histograms_Matching/back_projection/CalcBackProjectDemo1.java initialize
|
||||||
@endcode
|
@end_toggle
|
||||||
-# Calculate the Histogram and normalize it to the range \f$[0,255]\f$
|
|
||||||
@code{.cpp}
|
@add_toggle_python
|
||||||
calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );
|
@snippet samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo1.py initialize
|
||||||
normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Get the Backprojection of the same image by calling the function @ref cv::calcBackProject
|
- Calculate the Histogram and normalize it to the range \f$[0,255]\f$
|
||||||
@code{.cpp}
|
|
||||||
MatND backproj;
|
@add_toggle_cpp
|
||||||
calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Get the Histogram and normalize it
|
||||||
@endcode
|
@end_toggle
|
||||||
all the arguments are known (the same as used to calculate the histogram), only we add the
|
|
||||||
|
@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)
|
backproj matrix, which will store the backprojection of the source image (&hue)
|
||||||
|
|
||||||
-# Display backproj:
|
- 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 ++ )
|
@add_toggle_cpp
|
||||||
{ 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 ); }
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp Draw the backproj
|
||||||
|
@end_toggle
|
||||||
|
|
||||||
imshow( "Histogram", histImg );
|
@add_toggle_java
|
||||||
@endcode
|
@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
|
Results
|
||||||
-------
|
-------
|
||||||
|
@ -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*
|
- 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
|
- 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
|
- Let's see an example. Imagine that a Matrix contains information of an image (i.e. intensity in
|
||||||
the range \f$0-255\f$):
|
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
|
- 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
|
- Calculate the Histogram of each 1-channel plane by calling the function @ref cv::calcHist
|
||||||
- Plot the three histograms in a window
|
- Plot the three histograms in a window
|
||||||
|
|
||||||
|
@add_toggle_cpp
|
||||||
- **Downloadable code**: Click
|
- **Downloadable code**: Click
|
||||||
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp)
|
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp)
|
||||||
|
|
||||||
- **Code at glance:**
|
- **Code at glance:**
|
||||||
@include samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp
|
@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
|
Explanation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
-# Create the necessary matrices:
|
- Load the source image
|
||||||
@code{.cpp}
|
|
||||||
Mat src, dst;
|
|
||||||
@endcode
|
|
||||||
-# Load the source image
|
|
||||||
@code{.cpp}
|
|
||||||
src = imread( argv[1], 1 );
|
|
||||||
|
|
||||||
if( !src.data )
|
@add_toggle_cpp
|
||||||
{ return -1; }
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Load image
|
||||||
@endcode
|
@end_toggle
|
||||||
-# Separate the source image in its three R,G and B planes. For this we use the OpenCV function
|
|
||||||
|
@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 :
|
@ref cv::split :
|
||||||
@code{.cpp}
|
|
||||||
vector<Mat> bgr_planes;
|
@add_toggle_cpp
|
||||||
split( src, bgr_planes );
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Separate the image in 3 places ( B, G and R )
|
||||||
@endcode
|
@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
|
our input is the image to be divided (this case with three channels) and the output is a vector
|
||||||
of Mat )
|
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$
|
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)
|
- Establish the number of bins (5, 10...):
|
||||||
- **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
|
||||||
@code{.cpp}
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Establish the number of bins
|
||||||
// Draw the histograms for R, G and B
|
@end_toggle
|
||||||
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) );
|
@add_toggle_java
|
||||||
@endcode
|
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Establish the number of bins
|
||||||
-# Notice that before drawing, we first @ref cv::normalize the histogram so its values fall in the
|
@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:
|
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:** Input array
|
||||||
- **b_hist:** Output normalized array (can be the same)
|
- **b_hist:** Output normalized array (can be the same)
|
||||||
- **0** and\**histImage.rows: For this example, they are the lower and upper limits to
|
- **0** and **histImage.rows**: For this example, they are the lower and upper limits to
|
||||||
normalize the values ofr_hist*\*
|
normalize the values of **r_hist**
|
||||||
- **NORM_MINMAX:** Argument that indicates the type of normalization (as described above, it
|
- **NORM_MINMAX:** Argument that indicates the type of normalization (as described above, it
|
||||||
adjusts the values between the two limits set before)
|
adjusts the values between the two limits set before)
|
||||||
- **-1:** Implies that the output normalized array will be the same type as the input
|
- **-1:** Implies that the output normalized array will be the same type as the input
|
||||||
- **Mat():** Optional mask
|
- **Mat():** Optional mask
|
||||||
|
|
||||||
-# Finally, observe that to access the bin (in this case in this 1D-Histogram):
|
- Observe that to access the bin (in this case in this 1D-Histogram):
|
||||||
@code{.cpp}
|
|
||||||
/// Draw for each channel
|
@add_toggle_cpp
|
||||||
for( int i = 1; i < histSize; i++ )
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Draw for each channel
|
||||||
{
|
@end_toggle
|
||||||
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)) ),
|
@add_toggle_java
|
||||||
Scalar( 255, 0, 0), 2, 8, 0 );
|
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_calculation/CalcHistDemo.java Draw for each channel
|
||||||
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
|
@end_toggle
|
||||||
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
|
|
||||||
Scalar( 0, 255, 0), 2, 8, 0 );
|
@add_toggle_python
|
||||||
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
|
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_calculation/calcHist_Demo.py Draw for each channel
|
||||||
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
|
@end_toggle
|
||||||
Scalar( 0, 0, 255), 2, 8, 0 );
|
we use the expression (**C++ code**):
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
we use the expression:
|
|
||||||
@code{.cpp}
|
@code{.cpp}
|
||||||
b_hist.at<float>(i)
|
b_hist.at<float>(i)
|
||||||
@endcode
|
@endcode
|
||||||
@ -189,20 +261,24 @@ Explanation
|
|||||||
b_hist.at<float>( i, j )
|
b_hist.at<float>( i, j )
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
-# Finally we display our histograms and wait for the user to exit:
|
- Finally we display our histograms and wait for the user to exit:
|
||||||
@code{.cpp}
|
|
||||||
namedWindow("calcHist Demo", WINDOW_AUTOSIZE );
|
|
||||||
imshow("calcHist Demo", histImage );
|
|
||||||
|
|
||||||
waitKey(0);
|
@add_toggle_cpp
|
||||||
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp Display
|
||||||
|
@end_toggle
|
||||||
|
|
||||||
return 0;
|
@add_toggle_java
|
||||||
@endcode
|
@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
|
Result
|
||||||
------
|
------
|
||||||
|
|
||||||
-# Using as input argument an image like the shown below:
|
-# Using as input argument an image like the one shown below:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -43,90 +43,118 @@ Code
|
|||||||
- Compare the histogram of the *base image* with respect to the 2 test histograms, the
|
- 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.
|
histogram of the lower half base image and with the same base image histogram.
|
||||||
- Display the numerical matching parameters obtained.
|
- Display the numerical matching parameters obtained.
|
||||||
|
|
||||||
|
@add_toggle_cpp
|
||||||
- **Downloadable code**: Click
|
- **Downloadable code**: Click
|
||||||
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp)
|
[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
|
Explanation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
-# Declare variables such as the matrices to store the base image and the two other images to
|
- Load the base image (src_base) and the other two test images:
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
src_base = imread( argv[1], 1 );
|
@add_toggle_cpp
|
||||||
src_test1 = imread( argv[2], 1 );
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Load three images with different environment settings
|
||||||
src_test2 = imread( argv[3], 1 );
|
@end_toggle
|
||||||
@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 };
|
@add_toggle_java
|
||||||
float s_ranges[] = { 0, 256 };
|
@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 };
|
- Convert them to HSV format:
|
||||||
@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 );
|
@add_toggle_cpp
|
||||||
normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
|
@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 );
|
@add_toggle_java
|
||||||
normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
|
@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 );
|
@add_toggle_python
|
||||||
normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
|
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV
|
||||||
@endcode
|
@end_toggle
|
||||||
-# Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base)
|
|
||||||
|
- 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:
|
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 );
|
@add_toggle_cpp
|
||||||
}
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Apply the histogram comparison methods
|
||||||
@endcode
|
@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
|
Results
|
||||||
-------
|
-------
|
||||||
@ -144,13 +172,13 @@ Results
|
|||||||
are from the same source. For the other two test images, we can observe that they have very
|
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:
|
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
|
*Method* | Base - Base | Base - Half | Base - Test 1 | Base - Test 2
|
||||||
----------------- | ------------ | ------------ | -------------- | ---------------
|
----------------- | ------------ | ------------ | -------------- | ---------------
|
||||||
*Correlation* | 1.000000 | 0.930766 | 0.182073 | 0.120447
|
*Correlation* | 1.000000 | 0.880438 | 0.20457 | 0.0664547
|
||||||
*Chi-square* | 0.000000 | 4.940466 | 21.184536 | 49.273437
|
*Chi-square* | 0.000000 | 4.6834 | 2697.98 | 4763.8
|
||||||
*Intersection* | 24.391548 | 14.959809 | 3.889029 | 5.775088
|
*Intersection* | 18.8947 | 13.022 | 5.44085 | 2.58173
|
||||||
*Bhattacharyya* | 0.000000 | 0.222609 | 0.646576 | 0.801869
|
*Bhattacharyya* | 0.000000 | 0.237887 | 0.679826 | 0.874173
|
||||||
For the *Correlation* and *Intersection* methods, the higher the metric, the more accurate the
|
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
|
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,
|
that the match *base-half* is the second best match (as we predicted). For the other two metrics,
|
||||||
|
@ -22,7 +22,7 @@ Theory
|
|||||||
### What is Histogram Equalization?
|
### What is Histogram Equalization?
|
||||||
|
|
||||||
- It is a method that improves the contrast in an image, in order to stretch out the intensity
|
- 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
|
- 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
|
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
|
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
|
- Convert the original image to grayscale
|
||||||
- Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist
|
- Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist
|
||||||
- Display the source and equalized images in a window.
|
- Display the source and equalized images in a window.
|
||||||
|
|
||||||
|
@add_toggle_cpp
|
||||||
- **Downloadable code**: Click
|
- **Downloadable code**: Click
|
||||||
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp)
|
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp)
|
||||||
|
|
||||||
- **Code at glance:**
|
- **Code at glance:**
|
||||||
@include samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp
|
@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
|
Explanation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
-# Declare the source and destination images as well as the windows names:
|
- Load the source image:
|
||||||
@code{.cpp}
|
|
||||||
Mat src, dst;
|
|
||||||
|
|
||||||
char* source_window = "Source image";
|
@add_toggle_cpp
|
||||||
char* equalized_window = "Equalized Image";
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Load image
|
||||||
@endcode
|
@end_toggle
|
||||||
-# Load the source image:
|
|
||||||
@code{.cpp}
|
|
||||||
src = imread( argv[1], 1 );
|
|
||||||
|
|
||||||
if( !src.data )
|
@add_toggle_java
|
||||||
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
|
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Load image
|
||||||
return -1;}
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Convert it to grayscale:
|
@add_toggle_python
|
||||||
@code{.cpp}
|
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Load image
|
||||||
cvtColor( src, src, COLOR_BGR2GRAY );
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Apply histogram equalization with the function @ref cv::equalizeHist :
|
- Convert it to grayscale:
|
||||||
@code{.cpp}
|
|
||||||
equalizeHist( src, dst );
|
@add_toggle_cpp
|
||||||
@endcode
|
@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)
|
As it can be easily seen, the only arguments are the original image and the output (equalized)
|
||||||
image.
|
image.
|
||||||
|
|
||||||
-# Display both images (original and equalized) :
|
- Display both images (original and equalized):
|
||||||
@code{.cpp}
|
|
||||||
namedWindow( source_window, WINDOW_AUTOSIZE );
|
|
||||||
namedWindow( equalized_window, WINDOW_AUTOSIZE );
|
|
||||||
|
|
||||||
imshow( source_window, src );
|
@add_toggle_cpp
|
||||||
imshow( equalized_window, dst );
|
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Display results
|
||||||
@endcode
|
@end_toggle
|
||||||
-# Wait until user exists the program
|
|
||||||
@code{.cpp}
|
@add_toggle_java
|
||||||
waitKey(0);
|
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Display results
|
||||||
return 0;
|
@end_toggle
|
||||||
@endcode
|
|
||||||
|
@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
|
Results
|
||||||
-------
|
-------
|
||||||
|
@ -80,7 +80,7 @@ Theory
|
|||||||
Code
|
Code
|
||||||
----
|
----
|
||||||
|
|
||||||
-# **What does this program do?**
|
- **What does this program do?**
|
||||||
- Loads an image
|
- Loads an image
|
||||||
- Applies an Affine Transform to the image. This transform is obtained from the relation
|
- 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.
|
between three points. We use the function @ref cv::warpAffine for that purpose.
|
||||||
@ -88,57 +88,88 @@ Code
|
|||||||
the image center
|
the image center
|
||||||
- Waits until the user exits the program
|
- Waits until the user exits the program
|
||||||
|
|
||||||
-# The tutorial's code is shown below. You can also download it here
|
@add_toggle_cpp
|
||||||
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.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
|
@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
|
Explanation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
-# Declare some variables we will use, such as the matrices to store our results and 2 arrays of
|
- Load an image:
|
||||||
points to store the 2D points that define our Affine Transform.
|
|
||||||
@code{.cpp}
|
|
||||||
Point2f srcTri[3];
|
|
||||||
Point2f dstTri[3];
|
|
||||||
|
|
||||||
Mat rot_mat( 2, 3, CV_32FC1 );
|
@add_toggle_cpp
|
||||||
Mat warp_mat( 2, 3, CV_32FC1 );
|
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Load the image
|
||||||
Mat src, warp_dst, warp_rotate_dst;
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Load an image:
|
@add_toggle_java
|
||||||
@code{.cpp}
|
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Load the image
|
||||||
src = imread( argv[1], 1 );
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# Initialize the destination image as having the same size and type as the source:
|
@add_toggle_python
|
||||||
@code{.cpp}
|
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Load the image
|
||||||
warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# **Affine Transform:** As we explained in lines above, we need two sets of 3 points to derive the
|
- **Affine Transform:** As we explained in lines above, we need two sets of 3 points to derive the
|
||||||
affine transform relation. Have a look:
|
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 );
|
@add_toggle_cpp
|
||||||
dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );
|
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Set your 3 points to calculate the Affine Transform
|
||||||
dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );
|
@end_toggle
|
||||||
@endcode
|
|
||||||
|
@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
|
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
|
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.
|
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 :
|
cv::getAffineTransform :
|
||||||
@code{.cpp}
|
|
||||||
warp_mat = getAffineTransform( srcTri, dstTri );
|
@add_toggle_cpp
|
||||||
@endcode
|
@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 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
|
- We then apply the Affine Transform just found to the src image
|
||||||
@code{.cpp}
|
|
||||||
warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
|
@add_toggle_cpp
|
||||||
@endcode
|
@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:
|
with the following arguments:
|
||||||
|
|
||||||
- **src**: Input image
|
- **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
|
We just got our first transformed image! We will display it in one bit. Before that, we also
|
||||||
want to rotate it...
|
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 center with respect to which the image will rotate
|
||||||
-# The angle to be rotated. In OpenCV a positive angle is counter-clockwise
|
-# The angle to be rotated. In OpenCV a positive angle is counter-clockwise
|
||||||
-# *Optional:* A scale factor
|
-# *Optional:* A scale factor
|
||||||
|
|
||||||
We define these parameters with the following snippet:
|
We define these parameters with the following snippet:
|
||||||
@code{.cpp}
|
|
||||||
Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
|
@add_toggle_cpp
|
||||||
double angle = -50.0;
|
@snippet samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp Compute a rotation matrix with respect to the center of the image
|
||||||
double scale = 0.6;
|
@end_toggle
|
||||||
@endcode
|
|
||||||
-# We generate the rotation matrix with the OpenCV function @ref cv::getRotationMatrix2D , which
|
@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*)
|
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 );
|
@add_toggle_cpp
|
||||||
imshow( warp_window, warp_dst );
|
@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 );
|
@add_toggle_java
|
||||||
imshow( warp_rotate_window, warp_rotate_dst );
|
@snippet samples/java/tutorial_code/ImgTrans/warp_affine/GeometricTransformsDemo.java Get the rotation matrix with the specifications above
|
||||||
@endcode
|
@end_toggle
|
||||||
-# We just have to wait until the user exits the program
|
|
||||||
@code{.cpp}
|
@add_toggle_python
|
||||||
waitKey(0);
|
@snippet samples/python/tutorial_code/ImgTrans/warp_affine/Geometric_Transforms_Demo.py Get the rotation matrix with the specifications above
|
||||||
@endcode
|
@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
|
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:
|
for a picture like:
|
||||||
|
|
||||||

|

|
||||||
|
@ -165,6 +165,8 @@ In this section you will learn about the image processing (manipulation) functio
|
|||||||
|
|
||||||
- @subpage tutorial_warp_affine
|
- @subpage tutorial_warp_affine
|
||||||
|
|
||||||
|
*Languages:* C++, Java, Python
|
||||||
|
|
||||||
*Compatibility:* \> OpenCV 2.0
|
*Compatibility:* \> OpenCV 2.0
|
||||||
|
|
||||||
*Author:* Ana Huamán
|
*Author:* Ana Huamán
|
||||||
@ -173,6 +175,8 @@ In this section you will learn about the image processing (manipulation) functio
|
|||||||
|
|
||||||
- @subpage tutorial_histogram_equalization
|
- @subpage tutorial_histogram_equalization
|
||||||
|
|
||||||
|
*Languages:* C++, Java, Python
|
||||||
|
|
||||||
*Compatibility:* \> OpenCV 2.0
|
*Compatibility:* \> OpenCV 2.0
|
||||||
|
|
||||||
*Author:* Ana Huamán
|
*Author:* Ana Huamán
|
||||||
@ -181,6 +185,8 @@ In this section you will learn about the image processing (manipulation) functio
|
|||||||
|
|
||||||
- @subpage tutorial_histogram_calculation
|
- @subpage tutorial_histogram_calculation
|
||||||
|
|
||||||
|
*Languages:* C++, Java, Python
|
||||||
|
|
||||||
*Compatibility:* \> OpenCV 2.0
|
*Compatibility:* \> OpenCV 2.0
|
||||||
|
|
||||||
*Author:* Ana Huamán
|
*Author:* Ana Huamán
|
||||||
@ -189,6 +195,8 @@ In this section you will learn about the image processing (manipulation) functio
|
|||||||
|
|
||||||
- @subpage tutorial_histogram_comparison
|
- @subpage tutorial_histogram_comparison
|
||||||
|
|
||||||
|
*Languages:* C++, Java, Python
|
||||||
|
|
||||||
*Compatibility:* \> OpenCV 2.0
|
*Compatibility:* \> OpenCV 2.0
|
||||||
|
|
||||||
*Author:* Ana Huamán
|
*Author:* Ana Huamán
|
||||||
@ -197,6 +205,8 @@ In this section you will learn about the image processing (manipulation) functio
|
|||||||
|
|
||||||
- @subpage tutorial_back_projection
|
- @subpage tutorial_back_projection
|
||||||
|
|
||||||
|
*Languages:* C++, Java, Python
|
||||||
|
|
||||||
*Compatibility:* \> OpenCV 2.0
|
*Compatibility:* \> OpenCV 2.0
|
||||||
|
|
||||||
*Author:* Ana Huamán
|
*Author:* Ana Huamán
|
||||||
|
@ -17,37 +17,35 @@ using namespace std;
|
|||||||
*/
|
*/
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
Mat src, dst;
|
//! [Load image]
|
||||||
|
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
|
||||||
|
Mat src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
|
||||||
|
if( src.empty() )
|
||||||
|
{
|
||||||
|
cout << "Could not open or find the image!\n" << endl;
|
||||||
|
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//! [Load image]
|
||||||
|
|
||||||
const char* source_window = "Source image";
|
//! [Convert to grayscale]
|
||||||
const char* equalized_window = "Equalized Image";
|
cvtColor( src, src, COLOR_BGR2GRAY );
|
||||||
|
//! [Convert to grayscale]
|
||||||
|
|
||||||
/// Load image
|
//! [Apply Histogram Equalization]
|
||||||
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
|
Mat dst;
|
||||||
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
|
equalizeHist( src, dst );
|
||||||
if( src.empty() )
|
//! [Apply Histogram Equalization]
|
||||||
{
|
|
||||||
cout << "Could not open or find the image!\n" << endl;
|
|
||||||
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert to grayscale
|
//! [Display results]
|
||||||
cvtColor( src, src, COLOR_BGR2GRAY );
|
imshow( "Source image", src );
|
||||||
|
imshow( "Equalized Image", dst );
|
||||||
|
//! [Display results]
|
||||||
|
|
||||||
/// Apply Histogram Equalization
|
//! [Wait until user exits the program]
|
||||||
equalizeHist( src, dst );
|
waitKey();
|
||||||
|
//! [Wait until user exits the program]
|
||||||
|
|
||||||
/// Display results
|
return 0;
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,79 +14,93 @@ using namespace cv;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/// Global Variables
|
/// Global Variables
|
||||||
Mat src; Mat hsv; Mat hue;
|
Mat hue;
|
||||||
int bins = 25;
|
int bins = 25;
|
||||||
|
|
||||||
/// Function Headers
|
/// Function Headers
|
||||||
void Hist_and_Backproj(int, void* );
|
void Hist_and_Backproj(int, void* );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function main
|
* @function main
|
||||||
*/
|
*/
|
||||||
int main( int, char** argv )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
/// Read the image
|
//! [Read the image]
|
||||||
src = imread( argv[1], IMREAD_COLOR );
|
CommandLineParser parser( argc, argv, "{@input | | input image}" );
|
||||||
|
Mat src = imread( parser.get<String>( "@input" ) );
|
||||||
if( src.empty() )
|
if( src.empty() )
|
||||||
{ cout<<"Usage: ./calcBackProject_Demo1 <path_to_image>"<<endl;
|
{
|
||||||
return -1;
|
cout << "Could not open or find the image!\n" << endl;
|
||||||
|
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
//! [Read the image]
|
||||||
|
|
||||||
/// Transform it to HSV
|
//! [Transform it to HSV]
|
||||||
cvtColor( src, hsv, COLOR_BGR2HSV );
|
Mat hsv;
|
||||||
|
cvtColor( src, hsv, COLOR_BGR2HSV );
|
||||||
|
//! [Transform it to HSV]
|
||||||
|
|
||||||
/// Use only the Hue value
|
//! [Use only the Hue value]
|
||||||
hue.create( hsv.size(), hsv.depth() );
|
hue.create(hsv.size(), hsv.depth());
|
||||||
int ch[] = { 0, 0 };
|
int ch[] = { 0, 0 };
|
||||||
mixChannels( &hsv, 1, &hue, 1, ch, 1 );
|
mixChannels( &hsv, 1, &hue, 1, ch, 1 );
|
||||||
|
//! [Use only the Hue value]
|
||||||
|
|
||||||
/// Create Trackbar to enter the number of bins
|
//! [Create Trackbar to enter the number of bins]
|
||||||
const char* window_image = "Source image";
|
const char* window_image = "Source image";
|
||||||
namedWindow( window_image, WINDOW_AUTOSIZE );
|
namedWindow( window_image );
|
||||||
createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj );
|
createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj );
|
||||||
Hist_and_Backproj(0, 0);
|
Hist_and_Backproj(0, 0);
|
||||||
|
//! [Create Trackbar to enter the number of bins]
|
||||||
|
|
||||||
/// Show the image
|
//! [Show the image]
|
||||||
imshow( window_image, src );
|
imshow( window_image, src );
|
||||||
|
// Wait until user exits the program
|
||||||
|
waitKey();
|
||||||
|
//! [Show the image]
|
||||||
|
|
||||||
/// Wait until user exits the program
|
return 0;
|
||||||
waitKey(0);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function Hist_and_Backproj
|
* @function Hist_and_Backproj
|
||||||
* @brief Callback to Trackbar
|
* @brief Callback to Trackbar
|
||||||
*/
|
*/
|
||||||
void Hist_and_Backproj(int, void* )
|
void Hist_and_Backproj(int, void* )
|
||||||
{
|
{
|
||||||
MatND hist;
|
//! [initialize]
|
||||||
int histSize = MAX( bins, 2 );
|
int histSize = MAX( bins, 2 );
|
||||||
float hue_range[] = { 0, 180 };
|
float hue_range[] = { 0, 180 };
|
||||||
const float* ranges = { hue_range };
|
const float* ranges = { hue_range };
|
||||||
|
//! [initialize]
|
||||||
|
|
||||||
/// Get the Histogram and normalize it
|
//! [Get the Histogram and normalize it]
|
||||||
calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );
|
Mat hist;
|
||||||
normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
|
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
|
//! [Get Backprojection]
|
||||||
MatND backproj;
|
Mat backproj;
|
||||||
calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );
|
calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );
|
||||||
|
//! [Get Backprojection]
|
||||||
|
|
||||||
/// Draw the backproj
|
//! [Draw the backproj]
|
||||||
imshow( "BackProj", backproj );
|
imshow( "BackProj", backproj );
|
||||||
|
//! [Draw the backproj]
|
||||||
|
|
||||||
/// Draw the histogram
|
//! [Draw the histogram]
|
||||||
int w = 400; int h = 400;
|
int w = 400, h = 400;
|
||||||
int bin_w = cvRound( (double) w / histSize );
|
int bin_w = cvRound( (double) w / histSize );
|
||||||
Mat histImg = Mat::zeros( w, h, CV_8UC3 );
|
Mat histImg = Mat::zeros( h, w, CV_8UC3 );
|
||||||
|
|
||||||
for( int i = 0; i < bins; i ++ )
|
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 ); }
|
{
|
||||||
|
rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ),
|
||||||
imshow( "Histogram", histImg );
|
Scalar( 0, 0, 255 ), FILLED );
|
||||||
|
}
|
||||||
|
|
||||||
|
imshow( "Histogram", histImg );
|
||||||
|
//! [Draw the histogram]
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,9 @@ using namespace cv;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/// Global Variables
|
/// Global Variables
|
||||||
Mat src; Mat hsv;
|
Mat src, hsv, mask;
|
||||||
Mat mask;
|
|
||||||
|
|
||||||
int lo = 20; int up = 20;
|
int low = 20, up = 20;
|
||||||
const char* window_image = "Source image";
|
const char* window_image = "Source image";
|
||||||
|
|
||||||
/// Function Headers
|
/// Function Headers
|
||||||
@ -29,23 +28,24 @@ void pickPoint (int event, int x, int y, int, void* );
|
|||||||
*/
|
*/
|
||||||
int main( int, char** argv )
|
int main( int, char** argv )
|
||||||
{
|
{
|
||||||
/// Read the image
|
/// Read the image
|
||||||
src = imread( argv[1], IMREAD_COLOR );
|
src = imread( argv[1] );
|
||||||
/// Transform it to HSV
|
|
||||||
cvtColor( src, hsv, COLOR_BGR2HSV );
|
|
||||||
|
|
||||||
/// Show the image
|
/// Transform it to HSV
|
||||||
namedWindow( window_image, WINDOW_AUTOSIZE );
|
cvtColor( src, hsv, COLOR_BGR2HSV );
|
||||||
imshow( window_image, src );
|
|
||||||
|
|
||||||
/// Set Trackbars for floodfill thresholds
|
/// Show the image
|
||||||
createTrackbar( "Low thresh", window_image, &lo, 255, 0 );
|
namedWindow( window_image );
|
||||||
createTrackbar( "High thresh", window_image, &up, 255, 0 );
|
imshow( window_image, src );
|
||||||
/// Set a Mouse Callback
|
|
||||||
setMouseCallback( window_image, pickPoint, 0 );
|
|
||||||
|
|
||||||
waitKey(0);
|
/// Set Trackbars for floodfill thresholds
|
||||||
return 0;
|
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* )
|
void pickPoint (int event, int x, int y, int, void* )
|
||||||
{
|
{
|
||||||
if( event != EVENT_LBUTTONDOWN )
|
if( event != EVENT_LBUTTONDOWN )
|
||||||
{ return; }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill and get the mask
|
// Fill and get the mask
|
||||||
Point seed = Point( x, y );
|
Point seed = Point( x, y );
|
||||||
|
|
||||||
int newMaskVal = 255;
|
int newMaskVal = 255;
|
||||||
Scalar newVal = Scalar( 120, 120, 120 );
|
Scalar newVal = Scalar( 120, 120, 120 );
|
||||||
|
|
||||||
int connectivity = 8;
|
int connectivity = 8;
|
||||||
int flags = connectivity + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
|
int flags = connectivity + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
|
||||||
|
|
||||||
Mat mask2 = Mat::zeros( src.rows + 2, src.cols + 2, CV_8UC1 );
|
Mat mask2 = Mat::zeros( src.rows + 2, src.cols + 2, CV_8U );
|
||||||
floodFill( src, mask2, seed, newVal, 0, Scalar( lo, lo, lo ), Scalar( up, up, up), flags );
|
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 ) );
|
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( )
|
void Hist_and_Backproj( )
|
||||||
{
|
{
|
||||||
MatND hist;
|
Mat hist;
|
||||||
int h_bins = 30; int s_bins = 32;
|
int h_bins = 30; int s_bins = 32;
|
||||||
int histSize[] = { h_bins, s_bins };
|
int histSize[] = { h_bins, s_bins };
|
||||||
|
|
||||||
float h_range[] = { 0, 179 };
|
float h_range[] = { 0, 180 };
|
||||||
float s_range[] = { 0, 255 };
|
float s_range[] = { 0, 256 };
|
||||||
const float* ranges[] = { h_range, s_range };
|
const float* ranges[] = { h_range, s_range };
|
||||||
|
|
||||||
int channels[] = { 0, 1 };
|
int channels[] = { 0, 1 };
|
||||||
|
|
||||||
/// Get the Histogram and normalize it
|
/// Get the Histogram and normalize it
|
||||||
calcHist( &hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false );
|
calcHist( &hsv, 1, channels, mask, hist, 2, histSize, ranges, true, false );
|
||||||
|
|
||||||
normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
|
normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
|
||||||
|
|
||||||
/// Get Backprojection
|
/// Get Backprojection
|
||||||
MatND backproj;
|
Mat backproj;
|
||||||
calcBackProject( &hsv, 1, channels, hist, backproj, ranges, 1, true );
|
calcBackProject( &hsv, 1, channels, hist, backproj, ranges, 1, true );
|
||||||
|
|
||||||
/// Draw the backproj
|
|
||||||
imshow( "BackProj", backproj );
|
|
||||||
|
|
||||||
|
/// Draw the backproj
|
||||||
|
imshow( "BackProj", backproj );
|
||||||
}
|
}
|
||||||
|
@ -17,72 +17,73 @@ using namespace cv;
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
Mat src, dst;
|
//! [Load image]
|
||||||
|
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
|
||||||
|
Mat src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
|
||||||
|
if( src.empty() )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//! [Load image]
|
||||||
|
|
||||||
/// Load image
|
//! [Separate the image in 3 places ( B, G and R )]
|
||||||
String imageName( "../data/lena.jpg" ); // by default
|
vector<Mat> bgr_planes;
|
||||||
|
split( src, bgr_planes );
|
||||||
|
//! [Separate the image in 3 places ( B, G and R )]
|
||||||
|
|
||||||
if (argc > 1)
|
//! [Establish the number of bins]
|
||||||
{
|
int histSize = 256;
|
||||||
imageName = argv[1];
|
//! [Establish the number of bins]
|
||||||
}
|
|
||||||
|
|
||||||
src = imread( imageName, IMREAD_COLOR );
|
//! [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) )]
|
||||||
|
|
||||||
if( src.empty() )
|
//! [Set histogram param]
|
||||||
{ return -1; }
|
bool uniform = true, accumulate = false;
|
||||||
|
//! [Set histogram param]
|
||||||
|
|
||||||
/// Separate the image in 3 places ( B, G and R )
|
//! [Compute the histograms]
|
||||||
vector<Mat> bgr_planes;
|
Mat b_hist, g_hist, r_hist;
|
||||||
split( src, bgr_planes );
|
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]
|
||||||
|
|
||||||
/// Establish the number of bins
|
//! [Draw the histograms for B, G and R]
|
||||||
int histSize = 256;
|
int hist_w = 512, hist_h = 400;
|
||||||
|
int bin_w = cvRound( (double) hist_w/histSize );
|
||||||
|
|
||||||
/// Set the ranges ( for B,G,R) )
|
Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
|
||||||
float range[] = { 0, 256 } ;
|
//! [Draw the histograms for B, G and R]
|
||||||
const float* histRange = { range };
|
|
||||||
|
|
||||||
bool uniform = true; bool accumulate = false;
|
//! [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 )]
|
||||||
|
|
||||||
Mat b_hist, g_hist, r_hist;
|
//! [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 );
|
||||||
|
}
|
||||||
|
//! [Draw for each channel]
|
||||||
|
|
||||||
/// Compute the histograms:
|
//! [Display]
|
||||||
calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
|
imshow("Source image", src );
|
||||||
calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
|
imshow("calcHist Demo", histImage );
|
||||||
calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
|
waitKey();
|
||||||
|
//! [Display]
|
||||||
// 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<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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Display
|
|
||||||
namedWindow("calcHist Demo", WINDOW_AUTOSIZE );
|
|
||||||
imshow("calcHist Demo", histImage );
|
|
||||||
|
|
||||||
waitKey(0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,42 +12,43 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
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
|
* @function main
|
||||||
*/
|
*/
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
Mat src_base, hsv_base;
|
//! [Load three images with different environment settings]
|
||||||
Mat src_test1, hsv_test1;
|
CommandLineParser parser( argc, argv, keys );
|
||||||
Mat src_test2, hsv_test2;
|
Mat src_base = imread( parser.get<String>("input1") );
|
||||||
Mat hsv_half_down;
|
Mat src_test1 = imread( parser.get<String>("input2") );
|
||||||
|
Mat src_test2 = imread( parser.get<String>("input3") );
|
||||||
/// Load three images with different environment settings
|
if( src_base.empty() || src_test1.empty() || src_test2.empty() )
|
||||||
if( argc < 4 )
|
|
||||||
{
|
{
|
||||||
printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_settings1> <image_settings2>\n");
|
cout << "Could not open or find the images!\n" << endl;
|
||||||
|
parser.printMessage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
//! [Load three images with different environment settings]
|
||||||
|
|
||||||
src_base = imread( argv[1], IMREAD_COLOR );
|
//! [Convert to HSV]
|
||||||
src_test1 = imread( argv[2], IMREAD_COLOR );
|
Mat hsv_base, hsv_test1, hsv_test2;
|
||||||
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
|
|
||||||
cvtColor( src_base, hsv_base, COLOR_BGR2HSV );
|
cvtColor( src_base, hsv_base, COLOR_BGR2HSV );
|
||||||
cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );
|
cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );
|
||||||
cvtColor( src_test2, hsv_test2, 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
|
//! [Using 50 bins for hue and 60 for saturation]
|
||||||
int h_bins = 50; int s_bins = 60;
|
int h_bins = 50, s_bins = 60;
|
||||||
int histSize[] = { h_bins, s_bins };
|
int histSize[] = { h_bins, s_bins };
|
||||||
|
|
||||||
// hue varies from 0 to 179, saturation from 0 to 255
|
// 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 };
|
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 };
|
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 );
|
calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
|
||||||
normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
|
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 );
|
calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );
|
||||||
normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
|
normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||||
|
//! [Calculate the histograms for the HSV images]
|
||||||
|
|
||||||
/// Apply the histogram comparison methods
|
//! [Apply the histogram comparison methods]
|
||||||
for( int i = 0; i < 4; i++ )
|
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_base = compareHist( hist_base, hist_base, compare_method );
|
||||||
double base_half = compareHist( hist_base, hist_half_down, 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_test1 = compareHist( hist_base, hist_test1, compare_method );
|
||||||
double base_test2 = compareHist( hist_base, hist_test2, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,77 +12,71 @@
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace std;
|
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
|
* @function main
|
||||||
*/
|
*/
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
Point2f srcTri[3];
|
//! [Load the image]
|
||||||
Point2f dstTri[3];
|
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
|
||||||
|
Mat src = imread( parser.get<String>( "@input" ) );
|
||||||
|
if( src.empty() )
|
||||||
|
{
|
||||||
|
cout << "Could not open or find the image!\n" << endl;
|
||||||
|
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//! [Load the image]
|
||||||
|
|
||||||
Mat rot_mat( 2, 3, CV_32FC1 );
|
//! [Set your 3 points to calculate the Affine Transform]
|
||||||
Mat warp_mat( 2, 3, CV_32FC1 );
|
Point2f srcTri[3];
|
||||||
Mat src, warp_dst, warp_rotate_dst;
|
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 );
|
||||||
|
|
||||||
/// Load the image
|
Point2f dstTri[3];
|
||||||
CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
|
dstTri[0] = Point2f( 0.f, src.rows*0.33f );
|
||||||
src = imread( parser.get<String>( "@input" ), IMREAD_COLOR );
|
dstTri[1] = Point2f( src.cols*0.85f, src.rows*0.25f );
|
||||||
if( src.empty() )
|
dstTri[2] = Point2f( src.cols*0.15f, src.rows*0.7f );
|
||||||
{
|
//! [Set your 3 points to calculate the Affine Transform]
|
||||||
cout << "Could not open or find the image!\n" << endl;
|
|
||||||
cout << "Usage: " << argv[0] << " <Input image>" << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the dst image the same type and size as src
|
//! [Get the Affine Transform]
|
||||||
warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
|
Mat warp_mat = getAffineTransform( srcTri, dstTri );
|
||||||
|
//! [Get the Affine Transform]
|
||||||
|
|
||||||
/// Set your 3 points to calculate the Affine Transform
|
//! [Apply the Affine Transform just found to the src image]
|
||||||
srcTri[0] = Point2f( 0,0 );
|
/// Set the dst image the same type and size as src
|
||||||
srcTri[1] = Point2f( src.cols - 1.f, 0 );
|
Mat warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
|
||||||
srcTri[2] = Point2f( 0, src.rows - 1.f );
|
|
||||||
|
|
||||||
dstTri[0] = Point2f( src.cols*0.0f, src.rows*0.33f );
|
warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
|
||||||
dstTri[1] = Point2f( src.cols*0.85f, src.rows*0.25f );
|
//! [Apply the Affine Transform just found to the src image]
|
||||||
dstTri[2] = Point2f( src.cols*0.15f, src.rows*0.7f );
|
|
||||||
|
|
||||||
/// Get the Affine Transform
|
/** Rotating the image after Warp */
|
||||||
warp_mat = getAffineTransform( srcTri, dstTri );
|
|
||||||
|
|
||||||
/// Apply the Affine Transform just found to the src image
|
//! [Compute a rotation matrix with respect to the center of the image]
|
||||||
warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
|
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]
|
||||||
|
|
||||||
/** Rotating the image after Warp */
|
//! [Get the rotation matrix with the specifications above]
|
||||||
|
Mat rot_mat = getRotationMatrix2D( center, angle, scale );
|
||||||
|
//! [Get the rotation matrix with the specifications above]
|
||||||
|
|
||||||
/// Compute a rotation matrix with respect to the center of the image
|
//! [Rotate the warped image]
|
||||||
Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
|
Mat warp_rotate_dst;
|
||||||
double angle = -50.0;
|
warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
|
||||||
double scale = 0.6;
|
//! [Rotate the warped image]
|
||||||
|
|
||||||
/// Get the rotation matrix with the specifications above
|
//! [Show what you got]
|
||||||
rot_mat = getRotationMatrix2D( center, angle, scale );
|
imshow( "Source image", src );
|
||||||
|
imshow( "Warp", warp_dst );
|
||||||
|
imshow( "Warp + Rotate", warp_rotate_dst );
|
||||||
|
//! [Show what you got]
|
||||||
|
|
||||||
/// Rotate the warped image
|
//! [Wait until user exits the program]
|
||||||
warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
|
waitKey();
|
||||||
|
//! [Wait until user exits the program]
|
||||||
|
|
||||||
|
return 0;
|
||||||
/// 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;
|
|
||||||
}
|
}
|
||||||
|
@ -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<Mat> 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -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<Mat> 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -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<Mat> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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<Mat> 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<Mat> 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<Mat> 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<Mat> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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]
|
@ -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()
|
@ -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]
|
@ -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]
|
@ -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]
|
@ -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]
|
Loading…
Reference in New Issue
Block a user