OpenCV2马拉松第24圈——轮廓提取

计算机视觉讨论群162501053


收入囊中
  • 在图片中找到轮廓而且描绘轮廓
  • 使用多边形。圆,椭圆来逼近我们的轮廓

OpenCV2马拉松第24圈——轮廓提取

OpenCV2马拉松第24圈——轮廓提取



葵花宝典

关于轮廓提取,几乎相同是一个连通域的推断。

原理还是比較简单的。




初识API

C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())
 
  • image – 灰度图片.非0像素都被觉得是1.会被改动.
  • contours – 每个被检測到的轮廓都是points的集合
  • hierarchy – 可选输出, 跟轮廓数量大小一样.对每个contours[i]来说 ,hierarchy[i][0] , hiearchy[i][1] 分别表示与contours[i]同level的下一个。前一个轮廓索引hiearchy[i][2] , andhiearchy[i][3]分别表示contours[i]的子轮廓和父轮廓索引。

    假设不存在

    hierarchy[i] will be negative.
  • mode –
    • CV_RETR_EXTERNAL 仅仅获得最外面的轮廓,也就是说全部轮廓的hierarchy[i][2]=hierarchy[i][3]=-1 .
    • CV_RETR_LIST 获得全部的轮廓,无hierarchy
    • 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 获得全部的轮廓,并输出hierarchy组织
  • method –
    • CV_CHAIN_APPROX_NONE 保存全部的点。max(abs(x1-x2),abs(y2-y1))==1.也就是说,不论什么轮廓上的两个点都处在一个九宫格内.
    • CV_CHAIN_APPROX_SIMPLE 进行了简单的水平竖直对角线压缩.对于一个矩形,仅仅保留了4个顶点. 
    • CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS  [TehChin89]
  • offset – 可选的轮廓位移.当分析图片ROI比較实用.
OpenCV2马拉松第24圈——轮廓提取

找到轮廓后。就能够用drawContours画出来
#include "cv.h"
#include "highgui.h"

using namespace cv;

int main( int argc, char** argv )
{
    Mat src;
    // the first command-line parameter must be a filename of the binary
    // (black-n-white) image
    if( argc != 2 || !(src=imread(argv[1], 0)).data)
        return -1;

    Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);

    src = src > 1;
    namedWindow( "Source", 1 );
    imshow( "Source", src );

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    findContours( src, contours, hierarchy,
        CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    // iterate through all the top-level contours,
    // draw each connected component with its own random color
    int idx = 0;
    for( ; idx >= 0; idx = hierarchy[idx][0] )
    {
        Scalar color( rand()&255, rand()&255, rand()&255 );
        drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
    }

    namedWindow( "Components", 1 );
    imshow( "Components", dst );
    waitKey(0);
}

我们能够用矩形包围轮廓
cv::Rect r0= cv::boundingRect(cv::Mat(contours[0]));
cv::rectangle(result,r0,cv::Scalar(0),2);</span>

也能够用圆
float radius;
cv::Point2f center;
cv::minEnclosingCircle(cv::Mat(contours[1]),center,radius);
cv::circle(result,cv::Point(center),static_cast<int>(radius),cv::Scalar(0),2);

OpenCV2马拉松第24圈——轮廓提取     OpenCV2马拉松第24圈——轮廓提取


也能够用多边形
std::vector<cv::Point> poly;
cv::approxPolyDP(cv::Mat(contours[2]), poly, 5,  true); 
OpenCV2马拉松第24圈——轮廓提取最左边那个

也能够用还有一种多边形模拟convex hull
std::vector<cv::Point> hull;
cv::convexHull(cv::Mat(contours[3]),hull);

OpenCV2马拉松第24圈——轮廓提取       OpenCV2马拉松第24圈——轮廓提取

也能够用最小外接矩形
vector<RotatedRect> minRect( contours.size() );
for( int i = 0; i < contours.size(); i++ ) {
    minRect[i] = minAreaRect( Mat(contours[i]) );
}


也能够用椭圆
vector<RotatedRect> minEllipse( contours.size() );
for( int i = 0; i < contours.size(); i++ )
    if( contours[i].size() > 5 )
        minEllipse[i] = fitEllipse( Mat(contours[i]) ); 

OpenCV2马拉松第24圈——轮廓提取

OpenCV2马拉松第24圈——轮廓提取



还有非常多好用的函数

cv::contourArea  预计一个轮廓的像素数

cv::pointPolygonTest确定一个点是在轮廓内韩式轮廓外

cv::matchShapes度量两个轮廓的相似度

还有cv::moments用于计算重心等信息


荷枪实弹

參考1-轮廓提取 http://docs.opencv.org/master/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html#find-contours

參考2-convexhull逼近 http://docs.opencv.org/master/doc/tutorials/imgproc/shapedescriptors/hull/hull.html#hull

參考3-圆与矩形逼近 http://docs.opencv.org/master/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html

參考4-最小外接矩形与椭圆逼近 http://docs.opencv.org/master/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.html#bounding-rotated-ellipses