EmguCV学习笔记 VB.Net 6.4 霍夫变换

news2024/11/14 16:24:13

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

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.4 霍夫变换

霍夫变换(Hough Transform)是一种在图像中检测几何形状的常用方法,最初用于检测直线,后来也扩展到检测其他形状,如圆、椭圆等。霍夫变换的核心思想是将图像空间中的特征点映射到参数空间中,并通过在参数空间中寻找峰值来检测形状。

霍夫变换的优点是对于图像中的形状检测具有较好的鲁棒性,对于存在噪声和遮挡的情况仍能有效检测。然而,它的计算复杂度较高,对于大型图像或复杂形状的检测可能会消耗较多的计算资源。

在Emgu.CV中,霍夫变换相关的函数有CvInvoke.HoughLinesP用于检测直线线段,CvInvoke.HoughLines用于直线检测,CvInvoke.HoughCircles用于圆检测等。这些函数可以方便地在图像中进行霍夫变换来检测不同形状的目标。

6.4.1 HoughLines 

CvInvoke.HoughLines方法用于在图像中检测直线。该函数会返回检测到的直线的参数。该方法声明如下:

Public Shared Sub HoughLines(image As Emgu.CV.IInputArray, lines As Emgu.CV.IOutputArray, rho As Double, theta As Double, threshold As Integer, Optional srn As Double = 0, Optional stn As Double = 0)

参数说明:

  1. Image:输入源图像(一般为8位单通道二值图像)。
  2. lines:经过霍夫变换后检测线条的输出矢量。这里传入VectorOfPointF类型变量。返回的每一条线由两个元素的矢量(ρ, θ)表示, 其中ρ是离坐标原点的距离, θ是弧度线条旋转角度(0表示垂直线, n / 2度表示水平线)。
  3. rho:以像素为单位的距离精度, 可以认为是直线搜索时的步进尺寸的单位半径。
  4. theta:以弧度为单位的角度精度, 可以认为是直线搜索时的步进尺寸的角度单位,常设为 Math.PI / 180。
  5. threshold:直线检测的阈值,只有当检测到的点数大于该阈值时才认为是直线。
  6. srn:控制距离分辨率。将距离分辨率除以srn+1,从而减小距离分辨率。其默认值为0。该参数的值越大,累加器空间的距离分辨率就越低,检测到的直线数量也会相应地减少。
  7. stn:控制角度分辨率。将角度分辨率除以stn+1,从而减小角度分辨率。其默认值为0。该参数的值越大,累加器空间的角度分辨率就越低,检测到的直线数量也会相应地减少。

【代码位置:frmChapter6】Button16_Click

   'HoughLines

    Private Sub Button16_Click(sender As Object, e As EventArgs) Handles Button16.Click

        Dim m1 As New Mat("C:\learnEmgucv\line.jpg", CvEnum.ImreadModes.AnyColor)

        '边缘检测

        Dim mid1 As New Mat

        CvInvoke.Canny(m1, mid1, 80, 255, 3)

        '二值化

        Dim mid2 As New Mat

        CvInvoke.Threshold(mid1, mid2, 125, 255, ThresholdType.Binary)

        ImageBox1.Image = mid2

        'HoughLines检测直线

        Dim outlines As New  VectorOfPointF

        CvInvoke.HoughLines(mid2, outlines, 1, Math.PI / 180, 250, 0, 0)

        Dim m2 As New Mat

        m2 = mid1.Clone()

        m2.SetTo(New MCvScalar(0))

        '计算每条直线的起始坐标,并绘制出来

        For i As Integer = 0 To outlines.Size - 1

            Dim line As PointF = outlines(i)

            Dim rho As Double = line.X

            Dim theta As Double = line.Y

            Dim a As Double = Math.Cos(theta)

            Dim b As Double = Math.Sin(theta)

            Dim x0 As Double = rho * a

            Dim y0 As Double = rho * b

            Dim pt1 As New Point

            pt1.X = Math.Round(x0 + m2.Cols * (-b))

            pt1.Y = Math.Round(y0 + m2.Rows * a

            Dim pt2 As New Point

            pt2.X = Math.Round(x0 - m2.Cols * (-b))

            pt2.Y = Math.Round(y0 - m2.Rows * a)

            '绘制直线

            CvInvoke.Line(m2, pt1, pt2, New MCvScalar(255), 2)

        Next

        ImageBox2.Image = m2

        '减少检测到的点数

        Dim outlines3 As New VectorOfPointF

        CvInvoke.HoughLines(mid2, outlines3, 1, Math.PI / 180, 120, 0, 0)

        Dim m3 As New Mat

        m3 = mid1.Clone()

        m3.SetTo(New MCvScalar(0))

        Dim length3 As Double = Math.Max(m3.Rows, m3.Cols)

        For i As Integer = 0 To outlines3.Size - 1

            Dim line As PointF = outlines3(i)

            Dim rho As Double = line.X

            Dim theta As Double = line.Y

            Dim a As Double = Math.Cos(theta)

            Dim b As Double = Math.Sin(theta)

            Dim x0 As Double = rho * a

            Dim y0 As Double = rho * b

            Dim pt1 As New Point

            pt1.X = Math.Round(x0 + m2.Cols * (-b))

            pt1.Y = Math.Round(y0 + m2.Rows * a)

            Dim pt2 As New Point

            pt2.X = Math.Round(x0 - m2.Cols * (-b))

            pt2.Y = Math.Round(y0 - m2.Rows * a)

            CvInvoke.Line(m3, pt1, pt2, New MCvScalar(255), 2)

        Next

        ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-17 直线检测结果

6.4.2 HoughLinesP        

CvInvoke.HoughLinesP方法用于在图像中检测线段。该方法的两个声明如下:

Public Shared Sub HoughLinesP(image As Emgu.CV.IInputArray, lines As Emgu.CV.IOutputArray, rho As Double, theta As Double, threshold As Integer, Optional minLineLength As Double = 0, Optional maxGap As Double = 0)

Public Shared Function HoughLinesP(image As Emgu.CV.IInputArray, rho As Double, theta As Double, threshold As Integer, Optional minLineLength As Double = 0, Optional maxGap As Double = 0) As Emgu.CV.Structure.LineSegment2D()

参数解释:

  1. image:输入图像(Image(Of Gray, Byte)类型)。
  2. lines:经过霍夫变换后检测线条的输出矢量。VectorOfRect类型,每个成员是一个Rectangle类型,属性X 、Y、Width、Height分别表示第一个点的X、第一个点的Y,第二个点的X、第二个点的Y。
  3. rho:以像素为单位的距离精度。
  4. theta:以弧度为单位的角度精度。
  5. threshold:直线检测的阈值,只有当检测到的点数大于该阈值时才认为是直线。
  6. minLineLength:线段的最小长度,小于该长度的线段将被忽略。
  7. maxLineGap:线段之间的最大间隔,超过该间隔的线段将被认为是不同的线段。

返回值:

检测到的线段数组(LineSegment2D()类型)。

【代码位置:frmChapter6】Button17_Click

    'HoughLinesP

    Private Sub Button17_Click(sender As Object, e As EventArgs) Handles Button17.Click

        Dim m1 As New Mat("C:\learnEmgucv\line.jpg", CvEnum.ImreadModes.AnyColor)

        '边缘检测

        Dim mid1 As New Mat

        CvInvoke.Canny(m1, mid1, 80, 255, 3)

        '二值化

        Dim mid2 As New Mat

        CvInvoke.Threshold(mid1, mid2, 125, 255, ThresholdType.Binary)

        ImageBox1.Image = mid2

        Dim outlines() As LineSegment2D

        outlines = CvInvoke.HoughLinesP(mid2, 1, Math.PI / 180, 100, 0, 0)

        Dim m2 As New Mat

        m2 = mid1.Clone()

        m2.SetTo(New MCvScalar(0))

        '绘制检测出的线段

        For i As Integer = 0 To outlines.Length - 1

            CvInvoke.Line(m2, outlines(i).P1, outlines(i).P2, New MCvScalar(255), 2)

        Next

        ImageBox2.Image = m2

        Dim outlines2 As New VectorOfRect()

        CvInvoke.HoughLinesP(mid2, outlines2, 1, Math.PI / 180, 100 5 30)

        Dim m3 As New Mat

        m3 = mid1.Clone()

        m3.SetTo(New MCvScalar(0))

        For i As Integer = 0 To outlines2.Size - 1

            CvInvoke.Line(m3, New Point(outlines2(i).X, outlines2(i).Y), New Point(outlines2(i).Width, outlines2(i).Height), New MCvScalar(255), 2)

        Next

        ImageBox3.Image = m3

End Sub

运行后如下图所示:

图6-18 线段检测结果

6.4.3 HoughCircles

CvInvoke.HoughCircles函数用于在图像中检测圆形,该方法声明如下:

Public Shared Function HoughCircles(image As Emgu.CV.IInputArray, method As Emgu.CV.CvEnum.HoughModes, dp As Double, minDist As Double, Optional param1 As Double = 100, Optional param2 As Double = 100, Optional minRadius As Integer = 0, Optional maxRadius As Integer = 0) As Emgu.CV.Structure.CircleF()

参数说明:

  1. image:8位单通道灰度源图像(或者传入的源图像是Image(Of Gray, Byte)类型)。
  2. method:霍夫变换的方法,可以选择HoughType.Gradient或HoughType.GradientAlt。
  3. dp:累加器图像的分辨率与输入图像的分辨率之比。例如,dp = 1,则累加器具有与输入图像相同的分辨率。如果dp = 2,则累加器的宽度和高度都是一半。
  4. minDist:检测到的圆心之间的最小距离,太小会多检,太大会漏检。
  5. param1:Canny边缘检测的高阈值。
  6. param2:圆心累加器阈值,只有当累加器图像中的值大于该阈值时才认为是圆心。相应的该阈值越小,可得到越多的圆。
  7. minRadius:达到检测要求的最小圆半径。
  8. maxRadius:达到检测要求的最大圆半径。

返回值:

检测到的圆形数组(CircleF()类型)。

【代码位置:frmChapter6】Button18_Click

    'HoughCircles

    Private Sub Button18_Click(sender As Object, e As EventArgs) Handles Button18.Click

        Dim m1 As New Mat("C:\learnEmgucv\aoyun.jpg", CvEnum.ImreadModes.Grayscale)

        ImageBox1.Image = m1

        Dim mid1 As New Mat

        CvInvoke.GaussianBlur(m1, mid1, New Drawing.Size(3, 3), 3)

        ImageBox2.Image = mid1

        Dim outcircle() As CircleF

        outcircle = CvInvoke.HoughCircles(mid1, HoughModes.Gradient, 2, 50, 140, 220, 5)

        Dim m2 As New Mat

        m2 = mid1.Clone()

        m2.SetTo(New MCvScalar(255))

        For i As Integer = 0 To outcircle.Length - 1

            CvInvoke.Circle(m2, New Point(Integer.Parse(outcircle(i).Center.X), Integer.Parse(outcircle(i).Center.Y)), outcircle(i).Radius, New MCvScalar(0), 2)

        Next

        ImageBox3.Image = m2

End Sub

运行后如下图所示:

图6-19 圆形检测结果

另外一个例子,代码同上,只是载入的图片不同:

【代码位置:frmChapter6】Button19_Click

……

     Dim m1 As New Mat("C:\learnEmgucv\Matchimg.jpg", CvEnum.ImreadModes.Grayscale)

……

运行后如下图所示:

图6-20 圆形检测结果

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

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

相关文章

提升大模型内容创作能力

前言 现在的大模型能够创作一些故事、小说等等,但是大多数时候创作出来的剧情都是泛泛而谈,并没人给读者很爽的感觉。近期已经有一些工作开始在该方面进行发力,即让大模型做内容消费,如果大模型能够源源不断的创作出好的剧情来供…

幅频特性曲线分析及使用WPF绘制

文章目录 1、一阶惯性环节的幅频特性曲线分析及绘制2、二阶系统的幅频特性曲线分析及绘制3、一般的系统4、上位机代码实现4.1 一阶惯性系统4.2 二阶系统 5、稳定裕度5.1 幅值裕度5.2 相角裕度 参考 1、一阶惯性环节的幅频特性曲线分析及绘制 这里的a和b可以根据系统的不同修改,…

Ubuntu 22.04上稳定安装与配置搜狗输入法详细教程

摘要:本教程详细介绍了如何在Ubuntu 22.04上安装和配置搜狗输入法,每个步骤详细配图。由于在Ubuntu 24.04上存在兼容性问题,建议用户继续使用稳定的22.04版本。教程涵盖了从更新系统源、安装fcitx输入法框架,到下载和配置搜狗输入…

12、stm32通过dht11读取温湿度

一、配置 二、代码 dht11.c /** dht11.c** Created on: Aug 19, 2024* Author: Administrator*/#include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h" /**TIM3定时器实现us级延时*/ void Delay_us(uint16…

谷歌登录的时候,要求在手机的通知点是,并按数字来验证身份,但是手机通知栏没有收到通知和数字,原因是什么,怎么办?

前两天,有个朋友联系到GG账号服务,说他的一个谷歌账号在新设备登录的时候,提示说要在手机的通知栏点击谷歌发来的通知,点击是确认,并且要点按相应的数字。 但问题是他反复刷新手机的通知栏都没有看到谷歌发来的通知&a…

谷粒商城实战笔记-255~256-商城业务-消息队列-SpringBoot整合RabbitMQ

文章目录 一,Spring整合RabbittMq的步骤二,AmqpAdmin使用1. createExchange()2. testCreateQueue()3. createBinding()4,发送消息 这一部分讲解Spring整合RabbitMq的步骤及其使用,包括: 255-商城业务-消息队列-SpringB…

Tita的OKR :产品经理的OKR

产品经理制定的OKR,对组织发展有重大的意义,它能促使产品经理,产品团队,乃至是公司全体员工走出舒适区,超越能力边界。正因为挑战的存在,才使得产品经理才有忧患意识,不断改进产品,从…

【操作系统】10.虚拟内存管理有什么不同?

2.虚拟内存管理有什么不同? 2.1 虚拟内存的基本概念 虚拟内存的概念 具有请求调入和置换功能,从逻辑上对内存容量加以扩充的一种存储器系统 局部性原理 时间局部性 空间局部性 虚拟内存的特征 多次性 对换性 虚拟性 2.1.1 虚拟内存的实现 请求分页存储管…

了解一点电池的工作原理,让它们更好地为我们工作。【手机充电小技巧】(影响电池寿命的主要因素:过充、过放以及高温)

文章目录 引言I 充电小技巧,充分发挥电池性能随充随用都行充电时移除某些保护壳不正常的持续发烫,建议停止充电及时拔掉充电器或者关闭插座电源长期存放时,请保持一半电量。电池健康自动管理II 电池的工作原理快充为便捷,慢充保寿命。锂离子电池以充电周期方式工作,让充电更…

网络层 I(网络层的功能)【★★★★★★】

(★★)代表非常重要的知识点,(★)代表重要的知识点。 一、 路由与转发(★★) 路由器主要完成两个功能: 1. 路由选择 【(确定哪一条路径)根据路由选择协议构…

从零开始搭建Aliyun ESC高可用集群 (HaVip+KeepAlived)

从零开始搭建Aliyun ESC高可用集群 (HaVip+KeepAlived) 架构 架构 本设计方案采用两台阿里云ECS服务器搭建Keepalived结合LVS的高可用集群。使用LVS的TUN模式进行负载均衡,同时利用阿里云的弹性IP(EIP)与高可用虚拟HaVIP实现跨服务器的高可用性。架构中,一台ECS服务器作为…

一文彻底理解大模型 Agent 智能体原理和案例

1 什么是大模型 Agent ? 大模型 Agent,作为一种人工智能体,是具备环境感知能力、自主理解、决策制定及执行行动能力的智能实体。简而言之,它是构建于大模型之上的计算机程序,能够模拟独立思考过程,灵活调…

防火墙基础概念与实验配置

目录 1.防火墙简介 1.1 什么是防火墙? 1.2 防火墙的功能 1.3 防火墙的类型 2.防火墙配置实验 2.1 基本要求 2.2 实验top 3.实验配置 3.1 基础配置 3.1.1 基础配置 3.1.2 安全域配置 3.1.3 配置安全策略 3.1.4 配置NAT 3.1.5 trust->dmz 3.1.6 端口…

代码随想录算法训练营day27 | 贪心算法 | 455.分发饼干、376.摆动序列、53.最大子序和

文章目录 理论基础解题步骤455.分发饼干思路小结 376.摆动序列简单思路贪心思路 53.最大子序和思路 今天是贪心算法的第一天 理论基础 贪心的本质是选择每一阶段的局部最优,从而达到全局最优 在理论上,能使用贪心解决的问题有两个特点:具有…

buuctf [HDCTF2019]Maze

前言:做题笔记。 常规 下载 解压 查壳 脱壳后用32IDA Pro打开。 得,迷宫类型的题目。(字符串有说。) 咳,此前思路对半分不行了。。。 合理猜测步数为:14。 那可以看看7 * 10的迷宫类型。(手动猜测的时候去取倍数如:0 2…

什么牌子的蓝牙耳机性价比高?2024年四款最值得买王牌耳机推荐!

在当前的手机备件市场中,蓝牙耳机已经逐渐成为智能手机备件的热门之选。然而,面对众多的耳机品牌和型号,消费者在选购时可能会感到困惑,稍微不留言就会买到不专业产品,那么什么牌子的蓝牙耳机性价比高?作为…

STM32的串口通信——HAL库

TTL串口 TTL串口仅仅需要两根数据线就可以进行串口通信: ①一条是从A设备发送的IO口连接到B设备的接收IO口 ②一条是从B设备发送的IO口连接到A设备的接收IO口 ③共地(GND)是两个设备通信的前提(保证他们的电平标准一致&#x…

使用css如何获取最后一行的元素?使用css解决双边框问题

一、项目场景: 在小程序上需要实现一个如下图的ui效果图 需要满足以下条件 一行放不下 自动换行最后一行或者只有一行时,文字底部不能有线 二、初版实现 按照上面的要求,最开是的实现代码如下 我是给每一个元素都添加了一个下边框&#x…

Python酷库之旅-第三方库Pandas(095)

目录 一、用法精讲 406、pandas.DataFrame.index属性 406-1、语法 406-2、参数 406-3、功能 406-4、返回值 406-5、说明 406-6、用法 406-6-1、数据准备 406-6-2、代码示例 406-6-3、结果输出 407、pandas.DataFrame.columns属性 407-1、语法 407-2、参数 407-3…

楼顶气膜羽毛球馆:城市健身新空间—轻空间

随着城市化进程的加快,城市土地资源愈发紧张,如何高效利用有限的空间成为一大挑战。楼顶气膜羽毛球馆作为一种创新的体育场馆建设方式,凭借其独特的优势,逐渐成为城市健身的新宠。它不仅有效利用了楼顶闲置空间,还为市…