How can I pythonically us opencv find basketball in an image?

I was working on a pet project to learn a little how to find simple basketball in an image. I tried a bunch of permutations using hough.circles and transform, etc. Over the past few weeks, but I do not seem to come anywhere close to isolating basketball with code examples and my own master.

Here is an example photo: boy with a basketball And here is the result after a simple version of the circle search code I worked with: houghcircle transform circle finding

Does anyone know where I did wrong and how can I fix it?

Here is the code I'm playing:

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) 
+6
source share
2 answers

I agree with other posters that using basketball color is a good approach. Here is some simple code that does this:

 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) 

result:

enter image description here

I suppose that:

  • One and only one basketball is always present.
  • Basketball is the main orange item on the stage.

With these assumptions, if we find anything in the right color, we can take his ball and put a circle in it. Thus, we do not do any circle detection at all.

As you can see in the top image, there are some smaller orange elements (from shorts) that can ruin our estimate of the radius of the ball. The code uses the opening operation ( erosion followed by dilation ) to remove them. This works well for your sample image. But for other images, a different method might be better: using the detection of a circle or contour shape, size, or if we are dealing with video, we could track the position of the ball.

I ran this code (only modified for video) on a random short basketball video, and it worked surprisingly well (not great .. but good).

+3
source

A few thoughts:

  • Filter by color first to simplify the image. If you are looking specifically for orange basketball, you can eliminate many other colors. I would recommend using the HSI color space instead of RGB, but in any case you should be able to exclude colors that are at some distance in the color of 3 places from your trained basketball color.
  • Try replacing Sobel or some other kernel-based detector that does not rely on manual parameters. Display the edge image to see if it is right for you.
  • Allow weaker edges. In the grayscale image, the contrast between the basketball and the player’s dark shirt is not as great as the difference between the white shirt and the black shirt.
  • Hough can give unexpected results if the object is only nominally circular in cross section, but is actually elongated or has noisy edges in the real image. Usually I write my own Hough algorithm and do not affect the OpenCV implementation, so I'm not sure which parameter to change, but see if you can allow more crazy edges.
  • Perhaps this eliminates uptime. In any case, try to smooth out before you find the edges, and not vice versa.
  • Try writing your own Hough algorithm. Although the quickie implementation may not be as flexible as the OpenCV implementation, if you lose your hands, you might stumble upon the source of the problem.
+1
source

All Articles