• OpenCV函数:提取轮廓相关函数使用方法


    opencv中提供findContours()函数来寻找图像中物体的轮廓,并结合drawContours()函数将找到的轮廓绘制出。首先看一下findContours(),opencv中提供了两种定义形式

    官网:https://docs.opencv.org/3.3.1/d3/dc0/group__imgproc__shape.html#ga17ed9f5d79ae97bd4c7cf18403e1689a 

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

      

    #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)
    {
    	/// 加载源图像
    	src = imread("E:\VS2015Opencv\vs2015\project\picture\07.jpg", 1);
    
    	/// 转成灰度并模糊化降噪
    	cvtColor(src, src_gray, CV_BGR2GRAY);
    	blur(src_gray, src_gray, Size(3, 3));
    
    	/// 创建窗体
    	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;
    
    	/// 用Canny算子检测边缘
    	Canny(src_gray, canny_output, thresh, thresh * 2, 3);
    	/// 寻找轮廓
    	findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    
    	/// 绘出轮廓
    	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());
    	}
    
    	/// 在窗体中显示结果
    	namedWindow("Contours", CV_WINDOW_AUTOSIZE);
    	imshow("Contours", drawing);
    }
    

      

    OpenCV提取轮廓之后,还可以进行许多操作:

    ArcLength()                计算轮廓长度 
    ContourArea()            计算轮廓区域的面积 
    BoundingRect()          轮廓的外包矩形 
    ConvexHull()              提取轮廓的凸包 
    IsContourConvex()     测试轮廓的凸性 
    MinAreaRect()            轮廓的最小外包矩形 
    MinEnclosingCircle()  轮廓的最小外包圆
    fitEllipse()                   用椭圆拟合二维点集
    approxPolyDP()          逼近多边形曲线

    boundingRect函数简介

    boundingRect函数是用来计算轮廓的最小外接矩形,通常与findContours函数组合使用,findContours函数用来查找图像的轮廓,boundingRect获取轮廓的最小外接矩形!

    Rect boundingRect( InputArray array );

    (1) 第一个参数,InputArray array,一般为findContours函数查找的轮廓,包含轮廓的点集或者Mat;

    (2) 返回值,Rect,返回值为最小外接矩形的Rect,即左上点与矩形的宽度和高度;

    #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);
    
    /// 函数声明
    void thresh_callback(int, void*);
    
    /** @主函数 */
    int main(int argc, char** argv)
    {
    	/// 载入原图像, 返回3通道图像
    	src = imread("E:\VS2015Opencv\vs2015\project\picture\1.1.jpg", 1);
    
    	/// 转化成灰度图像并进行平滑
    	cvtColor(src, src_gray, CV_BGR2GRAY);
    	blur(src_gray, src_gray, Size(3, 3));
    
    	/// 创建窗口
    	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 函数 */
    void thresh_callback(int, void*)
    {
    	Mat threshold_output;
    	vector<vector<Point> > contours;
    	vector<Vec4i> hierarchy;
    
    	/// 使用Threshold检测边缘
    	threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
    	/// 找到轮廓
    	findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_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(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());
    		rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
    		circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);
    	}
    
    	/// 显示在一个窗口
    	namedWindow("Contours", CV_WINDOW_AUTOSIZE);
    	imshow("Contours", drawing);
    }
    

     

    minAreaRect()

    作用:找到一个能包围输入二维点集的面积最小的任意方向矩形。

    形式:minAreaRect(InputArray points);

    参数:points:输入二维点集,并用std::vector or Mat存储;

    fitEllipse()

    作用:寻找一个适合的围绕二维点集的椭圆。

    形式:fitEllipse(InputArray points);

    参数:points:输入二维点集,并用std::vector or Mat存储;

    ellipse()

    作用:画一个简单的或明显的椭圆弧,或填充一个椭圆部分。

    形式:void ellipse(Mat& img, const RotatedRect& box, const Scalar& color, int thickness=1, int lineType=8);

    或void ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

    参数:

    img:输入的图像;

    box:通过RotatedRect or CvBox2D选择椭圆代表,也就是在任意方向矩阵中镶嵌一个椭圆;

    后边三个参数分别是:颜色、边线粗细、边线的类型;

    #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)
    {
        /// 加载源图像
        src = imread("E:\VS2015Opencv\vs2015\project\picture\01.jpg");
    
        /// 转为灰度图并模糊化
        cvtColor(src, src_gray, CV_BGR2GRAY);
        blur(src_gray, src_gray, Size(3, 3));
    
        /// 创建窗体
        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;
    
        /// 阈值化检测边界
        threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
        /// 寻找轮廓
        findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    
        /// 对每个找到的轮廓创建可倾斜的边界框和椭圆
        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]));
            }
        }
    
        /// 绘出轮廓及其可倾斜的边界框和边界椭圆
        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);
        }
    
        /// 结果在窗体中显示
        namedWindow("Contours", CV_WINDOW_AUTOSIZE);
        imshow("Contours", drawing);
    }

     本文参考:OpenCV函数:提取轮廓相关函数使用方法

  • 相关阅读:
    函数模板、函数模板特化、重载函数模板、非模板函数重载
    输出流格式化(以操纵子方式格式化,以ios类成员函数方式格式化)
    文件的读写、二进制文件的读写、文件随机读写
    文件流(fstream, ifstream, ofstream)的打开关闭、流状态
    流类库继承体系(IO流,文件流,串流)和 字符串流的基本操作
    对象语义与值语义、资源管理(RAII、资源所有权)、模拟实现auto_ptr<class>、实现Ptr_vector
    operator new 和 operator delete 实现一个简单内存泄漏跟踪器
    异常与继承、异常与指针、异常规格说明
    程序错误、异常(语法、抛出、捕获、传播)、栈展开
    C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
  • 原文地址:https://www.cnblogs.com/fcfc940503/p/11314091.html
Copyright © 2020-2023  润新知