Opencv-C++笔记 (14) : 霍夫变换(直线、圆)

文章目录

  • 一、霍夫变换-直线
    • 1.1霍夫变换-直线 原理详解
  • 二、霍夫圆检测

一、霍夫变换-直线

Hough Line Transform用来做直线检测
前提条件 – 边缘检测已经完成

1、平面空间(x,y)到极坐标空间转换;
在这里插入图片描述

2、对极坐标进行变换,转化为θ与R的关系
在这里插入图片描述

1.1霍夫变换-直线 原理详解

对于任意一条直线上的所有点来说,变换到极坐标中,从[0~360]空间,可以得到r的大小,属于同一条直线上点在极坐标空 ( r , θ ) (r, \theta)(r,θ) 必然在一个点上有最强的信号出现,根据此反算到平面坐标中就可以得到直线上各点的像素坐标。从而得到直线。

标准的霍夫变换 cv::HoughLines 从平面坐标转换到霍夫空间,最终输出是 ( r , θ ) (r, \theta)(r,θ) 表示极坐标空间

void HoughLines(
InputArray image,     输入图像,必须8-bit的灰度图像
OutputArray lines,    输出的极坐标来表示直线
double rho,        极坐标素扫描步长
double theta,       极坐标角度步长,一般取值CV_PI/180
int threshold,       阈值,多少交点的极坐标点才被看成是直线
double srn = 0,       是否应用多尺度的霍夫变换,默认0表示经典霍夫变换
double stn = 0,       是否应用多尺度的霍夫变换,默认0表示经典霍夫变换 
double min_theta = 0,   表示角度扫描范围 0 ~180之间, 默认即可
double max_theta = CV_PI
);

霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点 ( x 0 , y 0 , x 1 , y 1 )

void HoughLinesP(
InputArray image,      输入图像,必须8-bit的灰度图像
OutputArray lines,     输出的极坐标来表示直线
double rho,         极坐标像素扫描步长
double theta,        极坐标角度步长,一般取值CV_PI/180
int threshold,        阈值,多少交点的极坐标点才被看成是直线
double minLineLength = 0,  最小直线长度
double maxLineGap = 0 );  最大间隔
//头文件 quick_opencv.h:声明类与公共函数
#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;class QuickDemo {
public:...void hough_Demo(Mat& image1);void laplance_Demo(Mat& image1);void canny_Demo(Mat& image1);
};
//主函数调用该类的公共成员函数
#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;int main(int argc, char** argv) {Mat src = imread("D:\\Desktop\\jianbian.png");if (src.empty()) {printf("Could not load images...\n");return -1;}QuickDemo qk;qk.hough_Demo(src1);qk.hough_Demo(src1);qk.canny_Demo(src1);waitKey(0);destroyAllWindows();return 0;
}
void QuickDemo::hough_Demo(Mat& image) {Mat image_line = image.clone();// 霍夫直线检测Mat gau_dst, gray_dst, grad_dst;GaussianBlur(image_line, gau_dst, Size(3, 3), 10);cvtColor(gau_dst, gray_dst, COLOR_BGR2GRAY);vector<Vec4f> plines;Canny(gray_dst, gray_dst, 100, 200);imshow("Canny", gray_dst);HoughLinesP(gray_dst, plines, 5, CV_PI/180, 10, 0, 10);// 斜线检测调整maxlineGapcout << "线条个数:" << plines.size() << endl;for (int i = 0; i < plines.size(); i++) {Vec4f hline = plines[i];line(image_line, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(0, 0, 255), 1, 8, 0);}imshow("HoughLinesP", image_line);// 霍夫圆检测Mat median_dst, gray_median_dst;vector<Vec3f> pcircles;medianBlur(image, median_dst, 3);cvtColor(median_dst, gray_median_dst, COLOR_BGR2GRAY);HoughCircles(gray_median_dst, pcircles, HOUGH_GRADIENT, 1, 10, 100, 30, 5, 100);cout << "圆形个数:" << pcircles.size() << endl;for (int i = 0; i < pcircles.size(); i++) {Vec3f cc = pcircles[i];circle(image, Point(cc[0], cc[1]), cc[2], Scalar(255, 0, 0), 2, 8, 0);circle(image, Point(cc[0], cc[1]), 2, Scalar(255, 0, 0), 2, 8, 0); // 标注圆形}imshow("circle", image);
}

在这里插入图片描述

二、霍夫圆检测

算法详情见:霍夫圆检测 官方给出了好的示例。
对直线来说,一条直线能由极径极角 ( r , θ ) (r,θ)(r,θ) 表示,而对于圆来说,我们需要三个参数:圆心( a , b ) (a,b)(a,b),半径 r 。
笛卡尔坐标系中圆的方程为:
在这里插入图片描述
这就意味着每一组(a,b,r)代表一个通过点(x0,y0)的圆。

对于一个给定点(x0,y0),我们可以在三维直角坐标系中,绘出所有通过它的圆。最终我们将得到一条三维的曲线。
由于霍夫线变换圆检测对噪声比较敏感,所以首先要对图像做中值滤波,而且需要更多的检测计算消耗。OpenCV 霍夫圆变换对标准霍夫圆变换做了运算上的优化。它采用的是 “霍夫梯度法”。

基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:

  1. 检测边缘,发现可能的圆心
  2. 基于第一步的基础上从候选圆心开始计算最佳半径大小

霍夫梯度法的原理

估计圆心

1、把原图做一次 Canny 边缘检测,得到边缘检测的二值图。

对原始图像执行一次 Sobel 算子,计算出所有像素的邻域梯度值。

初始化圆心空间 N(a,b),令所有的 N(a,b)=0。

遍历 Canny 边缘二值图中的所有非零像素点,沿着梯度方向 ( 切线的垂直方向 )画线,将线段经过的所有累加器中的点 (a,b) 的 N(a,b)+=1。

void HoughCircles(
InputArray image,      输入图像 ,必须是8位的单通道灰度图像
OutputArray circles,    输出结果,发现的圆信息
int method,         HOUGH_GRADIENT
double dp,         dp = 1 累加器图像的反比分辨率
double minDist=src_gray.rows/8, 检测到圆心之间的最小距离,否则认为是同心圆-
double param1 = 100,    canny edge detection low threshold
double param2 = 100,   中心点累加器阈值 – 候选圆心
int minRadius = 0,      能检测到的最小圆半径, 默认为0
int maxRadius = 0      能检测到的最大圆半径, 默认为0
);
参数: 
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的灰度单通道图像。
第二个参数,InputArray类型的circles,经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示。
第三个参数,int类型的method,即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可。
第四个参数,double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。
第五个参数,double类型的minDist,为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了。
第六个参数,double类型的param1,有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
第七个参数,double类型的param2,也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
第八个参数,int类型的minRadius,有默认值0,表示圆半径的最小值。
第九个参数,int类型的maxRadius,也有默认值0,表示圆半径的最大值。

在这里插入图片描述

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

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

相关文章

[mongo]应用场景及选型

应用场景及选型 MongoDB 数据库定位 OLTP 数据库横向扩展能力&#xff0c;数据量或并发量增加时候架构可以自动扩展灵活模型&#xff0c;适合迭代开发&#xff0c;数据模型多变场景JSON 数据结构&#xff0c;适合微服务/REST API基于功能选择 MongoDB 关系型数据库迁移 从基…

【Android】MVC,MVP,MVVM三种架构模式的区别

MVC 传统的代码架构模式&#xff0c;仅仅是对代码进行了分层&#xff0c;其中的C代表Controller&#xff0c;控制的意思 将代码划分为数据层&#xff0c;视图层&#xff0c;控制层&#xff0c;三层之间可以任意交互 MVP MVP是在MVC基础上改进而来的一种架构&#xff0c;其中的…

【图像去噪】基于原始对偶算法优化的TV-L1模型进行图像去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

C++入门--string类的实现

目录 1.string类常用函数实现&#xff08;1&#xff09;string类成员变量定义&#xff08;2&#xff09; string类默认构造函数实现&#xff08;3&#xff09; string类拷贝构造函数实现&#xff08;4&#xff09;string类析构函数&#xff08;5&#xff09;string类c_str()函数…

品牌宣传与媒体传播是声誉管理的主要方式之一

企业声誉是现如今影响品牌信任度、客户忠诚度的重要因素&#xff0c;也被视为企业的一种无形资&#xff0c;更影响着企业未来的发展。因此&#xff0c;企业声誉管理也日渐成为企业管理的重要课题之一&#xff0c;尤其在品牌营销管理领域。 什么是声誉管理&#xff1f;声誉管理有…

logstash 采集 docker 日志

1、nginx容器部署 参考&#xff1a;nginx容器部署 将容器内的nginx日志文件映射到宿主机/home/logs/nginx目录下 注意&#xff1a;并且需要需要将日志的输出格式修改为json 2、编辑vim /opt/logstash-7.4.2/config/nginx-log-es.conf 文件&#xff0c;收集docker nginx容器日…

Java训练五

一、跳动的心脏 心脏是动物的重要器官&#xff0c;不断跳动的心脏意味着鲜活的生命力。现在创建一个人类&#xff0c;把心脏类设计为人类里面的一个成员内部类。心脏类有一个跳动的方法&#xff0c;在一个人被创建时&#xff0c;心脏就开始不断地跳动。 package haha; publi…

Spring集成Seata

Seata的集成方式有&#xff1a; 1. Seata-All 2. Seata-Spring-Boot-Starter 3. Spring-Cloud-Starter-Seata 本案例使用Seata-All演示&#xff1a; 第一步&#xff1a;下载Seata 第二步&#xff1a;为了更好看到效果&#xff0c;我们将Seata的数据存储改为db 将seata\sc…

Vue3 —— to 全家桶及源码学习

该文章是在学习 小满vue3 课程的随堂记录示例均采用 <script setup>&#xff0c;且包含 typescript 的基础用法 前言 本篇主要学习几个 api 及相关源码&#xff1a; toReftoRefstoRaw 一、toRef toRef(reactiveObj, key) 接收两个参数&#xff0c;第一个是 响应式对象…

嘉楠勘智k230开发板上手记录(四)--HHB神经网络模型部署工具

按照K230_AI实战_HHB神经网络模型部署工具.md&#xff0c;HHB文档&#xff0c;RISC-V 编译器和模拟器安装来 一、环境 1. 拉取docker 镜像然后创建docker容器并进入容器 docker pull hhb4tools/hhb:2.4.5 docker run -itd --namehhb2_4 -p 22 "hhb4tools/hhb:2.4.5"…

【CSS】背景图定位问题适配不同机型

需求 如图, 实现一个带有飘带的渐变背景 其中头像必须显示飘带凹下去那里 , 需要适配不同的机型, 一不下心容易错位 实现 因为飘带背景是版本迭代中更新的, 所以飘带和渐变背景实则两个div 飘带切图如下 , 圆形部分需要契合头像 <view class"box-bg"><…

Linux ——实操篇

Linux ——实操篇 前言vi 和 vim 的基本介绍vi和vim常用的三种模式正常模式插入模式命令行模式 vi和vim基本使用各种模式的相互切换vi和vim快捷键关机&重启命令基本介绍注意细节 用户登录和注销基本介绍使用细节 用户管理基本介绍添加用户基本语法应用案例细节说明 指定/修…

获取接口的所有实现

一、获取接口所有实现类 方法1&#xff1a;JDK自带的ServiceLoader实现 ServiceLoader是JDK自带的一个类加载器&#xff0c;位于java.util包当中&#xff0c;作为 A simple service-provider loading facility。 &#xff08;1&#xff09;创建接口 package com.example.dem…

Springboot中拦截GET请求获取请求参数验证合法性

目录 目的 核心方法 完整代码 创建拦截器 注册拦截器 测试效果 目的 在Springboot中创建拦截器拦截所有GET类型请求&#xff0c;获取请求参数验证内容合法性防止SQL注入&#xff08;该方法仅适用拦截GET类型请求&#xff0c;POST类型请求参数是在body中&#xff0c;所以下面…

3.1 计算机网络和网络设备

数据参考&#xff1a;CISP官方 目录 计算机网络基础网络互联设备网络传输介质 一、计算机网络基础 1、ENIAC&#xff1a;世界上第一台计算机的诞生 1946年2月14日&#xff0c;宾夕法尼亚大学诞生了世界上第一台计算机&#xff0c;名为电子数字积分计算机&#xff08;ENIAC…

【Autolayout案例02-距离四周边距 Objective-C语言】

一、好,来看第二个案例 1.第二个案例,是什么意思呢,第二个案例,要求屏幕中间,有一个UIView UIView,是个红色的UIView UIView的大小,我不限定 但是无论你是什么屏幕下 这个UIView距离上边,始终是50 距离右边,始终是50, 距离下边,始终是50, 距离左边,始终是5…

Nginx跳转模块——location与rewrite

一、location 1、location作用 用于匹配uri&#xff08;文件、图片、视频&#xff09; uri&#xff1a;统一资源标识符。是一种字符串标识&#xff0c;用于标识抽象的或物理资源文件、图片、视频 2、locatin分类 1、精准匹配&#xff1a;location / {...} 2、一般匹配&a…

PROFINET转DeviceNet网关普通网线能代替profinet吗

捷米JM-DNT-PN这款神器&#xff0c;连接PROFINET和DeviceNet网络&#xff0c;让两边数据轻松传输。 这个网关不仅从ETHERNET/IP和DEVICENET一侧读写数据&#xff0c;还可以将缓冲区数据交换&#xff0c;这样就可以在两个网络之间愉快地传递数据了&#xff01;而且&#xff0c;…

虚幻引擎游戏开发过程中,游戏鼠标如何双击判定?

UE虚幻引擎对于游戏开发者来说都不陌生&#xff0c;市面上有47%主机游戏使用虚幻引擎开发游戏。作为是一款游戏的核心动力&#xff0c;它的功能十分完善&#xff0c;囊括了场景制作、灯光渲染、动作镜头、粒子特效、材质蓝图等。本文介绍了虚幻引擎游戏开发过程中游戏鼠标双击判…

springboot+mybatis实现简单的增、删、查、改

这篇文章主要针对java初学者&#xff0c;详细介绍怎么创建一个基本的springboot项目来对数据库进行crud操作。 目录 第一步&#xff1a;准备数据库 第二步&#xff1a;创建springboot项目 方法1&#xff1a;通过spring官网的spring initilizer创建springboot项目 方法2&am…