C++opencv找圆心?看着一篇,一定有你要(边缘轮廓检测,拟合,凸包)找出相应的轮廓或者全部轮廓画外界圆轮廓并且标出轮廓中心

这篇具有很好参考价值的文章主要介绍了C++opencv找圆心?看着一篇,一定有你要(边缘轮廓检测,拟合,凸包)找出相应的轮廓或者全部轮廓画外界圆轮廓并且标出轮廓中心。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一,利用面积对轮廓进行筛选

注意这种面积筛选有一个弊端就是比如有两个轮廓,

A轮廓为500

B轮廓为300

当面积设置为 area<400时就可以筛选出面积小于300的所有轮廓

反之大于300的轮廓 如果有两个圆轮廓一大一小,可能就只能保留一个了

如果知道这两个形状的轮廓面积,或许可以利用 逻辑与  进行筛选。

效果图

opencv找圆,c++,opencv,计算机视觉

//圆心
#include<iostream>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    //载入图像
    Mat src = imread("D:\\Besktop\\faimage\\Image\\21_25_27.bmp");
    Mat src_clone = src.clone();
    if (src.empty()) 
    {
        cout << "图片为空" << endl;
        return 0;
    }
    imshow("src", src);
    //转灰度图
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    //图像二值化
    threshold(gray, gray, 0, 255, THRESH_BINARY | THRESH_OTSU);
    imshow("threshold", gray);
    //执行形态学开操作去除噪点
    /*Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3), Point(-1, -1));
    morphologyEx(gray, gray, MORPH_OPEN, kernel, Point(-1, -1), 1);
    imshow("morphologyEx", gray);*/

    //边缘检测
    Canny(gray, gray, 0, 255);
    Mat graycanny;
    resize(gray, graycanny, Size(600, 600));
    imshow("canny", graycanny);

    //轮廓发现
    vector<vector<Point>> contours;
    vector<Vec4i> her;
    findContours(gray, contours, her, RETR_TREE, CHAIN_APPROX_SIMPLE);
    //获取某一轮廓重心点
    Moments M;
    M = moments(contours[0]);
    double cX = double(M.m10 / M.m00);
    double cY = double(M.m01 / M.m00);

    //Mat resultImage = Mat::zeros(gray.size(), CV_8UC3);
    RNG rng(12345);
    double area = 0.0;
    Point pRadius;
    for (int i = 0; i < contours.size(); i++) {
        double area = contourArea(contours[i], false);
        //根据面积及纵横比过滤轮廓
        if (area > 200) {
            Rect rect = boundingRect(contours[i]);
            float scale = float(rect.width) / float(rect.height);
            if (scale < 1 && scale>0) {
                drawContours(gray, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), -1);
                int x = rect.width / 2;
                int y = rect.height / 2;
                //找出圆心并绘制
                pRadius = Point(rect.x + x, rect.y + y);
                circle(gray, pRadius, 15, Scalar(0, 0, 255), 15);
            }
            
        }
    }
    Mat graycanny1;
    resize(gray, graycanny1, Size(600, 600));
    imshow("resultImage", graycanny1);
    //imshow("resultImage", resultImage);
    //在原图上绘制圆心
    circle(src_clone, pRadius, 15, Scalar(0, 0, 255), 15);
    cout << "圆心坐标:" << cX << "" << cY << endl;
    //cout <<"[x,y]" << pRadius << endl;
    Mat graycanny2;
    resize(src_clone, graycanny2, Size(600, 600));
    imshow("src_clone", graycanny2);
    //imshow("src_clone", src_clone);
    waitKey(0);
    return 0;
}

二,利用边缘检测和轮廓筛选找出轮廓

这一种则是利用轮廓的中心点对轮廓进行拟合,从而达到寻找轮廓

opencv找圆,c++,opencv,计算机视觉

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    Mat img = imread("D:\\Besktop\\faimage\\测试原图\\22_21_27.bmp");
    //String dest = "D:\\Besktop\\1\\";
    /*string path = "D:\\Besktop\\faimage\\测试原图\\";
    String dest = "D:\\Besktop\\1\\";
    String savedfilename;
    int len = path.length();
    vector<cv::String> filenames;
    cv::glob(path, filenames);
    for (int i = 0; i < filenames.size(); i++)
    
        Mat frame;
        frame = imread(filenames[i], i);
        savedfilename = dest + filenames[i].substr(len);*/
     
        Mat gray_img, thresh_img;
        //灰度
        cvtColor(img, gray_img, COLOR_BGR2GRAY);
        threshold(gray_img, thresh_img, 0, 255, THRESH_TRIANGLE);
        //开运算
        Mat ellipse = getStructuringElement(MORPH_ELLIPSE, Size(13, 13));
        morphologyEx(thresh_img, thresh_img, MORPH_OPEN, ellipse, Point(-1, -1), 2);

        //寻找轮廓
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy1;
        findContours(thresh_img, contours, hierarchy1, RETR_LIST, CHAIN_APPROX_NONE, Point());

        //获取某一轮廓重心点
        Moments M;
        M = moments(contours[0]);
        double cX = double(M.m10 / M.m00);
        double cY = double(M.m01 / M.m00);
        //绘制轮廓
        drawContours(img, contours, 0, Scalar(0, 255, 0), 2, 8, hierarchy1);
        //显示轮廓重心并提取坐标点
        circle(img, Point2d(cX, cY), 6, Scalar(0, 255, 0), 2, 8);

        namedWindow("Center Point", CV_WINDOW_NORMAL);
        imshow("Center Point", img);
        //imwrite("D:\\Besktop\\1\\22_21_27.bmp", img);
        putText(img, "center", Point2d(cX - 20, cY - 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);
        cout << "重心坐标:" << cX << " " << cY << endl << endl;
        waitKey(0);
    
    return 0;
}

三,这一种方法类似于第一种的面积筛选唯一不同的时候增加了几步形态学处理

 opencv找圆,c++,opencv,计算机视觉

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//第二步 通过面积过滤,通过纵横比的测量,圆形的纵横比应该在1:1左右,如果不是1:1,就把它过滤掉
Mat srcImg, binaryImg, dstImg;
void test()
{
    srcImg = imread("D:\\Besktop\\faimage\\Image\\21_25_27.bmp", IMREAD_GRAYSCALE);
    if (srcImg.empty())
    {
        cout << "could not load image...\n" << endl;
    }
    namedWindow("Original image", CV_WINDOW_NORMAL);  //CV_WINDOW_NORMAL 使得鼠标可以控制显示窗口的大小
    imshow("Original image", srcImg);

    //二值化
    threshold(srcImg, binaryImg, 0, 255, THRESH_BINARY | THRESH_OTSU);
    namedWindow("Binary Result", CV_WINDOW_NORMAL);
    imshow("Binary Result", binaryImg);

    //形态学操作,开操作,去掉小的对象,闭操作,连接里面的洞(开闭操作要先获得结构元素)
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));  //Point(-1, -1)是中心点,这里是 2 x 2位置
    morphologyEx(binaryImg, dstImg, MORPH_CLOSE, kernel, Point(-1, -1));
    namedWindow("Close Result", CV_WINDOW_NORMAL);
    imshow("Close Result", dstImg);

    kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
    morphologyEx(dstImg, dstImg, MORPH_OPEN, kernel, Point(-1, -1));
    namedWindow("Open Result", CV_WINDOW_NORMAL);
    imshow("Open Result", dstImg);

    //轮廓发现
    vector<vector<Point>> contours;  //存储轮廓
    vector<Vec4i> hireachy;
    findContours(dstImg, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

    //通过面积过滤,通过纵横比的测量,圆形的纵横比应该在1:1左右,如果不是1:1,就把它过滤掉
    Mat resultImg = Mat::zeros(srcImg.size(), CV_8SC3);
    Point cc;
    for (int i = 0; i < contours.size(); i++)
    {
        //面积过滤
        double area = contourArea(contours[i]);  //循环获取指定的面积
        if (area < 100)  //通过循环过滤掉小于100的面积
            continue;
        //横纵比过滤
        Rect rect = boundingRect(contours[i]);
        float ratio = float(rect.width) / float(rect.height);
        if (ratio < 1.1 && ratio> 0.9)  //把满足条件的保留画出来
        {
            drawContours(resultImg, contours, i, Scalar(0, 0, 255), -1, 8, Mat(), 0, Point());  //画出来 第五个参数改为 -1 ,使得整个圆形填充
            cout << "circle area: " << area << endl;  //面积和周长打印出来(像素度量)
            cout << "circle length: " << arcLength(contours[i], true) << endl;

            //找中心点
            int x = rect.x + rect.width / 2;
            int y = rect.y + rect.height / 2;
            cc = Point(x, y);
            circle(resultImg, cc, 2, Scalar(0, 0, 255), 2, 8, 0);  //画出中心点
        }
    }
    namedWindow("Final Result", CV_WINDOW_NORMAL);
    imshow("Final Result", resultImg);

    //在原图上定位显示中心点
    Mat circleImg = srcImg.clone();
    cvtColor(circleImg, circleImg, COLOR_GRAY2BGR);
    circle(circleImg, cc, 20, Scalar(0, 0, 255), 2, 8, 0);

    namedWindow("Center Point", CV_WINDOW_NORMAL);
    imshow("Center Point", circleImg);
}

int main()
{
    test();
    waitKey(0);
    return 0;
}

这三种方法都是opencv中的一些方法,有任何建议和问题均可评论区提问,说不定你的建议正是我疑惑的地方!!!

四,利用轮廓拟合的方法对图片中的某个轮廓进行拟合(这里主要是圆心)

此方法运行环境为opencv4.5.5

opencv找圆,c++,opencv,计算机视觉

 相关代码

#if 1
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // 读取图片
    Mat src = imread("图片路径");

    // 转换为灰度图
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);

    // 进行边缘检测
    Mat edge;
    Canny(gray, edge, 100, 200);

    // 圆形拟合
    vector<Vec3f> circles;
    HoughCircles(edge, circles, HOUGH_GRADIENT, 1, edge.rows / 16, 100, 30, 10, 50);

    // 绘制圆形和圆心
    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, radius, Scalar(0, 0, 255), 2);
        circle(src, center, 3, Scalar(0, 255, 0), -1);
    }

    // 显示结果
    namedWindow("src", WINDOW_NORMAL);
    imshow("src", src);
    waitKey(0);

    return 0;
}

#endif // 1

五,这种是利用凸包 对圆形进行拟合并且将所有的轮廓都绘制外界圆

opencv4.5.5

opencv找圆,c++,opencv,计算机视觉

 代码

#if 1
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // 读取图片
    Mat img = imread("图片路径");

    // 转换为灰度图
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);

    // 进行二值化处理
    Mat thresh;
    threshold(gray, thresh, 128, 255, THRESH_BINARY);

    // 找到所有轮廓
    vector<vector<Point>> contours;
    findContours(thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // 遍历轮廓,找到圆形轮廓
    for (size_t i = 0; i < contours.size(); i++)
    {
        // 只考虑凸包
        vector<Point> hull;
        convexHull(contours[i], hull);

        // 尝试将轮廓拟合为圆形
        Point2f center;
        float radius;
        //bool isCircle = fitCircle(hull, center, radius);
        minEnclosingCircle(hull, center, radius);
        cout << center.x << "," << center.y << endl;
        // 标出圆心
        circle(img, center, 5, Scalar(0, 255, 0), -1);
        // 绘制圆形
        circle(img, center, radius, Scalar(0, 0, 255), 2);

    }
    // 显示结果
    Mat ss;
    resize(img, ss, Size(600, 600));
    imshow("Contours", ss);
    waitKey();
}
#endif // 0

有问题欢迎评论区讨论文章来源地址https://www.toymoban.com/news/detail-675107.html

到了这里,关于C++opencv找圆心?看着一篇,一定有你要(边缘轮廓检测,拟合,凸包)找出相应的轮廓或者全部轮廓画外界圆轮廓并且标出轮廓中心的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++如何用OpenCV中实现图像的边缘检测和轮廓提取?

    主要实现代码:

    2024年02月07日
    浏览(40)
  • 数字图像处理【11】OpenCV-Canny边缘提取到FindContours轮廓发现

    本章主要介绍图像处理中一个比较基础的操作:Canny边缘发现、轮廓发现 和 绘制轮廓。概念不难,主要是结合OpenCV 4.5+的API相关操作,为往下 \\\"基于距离变换的分水岭图像分割\\\" 做知识储备。 在讲述轮廓之前,要花点时间学学边缘检测提取的一个著名算法——Canny边缘提取算法

    2024年02月16日
    浏览(41)
  • 【Ai工具合集,一定有你需要的!】

    花费了一天的时间测试了市面上各大Ai工具,然后帮大家整理总结出来了这些工具,一定记得点赞收藏保存,后面肯定会用到! 1.部分Ai工具需要魔法上网,请自行解决;部分工具需要收费,可以尝试用chatgpt代替这些功能 2.下列总结的Ai工具均已测试筛选,剔除掉了很多不实用

    2024年02月05日
    浏览(37)
  • 十大开源测试工具和框架,一定有你需要的

    目录 前言 Katalon Studio Selenium Appium JMeter SOAP UI Robot Framework Watir JUnit Robotium Citrus 总结 免费的开源框架和工具由于其开源特性,现在逐渐成为自动化测试的首选解决方案。区别在于,你是喜欢使用类库编写一个全新的自动化测试框架,或者喜欢使用一个现成的工具。   Katalon

    2024年02月16日
    浏览(46)
  • JSX看着一篇足以入门

    JSX 介绍 学习目标: 能够理解什么是 JSX,JSX 的底层是什么 概念: JSX 是 javaScriptXML(HTML) 的缩写,表示在 JS 代码中书写 HTML 结构 作用: 在 React 中创建 HTML 结构(页面 UI 结构) 优势:  1. 采用类似 HTML 的语法,降低学习成本,会 HTML 就会 JSX  2. 充分利用 JS 自生的可编程能

    2024年02月08日
    浏览(36)
  • OpenCV找出图片中的圆并标注圆心

    案例:输入一张图片找到图片中的一个圆,并标注圆心 实现步骤: 1.输入原图 2.图像图像灰度化 3.图像二值化 4.执行形态学操作去除噪点 5.边缘检测 6.轮廓发现 7.根据面积和纵横比过滤目标轮廓 8.找出圆心并绘制圆心 9.在原图上也绘制圆心并输出   本文福利, 莬 费领取Qt开

    2024年02月11日
    浏览(38)
  • AI:164- python获取图像边缘轮廓

    本文收录于专栏:精通AI实战千例专栏合集 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 每一个案例都附带关键代码,详细讲解供大家学习,希望可以帮到大家。正在不断更新中~ 在图像处理中,边缘检测是

    2024年04月26日
    浏览(22)
  • Halcon中亚像素边缘,轮廓提取处理的各种方法

    在图像处理中,提取图像特征主要从两个角度,区域或者边缘。提取亚像素边缘有三种思路,提取过后再用边缘模板匹配,连接与分割都可以。这里不涉及边缘对用作视觉测量类的算子,仅对刚学习halcon的新人而言。 这幅图代表着在项目的过程中使用边缘的三种思路。之前某

    2024年02月14日
    浏览(34)
  • c# OpenCvSharp 检测(斑点检测、边缘检测、轮廓检测)(五)

    在C#中使用OpenCV进行图像处理时,可以使用不同的算法和函数来实现斑点检测、边缘检测和轮廓检测。 斑点检测 边缘检测 轮廓检测 斑点检测是指在图像中找到明亮或暗的小区域(通常表示为斑点),并标记它们的位置。可以使用OpenCV中的函数SimpleBlobDetector来实现斑点检测。

    2024年02月04日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包