Added reST tutorials for Contours (6 in imgproc) and for Corner Detection (4 in features2D) + links in conf.py
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 80 KiB |
@ -0,0 +1,139 @@ |
|||||||
|
.. _corner_subpixeles: |
||||||
|
|
||||||
|
Detecting corners location in subpixeles |
||||||
|
**************************************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :corner_sub_pix:`cornerSubPix <>` to find more exact corner positions (more exact than integer pixels). |
||||||
|
|
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
/// Global variables |
||||||
|
Mat src, src_gray; |
||||||
|
|
||||||
|
int maxCorners = 10; |
||||||
|
int maxTrackbar = 25; |
||||||
|
|
||||||
|
RNG rng(12345); |
||||||
|
char* source_window = "Image"; |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void goodFeaturesToTrack_Demo( int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
|
||||||
|
/// Create Trackbar to set the number of corners |
||||||
|
createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo ); |
||||||
|
|
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
goodFeaturesToTrack_Demo( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @function goodFeaturesToTrack_Demo.cpp |
||||||
|
* @brief Apply Shi-Tomasi corner detector |
||||||
|
*/ |
||||||
|
void goodFeaturesToTrack_Demo( int, void* ) |
||||||
|
{ |
||||||
|
if( maxCorners < 1 ) { maxCorners = 1; } |
||||||
|
|
||||||
|
/// Parameters for Shi-Tomasi algorithm |
||||||
|
vector<Point2f> corners; |
||||||
|
double qualityLevel = 0.01; |
||||||
|
double minDistance = 10; |
||||||
|
int blockSize = 3; |
||||||
|
bool useHarrisDetector = false; |
||||||
|
double k = 0.04; |
||||||
|
|
||||||
|
/// Copy the source image |
||||||
|
Mat copy; |
||||||
|
copy = src.clone(); |
||||||
|
|
||||||
|
/// Apply corner detection |
||||||
|
goodFeaturesToTrack( src_gray, |
||||||
|
corners, |
||||||
|
maxCorners, |
||||||
|
qualityLevel, |
||||||
|
minDistance, |
||||||
|
Mat(), |
||||||
|
blockSize, |
||||||
|
useHarrisDetector, |
||||||
|
k ); |
||||||
|
|
||||||
|
|
||||||
|
/// Draw corners detected |
||||||
|
cout<<"** Number of corners detected: "<<corners.size()<<endl; |
||||||
|
int r = 4; |
||||||
|
for( int i = 0; i < corners.size(); i++ ) |
||||||
|
{ circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0 ); } |
||||||
|
|
||||||
|
/// Show what you got |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, copy ); |
||||||
|
|
||||||
|
/// Set the neeed parameters to find the refined corners |
||||||
|
Size winSize = Size( 5, 5 ); |
||||||
|
Size zeroZone = Size( -1, -1 ); |
||||||
|
TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 ); |
||||||
|
|
||||||
|
/// Calculate the refined corner locations |
||||||
|
cornerSubPix( src_gray, corners, winSize, zeroZone, criteria ); |
||||||
|
|
||||||
|
/// Write them down |
||||||
|
for( int i = 0; i < corners.size(); i++ ) |
||||||
|
{ cout<<" -- Refined Corner ["<<i<<"] ("<<corners[i].x<<","<<corners[i].y<<")"<<endl; } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
.. image:: images/Corner_Subpixeles_Original_Image.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
||||||
|
Here is the result: |
||||||
|
|
||||||
|
.. image:: images/Corner_Subpixeles_Result.jpg |
||||||
|
:height: 100pt |
||||||
|
:align: center |
||||||
|
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,155 @@ |
|||||||
|
.. _generic_corner_detector: |
||||||
|
|
||||||
|
Creating yor own corner detector |
||||||
|
******************************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :corner_eigenvals_and_vecs:`cornerEigenValsAndVecs <>` to find the eigenvalues and eigenvectors to determine if a pixel is a corner. |
||||||
|
* Use the OpenCV function :corner_min_eigenval:`cornerMinEigenVal <>` to find the minimum eigenvalues for corner detection. |
||||||
|
* To implement our own version of the Harris detector as well as the Shi-Tomasi detector, by using the two functions above. |
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
/// Global variables |
||||||
|
Mat src, src_gray; |
||||||
|
Mat myHarris_dst; Mat myHarris_copy; Mat Mc; |
||||||
|
Mat myShiTomasi_dst; Mat myShiTomasi_copy; |
||||||
|
|
||||||
|
int myShiTomasi_qualityLevel = 50; |
||||||
|
int myHarris_qualityLevel = 50; |
||||||
|
int max_qualityLevel = 100; |
||||||
|
|
||||||
|
double myHarris_minVal; double myHarris_maxVal; |
||||||
|
double myShiTomasi_minVal; double myShiTomasi_maxVal; |
||||||
|
|
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
char* myHarris_window = "My Harris corner detector"; |
||||||
|
char* myShiTomasi_window = "My Shi Tomasi corner detector"; |
||||||
|
|
||||||
|
/// Function headers |
||||||
|
void myShiTomasi_function( int, void* ); |
||||||
|
void myHarris_function( int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
|
||||||
|
/// Set some parameters |
||||||
|
int blockSize = 3; int apertureSize = 3; |
||||||
|
|
||||||
|
/// My Harris matrix -- Using cornerEigenValsAndVecs |
||||||
|
myHarris_dst = Mat::zeros( src_gray.size(), CV_32FC(6) ); |
||||||
|
Mc = Mat::zeros( src_gray.size(), CV_32FC1 ); |
||||||
|
|
||||||
|
cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize, BORDER_DEFAULT ); |
||||||
|
|
||||||
|
/* calculate Mc */ |
||||||
|
for( int j = 0; j < src_gray.rows; j++ ) |
||||||
|
{ for( int i = 0; i < src_gray.cols; i++ ) |
||||||
|
{ |
||||||
|
float lambda_1 = myHarris_dst.at<float>( j, i, 0 ); |
||||||
|
float lambda_2 = myHarris_dst.at<float>( j, i, 1 ); |
||||||
|
Mc.at<float>(j,i) = lambda_1*lambda_2 - 0.04*pow( ( lambda_1 + lambda_2 ), 2 ); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal, 0, 0, Mat() ); |
||||||
|
|
||||||
|
/* Create Window and Trackbar */ |
||||||
|
namedWindow( myHarris_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
createTrackbar( " Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myHarris_function ); |
||||||
|
myHarris_function( 0, 0 ); |
||||||
|
|
||||||
|
/// My Shi-Tomasi -- Using cornerMinEigenVal |
||||||
|
myShiTomasi_dst = Mat::zeros( src_gray.size(), CV_32FC1 ); |
||||||
|
cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize, BORDER_DEFAULT ); |
||||||
|
|
||||||
|
minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal, 0, 0, Mat() ); |
||||||
|
|
||||||
|
/* Create Window and Trackbar */ |
||||||
|
namedWindow( myShiTomasi_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
createTrackbar( " Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function ); |
||||||
|
myShiTomasi_function( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function myShiTomasi_function */ |
||||||
|
void myShiTomasi_function( int, void* ) |
||||||
|
{ |
||||||
|
myShiTomasi_copy = src.clone(); |
||||||
|
|
||||||
|
if( myShiTomasi_qualityLevel < 1 ) { myShiTomasi_qualityLevel = 1; } |
||||||
|
|
||||||
|
for( int j = 0; j < src_gray.rows; j++ ) |
||||||
|
{ for( int i = 0; i < src_gray.cols; i++ ) |
||||||
|
{ |
||||||
|
if( myShiTomasi_dst.at<float>(j,i) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel ) |
||||||
|
{ circle( myShiTomasi_copy, Point(i,j), 4, Scalar( rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255) ), -1, 8, 0 ); } |
||||||
|
} |
||||||
|
} |
||||||
|
imshow( myShiTomasi_window, myShiTomasi_copy ); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function myHarris_function */ |
||||||
|
void myHarris_function( int, void* ) |
||||||
|
{ |
||||||
|
myHarris_copy = src.clone(); |
||||||
|
|
||||||
|
if( myHarris_qualityLevel < 1 ) { myHarris_qualityLevel = 1; } |
||||||
|
|
||||||
|
for( int j = 0; j < src_gray.rows; j++ ) |
||||||
|
{ for( int i = 0; i < src_gray.cols; i++ ) |
||||||
|
{ |
||||||
|
if( Mc.at<float>(j,i) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel ) |
||||||
|
{ circle( myHarris_copy, Point(i,j), 4, Scalar( rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255) ), -1, 8, 0 ); } |
||||||
|
} |
||||||
|
} |
||||||
|
imshow( myHarris_window, myHarris_copy ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
.. image:: images/My_Harris_corner_detector_Result.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
||||||
|
|
||||||
|
.. image:: images/My_Shi_Tomasi_corner_detector_Result.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 63 KiB |
@ -0,0 +1,122 @@ |
|||||||
|
.. _good_features_to_track: |
||||||
|
|
||||||
|
Shi-Tomasi corner detector |
||||||
|
************************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the function :good_features_to_track:`goodFeaturesToTrack <>` to detect corners using the Shi-Tomasi method. |
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
/// Global variables |
||||||
|
Mat src, src_gray; |
||||||
|
|
||||||
|
int maxCorners = 23; |
||||||
|
int maxTrackbar = 100; |
||||||
|
|
||||||
|
RNG rng(12345); |
||||||
|
char* source_window = "Image"; |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void goodFeaturesToTrack_Demo( int, void* ); |
||||||
|
|
||||||
|
/** |
||||||
|
* @function main |
||||||
|
*/ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
|
||||||
|
/// Create Trackbar to set the number of corners |
||||||
|
createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo ); |
||||||
|
|
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
goodFeaturesToTrack_Demo( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @function goodFeaturesToTrack_Demo.cpp |
||||||
|
* @brief Apply Shi-Tomasi corner detector |
||||||
|
*/ |
||||||
|
void goodFeaturesToTrack_Demo( int, void* ) |
||||||
|
{ |
||||||
|
if( maxCorners < 1 ) { maxCorners = 1; } |
||||||
|
|
||||||
|
/// Parameters for Shi-Tomasi algorithm |
||||||
|
vector<Point2f> corners; |
||||||
|
double qualityLevel = 0.01; |
||||||
|
double minDistance = 10; |
||||||
|
int blockSize = 3; |
||||||
|
bool useHarrisDetector = false; |
||||||
|
double k = 0.04; |
||||||
|
|
||||||
|
/// Copy the source image |
||||||
|
Mat copy; |
||||||
|
copy = src.clone(); |
||||||
|
|
||||||
|
/// Apply corner detection |
||||||
|
goodFeaturesToTrack( src_gray, |
||||||
|
corners, |
||||||
|
maxCorners, |
||||||
|
qualityLevel, |
||||||
|
minDistance, |
||||||
|
Mat(), |
||||||
|
blockSize, |
||||||
|
useHarrisDetector, |
||||||
|
k ); |
||||||
|
|
||||||
|
|
||||||
|
/// Draw corners detected |
||||||
|
cout<<"** Number of corners detected: "<<corners.size()<<endl; |
||||||
|
int r = 4; |
||||||
|
for( int i = 0; i < corners.size(); i++ ) |
||||||
|
{ circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0 ); } |
||||||
|
|
||||||
|
/// Show what you got |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, copy ); |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
.. image:: images/Shi_Tomasi_Detector_Result.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 80 KiB |
@ -0,0 +1,116 @@ |
|||||||
|
.. _harris_detector: |
||||||
|
|
||||||
|
Harris corner detector |
||||||
|
********************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the function :corner_harris:`cornerHarris <>` to detect corners using the Harris-Stephens method. |
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
/// Global variables |
||||||
|
Mat src, src_gray; |
||||||
|
int thresh = 200; |
||||||
|
int max_thresh = 255; |
||||||
|
|
||||||
|
char* source_window = "Source image"; |
||||||
|
char* corners_window = "Corners detected"; |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void cornerHarris_demo( int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
|
||||||
|
/// Create a window and a trackbar |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
cornerHarris_demo( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function cornerHarris_demo */ |
||||||
|
void cornerHarris_demo( int, void* ) |
||||||
|
{ |
||||||
|
|
||||||
|
Mat dst, dst_norm, dst_norm_scaled; |
||||||
|
dst = Mat::zeros( src.size(), CV_32FC1 ); |
||||||
|
|
||||||
|
/// Detector parameters |
||||||
|
int blockSize = 2; |
||||||
|
int apertureSize = 3; |
||||||
|
double k = 0.04; |
||||||
|
|
||||||
|
/// Detecting corners |
||||||
|
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT ); |
||||||
|
|
||||||
|
/// Normalizing |
||||||
|
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() ); |
||||||
|
convertScaleAbs( dst_norm, dst_norm_scaled ); |
||||||
|
|
||||||
|
/// Drawing a circle around corners |
||||||
|
for( int j = 0; j < dst_norm.rows ; j++ ) |
||||||
|
{ for( int i = 0; i < dst_norm.cols; i++ ) |
||||||
|
{ |
||||||
|
if( (int) dst_norm.at<float>(j,i) > thresh ) |
||||||
|
{ |
||||||
|
circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 ); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/// Showing the result |
||||||
|
namedWindow( corners_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( corners_window, dst_norm_scaled ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
The original image: |
||||||
|
|
||||||
|
.. image:: images/Harris_Detector_Original_Image.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
||||||
|
The detected corners are surrounded by a small black circle |
||||||
|
|
||||||
|
.. image:: images/Harris_Detector_Result.jpg |
||||||
|
:height: 200pt |
||||||
|
:align: center |
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 30 KiB |
@ -0,0 +1,126 @@ |
|||||||
|
.. _bounding_rects_circles: |
||||||
|
|
||||||
|
|
||||||
|
Creating Bounding boxes and circles for contours |
||||||
|
************************************************* |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :bounding_rect:`boundingRect <>` |
||||||
|
* Use the OpenCV function :min_enclosing_circle:`minEnclosingCircle <>` |
||||||
|
|
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
Mat src; Mat src_gray; |
||||||
|
int thresh = 100; |
||||||
|
int max_thresh = 255; |
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void thresh_callback(int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
|
||||||
|
/// Convert image to gray and blur it |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
blur( src_gray, src_gray, Size(3,3) ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback ); |
||||||
|
thresh_callback( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function thresh_callback */ |
||||||
|
void thresh_callback(int, void* ) |
||||||
|
{ |
||||||
|
Mat threshold_output; |
||||||
|
vector<vector<Point> > contours; |
||||||
|
vector<Vec4i> hierarchy; |
||||||
|
|
||||||
|
/// Detect edges using Threshold |
||||||
|
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY ); |
||||||
|
/// Find contours |
||||||
|
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); |
||||||
|
|
||||||
|
/// Approximate contours to polygons + get bounding rects and circles |
||||||
|
vector<vector<Point> > contours_poly( contours.size() ); |
||||||
|
vector<Rect> boundRect( contours.size() ); |
||||||
|
vector<Point2f>center( contours.size() ); |
||||||
|
vector<float>radius( contours.size() ); |
||||||
|
|
||||||
|
for( int i = 0; i < contours.size(); i++ ) |
||||||
|
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); |
||||||
|
boundRect[i] = boundingRect( Mat(contours_poly[i]) ); |
||||||
|
minEnclosingCircle( contours_poly[i], center[i], radius[i] ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// Draw polygonal contour + bonding rects + circles |
||||||
|
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); |
||||||
|
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 ); |
||||||
|
circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
/// Show in a window |
||||||
|
namedWindow( "Contours", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Contours", drawing ); |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
========== ========== |
||||||
|
|BRC_0| |BRC_1| |
||||||
|
========== ========== |
||||||
|
|
||||||
|
.. |BRC_0| image:: images/Bounding_Rects_Circles_Source_Image.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |BRC_1| image:: images/Bounding_Rects_Circles_Result.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,128 @@ |
|||||||
|
.. _bounding_rotated_ellipses: |
||||||
|
|
||||||
|
|
||||||
|
Creating Bounding rotated boxes and ellipses for contours |
||||||
|
********************************************************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :min_area_rect:`minAreaRect <>` |
||||||
|
* Use the OpenCV function :fit_ellipse:`fitEllipse <>` |
||||||
|
|
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
Mat src; Mat src_gray; |
||||||
|
int thresh = 100; |
||||||
|
int max_thresh = 255; |
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void thresh_callback(int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
|
||||||
|
/// Convert image to gray and blur it |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
blur( src_gray, src_gray, Size(3,3) ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback ); |
||||||
|
thresh_callback( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function thresh_callback */ |
||||||
|
void thresh_callback(int, void* ) |
||||||
|
{ |
||||||
|
Mat threshold_output; |
||||||
|
vector<vector<Point> > contours; |
||||||
|
vector<Vec4i> hierarchy; |
||||||
|
|
||||||
|
/// Detect edges using Threshold |
||||||
|
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY ); |
||||||
|
/// Find contours |
||||||
|
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); |
||||||
|
|
||||||
|
/// Find the rotated rectangles and ellipses for each contour |
||||||
|
vector<RotatedRect> minRect( contours.size() ); |
||||||
|
vector<RotatedRect> minEllipse( contours.size() ); |
||||||
|
|
||||||
|
for( int i = 0; i < contours.size(); i++ ) |
||||||
|
{ minRect[i] = minAreaRect( Mat(contours[i]) ); |
||||||
|
if( contours[i].size() > 5 ) |
||||||
|
{ minEllipse[i] = fitEllipse( Mat(contours[i]) ); } |
||||||
|
} |
||||||
|
|
||||||
|
/// Draw contours + rotated rects + ellipses |
||||||
|
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
// contour |
||||||
|
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); |
||||||
|
// ellipse |
||||||
|
ellipse( drawing, minEllipse[i], color, 2, 8 ); |
||||||
|
// rotated rectangle |
||||||
|
Point2f rect_points[4]; minRect[i].points( rect_points ); |
||||||
|
for( int j = 0; j < 4; j++ ) |
||||||
|
line( drawing, rect_points[j], rect_points[(j+1)%4], color, 1, 8 ); |
||||||
|
} |
||||||
|
|
||||||
|
/// Show in a window |
||||||
|
namedWindow( "Contours", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Contours", drawing ); |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
========== ========== |
||||||
|
|BRE_0| |BRE_1| |
||||||
|
========== ========== |
||||||
|
|
||||||
|
.. |BRE_0| image:: images/Bounding_Rotated_Ellipses_Source_Image.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |BRE_1| image:: images/Bounding_Rotated_Ellipses_Result.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,109 @@ |
|||||||
|
.. _find_contours: |
||||||
|
|
||||||
|
Finding contours in your image |
||||||
|
****************************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :find_contours:`findContours <>` |
||||||
|
* Use the OpenCV function :draw_contours:`drawContours <>` |
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
Mat src; Mat src_gray; |
||||||
|
int thresh = 100; |
||||||
|
int max_thresh = 255; |
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void thresh_callback(int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
|
||||||
|
/// Convert image to gray and blur it |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
blur( src_gray, src_gray, Size(3,3) ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback ); |
||||||
|
thresh_callback( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function thresh_callback */ |
||||||
|
void thresh_callback(int, void* ) |
||||||
|
{ |
||||||
|
Mat canny_output; |
||||||
|
vector<vector<Point> > contours; |
||||||
|
vector<Vec4i> hierarchy; |
||||||
|
|
||||||
|
/// Detect edges using canny |
||||||
|
Canny( src_gray, canny_output, thresh, thresh*2, 3 ); |
||||||
|
/// Find contours |
||||||
|
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); |
||||||
|
|
||||||
|
/// Draw contours |
||||||
|
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() ); |
||||||
|
} |
||||||
|
|
||||||
|
/// Show in a window |
||||||
|
namedWindow( "Contours", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Contours", drawing ); |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
============= ============= |
||||||
|
|contour_0| |contour_1| |
||||||
|
============= ============= |
||||||
|
|
||||||
|
.. |contour_0| image:: images/Find_Contours_Original_Image.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |contour_1| image:: images/Find_Contours_Result.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,118 @@ |
|||||||
|
.. _hull: |
||||||
|
|
||||||
|
Convex Hull |
||||||
|
*********** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :convex_hull:`convexHull <>` |
||||||
|
|
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
Mat src; Mat src_gray; |
||||||
|
int thresh = 100; |
||||||
|
int max_thresh = 255; |
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void thresh_callback(int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
|
||||||
|
/// Convert image to gray and blur it |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
blur( src_gray, src_gray, Size(3,3) ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback ); |
||||||
|
thresh_callback( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function thresh_callback */ |
||||||
|
void thresh_callback(int, void* ) |
||||||
|
{ |
||||||
|
Mat src_copy = src.clone(); |
||||||
|
Mat threshold_output; |
||||||
|
vector<vector<Point> > contours; |
||||||
|
vector<Vec4i> hierarchy; |
||||||
|
|
||||||
|
/// Detect edges using Threshold |
||||||
|
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY ); |
||||||
|
|
||||||
|
/// Find contours |
||||||
|
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); |
||||||
|
|
||||||
|
/// Find the convex hull object for each contour |
||||||
|
vector<vector<Point> >hull( contours.size() ); |
||||||
|
for( int i = 0; i < contours.size(); i++ ) |
||||||
|
{ convexHull( Mat(contours[i]), hull[i], false ); } |
||||||
|
|
||||||
|
/// Draw contours + hull results |
||||||
|
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); |
||||||
|
drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); |
||||||
|
} |
||||||
|
|
||||||
|
/// Show in a window |
||||||
|
namedWindow( "Hull demo", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Hull demo", drawing ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
========== ========== |
||||||
|
|Hull_0| |Hull_1| |
||||||
|
========== ========== |
||||||
|
|
||||||
|
.. |Hull_0| image:: images/Hull_Original_Image.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |Hull_1| image:: images/Hull_Result.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,136 @@ |
|||||||
|
.. _moments: |
||||||
|
|
||||||
|
|
||||||
|
Image Moments |
||||||
|
************** |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :moments:`moments <>` |
||||||
|
* Use the OpenCV function :contour_area:`contourArea <>` |
||||||
|
* Use the OpenCV function :arc_length:`arcLength <>` |
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
Mat src; Mat src_gray; |
||||||
|
int thresh = 100; |
||||||
|
int max_thresh = 255; |
||||||
|
RNG rng(12345); |
||||||
|
|
||||||
|
/// Function header |
||||||
|
void thresh_callback(int, void* ); |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Load source image and convert it to gray |
||||||
|
src = imread( argv[1], 1 ); |
||||||
|
|
||||||
|
/// Convert image to gray and blur it |
||||||
|
cvtColor( src, src_gray, CV_BGR2GRAY ); |
||||||
|
blur( src_gray, src_gray, Size(3,3) ); |
||||||
|
|
||||||
|
/// Create Window |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
|
||||||
|
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback ); |
||||||
|
thresh_callback( 0, 0 ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** @function thresh_callback */ |
||||||
|
void thresh_callback(int, void* ) |
||||||
|
{ |
||||||
|
Mat canny_output; |
||||||
|
vector<vector<Point> > contours; |
||||||
|
vector<Vec4i> hierarchy; |
||||||
|
|
||||||
|
/// Detect edges using canny |
||||||
|
Canny( src_gray, canny_output, thresh, thresh*2, 3 ); |
||||||
|
/// Find contours |
||||||
|
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); |
||||||
|
|
||||||
|
/// Get the moments |
||||||
|
vector<Moments> mu(contours.size() ); |
||||||
|
for( int i = 0; i < contours.size(); i++ ) |
||||||
|
{ mu[i] = moments( contours[i], false ); } |
||||||
|
|
||||||
|
/// Get the mass centers: |
||||||
|
vector<Point2f> mc( contours.size() ); |
||||||
|
for( int i = 0; i < contours.size(); i++ ) |
||||||
|
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); } |
||||||
|
|
||||||
|
/// Draw contours |
||||||
|
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() ); |
||||||
|
circle( drawing, mc[i], 4, color, -1, 8, 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
/// Show in a window |
||||||
|
namedWindow( "Contours", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Contours", drawing ); |
||||||
|
|
||||||
|
/// Calculate the area with the moments 00 and compare with the result of the OpenCV function |
||||||
|
printf("\t Info: Area and Contour Length \n"); |
||||||
|
for( int i = 0; i< contours.size(); i++ ) |
||||||
|
{ |
||||||
|
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) ); |
||||||
|
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); |
||||||
|
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() ); |
||||||
|
circle( drawing, mc[i], 4, color, -1, 8, 0 ); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
========== ========== ========== |
||||||
|
|MU_0| |MU_1| |MU_2| |
||||||
|
========== ========== ========== |
||||||
|
|
||||||
|
.. |MU_0| image:: images/Moments_Source_Image.jpg |
||||||
|
:width: 250pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |MU_1| image:: images/Moments_Result1.jpg |
||||||
|
:width: 250pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |MU_2| image:: images/Moments_Result2.jpg |
||||||
|
:width: 250pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 9.8 KiB |
@ -0,0 +1,119 @@ |
|||||||
|
.. _point_polygon_test: |
||||||
|
|
||||||
|
Point Polygon Test |
||||||
|
******************* |
||||||
|
|
||||||
|
Goal |
||||||
|
===== |
||||||
|
|
||||||
|
In this tutorial you will learn how to: |
||||||
|
|
||||||
|
.. container:: enumeratevisibleitemswithsquare |
||||||
|
|
||||||
|
* Use the OpenCV function :point_polygon_test:`pointPolygonTest <>` |
||||||
|
|
||||||
|
|
||||||
|
Theory |
||||||
|
====== |
||||||
|
|
||||||
|
Code |
||||||
|
==== |
||||||
|
|
||||||
|
This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp>`_ |
||||||
|
|
||||||
|
.. code-block:: cpp |
||||||
|
|
||||||
|
#include "opencv2/highgui/highgui.hpp" |
||||||
|
#include "opencv2/imgproc/imgproc.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
/** @function main */ |
||||||
|
int main( int argc, char** argv ) |
||||||
|
{ |
||||||
|
/// Create an image |
||||||
|
const int r = 100; |
||||||
|
Mat src = Mat::zeros( Size( 4*r, 4*r ), CV_8UC1 ); |
||||||
|
|
||||||
|
/// Create a sequence of points to make a contour: |
||||||
|
vector<Point2f> vert(6); |
||||||
|
|
||||||
|
vert[0] = Point( 1.5*r, 1.34*r ); |
||||||
|
vert[1] = Point( 1*r, 2*r ); |
||||||
|
vert[2] = Point( 1.5*r, 2.866*r ); |
||||||
|
vert[3] = Point( 2.5*r, 2.866*r ); |
||||||
|
vert[4] = Point( 3*r, 2*r ); |
||||||
|
vert[5] = Point( 2.5*r, 1.34*r ); |
||||||
|
|
||||||
|
/// Draw it in src |
||||||
|
for( int j = 0; j < 6; j++ ) |
||||||
|
{ line( src, vert[j], vert[(j+1)%6], Scalar( 255 ), 3, 8 ); } |
||||||
|
|
||||||
|
/// Get the contours |
||||||
|
vector<vector<Point> > contours; vector<Vec4i> hierarchy; |
||||||
|
Mat src_copy = src.clone(); |
||||||
|
|
||||||
|
findContours( src_copy, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); |
||||||
|
|
||||||
|
/// Calculate the distances to the contour |
||||||
|
Mat raw_dist( src.size(), CV_32FC1 ); |
||||||
|
|
||||||
|
for( int j = 0; j < src.rows; j++ ) |
||||||
|
{ for( int i = 0; i < src.cols; i++ ) |
||||||
|
{ raw_dist.at<float>(j,i) = pointPolygonTest( contours[0], Point2f(i,j), true ); } |
||||||
|
} |
||||||
|
|
||||||
|
double minVal; double maxVal; |
||||||
|
minMaxLoc( raw_dist, &minVal, &maxVal, 0, 0, Mat() ); |
||||||
|
minVal = abs(minVal); maxVal = abs(maxVal); |
||||||
|
|
||||||
|
/// Depicting the distances graphically |
||||||
|
Mat drawing = Mat::zeros( src.size(), CV_8UC3 ); |
||||||
|
|
||||||
|
for( int j = 0; j < src.rows; j++ ) |
||||||
|
{ for( int i = 0; i < src.cols; i++ ) |
||||||
|
{ |
||||||
|
if( raw_dist.at<float>(j,i) < 0 ) |
||||||
|
{ drawing.at<Vec3b>(j,i)[0] = 255 - (int) abs(raw_dist.at<float>(j,i))*255/minVal; } |
||||||
|
else if( raw_dist.at<float>(j,i) > 0 ) |
||||||
|
{ drawing.at<Vec3b>(j,i)[2] = 255 - (int) raw_dist.at<float>(j,i)*255/maxVal; } |
||||||
|
else |
||||||
|
{ drawing.at<Vec3b>(j,i)[0] = 255; drawing.at<Vec3b>(j,i)[1] = 255; drawing.at<Vec3b>(j,i)[2] = 255; } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Create Window and show your results |
||||||
|
char* source_window = "Source"; |
||||||
|
namedWindow( source_window, CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( source_window, src ); |
||||||
|
namedWindow( "Distance", CV_WINDOW_AUTOSIZE ); |
||||||
|
imshow( "Distance", drawing ); |
||||||
|
|
||||||
|
waitKey(0); |
||||||
|
return(0); |
||||||
|
} |
||||||
|
|
||||||
|
Explanation |
||||||
|
============ |
||||||
|
|
||||||
|
Result |
||||||
|
====== |
||||||
|
|
||||||
|
#. Here it is: |
||||||
|
|
||||||
|
========== ========== |
||||||
|
|PPT_0| |PPT_1| |
||||||
|
========== ========== |
||||||
|
|
||||||
|
.. |PPT_0| image:: images/Point_Polygon_Test_Source_Image.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
||||||
|
.. |PPT_1| image:: images/Point_Polygon_Test_Result.jpg |
||||||
|
:height: 300pt |
||||||
|
:align: middle |
||||||
|
|
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 14 KiB |