EmguCV学习笔记 C# 6.S 特别示例

news2024/9/24 21:21:02

  版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。

教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客

教程C#版本请访问:EmguCV学习笔记 C# 目录-CSDN博客

笔者的博客网址:https://blog.csdn.net/uruseibest

教程配套文件及相关说明以及如何获得pdf教程和代码,请移步:EmguCV学习笔记

学习VB.Net知识,请移步: vb.net 教程 目录_vb中如何用datagridview-CSDN博客

 学习C#知识,请移步:C# 教程 目录_c#教程目录-CSDN博客

6.S 特别示例

6.S.1图像中的圆半径

本示例来自一名网友咨询如何获得图像中圆形的半径,其中有两个十字作为标记,十字之间距离为100mm。如下图:

 

图6-28 根据给出的定位标记求圆半径

【代码位置:frmChapter6_S1】Button1_Click、PointFToPoint

        private void Button1_Click(object sender, EventArgs e)

        {

            Mat msrc = new Mat("C:\\learnEmgucv\\celiang.jpg", ImreadModes.Color);

            Mat mgray = new Mat();

            CvInvoke.CvtColor(msrc, mgray, ColorConversion.Bgr2Gray);

            Mat kernel = new Mat();

            kernel = CvInvoke.GetStructuringElement(ElementShape.Cross, new Size(3, 3), new Point(-1, -1));

            Mat merode = new Mat();

            //这里使用了2次迭代

            CvInvoke.Dilate(mgray, merode, kernel, new Point(-1, -1), 1, BorderType.Constant, new MCvScalar());

            CvInvoke.Threshold(merode, merode, 200, 255, ThresholdType.BinaryInv);

            ImageBox1.Image = merode;

            //获得所有轮廓

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

            VectorOfRect hierarchy = new VectorOfRect();

            CvInvoke.FindContours(merode, contours, hierarchy, RetrType.List, ChainApproxMethod.ChainApproxSimple);

            Mat m2 = new Mat(merode.Size, DepthType.Cv8U, 1);

            m2.SetTo(new MCvScalar(0));

            //圆轮廓

            VectorOfPoint contourCircle =new VectorOfPoint();

            //圆轮廓的周长

            Double perimeter =0;

            //绘制轮廓

            for (int i = 0; i < contours.Size; i++)

            {

                VectorOfPoint carea = contours[i];

                //获得轮廓面积

                Double area = CvInvoke.ContourArea(carea, false);

                //符合条件时,绘制轮廓,排除圆形,只保留十字线

                //本图中圆形面积为2449,直线面积为8,需要根据实际情况调整

                if (area < 200)

                {

                    CvInvoke.DrawContours(m2, contours, i, new MCvScalar(255),1);

                }

                else

                {

                    //得到圆形,图像中只有三个轮廓:2个交叉十字线段、1个圆形

                    //这里简化操作,否则在多个轮廓情况下,应获取最大面积的轮廓判断为圆形

                    contourCircle = contours[i];

                    //获取轮廓周长

                    perimeter = CvInvoke.ArcLength(contourCircle, true);

                }

            }

            ImageBox1.Image = m2;

            //使用HoughLinesP方法检测图像中的直线,并将其绘制到图像

            //因为本图中十字线上的线段较短,所以这里阈值设置很小

            LineSegment2D[] lines = CvInvoke.HoughLinesP(m2, 1, Math.PI / 180, 5, 5, 80);

            Mat m3 = new Mat(merode.Size, DepthType.Cv8U, 3);

            m3.SetTo(new MCvScalar(0, 0, 0));

            foreach (LineSegment2D line in lines)

                CvInvoke.Line(m3, line.P1, line.P2, new MCvScalar(0, 255, 0), 2);

            ImageBox2.Image = m3;

            //对直线进行分类,将其分为垂直和水平两类:

            List<LineSegment2D> verticalLines = new List<LineSegment2D>();

            List<LineSegment2D> horizontalLines = new List<LineSegment2D>();

            //计算每条直线的倾斜角度来进行分类,

            //将倾斜角度在60 - 120度之间的直线划分为垂直类,

            //将倾斜角度在30 - 150度之间的直线划分为水平类。

            foreach (LineSegment2D line in lines)

            {

                Double angle = Math.Atan2(line.P2.Y - line.P1.Y, line.P2.X - line.P1.X) * 180 / Math.PI;

                if (angle < 0)

                    angle += 180;

                if (angle > 60 && angle < 120)

                    verticalLines.Add(line);

                else if ( angle > 150 || angle< 30 )

                    horizontalLines.Add(line);

            }

            //对垂直和水平直线进行匹配,并计算十字中心点的位置:

            List<PointF> intersections = new List<PointF>();

            //得到两个相交点

            foreach (LineSegment2D verticalLine in verticalLines)

            {

                foreach (LineSegment2D horizontalLine in horizontalLines)

                {

                    //基于图像中两条直线真实相交,

                    //如果垂直线的中点X坐标在水平线两端点X坐标之间

                    //那么,这条垂直线段和这条水平线段相交

                    Single centerX = (verticalLine.P1.X + verticalLine.P2.X) / 2;

                    if (horizontalLine.P1.X < horizontalLine.P2.X)

                    {

                        if ((centerX > horizontalLine.P1.X) && (centerX < horizontalLine.P2.X))

                        {

                            PointF intersectionPoint = new PointF(

                                    (horizontalLine.P1.X + horizontalLine.P2.X + verticalLine.P1.X + verticalLine.P2.X) / 4,

                                    (horizontalLine.P1.Y + horizontalLine.P2.Y + verticalLine.P1.Y + verticalLine.P2.Y) / 4

                                );

                            intersections.Add(intersectionPoint);

                        }

                    }

                    else

                    {

                        if (centerX > horizontalLine.P2.X && centerX < horizontalLine.P1.X)

                        {

                            PointF intersectionPoint = new PointF(

                                    (horizontalLine.P1.X + horizontalLine.P2.X + verticalLine.P1.X + verticalLine.P2.X) / 4,

                                    (horizontalLine.P1.Y + horizontalLine.P2.Y + verticalLine.P1.Y + verticalLine.P2.Y) / 4

                                );

                            intersections.Add(intersectionPoint);

                        }

                    }

                }

            }

            if (intersections.Count != 2)

            {

                MessageBox.Show("未能获得两个十字线的交叉点");

                return;

            }

            CvInvoke.Line(msrc, PointFToPoint(intersections[0]), PointFToPoint(intersections[1]), new MCvScalar(0, 255, 0), 2);

            CvInvoke.Imshow("m3", msrc);

            //计算两个交点的距离

            Double distance = Math.Sqrt(

                    Math.Pow((intersections[0].X - intersections[1].X),2) +Math.Pow((intersections[0].Y - intersections[1].Y) ,2)

                    );

            //实际中两交点距离为100毫米,计算相应比例

            Double proportion = 100 / distance;

            //以下是基于最小外接圆来计算实际圆半径

            CircleF cf = CvInvoke.MinEnclosingCircle(contourCircle);

            //获得外接圆形

            CvInvoke.Circle(msrc, new Point((int)cf.Center.X, (int)cf.Center.Y), (int)cf.Radius, new MCvScalar(0, 0, 255), 2);

            CvInvoke.Imshow("m4", msrc);

            //实际圆半径

            Double realradius1 = proportion * cf.Radius;

            //以下是基于轮廓周长来计算实际圆半径

            //实际圆周长

            Double realperimeter = perimeter * proportion;

            //图像中的圆半径

            Double radius = (perimeter / Math.PI) / 2;

            //实际圆半径

            Double realradius2 = proportion * radius;

            MessageBox.Show("最小外接圆来计算实际圆半径:" + realradius1 + "\r\n" +

                                "基于轮廓周长来计算实际圆半径:" + realradius2);

        }

输出结果如下图所示:

 

图6-29 求出的圆半径

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

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

相关文章

Datawhale AI夏令营 第五期 CV方向 Task1笔记

Task1&#xff1a;跑通YOLO方案baseline&#xff01; 赛题解读 根据您提供的图片内容&#xff0c;这是一份关于城市管理违规行为智能识别竞赛的赛题描述。以下是对内容的分析&#xff1a; 一、赛题描述 背景&#xff1a;随着城市化进程的加速&#xff0c;城市管理面临新的挑…

JavaScript初级——获取元素的样式

1、获取元素当前的显示样式 语法&#xff1a;元素.currentStyle.样式名 可以用来读取当前元素正在显示的样式&#xff0c;如果当前的元素没有设置样式&#xff0c;则获取他的默认值 currentStyle只有IE8浏览器支持&#xff0c;其他的浏览器不支持。 2、在其他浏览器中&#xf…

修复 502 Bad Gateway 错误的 6 种方法

通常&#xff0c;我们在使用网站时可能会遇到一系列错误。有些非常常见&#xff0c;例如 404&#xff0c;有些则不太常见&#xff0c;例如 101。这些被称为 HTTP 状态代码。其中&#xff0c;502 错误是某种服务器错误。那么&#xff0c;让我们先了解一下 Bad Gateway 502 的含义…

JetBrains Rider 2024 for Mac/Win:跨平台.NET IDE集成开发环境的全面解析

JetBrains Rider 2024作为一款专为Mac和Windows用户设计的跨平台.NET IDE集成开发环境&#xff0c;以其强大的功能和卓越的性能&#xff0c;在.NET开发领域脱颖而出。这款IDE不仅集成了IntelliJ IDEA的代码编辑优势&#xff0c;还融合了ReSharper的C#开发体验&#xff0c;为开发…

STM32(F103ZET6)第十六课:WIFI模块的配置与应用

目录 需求一、wifi模块简述二、配置流程1.配置通信串口2.配置引脚与中断接受3.简述AT指令4.程序编写 三、需求实现代码 需求 完成WiFi模块的配置,使其能连接服务器并最终能和服务器相互发送消息。 一、wifi模块简述 本项目开发版上没有封装好的WIFI模块&#xff0c;所以借助…

SpringBoot日常:基于DeferredResult的异步处理

文章目录 示例代码代码执行结果代码执行过程解析DeferredResult 的优势 本章内容主要讲讲基于DeferredResult的异步处理 在 Servlet 容器中启用了异步请求处理功能&#xff0c;控制器方法就可以用 包装任何支持的控制器方法返回值DeferredResult&#xff0c;控制器可以从不同的…

谷粒商城实战笔记-261~262-商城业务-订单服务-页面环境搭建-SpringSession

文章目录 一&#xff0c;261-商城业务-订单服务-页面环境搭建1&#xff0c;静态资源上传2&#xff0c;配置域名映射3&#xff0c;网关配置4&#xff0c;页面静态资源引用修改 二&#xff0c;262-商城业务-订单服务-整合SpringSession1&#xff0c;页面跳转2&#xff0c;配置Spr…

Python实战:如何使用K-means算法进行餐馆满意度NLP情感分析

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

详解Apache 和 Tomcat 整合原理及区别

Apache 和 Tomcat 都是Web服务器&#xff0c;它们之间既有联系又有区别。Apache主要负责静态解析&#xff0c;如HTML。Tomcat主要负责动态解析&#xff0c;如JSP。 为什么要让 Apache 与 Tomcat 之间进行连接呢? 原因有下面几个&#xff1a; 提升对静态文件的处理性能 利用…

ms_送给新人的面试题简单解答

第一部分 1 项目中遇到的bug或者难题 这个问题比较容易&#xff0c;每个人都会在开发过程中遇到或多或少的问题&#xff0c;你不可能答我已经天下无敌了&#xff0c;大家开发的项目类型都不太一样&#xff0c;事实上也没人听得太仔细&#xff0c;就算你要说的‘难题‘并不难&…

Apache Druid日志实时分析

业务分析 ​ 秒杀业务中&#xff0c;通常会有很多用户同时蜂拥而上去抢购热卖商品&#xff0c;经常会出现抢购人数远大于商品库存。其实在秒杀过程中&#xff0c;热卖商品并不多&#xff0c;几乎只占1%&#xff0c;而99%的流量都源自热卖商品&#xff0c;很有可能因为这1%的热…

【SQL】分类统计的薪水

目录 题目 分析 代码 题目 表: Accounts ------------------- | 列名 | 类型 | ------------------- | account_id | int | | income | int | ------------------- 在 SQL 中&#xff0c;account_id 是这个表的主键。 每一行都包含一个银行帐户的月收入的…

深入解析Go语言os/user包:用户和组管理实战指南

深入解析Go语言os/user包&#xff1a;用户和组管理实战指南 引言什么是os/user包&#xff1f;为什么要学习os/user包&#xff1f;本文将介绍的内容 os/user包基础如何导入os/user包获取当前用户信息示例代码 *user.User类型详解常见错误处理小结 用户查询与管理根据用户名查询用…

这本大模型书籍我敢说知道的人不超过1%,大模型入门必备书籍

当然可以&#xff01;我为您推荐一本关于大模型的书籍&#xff1a;《Transformer Tutorials: From Theory to Practice》。虽然这本书不是直接以“大模型”命名&#xff0c;但它涵盖了构建和理解大规模语言模型&#xff08;如GPT系列和BERT&#xff09;所需的关键技术和理论。接…

娱乐社交、游戏行业的最新玩法实践与未来增长趋势解读|网易数智x华为云城市沙龙杭州站邀你前来!

随着5G、AI、区块链等前沿技术的深度融合应用&#xff0c;泛娱乐行业正经历深刻变革的同时&#xff0c;也面临着一系列挑战与问题&#xff0c;面对社交产品监管的加强、海外市场的双重机遇与风险以及增速放缓的游戏行业...... 探求新增长点与新思路成为当下泛娱乐行业从业者的关…

收银系统源码助力零售门店数字化升级

一、国内零售业数字化转型迈入深水区 近年来&#xff0c;我国零售业数字化进程显著加速&#xff0c;从线上电商到新零售模式&#xff0c;再到利用大数据、人工智能等技术优化供应链、提升体验&#xff0c;每一步都见证了行业的深刻变革。随着零售行业进入存量市场竞争&#xf…

nuxt3连接mongodb操作

文章目录 创建一个nuxt3应用添加nuxt后端服务nuxt3路由创建mongo数据连接mongodb数据库补充添加显示(用v-for打印出数组)nuxt-server-insertmongodb删除数据创建一个nuxt3应用 Node.js - v18.0.0 或更新版本推荐使用 Visual Studio Code 以及 Volar 扩展npx nuxi@latest init p…

使用jwt实现登录验证

jwt工具类 public class JwtUtil {public static String key"mykey";public static String genToken(String username) {JWTCreator.Builder builder JWT.create();Map<String, Object> headersnew HashMap<>();headers.put("typ","jwt&…

uniapp重新编译在微信开发者工具跳转指定页面

uniapp重新编译在微信开发者工具跳转指定页面 步骤 选择编译模式添加编译模式设置启动页面

rk3588调用NPU、查看npu的使用情况

1、rk3588启用NPU 启用三个内核->RKNNLite.NPU_CORE_0_1_2 rknn_lite RKNNLite(verboseFalse) ret rknn_lite.load_rknn(RKNN_MODEL) ret rknn_lite.init_runtime(core_maskRKNNLite.NPU_CORE_0_1_2) 2、查看NPU使用情况&#xff1a; watch sudo cat /sys/kernel/deb…