打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
编写健壮(颜色和大小不变),圆检测用opencv实现(基于Hough变换或其他特征)

编写健壮(颜色和大小不变),圆检测用opencv实现(基于Hough变换或其他特征)

c++pythoncopencvcomputer-vision-电脑-视力
我写了下面很简单的Python代码找到圈中的图像:
import cvimport numpy as npWAITKEY_DELAY_MS = 10STOP_KEY = 'q'cv.NamedWindow("image - press 'q' to quit", cv.CV_WINDOW_AUTOSIZE);cv.NamedWindow("post-process", cv.CV_WINDOW_AUTOSIZE);key_pressed = Falsewhile 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)
正如你可以从下面的两个例子看到,“圈子发现质量”变化颇多: CASE1: CASE2: 案例1案例2和基本形象,但仍算法检测到不同的圈子。如果我提出的算法的图像与不同大小的圆圈,在圆检测甚至可能这主要是由于HIGHLOW这需要单独为每个新的图片。 因此,我的问题:什么使这个算法的可能性更应该是大小和颜色不变,让各界有不同的颜色和不同尺寸的检测。 Hough变换是不是做事情的最好方法是什么?有没有更好的办法?
本文地址 :CodeGo.net/435070/

-------------------------------------------------------------------------------------------------------------------------

1. 下面是根据我作为一个愿景研究员体验。从你的问题,你似乎有兴趣在可能的算法的代码,而只是一个工作片。首先,我给你的样本图像和结果的快速和肮脏的Python脚本显示证明它也可能解决您的问题。得到这些闪开之后,我尝试回答你的问题有关检测算法。 快速结果 样本图像(除了你的所有图像都是从下载并消委会行货)与检测到的圆圈(不改变/调整任何确切下面的代码来提取圈子中的所有图像):代码(基于MSER的Blob检测器) 这里是代码:
import cv2import mathimport numpy as npd_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 Truesfs = [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] = origvis[:h, w+5:w*2+5] = imgcv2.imshow("image", vis)cv2.imwrite("c_o.jpg", vis)cv2.waitKey()cv2.destroyAllWindows()
正如你可以看到它的基础上,MSER的blob检测。代码没有预处理的图像除了简单的映射成灰度。缺少这些淡yellow的斑点在你的图像的预期。 理论 总之:你不知道怎么样的问题,除了与他们的描述只给出两个示例图像。在这里,我解释为什么我在我的愚见是问什么是攻击问题之前,有关于这个问题是很重要的。 回到主要问题:什么是这个问题?让我们来看看这是一个搜索问题。为了简化,我们正在寻找圆与给定尺寸/问题归结为找到中心.each像素是候选中心,因此,在搜索空间中包含的所有像素。
P = {p1, ..., pn} P: search spacep1...pn: pixels
为了解决这个问题,寻找其他两个函数应该被定义为:
E(P) : enumerates the search spaceV(p) : checks whether the item/pixel has the desirable properties, the items passing the check are added to the output list
假设算法无所谓,或将强力搜索可以在其中E需要的每一个像素,并传递到五,在实际应用中,重要的是要减少搜索空间和V的效率 我们正在接近主要问题。我们如何定义V,更准确地说应该如何应做什么候选人的性能解决分割成的两分法的问题可取和不可取。该方法是找到定义基于属性的简单决策规则的属性可以。这是你做的试验和错误是什么。你是从正面和负面的例子,学习编程的分类。这是你不知道你想要做什么。你必须/乐曲的决策规则和/或预处理的数据,即,对于二分法问题所用的属性的变化(所希望的候选)被减少。你的机器学习算法,以找到一组给定的例子的最优值。还有一大堆的从决策树学习算法编程你这个问题。你可以一个学习算法找到几个圆检测算法的最优值,看看哪一个给出了一个更好的精度。这需要你只需要收集样本图像的学习算法的主要负担。 另一种方法来提高它经常被忽视的是利用额外随手如果您知道圆的颜色几乎为零额外的努力,你可以提高检测的准确性显著。如果您知道圆的平面上的位置,你想检测的成像圈,你应该把这两套位置之间的转换是通过一个2D单应说明。和单应可只得到4分。然后,你可以提高到有石头的特定领域的知识的价值往往被低估。看它这样,在第一种方法中,我们尝试基于样本数量有限近似决策规则。在第二种方法中,我们知道了决策规则,只需要找到一种方法来有效地利用他们的算法。 总结 总之,有两种方法来提高解的精度/:工具型:找到一个更简单的算法/用较少的/扭捏算法/自动化这个过程中机器学习算法号 信息化:都是很容易在你不要的问题“你知道的问题是什么。对于这两个图像您分享我一个blob检测不是针对背景减除我建议尝试估计的背景颜色的两个图像是没有变化的,而圆圈的颜色有所不同。和大部分区域是光秃秃的。

2. 这是一个伟大的建模问题。我有以下想法:分割图像为RGB然后处理。 预处理。 动态搜索。 添加约束。 可以肯定你正在尝试检测一下。更详细地说: 1:正如在其他的答案,直接转换为灰度丢弃了-一个类似的亮度与背景的任何圈子都将丢失。好得多考虑颜色通道或单独或以不同的颜色空间。有相当多的两种方法去这里:执行HoughCircles在隔离,结果,或者,处理通道,每个通道处理前通道上,其中,然后操作HoughCircles。在下面我尝试,我试图分裂为RGB通道,处理,警惕过度饱和的图像cv.And为了避免这个问题(在这个阶段我的圈子总是在白色背景上的黑色戒指/盘)。 2:前处理是相当棘手的,其往往是最好的玩弄。我已经为AdaptiveThreshold这是一个非常强大的,可以通过阈值处理根据他们当地的平均像素提升图像边缘(类似的过程也发生在哺乳动物视觉系统的早期通路)。这是因为它降低了噪音。我dilate/erode只有一个通行证。我一直保留着你如何让他们的其他。它CannyHoughCircles的确帮助了很多与发现“实心圆',所以可能最好保持它。这前处理是相当沉重的,并可能导致更多的'滴状圈子'假阳性,但在我们的情况下,这或许是可取的? 3:正如您所指出的HoughCirclesparam2(您的LOW)需要为每个图像,以获得最佳的解决方案,其实从文档:较小的是,可以检测到更多的假圆圈。trouble的是甜蜜点将会是不同的每张图片。我觉得这里的最好的办法是让设置一个条件,通过做不同的搜索param2值,直到这个条件你的图片显示不重叠的圆圈,而当param2太低,我们通常会得到重叠的圆圈负荷。所以我建议寻找的:的非重叠的最大数量,和非包含的圆因此,我们继续呼吁HoughCircles用不同的值param2直到我做到这一点我下面的例子中,仅仅通过param2直到它达到阈值的假设。这将是更快的方式(而且很容易做到),如果你执行一个二进制搜索找到的时候,但你必须要小心,异常处理作为opencv的经常抛出一个错误,对无辜的值param2(至少在我的安装)。不同的条件,我们将要匹配的将是圆的数量。 4:有没有更多的约束,我们可以添加到模型?越多的东西,我们可以告诉我们的模型的一个简单的任务,我们可以把它检测圈。例如,我们知道:圈数。-即使是上限或下限是有帮助的。 或背景的圆圈的可能的颜色,或“非圆形”。 它们的大小。 在那里他们可以在一个图像。5:影像中的斑点可能只是笼统地被称为圈子!考虑两个'非圆形的斑点“在你的第二个形象,我的代码无法找到他们(good!),但...如果我'的Photoshop'他们,让他们有更圆,我的代码中可以找到它们...也许如果你要检测的东西都是不圆,采用不同的方法,如Tim Lukins可能会更好。 问题 通过这样做繁重的预处理AdaptiveThresholding和`康力“可以有很多失真特性的图像,这可能会导致错误的检测圆的,或不正确的报告。例如加工后大量固态盘会出现一个圈,所以HughesCircles可能会发现内环。此外,即使该文档注意:...通常功能检测的圆圈“中心好,但它可能无法找到正确的半径。如果您需要更精确的半径的检测,我建议以下方法(不原始图像,光线追迹从圆的中心报道,在不断扩大的交叉(4条:上/下/左/右) 在每个RGB通道单独做到这一点 在一个合理的方式结合起来,每个通道的每个射线(即翻转,偏移,规模等必要的) 取平均值为每条射线的前几个像素,用它来检测其中射线上的显著发生偏差。 这4点是圆周上的点估计。 使用这四个估计,以确定更精确和中心位置(!)。 这可以推广的膨胀环来代替4射线。结果 在结束该代码确实很不错了不少的这些例子介绍的都是代码如下所示: 检测各界在你的第一个图像: 如何处理前图像看上去之前精明的过滤器被应用(不同颜色的圆圈是高度可见的): 检测所有,但两(斑点)在第二个图像: 改变第二图像(斑点是圆afied,和大的椭圆形变得更圆,提高检测),所有检测到的: 确实颇能检测这个康定斯基的绘画中心(我无法找到,由于他的边界条件同心环)。 代码:
import cvimport numpy as npoutput = cv.LoadImage('case1.jpg')orig = cv.LoadImage('case1.jpg')# create tmp imagesrrr=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)ggg=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)bbb=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)processed = cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)def channel_processing(channel): pass cv.AdaptiveThreshold(channel, channel, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=55, param1=7) #mop up the dirt cv.Dilate(channel, channel, None, 1) cv.Erode(channel, channel, None, 1)def inter_centre_distance(x1,y1,x2,y2): return ((x1-x2)**2 + (y1-y2)**2)**0.5def colliding_circles(circles): for index1, circle1 in enumerate(circles):  for circle2 in circles[index1+1:]:   x1, y1, Radius1 = circle1[0]   x2, y2, Radius2 = circle2[0]   #collision or containment:   if inter_centre_distance(x1,y1,x2,y2) < Radius1 + Radius2:    return Truedef find_circles(processed, storage, LOW): try:  cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, LOW)#, 0, 100) great to add circle constraint sizes. except:  LOW += 1  print 'try'  find_circles(processed, storage, LOW) circles = np.asarray(storage) print 'number of circles:', len(circles) if colliding_circles(circles):  LOW += 1  storage = find_circles(processed, storage, LOW) print 'c', LOW return storagedef draw_circles(storage, output): circles = np.asarray(storage) print len(circles), 'circles found' for circle in circles:  Radius, x, y = int(circle[0][2]), int(circle[0][0]), int(circle[0][1])  cv.Circle(output, (x, y), 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)  cv.Circle(output, (x, y), Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)#split image into RGB componentscv.Split(orig,rrr,ggg,bbb,None)#process each componentchannel_processing(rrr)channel_processing(ggg)channel_processing(bbb)#combine images using logical 'And' to avoid saturationcv.And(rrr, ggg, rrr)cv.And(rrr, bbb, processed)cv.ShowImage('before canny', processed)# cv.SaveImage('case3_processed.jpg',processed)#use canny, as HoughCircles seems to prefer ring like circles to filled ones.cv.Canny(processed, processed, 5, 70, 3)#smooth to reduce noise a bit morecv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)cv.ShowImage('processed', processed)#find circles, with parameter searchstorage = find_circles(processed, storage, 100)draw_circles(storage, output)# show imagescv.ShowImage("original with circles", output)cv.SaveImage('case1.jpg',output)cv.WaitKey(0)


3. 啊,是的......旧颜色/尺码不变量界问题(又名Hough变换过于具体,不 在过去,我一直依赖更OpenCV的,而不是结构和形状分析等功能。你可以得到一个很好的主意从什么是可能的“样本”文件夹中-尤其是fitellipse.pysquares.py。 为了您的阐发,我介绍的这些实例的混合动力版,并根据您的原始来源。检测到的轮廓是在红,绿和拟合椭圆。这还没有应用:预处理步骤需要一些调整,以检测更微弱的圈子。 可以进一步测试该轮廓以确定它是否是一个圆或不...祝你好运!
import cvimport numpy as np# grab imageorig = cv.LoadImage('circles3.jpg')# create tmp imagesgrey_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 imagecv.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)storage = cv.CreateMemStorage(0)contours = cv.FindContours(processed, storage, cv.CV_RETR_EXTERNAL)# N.B. 'processed' image is modified by this!#contours = cv.ApproxPoly (contours, storage, cv.CV_POLY_APPROX_DP, 3, 1) # If you wanted to reduce the number of points...cv.DrawContours (orig, contours, cv.RGB(0,255,0), cv.RGB(255,0,0), 2, 3, cv.CV_AA, (0, 0)) def contour_iterator(contour): while contour: yield contour contour = contour.h_next()for c in contour_iterator(contours): # Number of points must be more than or equal to 6 for cv.FitEllipse2 if len(c) >= 6: # Copy the contour into an array of (x,y)s PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2) for (i, (x, y)) in enumerate(c):  PointArray2D32f[0, i] = (x, y) # Fits ellipse to current contour. (center, size, angle) = cv.FitEllipse2(PointArray2D32f) # Convert ellipse data from float to integer representation. center = (cv.Round(center[0]), cv.Round(center[1])) size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5)) # Draw ellipse cv.Ellipse(orig, center, size, angle, 0, 360, cv.RGB(255,0,0), 2,cv.CV_AA, 0)# show imagescv.ShowImage("image - press 'q' to quit", orig)#cv.ShowImage("post-process", processed)cv.WaitKey(-1)
编辑: 刚刚更新的说,我认为一个重要的所有这些答案是,有很多可以应用到你寻求承认为圆形哪些进一步的假设和约束条件。我自己的答案是没有借口在这一点-无论是在低级别的预处理或高级装修。事实上,许多的圆圈是不是真正的圆形,由于它们的绘制方法或图像的non-affine/projective变换,并与它们是如何呈现的其他属性/捕获(颜色,噪声,照明边厚)-所有的结果在短短的一个图像在任何数量的可能的候选圈。 有更复杂的技术。但他们会花费你。我个人喜欢@飞梭想法addaptive门槛。这是快速,可靠,合理,您可以再进一步的测试最终的轮廓(例如使用胡或管件与椭圆轴的一个简单的比率测试-例如,如果((分(大小)/最大(大小))> 0.7)。 一如以往与计算机视觉有实用主义,原则,parsomony之间的紧张关系。由于我喜欢告诉别人谁认为简历是很容易的,它不是-它实际上是一个问题。最好的,你经常可以希望这外面是工作的大部分

4. 翻翻你的代码,我注意到以下几点:灰度转换。我明白你为什么这样做,但要意识到你扔 那里。当您在“后处理”的图像看,你的yellow圆圈的强度为背景,只是以不同的颜色。 边缘检测后噪声消除(erae /扩张)。这不应该是必要的;康力应该利用这一服务。 Canny边缘检测。你的“开放式”圆圈有两个边缘,内和外边缘。因为他们是相当接近,在康力过滤器可能加在一起。如果没有,你就会有两条边紧靠在一起。即康力之前,你必须打开和实心圆。之后,你有0/2和1的边缘,分别。由于霍夫再次调用Canny算子,在第一种情况下的两个边缘可能会平滑地(取决于初始宽度),这就是为什么在核心的Hough算法可以治疗开放和实心圆的所以,我的第一个办法是改变灰度映射。唐的强度,色相/饱和度/值。另外,使用差分方法-你要找的边缘。因此,计算HSV变换,平滑的副本,然后取原和平滑副本之间的差异。这将让你dH, dS, dV值的每个点(在色调,饱和度,数值局部变化)。广场和添加来获得一个图像,附近所有的边(内部和外部)的山峰。 我的第二个是本地的正常化,但我不知道如果这甚至是必要的。这个想法是,你不关心特别多关于你离开了边缘信号的精确值,它应该是二进制反正(边或不)。因此,您可以通过当地的平均水平(其中地方是在你边尺寸的量级)除以正常化的每个值。

5. 霍夫一个“模型”,以找到一个(典型值)边缘检测图像的某些功能,你可知道。在的情况下HoughCircles该模型是一个完美的圆。的,有可能不存在将使得检测更加不稳定和椭圆形的圈里你的照片,而不会增加误报的数量。在另一方面,由于相关的非封闭的正圆或一个完美的圆圈,一个“凹”可能会持续出现。所以根据您的期望输出您可能会或可能不希望 这就是说,有我看这可能会帮助你对你的方式使用此功能的几件事情:HoughCircles电话Canny在内部,所以我想你可以离开了呼叫。param1(你叫HIGH)通常被初始化周围的一个值200。它作为一个到内部调用Cannycv.Canny(processed, cannied, HIGH, HIGH/2)。这可能有助于运行Canny自己喜欢这个,看看如何设置HIGH受影响的霍夫正在处理与图像变换。param2(你叫LOW)通常被初始化围绕一个值100。这是Hough变换的蓄电池的投票门槛。设置它更多的假阴性,更降低误报。我相信这是你想开始摆弄周围的第一个。参考: 重新更新:实心圆:当你发现圆的形状与Hough变换可以测试,如果他们通过采样边界的颜色它假想圆内的一个或多个点的填补。或者你应该圈子给定的背景色内一个或多个点。如果比较或的情况下,如果它失败圆圈显示为实心。

6. 好吧看的图像。我**Active Contours**活动轮廓模型关于活动轮廓的好处是,他们几乎完美融入任何给定的形状。无论是正方形或三角形,在你的情况下,他们是完美的人选。 如果你能够提取圆的中心,这是伟大的。活动轮廓总是需要一个点开始从他们既可以增大或缩小以适合。没有必要使中心总是对准到中心。有一点偏移仍然是好的。 和你的情况,如果你让轮廓,从中心向外生长,应休息一圆的边界。 需要注意的是活动轮廓生长或气球的能量可以设置轮廓的方向,向内或向外。 你可能会需要在灰度梯度图像。但你仍然可以在色彩尝试为好。如果它的工作原理! 如果你不提供中心,扔在大量活跃的轮廓,然后让增长/萎缩。该安定下来的轮廓被保留,不安的是扔掉。这是一个暴力的方法。将CPU密集型。但将需要更多细致的工作,以确保你离开正确的轮廓和扔掉坏的。我希望这种方式可以解决这个问题。



本文标题 :编写健壮(颜色和大小不变),圆检测用opencv实现(基于Hough变换或其他特征)
本文地址 :CodeGo.net/435070/
继续浏览 :python覆盖上一行
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
openCV综合运用:三角形检测
OpenCV基础知识入门
OpenCV下车牌定位算法实现代码(一)
OpenCV学习笔记(6)基于 VC+OpenCV+DirectShow 的多个摄像头同步工作
简单的图像变换
OpenCV成长之路(8):直线、轮廓的提取与描述 - 博客 - 伯乐在线
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服