• Opecv检测多个圆形(霍夫圆检测,轮廓面积筛选,C/C++)


    主要是利用霍夫圆检测、面积筛选等完成多个圆形检测,具体代码及结果如下。
    第一部分是头文件(common.h):

    #pragma once
    #include
    #include
    #include
    
    using namespace std;
    using namespace cv;
    
    extern Mat src;
    void imageBasicInformation(Mat& src);//图像基本信息
    
    const Mat houghCirclePre(Mat& srcPre);//霍夫圆检测预处理
    void  houghCircle(Mat& srcPreHough);//霍夫圆检测
    const Mat RectCirclePre(Mat& srcPre);//面积筛选拟合圆的预处理
    void AreaCircles(Mat& AreaInput);//面积筛选拟合圆检测
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    第二部分是主函数:

    #include"common.h"
    Mat src;
    int main()
    {
        src = imread("1.jpg",1);
        if (src.empty())
        {
            cout << "图像不存在!" << endl;
        }
        else
        {
            namedWindow("原图", 1);
            imshow("原图", src);
            imageBasicInformation(src);
            Mat srcPreHough = houghCirclePre(src);
            houghCircle(srcPreHough);
    
            Mat RectCir = RectCirclePre(src);
            AreaCircles(RectCir);
            waitKey(0);
            destroyAllWindows();
        }
        return 0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    第三部分为霍夫圆检测函数(hough.cpp)
    主要包括输出图像的基本信息函数:void imageBasicInformation(Mat& src)
    霍夫圆检测预处理函数:const Mat houghCirclePre(Mat& srcPre)
    霍夫圆检测函数:void houghCircle(Mat& srcPreHough)

    #include"common.h"
    
    Mat graySrc, srcPre;//灰度图,霍夫检测预处理,
    Mat threshold_grayaSrc;//二值化图
    Mat erode_threshold_graySrc, dilate_threshold_graySrc;//二值化后腐蚀,二值化后膨胀
    
    void imageBasicInformation(Mat& src)
    {
        int cols = src.cols;
        int rows = src.rows;
        int channels = src.channels();
        cout << "图像宽为:" << cols << endl;
        cout << "图像高为:" << rows << endl;
        cout << "图像通道数:" << channels << endl;
    }
    
    const Mat houghCirclePre(Mat& srcPre)
    {
        double houghCirclePreTime = static_cast<double>(getTickCount());
    
        cvtColor(srcPre, graySrc, COLOR_BGR2GRAY);
        GaussianBlur(graySrc, graySrc, Size(3, 3), 2, 2);//滤波
        threshold(graySrc, threshold_grayaSrc, 150, 255, 1);//二值化
       
        Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
        dilate(threshold_grayaSrc, dilate_threshold_graySrc, element);//膨胀
        erode(dilate_threshold_graySrc, erode_threshold_graySrc, element);//腐蚀
        houghCirclePreTime = ((double)getTickCount() - houghCirclePreTime) / getTickFrequency();
        cout << "霍夫圆预处理时间为:" << houghCirclePreTime << "秒" << endl;
        return erode_threshold_graySrc;
    }
    
    void houghCircle(Mat& srcPreHough)
    {
        cout << "进入霍夫圆检测" << endl;
        vector<Vec3f> circles;
        HoughCircles(srcPreHough, circles, HOUGH_GRADIENT, 1, 60, 1, 35, 0, 0);
        cout << "圆的个数" << circles.size() << endl;
        for (size_t i = 0;i < circles.size();i++)
        {
            Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
            int radius = cvRound(circles[i][2]);
            circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);//画圆心
            circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);//画圆
        }
        namedWindow("霍夫检测结果", 0);
        imshow("霍夫检测结果", src);
        imwrite("霍夫圆检测结果.jpg", src);//保存检测结果
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    第四部分为利用面积筛选拟合圆检测(AreaCircle.cpp)
    主要包括预处理函数:const Mat RectCirclePre(Mat& srcPre)
    面积筛选拟合圆检测函数:void AreaCircles(Mat& AreaInput)

    #include"common.h"
    
    Mat graySrcArea, thresholdGraySrc;//灰度图像,二值化图像
    Mat dilateThresholdGraySrc, erodeThresholdGraySrc;//二值化后膨胀图像,膨胀之后的腐蚀图像
    
    const Mat RectCirclePre(Mat& srcPre)
    { 
    	cvtColor(srcPre, graySrcArea, COLOR_BGR2GRAY);
    	GaussianBlur(graySrcArea, graySrcArea, Size(3, 3), 2, 2);
    	threshold(graySrcArea, thresholdGraySrc, 100, 255, 1);//二值化,阈值要根据自己的图像自己调整
    	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
    	dilate(thresholdGraySrc, dilateThresholdGraySrc, element);//膨胀
    	erode(dilateThresholdGraySrc, erodeThresholdGraySrc, element);//腐蚀
    	
    	return erodeThresholdGraySrc;
    }
    
    void AreaCircles(Mat& AreaInput)
    {
    	vector<vector<Point>> RectContours;
    	vector<Vec4i> Hierarchy;
    	findContours(AreaInput, RectContours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    	Mat drawing = Mat::zeros(src.size(), CV_8UC3);
    
    	for (int i = 0;i < RectContours.size();i++)
    	{
    		double area = contourArea(RectContours[i]);
    		cout << area << endl;//输出所有计算出来的面积,方便下一步设置阈值
    		if (area > 15000 && area < 100000)//根据上一步计算的阈值设置范围
    		{
    			drawContours(drawing, RectContours, i, Scalar(0, 255, 0), 2,8, Hierarchy, 0, Point());
    			RotatedRect Rect = fitEllipse(RectContours[i]);
    			circle(src, Rect.center, 2, Scalar(0, 255, 0), 2, 8, 0);//在原图画出圆心
    			ellipse(src, Rect, Scalar(0, 0, 255), 2);//在原图画出轮廓
    		}
    	}
    	namedWindow("面积筛选拟合圆", 0);
    	imshow("面积筛选拟合圆", src);
    	imwrite("面积筛选拟合圆.jpg", src);//保存检测结果
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    结果如下(自己画的两个圆):
    原图:
    在这里插入图片描述

    以下为霍夫圆检测结果:
    在这里插入图片描述
    以下为面积筛选拟合圆结果:
    在这里插入图片描述

  • 相关阅读:
    Java | 选择排序算法实现
    学习笔记——斯坦纳树
    【Java并发编程 】线程同步机制和锁的相关介绍
    最具有中国特色的微服务组件,阿里新一代SpringCloud学习指南
    (51单片机)第四章-键盘检测原理及应用实现-矩阵键盘检测
    【数据结构】堆和优先级队列
    java后端返回给前端不为空的属性
    【C++初阶7-string】真方便,真舒服
    有哪些设计原则
    JAVA毕业设计105—基于Java+Springboot+Vue的校园跑腿系统(源码+数据库)
  • 原文地址:https://blog.csdn.net/weixin_45718019/article/details/126196955