如何通过pythonicalius opencv在图像中查找篮球?

如何通过pythonicalius opencv在图像中查找篮球?,python,opencv,image-processing,numpy,hough-transform,Python,Opencv,Image Processing,Numpy,Hough Transform,我一直在做一个宠物项目,研究如何在图片中找到一个简单的篮球。在过去的几周里,我尝试了使用hough.circles和transform等的一系列排列,但我似乎无法用代码示例和我自己的修补程序来孤立篮球 以下是一张示例照片: 下面是我一直在修补的一个简单版本的圆查找代码的结果: 有人知道我哪里出了错,我怎样才能把它弄对吗 以下是我正在处理的代码: import cv2 import cv2.cv as cv # here import numpy as np def draw_circles(

我一直在做一个宠物项目,研究如何在图片中找到一个简单的篮球。在过去的几周里,我尝试了使用hough.circles和transform等的一系列排列,但我似乎无法用代码示例和我自己的修补程序来孤立篮球

以下是一张示例照片: 下面是我一直在修补的一个简单版本的圆查找代码的结果:

有人知道我哪里出了错,我怎样才能把它弄对吗

以下是我正在处理的代码:

import cv2
import cv2.cv as cv # here
import numpy as np

def draw_circles(storage, output):
    circles = np.asarray(storage)
    for circle in circles:
        Radius, x, y = int(circle[0][3]), int(circle[0][0]), int(circle[0][4])
        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)

 orig = cv.LoadImage('basket.jpg')
 processed = cv.LoadImage('basket.jpg',cv.CV_LOAD_IMAGE_GRAYSCALE)
 storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)
 #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 more
 cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)

 cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, 550)
 draw_circles(storage, orig)

 cv.imwrite('found_basketball.jpg',orig)
一些想法:

  • 首先按颜色过滤以简化图像。如果你特别想要一个橙色的篮球,你可以去掉很多其他颜色。我建议使用HSI颜色空间而不是RGB,但在任何情况下,你都应该能够排除颜色空间中与你训练过的篮球颜色有一定距离的颜色
  • 尝试替换Sobel或其他不依赖手动参数的基于内核的边缘检测器。显示边缘图像,以查看它在您看来是否“正确”
  • 考虑到较弱的边缘。在灰度图像中,篮球和球员深色球衣之间的对比度不如白色汗衫和黑色球衣之间的差异大
  • 如果对象在横截面上只是名义上的圆形,但实际上被拉长或在实际图像中有噪声边缘,则Hough可能会产生意外的结果。我通常编写自己的Hough算法,但没有涉及OpenCV实现,因此我不确定要更改哪些参数,但看看是否可以允许更模糊的边
  • 可能会影响平稳运行。在任何情况下,在找到边之前都要尝试平滑,而不是相反
  • 尝试编写自己的粗略Hough算法。尽管快速实现可能不如OpenCV实现灵活,但弄脏手后,您可能会无意中发现问题的根源

  • 我同意其他的海报,使用篮球的颜色是一个很好的方法。下面是一些简单的代码:

    import cv2
    import numpy as np
    
    im = cv2.imread('../media/basketball.jpg')
    
    # convert to HSV space
    im_hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
    # take only the orange, highly saturated, and bright parts
    im_hsv = cv2.inRange(im_hsv, (7,180,180), (11,255,255))
    
    # To show the detected orange parts:
    im_orange = im.copy()
    im_orange[im_hsv==0] = 0
    # cv2.imshow('im_orange',im_orange)
    
    # Perform opening to remove smaller elements
    element = np.ones((5,5)).astype(np.uint8)
    im_hsv = cv2.erode(im_hsv, element)
    im_hsv = cv2.dilate(im_hsv, element)
    
    points = np.dstack(np.where(im_hsv>0)).astype(np.float32)
    # fit a bounding circle to the orange points
    center, radius = cv2.minEnclosingCircle(points)
    # draw this circle
    cv2.circle(im, (int(center[1]), int(center[0])), int(radius), (255,0,0), thickness=3)
    
    out = np.vstack([im_orange,im])
    cv2.imwrite('out.png',out)
    
    结果:

    我假设:

  • 始终只有一个篮球在场
  • 篮球是场景中主要的橙色项目
  • 根据这些假设,如果我们发现任何颜色正确的东西,我们可以假设它是球,并在球上画一个圆。这样我们根本不做任何圆检测

    正如你在上图中看到的,有一些较小的橙色元素(来自短裤),这会打乱我们的球半径估计。代码使用
    打开
    操作(
    腐蚀
    ,然后是
    膨胀
    )来删除这些。这对于您的示例图像非常有效。但对于其他图像,另一种方法可能更好:也使用圆检测,或者轮廓形状、大小,或者如果我们正在处理视频,我们可以跟踪球的位置


    我在一个随机的短篮球视频上运行了这段代码(仅针对视频进行了修改),它运行得出奇地正常(不太好..但正常)。

    与其将文件加载为灰度图像,不如将其加载为彩色图像,在将图像展平并将其传递给Canny过滤器之前,进行一些预处理以强调球的橙色?感谢您花时间玩这个游戏,并分享一些代码进行实验,并解释解决它背后的逻辑,这是在编码之前解决问题的一个很好的基本方法。