/**

 * @function findContours_Demo.cpp
 * @brief Demo code to find contours in an image
 * @author OpenCV team
 */

#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;                        // scollbar預設值(門檻值)   
int max_thresh = 255;                    // scrollbar上限(max value)
RNG rng(12345);                          // Random Number Generator, 參考core.hpp

/// Function header
void thresh_callback(int, void* );       // 門檻回呼函式

/**
 * @function main
 */
int main( int arg, char** argv )
{
  /// Load source image and convert it to gray
     const char* filename = arg == 2 ? argv[1] : "sample.jpg";      
    src = imread(filename, 1 );

  /// Convert image to gray and blur it
  cvtColor( src, src_gray, CV_BGR2GRAY );      // 轉灰階
  blur( src_gray, src_gray, Size(3,3) );             // 模糊化

  /// Create Window
  const char* source_window = "Source";
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );  // CV_WINDOW_AUTOSIZE:使用者無法調整視窗大小
  imshow( source_window, src );

  createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );/* createTrackbar(scrollbar名稱,
                                                                                                       視窗標題,
                                                                                                       scrollbar預設值,
                                                                                                       scrollbar上限值,
                                                                                                       回呼函式)
                                                                                     */
  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 );

  namedWindow( "Canny", CV_WINDOW_AUTOSIZE );     // Canny output
  imshow( "Canny", canny_output );

  /// 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 );   // contour 輸出
  Mat drawing;
  src.copyTo(drawing);
 
  for( size_t i = 0; i< contours.size(); i++ )
     {
       Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
       drawContours( drawing, contours, (int)i, color, 3, 8, hierarchy, 0, Point() );
       /*
           void drawContours( InputOutputArray image,
                              InputArrayOfArrays contours,
                              int contourIdx,
                              const Scalar& color,
                              int thickness=1,
                              int lineType=8,
                              InputArray hierarchy=noArray(),
                              int maxLevel=INT_MAX,
                              Point offset=Point() );
       */
     }

  /// Show in a window
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );
}

範例程式sample code: find contour VS2010 OpenCV2.4.6

C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())

image: 為影像來源其格式8 bit 1 channel, 經過簡單的二值化: 非零數值視為1, 零值仍為0

          可以是下列函式處理後的矩陣, compare() , inRange() , threshold() , adaptiveThreshold() , Canny()

contours: 記錄每一個輪廓, 單一輪廓由多個點所構成的向量

如何取出每個輪廓contour的點座標呢? 

for(int i= 0; i < contours.size(); i++)
  {
      cout << "-------contour " << i << "-------";
      for(int j=0; j < contours[i].size(); j++)
      {
          cout << "[" << j << "]" << ": (" << contours[i][j].x << "," << contours[i][j].y << ")" << endl ; //do whatever
      }
      cout << endl;
  }

hierarchy: 影像拓樸(image topology)資訊, 跟contours數量一樣

如何取出每個hierarchy的四維資訊呢? 

 cout << "hierarchy個數 = " << hierarchy.size() << endl;
 for(int i=0; i < hierarchy.size(); i++)
 cout << "[" << i << "]= " << hierarchy[i][0] << ", " << hierarchy[i][1] << ", " << hierarchy[i][2] << ", " << hierarchy[i][3] << endl;
 

For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next[column:0] and previous[column:1] contours at the same hierarchical level, the first child contour[column:2] and the parent contour[column:3]

 

contour & hierarchy.txt

------------------------------------------------------------------------------------------------------------------------------------

Parameters:

  • image – Source, an 8-bit single-channel image. Non-zero pixels are treated as 1’s. Zero pixels remain 0’s, so the image is treated as binary . You can use compare() , inRange() , threshold() , adaptiveThreshold() , Canny() , and others to create a binary image out of a grayscale or color one. The function modifies the image while extracting the contours.
  • contours – Detected contours. Each contour is stored as a vector of points.
  • hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.
  • mode

    Contour retrieval mode (if you use Python see also a note below).

    • CV_RETR_EXTERNAL retrieves only the extreme outer contours. It sets hierarchy[i][2]=hierarchy[i][3]=-1 for all the contours.
    • CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships.
    • CV_RETR_CCOMP retrieves all of the contours and organizes them into a two-level hierarchy. At the top level, there are external boundaries of the components. At the second level, there are boundaries of the holes. If there is another contour inside a hole of a connected component, it is still put at the top level.
    • CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours. This full hierarchy is built and shown in the OpenCV contours.c demo.
  • method

    Contour approximation method (if you use Python see also a note below).

    • CV_CHAIN_APPROX_NONE stores absolutely all the contour points. That is, any 2 subsequent points (x1,y1) and (x2,y2) of the contour will be either horizontal, vertical or diagonal neighbors, that is, max(abs(x1-x2),abs(y2-y1))==1.
    • CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.
    • CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS applies one of the flavors of the Teh-Chin chain approximation algorithm. See [TehChin89] for details.
  • offset – Optional offset by which every contour point is shifted. This is useful if the contours are extracted from the image ROI and then they should be analyzed in the whole image context.

 參考文獻:Topological structural analysis of digitized binary images by border following

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()