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

news2025/1/19 20:39:08

最近有个项目需要做细孔定位和孔距测量,需要做边缘检测和轮廓提取,先看初步效果图:

主要实现代码:


int MainWindow::Test()
{
    // 2.9 单个像素长度um  5倍
    double dbUnit = 2.9/(1000*5);

    // 定义显示窗口
    namedWindow("src", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    namedWindow("threshold", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    namedWindow("morphologyEx x1", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    namedWindow("morphologyEx x2", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    namedWindow("canny", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    namedWindow("dst", WINDOW_NORMAL|WINDOW_KEEPRATIO);
    resizeWindow("src", 1080,720);
    resizeWindow("threshold", 1080,720);
    resizeWindow("morphologyEx x1", 1080,720);
    resizeWindow("morphologyEx x2", 1080,720);
    resizeWindow("canny", 1080,720);
    resizeWindow("dst", 1080,720);

    //【1】载入图像
    Mat src = imread("0.28um+5x.jpg");  
    Mat src_clone = src.clone();
    if(src.empty()){
        qDebug()<<"图片为空";
        return 1;
    }
    imshow("src",src);
    //【2】转灰度图
    Mat gray;
    cvtColor(src,gray,COLOR_BGR2GRAY);

    //imshow("gray",gray);

    //【3】图像二值化
    threshold(gray,gray,130,190,THRESH_BINARY);
    imshow("threshold",gray);

    //【4】执行形态学开操作去除噪点
    Mat kernel = getStructuringElement(MORPH_RECT,Size(15,15),Point(-1,-1));
    morphologyEx(gray,gray,MORPH_CLOSE,kernel,Point(-1,-1),1);
    imshow("morphologyEx x1",gray);

    //【4】执行形态学开操作去除噪点
    Mat kernel1 = getStructuringElement(MORPH_RECT,Size(10,10),Point(-1,-1));
    morphologyEx(gray,gray,MORPH_CLOSE,kernel1,Point(-1,-1),1);
    imshow("morphologyEx x2",gray);

    //【5】边缘检测
    Canny(gray,gray,0,255);
    imshow("canny",gray);

    //【6】轮廓发现
    vector<vector<Point>> contours;
    vector<Vec4i> her;
    findContours(gray,contours,her,RETR_TREE,CHAIN_APPROX_SIMPLE);

    Mat srcImg = src;
    //拟合椭圆:fitEllipse()
    vector<RotatedRect> box(contours.size());
    Point2f rect[4];
    for (int i = 0; i<contours.size(); i++)
    {
        Rect rect = boundingRect(contours[i]);

        Point2f pRadius;
        if(contours[i].size()>105){
            box[i] = fitEllipse(Mat(contours[i]));

            //条件过滤
            if( box[i].size.aspectRatio()<0.8||box[i].size.area()>10000000||rect.width<300 )
                continue;

            float majorAxis = std::max(box[i].size.width, box[i].size.height);

            rectangle(srcImg,rect,Scalar(0, 0, 255));

            ellipse(srcImg, box[i], Scalar(255, 0, 0), 1, 8);

            float x = rect.width/2.0;
            float y = rect.height/2.0;
            //【8】找出圆心并绘制
            pRadius=Point2f(rect.x+x,rect.y+y);
           
            cv::String det_info = cv::format("[%d] %.1f,%.1f(%dx%d),%.5f mm, %.5f mm",i,
            pRadius.x, pRadius.y, rect.width, rect.height,dbUnit*rect.width, dbUnit*majorAxis);


            cv::Point bbox_points;
            bbox_points = cv::Point(rect.x, rect.y);
            bbox_points = cv::Point(rect.x + det_info.size() * 11, rect.y);
            bbox_points = cv::Point(rect.x + det_info.size() * 11, rect.y - 15);
            bbox_points = cv::Point(rect.x, rect.y - 15);

            cv::putText(srcImg, det_info, bbox_points, cv::FONT_HERSHEY_DUPLEX, 0.4, cv::Scalar(255, 255, 255), 1, cv::LINE_AA);

            circle(srcImg,pRadius,1,Scalar(0,0,255),1);

            pRadius=box[i].center;
            circle(srcImg,pRadius,1,Scalar(255,0,0),1);

        }
    }
    // 绘制结果
    imshow("dst", srcImg);
    // 保存结果
    imwrite("dst.png", srcImg);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/828939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

控件旋转90度,并跟随大小缩放

控件旋转角度&#xff0c;并跟随缩放改变大小 背景使用控件结果 背景 一个项目需求&#xff0c;需要旋转某个控件90使用&#xff0c;在网上找了很多资料&#xff0c;没有特别合适的&#xff0c;自己试水试了一天半&#xff0c;终于弄了个大概其&#xff0c;特此记录 使用控件…

机器学习笔记之优化算法(七)线搜索方法(步长角度;非精确搜索;Wolfe Condition)

机器学习笔记之优化算法——线搜索方法[步长角度&#xff0c;非精确搜索&#xff0c;Wolfe Condition] 引言回顾&#xff1a; Armijo \text{Armijo} Armijo准则及其弊端 Glodstein \text{Glodstein} Glodstein准则及其弊端 Wolfe Condition \text{Wolfe Condition} Wolfe Condi…

CDH基于Kerberos开启身份验证实践总结

CDH基于Kerberos开启身份验证实践总结 前言简介Kerberos是什么Kerberos解决什么问题 Kerberos基本概念Kerberos认证流程Kerberos基本配置principalkeytabkrb5.confkdc.confkadm5.aclkerberos数据库 访问示例数据库访问信息 其他kerberos常用命令[Git Bash支持make命令](https:/…

在线餐饮油烟实时监测系统的设计与实现

安科瑞 华楠 摘 要&#xff1a;为了解决传统油烟检测方法中成本高、效率低、实时性差等问题&#xff0c;设计开发了一种在线油烟实时监测系统&#xff1b;系统由采集、通讯、服务器和用户交互四个模块组成&#xff1b;采集模块采集油烟数据&#xff0c;通过GPRS通讯技术将数据发…

13.元素尺寸与位置

原理&#xff1a;通过js的方式&#xff0c;得到元素在页面中的位置 13.1 元素尺寸与位置-尺寸 1.获取宽高: ●获取元素的自身宽高、包含元素自身设置的宽高、padding、border ● offsetWidth和offsetHeight ●获取出来的是数值&#xff0c;方便计算 ●注意&#xff1a;获取的…

基于DCT变换和huffman编码的语音压缩算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 多通道滤波 4.2 DCT变换 4.3 量化 4.3 哈夫曼编码 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................…

HTTP杂谈之Referer和Origin请求头再探

一 关于Referer和Origin的汇总 1) 知识是凌乱的,各位看官看个热闹即可2) 内容不断更新1、理解有盲区,需要及时纠正2、内容交叉有重复,需要适当删减3、扩展视野3) 以下内容都与Referer和Origin请求头有关联 nginx防盗链 HTTP杂谈之Referrer-Policy响应头 iframe标签referre…

go练习 day01

DTO: note_dto.go package dtoimport "king/model"type NoteAddDTO struct {ID uintTitle string json:"title" form:"title" binding:"required" message:"标题不能为空"Content string json:"conten…

青少年软件编程(Python六级)等级考试试卷(2022年9月)

青少年软件编程&#xff08;Python六级&#xff09;等级考试试卷&#xff08;2022年9月&#xff09; 第 1 题 单选题 以下关于Python二维数据的描述中&#xff0c;错误的是&#xff1f;&#xff08; &#xff09; A. 表格数据属于二维数据&#xff0c;由整数索引的数据构成 …

[自学记录05|百人计划]Early-Z和Z-Prepass

其实这篇我是不想写的&#xff0c;因为网上资料真的非常非常多很多人都写过&#xff0c;但是我后来想了想&#xff0c;做笔记不就是这样吗&#xff0c;所以就写吧~。前置知识&#xff1a;深度测试Z-Buffer[计算机图形学]可见性与遮挡,Z-Buffer(前瞻预习/复习回顾)__Yhisken的博…

Vue 自定义事件绑定与解绑

绑定自定义事件 说到 Vue 自定义事件&#xff0c;那就需要搞清楚一个问题&#xff0c;为啥有这个玩意。 说到自定义事件之前&#xff0c;需要理解 组件基础的概念。理解了基础概念之后&#xff0c;我们就知道 Vue 的父子之间的通信&#xff0c; 一是 父组件通过 Prop 向子组件…

CK_Label_V1 CK_Label_V9 CK_Label_V11 System Developer‘s Manual

一、Register PTL You should register the PTL to our Management System first&#xff1b; 1、Register CK_Label_V1 Quickly press the side button three times Register ok&#xff1a;The led will turn off after flashing red light and the buzzer will beep once…

一个3年Android的找工作记录

作者&#xff1a;Petterp 这是我最近 1个月 的找工作记录&#xff0c;希望这些经历对你会有所帮助。 有时机会就像一阵风&#xff0c;如果没有握住&#xff0c;那下一阵风什么时候吹来&#xff0c;往往是个运气问题。 写在开始 先说背景: 自考本&#xff0c;3年经验&#xff0…

【JVM】(二)深入理解Java类加载机制与双亲委派模型

文章目录 前言一、类加载过程1.1 加载&#xff08;Loading&#xff09;1.2 验证&#xff08;Verification&#xff09;1.3 准备&#xff08;Preparation&#xff09;1.4 解析&#xff08;Resolution&#xff09;1.5 初始化&#xff08;Initialization&#xff09; 二、双亲委派…

在线/开源GNSS处理软件/平台介绍

当前&#xff0c;存在较多的GNSS开源/免费软件&#xff0c;可用于质量检核、RTK解算和PPP解算等&#xff0c;本文总结了部分常用的处理软件&#xff0c;其详细信息如表1和表2所示。 表1 常用GNSS预处理&#xff08;格式转换、质量检核&#xff09;软件&#xff1a; 软件名称 …

RunnerGo五种压测模式你会配置吗

我们在做性能测试时需要根据性能需求配置不同的压测模式如&#xff1a;阶梯模式。使用jmeter时我们需要安装插件来配置测试模式&#xff0c;为了方便用户使用&#xff0c;RunnerGo内嵌了压测模式这一选项&#xff0c;今天给大家介绍一下RunnerGo的几种压测模式和怎么根据性能需…

基于各种方式划分 vlan

划分VLAN的方式有&#xff1a;基于接口、基于MAC地址、基于IP子网、基于协议、基于策略&#xff08;MAC地址、IP地址、接口&#xff09;。 VLAN&#xff08;虚拟局域网&#xff09;可以按照以下几种方式进行划分&#xff1a; 端口划分方式 将交换机端口按照需要划分成不同的…

低碳 Web 实践指南

现状和问题 2023年7月6日&#xff0c;世界迎来有记录以来最热的一天。气候变化是如今人类面临的最大健康威胁。据世界卫生组织预测2030年至2050年期间&#xff0c;气候变化预计每年将造成约25万人死亡。这是人们可以真切感受到的变化&#xff0c;而背后的主要推手是碳排放。 …

软件定时器

Q: 什么是定时器&#xff1f; A: 其实在单片机的学习中&#xff0c;已经接触过无数次定时器了&#xff0c;所谓定时器&#xff0c;简单可以理解为闹钟&#xff0c;到达指定一段时间后&#xff0c;就会响铃。 STM32 芯片自带硬件定时器&#xff0c;精度较高&#xff0c;达到定时…

一年级数学 数一数(一到十)

今天我们来学习数一数 有一些老人 眼睛可能花了 需要我们在动物园数清楚是多少个动物 然后告诉他们 可能有的小朋友 不知道某些数字怎么读 您可以打开地址 https://fanyi.baidu.com/?aldtype16047#zh/en/ 将数字 输入到 输入框内 然后点击 下面的小话筒 系统就会读出来了 小…