opencv学习(四十二)之多边形包围图像轮廓

来源:互联网 发布:改变 知乎 编辑:程序博客网 时间:2024/05/22 18:23

首先介绍一个逼近多边形的函数approxPolyDP(),其定义如下:

void cv::approxPolyDP   (   InputArray  curve,                            OutputArray     approxCurve,                            double  epsilon,                            bool    closed                         )   

函数作用是用指定精度逼近多边形曲线
curve:输入的二维点集,可以是vector类型或Mat类型
approxCurve:多边形逼近的结果,其类型与输入的点集类型一致
epsilon:逼近的精度,为原始曲线和逼近曲线间的最大值
closed:如果为true,逼近的曲线为封闭曲线,如果为false则逼近曲线不封闭

1.使用矩形和最小圆包围图像

使用boundingRect()函数计算包围轮廓的矩形框,使用minEnclosingCircle()函数计算包围轮廓的最小圆包围

boundingRect()
函数计算并返回点集最外面的矩形边界,其函数定义如下:

cv::boundingRect    (   InputArray  points  )   

minEnclosingCircle()
利用迭代算法,对给定的二维点集寻找计算可包围点集的最小圆形,其定义如下

void cv::minEnclosingCircle (   InputArray  points,                                Point2f &   center,                                float &     radius                             )

参数解释:

points:输入的二维点集,数据类型为vector<>或Mat类型
center:绘制圆的圆心坐标
radius:圆的半径

示例代码

#include <iostream>#include <opencv2\core\core.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>using namespace std;using namespace cv;//定义全局变量Mat srcImage, grayImage;int thresh = 100;const int threshMaxValue = 255;RNG rng(12345);//声明回调函数void thresh_callback(int, void*);int main(){    srcImage = imread("bundingRect_1.jpg");    //判断图像是否加载成功    if (srcImage.empty())    {        cout << "图像加载失败!";        return -1;    }    else        cout << "图像加载成功!" << endl << endl;    cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);    blur(grayImage, grayImage, Size(3, 3));    namedWindow("原图像", WINDOW_AUTOSIZE);    imshow("原图像", grayImage);    //创建轨迹条    createTrackbar("Thresh:", "原图像", &thresh, threshMaxValue, thresh_callback);    thresh_callback(thresh, 0);    waitKey(0);    return 0;}void thresh_callback(int, void*){    Mat threshold_output;    vector<vector<Point>>contours;    vector<Vec4i>hierarchy;    //图像二值化检测边缘    threshold(grayImage, threshold_output, thresh, 255, THRESH_BINARY);    //寻找图像轮廓    findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));    //使用多边形逼近检测到的图像轮廓来寻找包围轮廓的矩形和最小圆    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((Mat)contours_poly[i], center[i], radius[i]);    }    //绘制检测到的图像轮廓、矩形和最小包围圆    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());        /*Rect类中tl表示top_left即左上角的点,br表示bottom_right即右下方的点*/        rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);        circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);    }    namedWindow("轮廓图", WINDOW_AUTOSIZE);    imshow("轮廓图", drawing);}

运行结果:

2.使用旋转的矩形和椭圆包围图像轮廓

minAreaRect()

cv::minAreaRect (   InputArray  points  )   

对于输入的二维点集,计算包围点集的最小矩形

fitEllipse()

cv::fitEllipse  (   InputArray  points  )   

根据输入的二维点集使用椭圆拟合方法包围二维点集

示例代码

#include <iostream>#include <opencv2\core\core.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>using namespace std;using namespace cv;//定义全局变量Mat srcImage, grayImage;int thresh = 100;const int threshMaxValue = 255;RNG rng(12345);//声明回调函数void thresh_callback(int, void*);int main(){    srcImage = imread("bundingRect_1.jpg");    //判断图像是否加载成功    if (srcImage.empty())    {        cout << "图像加载失败!";        return -1;    }    else        cout << "图像加载成功!" << endl << endl;    cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);    blur(grayImage, grayImage, Size(3, 3));    namedWindow("原图像", WINDOW_AUTOSIZE);    imshow("原图像", grayImage);    //创建轨迹条    createTrackbar("Thresh:", "原图像", &thresh, threshMaxValue, thresh_callback);    thresh_callback(thresh, 0);    waitKey(0);    return 0;}void thresh_callback(int, void*){    Mat threshold_output;    vector<vector<Point>>contours;    vector<Vec4i>hierarchy;    //图像二值化检测边缘    threshold(grayImage, threshold_output, thresh, 255, THRESH_BINARY);    //寻找图像轮廓    findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));    //为每个轮廓寻找旋转的矩形和椭圆    vector<RotatedRect>minRect(contours.size());    vector<RotatedRect>minEllipse(contours.size());    //如果轮廓上的点大于5个则用椭圆填充    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]));        }    }    //绘制检测到的图像轮廓、旋转矩形和椭圆    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());        ellipse(drawing, minEllipse[i], color, 2, 8);        //旋转矩形        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);        }    }    namedWindow("轮廓图", WINDOW_AUTOSIZE);    imshow("轮廓图", drawing);}

运行结果:


此外还有最小三角包围轮廓函数minEnclosingTriangle(),请自行查阅

5 0
原创粉丝点击