gpt4 book ai didi

c++ - 使用 OpenCV(基于霍夫变换或其他功能)编写稳健(颜色和大小不变)的圆检测

转载 作者:IT老高 更新时间:2023-10-28 13:58:11 26 4
gpt4 key购买 nike

我编写了以下非常简单的 python 代码来查找图像中的圆圈:

import cv
import numpy as np

WAITKEY_DELAY_MS = 10
STOP_KEY = 'q'

cv.NamedWindow("image - press 'q' to quit", cv.CV_WINDOW_AUTOSIZE);
cv.NamedWindow("post-process", cv.CV_WINDOW_AUTOSIZE);

key_pressed = False
while key_pressed != STOP_KEY:

# grab image
orig = cv.LoadImage('circles3.jpg')

# create tmp images
grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
processed = cv.CreateImage(cv.GetSize(orig), 8, 1)


cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

# do some processing on the grey scale image
cv.Erode(grey_scale, processed, None, 10)
cv.Dilate(processed, processed, None, 10)
cv.Canny(processed, processed, 5, 70, 3)
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

# these parameters need to be adjusted for every single image
HIGH = 50
LOW = 140

try:
# extract circles
cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, HIGH, LOW)

for i in range(0, len(np.asarray(storage))):
print "circle #%d" %i
Radius = int(np.asarray(storage)[i][0][2])
x = int(np.asarray(storage)[i][0][0])
y = int(np.asarray(storage)[i][0][1])
center = (x, y)

# green dot on center and red circle around
cv.Circle(orig, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
cv.Circle(orig, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

cv.Circle(processed, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
cv.Circle(processed, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

except:
print "nothing found"
pass

# show images
cv.ShowImage("image - press 'q' to quit", orig)
cv.ShowImage("post-process", processed)

cv_key = cv.WaitKey(WAITKEY_DELAY_MS)
key_pressed = chr(cv_key & 255)

从以下两个示例中可以看出,“寻圈质量”差异很大:

案例1:

input1
detection1
post-processed1

案例2:

input2
detection2
post-processed2

Case1 和 Case2 基本上是同一张图片,但是算法检测的圆还是不同的。如果我向算法展示具有不同大小圆圈的图像,则圆圈检测甚至可能完全失败。这主要是由于 HIGHLOW需要为每张新图片单独调整的参数。

因此我的问题是:使该算法更加健壮的各种可能性是什么?它应该是大小和颜色不变的,以便检测不同颜色和不同大小的不同圆圈。也许使用霍夫变换不是最好的做事方式?有更好的方法吗?

最佳答案

以下内容基于我作为视觉研究员的经验。从您的问题来看,您似乎对可能的算法和方法感兴趣,而只是对一段有效的代码感兴趣。首先,我为您的示例图像提供了一个快速而肮脏的 Python 脚本,并显示了一些结果以证明它可能会解决您的问题。在解决这些问题之后,我尝试回答您关于稳健检测算法的问题。

快速结果

一些带有检测到的圆圈的示例图像(除您之外的所有图像均从 flickr.com 下载并获得 CC 许可)(无需更改/调整任何参数,正是使用以下代码提取所有图像中的圆圈):
detected blobs in the sample image 1
detected blobs in the sample image 2
lots of circles
blobs in the flickr image 1

代码(基于 MSER Blob Detector)

这是代码:

import cv2
import math
import numpy as np

d_red = cv2.cv.RGB(150, 55, 65)
l_red = cv2.cv.RGB(250, 200, 200)

orig = cv2.imread("c.jpg")
img = orig.copy()
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

detector = cv2.FeatureDetector_create('MSER')
fs = detector.detect(img2)
fs.sort(key = lambda x: -x.size)

def supress(x):
for f in fs:
distx = f.pt[0] - x.pt[0]
disty = f.pt[1] - x.pt[1]
dist = math.sqrt(distx*distx + disty*disty)
if (f.size > x.size) and (dist<f.size/2):
return True

sfs = [x for x in fs if not supress(x)]

for f in sfs:
cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), d_red, 2, cv2.CV_AA)
cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), l_red, 1, cv2.CV_AA)

h, w = orig.shape[:2]
vis = np.zeros((h, w*2+5), np.uint8)
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
vis[:h, :w] = orig
vis[:h, w+5:w*2+5] = img

cv2.imshow("image", vis)
cv2.imwrite("c_o.jpg", vis)
cv2.waitKey()
cv2.destroyAllWindows()

如您所见,它基于 MSER Blob 检测器。除了简单地映射到灰度之外,代码不会对图像进行预处理。因此,预计在您的图像中会丢失那些微弱的黄色 Blob 。

理论

简而言之:除了仅提供两个没有描述的示例图像之外,您不会告诉我们您对问题的了解。在这里,我解释了为什么我以我的拙见,在询问什么是解决问题的有效方法之前获得有关问题的更多信息很重要。

回到主要问题:解决这个问题的最佳方法是什么?
让我们把它看成一个搜索问题。为了简化讨论,假设我们正在寻找具有给定大小/半径的圆。因此,问题归结为找到中心。每个像素都是一个候选中心,因此,搜索空间包含所有像素。
P = {p1, ..., pn} 
P: search space
p1...pn: pixels

为了解决这个搜索问题,应该定义另外两个函数:
E(P) : enumerates the search space
V(p) : checks whether the item/pixel has the desirable properties, the items passing the check are added to the output list

假设算法的复杂性无关紧要,可以使用穷举搜索或蛮力搜索,其中 E 获取每个像素并传递给 V。在实时应用程序中,减少搜索空间并优化 V 的计算效率很重要.

我们离主要问题越来越近了。我们如何定义 V,更准确地说,候选者的哪些属性应该是度量,以及如何解决将它们分为合意和不合意的二分法问题。最常见的方法是找到一些属性,这些属性可用于基于属性的度量来定义简单的决策规则。这就是你通过反复试验所做的。您正在通过从正面和负面示例中学习来编程分类器。这是因为您使用的方法不知道您想要做什么。您必须调整/调整决策规则的参数和/或预处理数据,以便减少用于二分法问题的方法所使用的(理想候选者的)属性的变化。您可以使用机器学习算法为给定的一组示例找到最佳参数值。您可以使用从决策树到遗传编程的大量学习算法来解决这个问题。您还可以使用学习算法为多种圆检测算法找到最佳参数值,并查看哪种算法的准确性更高。这为您只需要收集样本图像的学习算法承担了主要负担。

另一个经常被忽视的提高鲁棒性的方法是利用额外容易获得的信息。如果您以几乎为零的额外努力知道圆圈的颜色,则可以显着提高检测器的准确度。如果您知道圆在平面上的位置并且想要检测成像的圆,您应该记住这两组位置之间的转换是由 2D 单应性描述的。并且可以仅使用四个点来估计单应性。然后,您可以提高鲁棒性以获得坚如磐石的方法。特定领域知识的值(value)常常被低估。这样看,在第一种方法中,我们尝试基于有限数量的样本来近似一些决策规则。在第二种方法中,我们知道决策规则,只需要找到一种方法在算法中有效地利用它们。

概括

总而言之,有两种方法可以提高解决方案的准确性/稳健性:
  • 基于工具 :找到一种更易于使用的算法/参数数量较少/调整算法/通过使用机器学习算法自动化此过程
  • 信息化 : 您是否使用了所有现成的信息?在问题中,您没有提及您对问题的了解。

  • 对于您共享的这两张图像,我将使用 Blob 检测器而不是 HT 方法。对于背景减法,我建议尝试估计背景的颜色,因为在这两个图像中,它不会变化,而圆圈的颜色会有所不同。而且大部分地区都是空的。

    关于c++ - 使用 OpenCV(基于霍夫变换或其他功能)编写稳健(颜色和大小不变)的圆检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9860667/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com