【千律】OpenCV基础:Hough圆检测

2023-10-29

环境:Python3.8 和 OpenCV

内容:Hough圆检测

将直角坐标系中的一个圆映射为新坐标系中的一个点,对于原直角坐标系中的每一个圆,可以对应(a, b, r) 这样一个点,这个点即为新三维中的点。

标准法实现步骤:
1.获取原图像的边缘检测图像;

2.设置最小半径、最大半径和半径分辨率等超参数;

3.根据转化后空间的圆心分辨率等信息,设置计数器N(a, b, r);

4.对边缘检测图像的每个白色边缘像素点,其坐标记为(x, y),对于指定的半径r,根据公式 (a-x)^2 + (b-y)^2 = r^2 得到点(a, b)形成的轨迹圆,将轨迹圆经过的计数器N(a, b, r) 加1;

5.如果某个计数器的点数超过设定阈值,则认为存在对应的圆,取出(a, b, r),求出对应的圆方程。

梯度法实现步骤:

1.获取原图像的边缘检测图像;

2.设置最小半径、最大半径和半径分辨率等超参数;

3.计算原图像各点x和y方向的梯度;

4.设置计数器N(a, b);

5.对边缘图像中任意一点p,其梯度为(px, py),由该点p和其梯度决定一条直线,将直线经过的计数器N(a, b)加1。

6.如果某计数器点数超过阈值,则认为存在圆,取出的(a, b)记为圆心,通过不断变换半径,若与边缘图的交集点数超过设定阈值,则认为存在圆,从而获得圆方程。

实现方式1(梯度法):

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()

# Hough圆检测


if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 参数设置
    img_dp = 2           # 图像分辨率与累加器分辨率之比,建议范围为1-2
    MinDist = 50         # 两个不同圆圆心之间的距离
    Param1 = 400         # Canny边缘阈值的上限,其下限为上限的1/2
    Param2 = 80          # cv.HOUGH_GRADIENT 方法的累加器阈值,阈值越小,检测的圆越多
                         # cv.HOUGH_GRADIENT_ALT 方法中,该参数用于衡量圆的完美度,范围为0-1
    MinRadius = 10       # 最小圆半径
    MaxRadius = 100      # 最大圆半径

    # 霍夫圆检测
    circles = cv.HoughCircles(img_gray, cv.HOUGH_GRADIENT, dp=img_dp, minDist=MinDist,
                              param1=Param1, param2=Param2, minRadius=MinRadius, maxRadius=MaxRadius)

    # 绘制结果
    for (x, y, r) in circles.squeeze():
        cv.circle(img_desk, (int(x), int(y)), int(r), (0, 0, 255), 2)

    image_show(img_desk)

实现方式2(标准法): 

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()



if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 边缘检测
    img_canny = cv.Canny(img_gray, 100, 400)

    # 参数设置
    img_dr = 1            # 半径分辨率
    MinRadius = 10        # 最小圆半径
    MaxRadius = 100       # 最大圆半径
    thresh = 80           # 累加的阈值

    # 初始化计数器
    height, width = img_gray.shape
    radius = int((MaxRadius - MinRadius) / img_dr) + 1
    N = np.zeros((width, height, radius))

    # 获取边缘像素位置
    edge_y, edge_x = np.where(img_canny == 255)

    # 循环绘制不同圆
    for (x, y) in zip(edge_x, edge_y):
        for r in range(MinRadius, MaxRadius, img_dr):

            # 根据个点绘制不同圆
            circle = np.zeros((height, width), np.uint8)
            cv.circle(circle, (x, y), r, 255, 1)

            # 获取不同圆的轨迹位置
            bsi, asi = np.where(circle == 255)

            # 将轨迹经过位置计数器累加
            N[asi, bsi, r - MinRadius] += 1

    # 显示累加图
    plt.imshow(N[:, :, 50], cmap='jet')
    plt.show()

    # 获取圆的位置和半径
    xs, ys, rs = np.where(N > thresh)

    # 绘制图上检测的圆
    for (x, y, r) in zip(xs, ys, rs):
        cv.circle(img_desk, (x, y), r, (0, 0, 255), 2)

    # 显示结果
    image_show(img_desk)

实现方式3(梯度法):

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()


if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 边缘检测
    img_canny = cv.Canny(img_gray, 100, 400)

    # 参数设置
    img_dr = 1            # 半径分辨率
    MinRadius = 10        # 最小圆半径
    MaxRadius = 100       # 最大圆半径
    thresh1 = 40          # 累加的阈值
    thresh2 = 90          # 交集的阈值

    # 设置直线长度
    height, width = img_canny.shape
    lmax = height + width

    # 计算梯度
    Ix = cv.Sobel(img_gray, cv.CV_64F, 1, 0)
    Iy = cv.Sobel(img_gray, cv.CV_64F, 0, 1)
    Ix = Ix / (np.sqrt(Ix**2 + Iy**2) + 1e-5)
    Iy = Iy / (np.sqrt(Ix ** 2 + Iy ** 2) + 1e-5)

    # 设置计数器
    N = np.zeros((height, width), np.int32)

    # 获取边缘像素位置
    edge_y, edge_x = np.where(img_canny == 255)

    # 循环绘制不同直线
    for (x, y) in zip(edge_x, edge_y):

        # 获取不同点梯度
        grad_x = Ix[y, x]
        grad_y = Iy[y, x]

        # 根据点和梯度绘制直线
        line_sx = int(x + grad_x * lmax)
        line_sy = int(y + grad_y * lmax)

        line_ex = int(x - grad_x * lmax)
        line_ey = int(y - grad_y * lmax)

        line = np.zeros((height, width), np.uint8)
        cv.line(line, (line_sx, line_sy), (line_ex, line_ey), 255, 1)

        # 获取不同圆的轨迹位置
        bsi, asi = np.where(line == 255)

        # 将轨迹经过位置计数器累加
        N[bsi, asi] += 1

    # 显示累加图
    plt.imshow(N, cmap='jet')
    plt.show()

    # 获取圆的位置和半径
    bsi, asi = np.where(N > thresh1)

    # 根据已知的圆心绘制不同半径的圆
    cir_abr = []
    for (a, b) in zip(asi, bsi):
        for r in range(MinRadius, MaxRadius, img_dr):

            # 绘制不同半径的圆
            circles = np.zeros((height, width), np.uint8)
            cv.circle(circles, (a, b), r, 255, 1)

            # 获取绘制圆和边缘图的交集
            intersection = cv.bitwise_and(circles, img_canny)

            # 累计交集的点数
            num_sum = (intersection == 255).sum()

            # 获取超过阈值的圆心和半径
            if num_sum > thresh2:

                cir_abr.append((a, b, r))

    # 绘制检测的圆
    for (a, b, r) in cir_abr:
        cv.circle(img_desk, (a, b), r, (0, 0, 255), 2)

    # 显示结果
    image_show(img_desk)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【千律】OpenCV基础:Hough圆检测 的相关文章

随机推荐

  • MATLAB 排列组合问题

    毕设ing 最近每天除了看论文就是matlab仿真 MATLAB编程强调 vectorization 对矩阵进行操作 毕竟人家名字就叫Mat Lab 矩阵的实验室 对于排列组合问题 按照C语言的思路肯定就用for循环 但是在matlab里
  • MAC-下载安装robotframework

    1 首先 先看自己的电脑有没有自带python which python gt usr bin python 2 查看当前python 版本 python version gt Python 2 7 10 default Oct 23 20
  • 以太坊源码(03):POA委员会选举机制

    目录 1 名词介绍 2 矿工投票方法 3 委员会确定投票流程 3 1 关键概念描述 3 1 1 Epoch checkpointInterval 3 1 2 Snapshot 3 2 投票方法 1 名词介绍 节点 普通的以太坊节点 没有区块
  • 1000 BASE-T1 PMA一致性测试解析

    车载以太网是为了满足汽车行业对高可靠性 低电磁辐射 低功耗 带宽分配 低延迟以及同步实时性等方面的要求而产生的 目前车载电子控制单元中 最常用的是1000BASE T1技术 其遵循的是IEEE 802 3bp标准规范要求 1000BASE
  • Nginx代理(Linux&Windows)-服务器

    Linux linux一般都是用宝塔面板 一键安装使用 下面是安装完后添加配置就可以指定文件目录了 注意好空格 宝塔阿里云开启端口 宝塔阿里云开启端口 宝塔阿里云开启端口 就okk了 Windows 直接下一个Nginx https pan
  • Angular 和 Flask 全栈简易演示

    对于 JavaScript 框架 MEAN 堆栈以其方式非常有名 我经常遇到项目要求 人们希望使用 Python 构建服务器代码 主要是因为它与物联网 图像处理 数学应用程序或语言选择有关 Django 是 Python 爱好者构建服务器端
  • qt在没有环境下如何运行exe 打包流程-亲测简介可用

    配图 文字流程叙述 0 最好使用release 生成的exe 进行打包 不然最后的文件会特别大几个G 用relese生成的exe打包几十MB 1 用release生成的exe单独复制一份 放入一个自定义的文件夹 2 打开qt编译器命令框 注
  • 计算机网络打不开怎么办,电脑网页打不开怎么回事

    电脑网页打不开怎么回事 电脑网页打不开怎么回事 电脑没有断开网络 却打不开网页 这是怎么回事呢 通常由于电脑的DNS解析出现问题 所以才会导致网页打不开 下面教大家电脑网页打不开怎么回事的解决办法 一 清除DNS解析缓存 关于电脑网页打不开
  • 详细分析vcoco2014HOI数据集

    vcoco images 图片 train2014 共82783张 COCO train2014 000000581921 jpg COCO train2014 000000581922 jpg COCO train2014 0000005
  • 记录ubuntu启动卡在logo界面有鼠标进不了桌面的经历,以及安装ubuntu踩的坑

    出现问题前 我之前安装过很多次ubuntu 不管是虚拟机 4 5次 还是双系统 3 4次 每次都是我自己搞崩的 就是我和之前一样开始安装搜狗输入法 之前没出过问题 然后就是这次安装完 我感觉和之前不一样 就是之前不知道为什么安装完会有pin
  • 波兰表达式 - 前,中,后缀表达式计算转换

    先看一个算术题 3 4 5 6 29 前缀表达式 3456 中缀表达式 3 4 5 6 你会算的 后缀表达式 34 5 6 利用栈的特性来运算表达式 当前我只拿到了 3 4 5 6 让我求它的前缀和后缀 求后缀口诀 1 从左到右看 数字忙显
  • ubuntu 提示 Could not get lock /var/lib/dpkg/lock-frontend.的处理办法

    今天可能操作删除某个程序的时候提示无法删除 给锁定了 一直显示 Waiting for cache lock Could not get lock var lib dpkg lock frontend It is held by proce
  • Optimizer trance—mysql进阶(五十三)

    前面介绍了 如果加个format JOSN会把数据以json的格式返回 如果想看查询的额外信息 还可以在explain之后加个show warning查看 其中如果code为1003 则代表message里的内容是mysql优化器优化之后的
  • Python学习十二:Flask框架

    文章目录 一 Flask 简介 1 1 安装虚拟环境 1 1 1 安装Virtualenv 1 1 2 创建虚拟环境 1 1 3 激活虚拟环境 1 2 安装Flask 1 3 第一个Flask 二 Flask基础 2 1 开启调试模式 2
  • Java测试(1)

    1 什么是软件测试 软件测试就是软件测试人员验证软件是否满足用户的需求 测试的时候要测试满足和不满足的数据 2 软件测试和软件开发的区别 1 本身 开发 广度小 专业度高 测试 所需技能比价广泛 但是专业度低 2 软件测试和软件调式 目的
  • 阿里版GPT来袭——“通义千问”

    4月7日 阿里云在官方公众号中宣布 大模型 通义千问 开始邀请测试 你好 我叫通义千问 在 通义千问 的自我介绍中可知 它是达摩院自主研发的预训练语言模型 能够回答问题 创作文字 还能表达观点 撰写代码 基于上述能力 通义千问 认为其可以在
  • 数据仓库的选择

    author skate time 2010 03 11 数据仓库的选择 数据仓库的选择单从技术方面要从服务器硬件 数据库软件 ETL和前端展示软件 存储系统 仓库的架构设计几方面综合考虑 根据数据库的操作类型不同 数据库一般分为OLAP和
  • ORA-12505, TNS:listener does not currently know of SID given in connect descriptor解决方式

    启动项目连接oracle数据报 ORA 12505 TNS listener does not currently know of SID given in connect descriptor ORA 12505 TNS 监听程序当前无法
  • .NET网站部署到阿里云服务器经验分享

    由于笔者需要将自己的网站上线 所以第一步就是去买了一个阿里云服务器 想要远程访问的话 首先是云数据库的部署 然后是网站的部署 1 云数据库的部署 过程 在云服务器上下载SQLServer 然后把本地的数据库 架构和数据 使用脚本导出保存 再
  • 【千律】OpenCV基础:Hough圆检测

    环境 Python3 8 和 OpenCV 内容 Hough圆检测 将直角坐标系中的一个圆映射为新坐标系中的一个点 对于原直角坐标系中的每一个圆 可以对应 a b r 这样一个点 这个点即为新三维中的点 标准法实现步骤 1 获取原图像的边缘