Contour correlation algorithm

Posted by marf on Tue, 07 Sep 2021 05:57:34 +0200

Contour detection refers to the detection of object boundaries in an image, more focused on the upper semantic objects.For example, the findContours() function in OpenCV gets each contour and stores it as a point vector. In addition, it gets the topological information of an image, that is, the index number of the last contour, the previous contour, the parent contour and the embedded contour of a contour.

1. Code,

#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
  src = imread( argv[1], 1 );

  ///Convert to grayscale and blur noise reduction
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3) );

  ///Create Form
  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;

  ///Use Canny operator to detect edges
  Canny( src_gray, canny_output, thresh, thresh*2, 3 );
  ///Find Outline
  findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
First parameter: image,A single-channel image matrix, which can be a grayscale image, but is more commonly a binary image, typically through Canny,Laplace Equilateral
                     Binary image processed by edge detection operator;

Second parameter: contours,Defined as " vector<vector<Point>> contours",Is a vector, and is a double vector, a vector
           Within each element a set of consecutive elements is saved Point The vector of the set of points made up of points, each group Point A point set is a contour.  
           How many contours, vectors contours How many elements are there.

Third parameter: hierarchy,Defined as " vector<Vec4i> hierarchy",Take a look first Vec4i Definition:
                           typedef    Vec<int, 4>   Vec4i;                                                                                                                                       
           Vec4i yes Vec<int,4>An alias that defines a vector in which each element contains four int Vector of type variable.

           So by definition, hierarchy It is also a vector in which each element holds one containing four int An array of integers.
           vector hiararchy Elements and outline vectors within contours The elements within are one-to-one, and the capacity of the vectors is the same.
           hierarchy Four for each element in a vector int Type variable-- hierarchy[i][0] ~hierarchy[i][3],Individually denotes
        i The index number of the last contour, the previous contour, the parent contour, and the inline contour of each contour.If the current outline does not correspond to the next one
        Contour, previous contour, parent contour, or inline contour hierarchy[i][0] ~hierarchy[i][3]The corresponding bit is set to
        Default value-1. 

Fourth parameter: int Type mode,Retrieval modes that define contours:

           Value one: CV_RETR_EXTERNAL Only the periphery outline is detected, and the inner outline contained within the periphery outline is ignored

           Value two: CV_RETR_LIST   Detects all contours, including the inner and outer contours, but the detected contours do not establish a hierarchical level.
                  System, independent of each other, has no hierarchical relationship, which means there is no parent or embedded contour in this retrieval mode.
                  therefore hierarchy The third and fourth components of all elements in a vector are set to-1,As you will see below

           Value three: CV_RETR_CCOMP  All contours are detected, but only two hierarchical relationships are established for all contours, with the periphery at the top, if the periphery
                  The inner contour also contains other contour information, so all contours within the inner contour belong to the top level

           Value four: CV_RETR_TREE, All outlines are detected and a hierarchical tree structure is established for all outlines.Outer outline contains inner outline, inner outline
                   Layer outlines can also continue to contain embedded outlines.

Fifth parameter: int Type method,Approximate methods for defining contours:

           Value one: CV_CHAIN_APPROX_NONE Save all contour points on the boundary of the object to contours Within Vector

           Value two: CV_CHAIN_APPROX_SIMPLE Save only the inflection point information of the contour, and save all the points at the inflection point of the contour contours
                   Within a vector, information points on the straight line between the inflection point and the inflection point are not preserved

           Value three and four: CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS Use teh-Chinl chain near
                   Similar algorithm

Sixth parameter: Point Offset, the amount by which all contour information is offset from the corresponding points in the original image, equal to adding at each detected contour point
            The offset above, and Point It can also be negative!


  ///outline
  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() );
     }

  ///Display results in the form
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );
}

2. Definition of outline convex hull

Convex Hull is a concept in computational geometry (graphics).
In a real vector space V, for a given set X, the intersection S of all convex sets containing X is called the convex hull of X.The convex hull of X can be constructed by a convex combination of all points (X1,... Xn) in X.
In two-dimensional Euclidean space, a convex hull can be imagined as a rubber ring enclosing exactly all points.
In an imprecise way, given a point set on a two-dimensional plane, a convex hull is a convex polygon that connects the outermost points together and contains all the points in the point set.

#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
   src = imread( argv[1], 1 );

   ///Convert to grayscale and blur noise reduction
   cvtColor( src, src_gray, CV_BGR2GRAY );
   blur( src_gray, src_gray, Size(3,3) );

   ///Create Form
   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;

   ///Binarize the image
   threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );

   ///Find Outline
   findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

   ///Calculate its convex hull for each contour
   vector<vector<Point> >hull( contours.size() );
   for( int i = 0; i < contours.size(); i++ )
      {  convexHull( Mat(contours[i]), hull[i], false ); }
First parameter: the set of points entered, which can be Mat Type matrix, or it can be std::vector<point>Point container for

The second parameter can be vector<int>,This returns the index of each convex hull point in the container of the origin outline point, or vector<Point>,The location of the convex hull point is stored here,Point ( x,y)Coordinates.

Third parameter: bool Variable indicating whether the output convex hull is clockwise or counterclockwise. true Is clockwise,false Is counterclockwise, the default is true,That is, output convex hull clockwise.

Fourth parameter: bool Type variable returnPoints,Represents the output type of the second parameter, which defaults to true,That is to return the points of the convex hull, set to false Represents the index that returns the points of the convex hull.When the second parameter type is std::vector,Then this flag bit is ignored, that is, it takes the second parameter as the criterion, that is vector<int>,This returns the index of each convex hull point in the container of the origin outline point, which is vector<Point>Then, the location of the convex hull point is stored,Point ( x,y)Coordinates.

   ///Draw outlines and their convex hulls
   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 results in form
   namedWindow( "Hull demo", CV_WINDOW_AUTOSIZE );
   imshow( "Hull demo", drawing );
 }

3. Create rectangular and circular bounding boxes around outlines

Create rectangular and circular bounding boxes around outlines

using namespace cv;
using namespace std;

Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

///Function declaration
void thresh_callback(int, void* );

/** @Principal function */
int main( int argc, char** argv )
{
  ///Load original image, return 3-channel image
  src = imread( argv[1], 1 );

  ///Convert to grayscale image and smooth
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3) );

  ///Create a 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);
}

/** @thresh_callback function */
void thresh_callback(int, void* )
{
  Mat threshold_output;
  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;

  ///Use Threshold to detect edges
  threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
  ///Find Outline
  findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

  ///Polygon approximates contour + Get rectangular and circular bounding boxes
  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 outline + surrounded rectangular box + circular box
  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 );
}

4. Contour Moment

using namespace cv;
using namespace std;

Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

///Function declaration
void thresh_callback(int, void* );

/** @Principal function */
int main( int argc, char** argv )
{
  ///Read in the original image and return 3 channels of image data
  src = imread( argv[1], 1 );

  ///Convert the original image to grayscale and smooth it
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3) );

  ///Create a new 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);
}

/** @thresh_callback function */
void thresh_callback(int, void* )
{
  Mat canny_output;
  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;

  ///Use Canndy to detect edges
  Canny( src_gray, canny_output, thresh, thresh*2, 3 );
  ///Find Outline
  findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

  ///Calculate Moment
  vector<Moments> mu(contours.size() );
  for( int i = 0; i < contours.size(); i++ )
     { mu[i] = moments( contours[i], false ); }

  ///Calculate center moment:
  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 window
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );

  ///Calculate contour area from m00 and compare with 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 );
     }
}

1) Moment finding

Moments moments(inputArray array, bool binaryImage=false)
Input parameters, which can be raster images (single channel, two-dimensional arrays of 8 bits or floating points) or two-dimensional arrays (1N or N1)
The default value is false, and if this parameter is true, all non-zero pixels are 1. This parameter is used only for images
(2) Calculating contour area

double contourArea(inputArray contour, bool oriented=false)
Input vector, 2-D point (outline vertex)
Area-oriented identifier, if true, returns a signed area value that is positive or negative depending on the direction of the outline (clockwise or counterclockwise).Based on this feature, we can determine the position of the outline by the area symbol.It is important to note that this parameter has a default value of false, meaning it is returned as an absolute value, unsigned.
(3) Calculating the outline length

double arcLength(inputArray curve,bool closed)
Input two-dimensional point set
An identifier indicating whether a curve is closed or not, the default is closed, indicating that the curve is closed

4. About Several Moments

Point2d center(m.m10 / m.m00, m.m01 / m.m00); //This is the focus
double a = m.m20 / m.m00 - center.xcenter.x;
double b = m.m11 / m.m00 - center.xcenter.y;
double c = m.m02 / m.m00 - center.y*center.y;
Double theta = fastAtan2 (2 * b, (a - c))/ 2; //This is the direction of the shape
The angle returned by fastAtan2() refers to the angle clockwise from the positive x-axis to the image axis in a natural coordinate system
Note: Direction is defined by the axis of the image

5. The relationship between points and outlines

The pointPolygonTest checks if the point is within the contour:
C++: double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)
When measureDist is set to true, the actual distance value is returned.If the return value is positive, the point is inside the polygon, the return value is negative, the return value is outside the polygon, the return value is 0, the return value is on the polygon.When measureDist is set to false, three fixed values - 1, 0, 1 are returned.If the return value is + 1, the point is inside the polygon, and the return value is -1, which is outside the polygon, and the return value is 0, which is on the polygon.

Topics: OpenCV Algorithm