HoughCircles 无法检测到该图像上的圆圈

2023-11-25

我试图检测图像中包含圆点的圆圈,但不幸的是我无法这样做。我正在使用 opencv 霍夫变换,但找不到使其工作的参数。

src = imread("encoded.jpg",1);
    /// Convert it to gray
    cvtColor(src, src_gray, CV_BGR2GRAY);

    vector<Vec3f> circles;

    /// Apply the Hough Transform to find the circles
    HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, 10,
        100, 30, 1, 30 // change the last two parameters
        // (min_radius & max_radius) to detect larger circles
        );

    /// Draw the circles detected
    for (size_t i = 0; i < circles.size(); i++)
    {
        cout << "Positive" << endl;
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);
        // circle center
        circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
        // circle outline
        circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);
    }

    /// Show your results
    namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
    imshow("Hough Circle Transform Demo", src_gray);
    waitKey(0);

My Image is here: Input Image

为什么 HoughCircles 无法检测到该图像中的圆圈?它似乎正在研究其他更简单的图像,例如电路板。


我遇到了你的确切问题并找到了解决方案

关键是对 HoughCircles 正在做的事情有足够的直觉,这样您就可以构建一个程序,为您想要在其中查找圆圈的所有各种图像自动调整超参数。

核心问题,一些直觉

HoughCircles 并不是独立存在的,尽管它建议它可以使用最小和最大半径参数,但您需要运行数百或数千次迭代才能在正确的设置中自动调整和自动拨号。完成后,您需要进行后处理验证步骤,以 100% 确定该圆是您想要的。问题是您试图通过猜测和检查来手动调整 HoughCircles 的输入参数。那根本行不通。让计算机为您自动调整这些参数。

HoughCircles 的手动调整什么时候才能令人满意?

如果您想手动对参数进行硬编码,那么您绝对需要的一件事就是圆的精确半径在一两个像素之内。您可以猜测 dp 分辨率并设置累加器数组投票阈值,您可能会没事。但如果您不知道半径,HoughCircles 输出就没用,因为它要么到处都能找到圆,要么根本找不到圆。假设您确实手动找到了可接受的调整,您向它显示了一个有几个像素不同的图像,您的 HoughCircles 会惊慌失措,在图像中发现了 200 个圆圈。一文不值。

还有希望:

希望来自这样一个事实:即使在处理大图像时,HoughCircles 也非常快。您可以为 HoughCircles 编写一个程序来完美地自动调整设置。如果您不知道半径并且它可能很小或很大,那么您可以从较大的“最小距离参数”、非常精细的 dp 分辨率和非常高的投票阈值开始。因此,当您开始迭代时,HoughCircles 可以预见地拒绝找到任何圈子,因为设置过于激进并且投票没有清除阈值。但循环会不断迭代并逐渐达到最佳设置,让最佳设置成为指示您已完成的避雷针。您找到的第一个圆将是图像中像素完美的最大且最佳的圆,您会对 HoughCircles 为您提供的像素完美的圆印象深刻,就在它应该在的位置。只是你必须运行它 5000 次。

python 代码示例(抱歉,它不是 C++):

它的边缘仍然很粗糙,但你应该能够清理它,这样你就可以在不到一秒钟的时间内获得令人满意的像素完美结果。

import numpy as np
import argparse
import cv2
import signal

from functools import wraps
import errno
import os
import copy

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())

# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args["image"])
orig_image = np.copy(image)
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

cv2.imshow("gray", gray)
cv2.waitKey(0)

circles = None

minimum_circle_size = 100      #this is the range of possible circle in pixels you want to find
maximum_circle_size = 150     #maximum possible circle size you're willing to find in pixels

guess_dp = 1.0

number_of_circles_expected = 1          #we expect to find just one circle
breakout = False

#hand tune this
max_guess_accumulator_array_threshold = 100     #minimum of 1, no maximum, (max 300?) the quantity of votes 
                                                #needed to qualify for a circle to be found.
circleLog = []

guess_accumulator_array_threshold = max_guess_accumulator_array_threshold

while guess_accumulator_array_threshold > 1 and breakout == False:
    #start out with smallest resolution possible, to find the most precise circle, then creep bigger if none found
    guess_dp = 1.0
    print("resetting guess_dp:" + str(guess_dp))
    while guess_dp < 9 and breakout == False:
        guess_radius = maximum_circle_size
        print("setting guess_radius: " + str(guess_radius))
        print(circles is None)
        while True:

            #HoughCircles algorithm isn't strong enough to stand on its own if you don't
            #know EXACTLY what radius the circle in the image is, (accurate to within 3 pixels) 
            #If you don't know radius, you need lots of guess and check and lots of post-processing 
            #verification.  Luckily HoughCircles is pretty quick so we can brute force.

            print("guessing radius: " + str(guess_radius) + 
                    " and dp: " + str(guess_dp) + " vote threshold: " + 
                    str(guess_accumulator_array_threshold))

            circles = cv2.HoughCircles(gray, 
                cv2.HOUGH_GRADIENT, 
                dp=guess_dp,               #resolution of accumulator array.
                minDist=100,                #number of pixels center of circles should be from each other, hardcode
                param1=50,
                param2=guess_accumulator_array_threshold,
                minRadius=(guess_radius-3),    #HoughCircles will look for circles at minimum this size
                maxRadius=(guess_radius+3)     #HoughCircles will look for circles at maximum this size
                )

            if circles is not None:
                if len(circles[0]) == number_of_circles_expected:
                    print("len of circles: " + str(len(circles)))
                    circleLog.append(copy.copy(circles))
                    print("k1")
                break
                circles = None
            guess_radius -= 5 
            if guess_radius < 40:
                break;

        guess_dp += 1.5

    guess_accumulator_array_threshold -= 2

#Return the circleLog with the highest accumulator threshold

# ensure at least some circles were found
for cir in circleLog:
    # convert the (x, y) coordinates and radius of the circles to integers
    output = np.copy(orig_image)

    if (len(cir) > 1):
        print("FAIL before")
        exit()

    print(cir[0, :])

    cir = np.round(cir[0, :]).astype("int")

    # loop over the (x, y) coordinates and radius of the circles
    if (len(cir) > 1):
        print("FAIL after")
        exit()

    for (x, y, r) in cir:
        # draw the circle in the output image, then draw a rectangle
        # corresponding to the center of the circle
        cv2.circle(output, (x, y), r, (0, 0, 255), 2)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

    # show the output image
    cv2.imshow("output", np.hstack([orig_image, output]))
    cv2.waitKey(0)

因此,如果你运行它,需要花费 5 秒的时间,但它几乎可以达到像素完美(进一步手动调整自动调谐器可以使其达到亚像素完美):

The above code converts this: Original

To this:

HoughCircles

让这项工作成功的秘诀在于在开始之前你掌握了多少信息。如果您知道半径达到一定的公差(例如 20 像素),那么这非常有效,您就完成了。但如果你不这样做,你就必须聪明地了解如何通过小心接近决议和投票阈值来爬升最大投票半径。如果圆圈的形状很奇怪,则 dp 分辨率需要更高,而投票阈值则需要探索更低的范围。

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

HoughCircles 无法检测到该图像上的圆圈 的相关文章

随机推荐

  • jQuery detach() vs remove() vs hide() [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我在我的页面中使用高图表
  • -1 到 1 之间的随机数总和为 0 [关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 用R 如何生成n随机数x 1 x n位于之间 1 and 1总和为0 推广到另一个总和和另一个范围怎么样 简单解决第一个问题 这是第一个问题的简单解决方案 模拟u 1 u n之间 1
  • Asp.Net MVC Core 启用双重转义

    我正在开发一个 asp net mvc 核心应用程序并尝试允许双重转义 我的编辑网址有一个电话号码作为超链接 例如 123 我知道如何使用普通的 ASP NET MVC 应用程序 我曾经将 web config 文件更改为
  • 创建类型的默认实例[重复]

    这个问题在这里已经有答案了 反射等价于 default object null 当我直到运行时才知道类型时 例如 public void Method Type type var instance type CreateDefault no
  • iPhone 使用 GData 框架将视频上传到 YouTube 应用

    我想将视频从我的应用上传到 YouTube 我正在使用 YoutubeTest 示例来实现此目的 我已经为我的应用程序设置了开发人员密钥和客户端 ID 现在 当尝试使用示例源代码上传视频时 它显示一个错误 2012 03 19 10 51
  • nd_pdo_mysql 和 pdo_mysql 扩展之间有什么区别?

    由于某种原因pdo mysql我们的托管服务器上的 PHP 扩展无法运行使用 MySQL 视图的查询 并出现此错误消息 SQLSTATE HY000 一般错误 1615 准备好的语句需要重新准备 有一个讨论Bug 42041 当 MySQL
  • app.UseErrorHandler() 可以访问错误详细信息吗?

    在我的 MVC4 应用程序中 我覆盖了 global asax csApplication Error object sender EventArgs e 我可以在哪里提取exception statusCode and requested
  • gcloud docker Push 403 禁止

    我正在尝试将 docker 映像推送到 eu gcr io 但收到 403 Forbidden gcloud docker push eu gcr io
  • Schema.org 中网页结构的隐含性

    在阅读了数千篇帖子 问题 博客文章和意见之后 我仍然对如何使用微数据标记网页感到有点困惑 如果微数据的主要目的是帮助搜索引擎更好地理解网页的内容 并且隐式假设网页 那么在 body 元素中从 itemtype Webpage 开始 然后继续
  • 模板类特化的模板方法

    这是我的代码 template
  • 泛型的 JSON 序列化

    我有一堂课 看起来像这样 public class MyData IList
  • Google Chrome 扩展程序的 Paypal 按钮

    我正在尝试向我的 google chrome 扩展添加一个捐赠按钮 因为我喜欢钱 我遇到了麻烦 因为 Chrome 扩展程序尝试在 popup html 窗口中打开 paypal 创建的捐赠按钮 当我单击该按钮时 我的扩展程序会重新启动 并
  • 不带逗号的 NumberFormat 文本字段

    我有一个JFormattedTextField我想接受 5 位数字范围内的数字 以下代码可以正确运行 myNumberBox new JFormattedTextField NumberFormat getIntegerInstance 但
  • Python:以 Value 作为字典获取前 n 个键

    我有一本字典 比如 data sachin score 15000 out 100 Dhoni score 8000 out 80 Shewag score 12000 out 150 我想要两名得分最高的球员 所以我尝试过 key key
  • 将工具提示与 link_to 结合使用 (Ruby on Rails 3.2.3)

    我已经成功使用类似于以下的代码创建了文本工具提示 a href title something text on page a 不过 我想使用 link to 命令为菜单中定义的链接提供工具提示 我已经包含了我希望出现工具提示的声明 li i
  • Perl 脚本可以修改自身吗?

    我想让我的脚本在内部跟踪最后一次修订日期作为评论 这可能吗 在我看来 它需要获取日期 然后打开其脚本文件进行追加 写入数据并保存文件 谢谢 Everone 非常好的答案 根据 GreenMatt 留下的代码片段 我将其放在一起 usr bi
  • 为 UIView 及其所有子视图着色

    有什么方法可以给 UIView 着色吗 不是背景颜色 而是整个 UIView 及其所有子视图 例如 带有星星旋转动画的 UIView 即 UIView 形状不断变化 最终我创建了一个 UIView 类别 可以对 UIView 进行着色 没有
  • Laravel 本地化以及来自 Jetstream / Fortify 的路线

    我有一个新的 Laravel 项目要处理 我们希望以多种语言提供它 我从 JetStream 开始了这个项目 身份验证等路由由 JetStream Fortify 自动处理 然后我添加了https github com mcamara la
  • 如何构建和使用 Google TensorFlow C++ api

    我真的很渴望开始在 C 中使用 Google 新的 Tensorflow 库 网站和文档对于如何构建项目的 C API 确实不清楚 我不知道从哪里开始 有更多经验的人可以通过发现和分享使用 TensorFlow 的 C API 的指南来提供
  • HoughCircles 无法检测到该图像上的圆圈

    我试图检测图像中包含圆点的圆圈 但不幸的是我无法这样做 我正在使用 opencv 霍夫变换 但找不到使其工作的参数 src imread encoded jpg 1 Convert it to gray cvtColor src src g