Detecting balls on a pool table (stripes and solids)

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Detecting balls on a pool table (stripes and solids)



I couldn't find any satisfying answer on that topic. I want to make a program that will get snapshots from camera above the pool table and detect balls. I am using OpenCV and Java. My algorithm now is basically:



blurring image -> converting RGB to HSV -> splitting into 3 planes -> using Canny() on H plane -> using HoughCircles() method to detect balls



This algorithm detects balls quite well, it has problem with two balls only (green and blue, because background of the table is green). But I want to go one step further and:



Do you have any idea how to implement task #1? My idea is to use inRange() function, but then I'd have to prepare a mask for every ball that detects that one ball in specified range of colors, and do this detection for every ball, am I right? Thanks for sharing your opinions.



@Edit: Here I give you some samples of how my algorithm works. I changed some parameters because I wanted to detect everything, and now it works worse, but it still works with quite nice accuracy. I`ll give you three samples of original image from camera, image where I detect balls (undistorted, with some filters) and image with detected balls.



Original image number 1Canny image number 1Image with detected balls number 1



Original image number 2Canny image number 2Image with detected balls number 2





Try posting a sample image for users to test their hypothesis. Even green colored ball is not of same color as green table background.
– saurabheights
Aug 10 at 20:02





I can see detecting solids but stripes would be difficult. I think your best bet would be to get another camera involved and start making comparisons and cross-checking.
– Rob
Aug 10 at 21:16




1 Answer
1



Recommendation:



If you can mask out the pixels corresponding to a ball, the following method should work to differentiate striped/solid balls based on their associated pixels:


p


q



(The idea being that the stripes are white, and always at least partially visible, so striped balls will have a higher proportion of white pixels).



Sample Testing:



Here's an example of this applied (by hand, with p = 0.7) to some of the balls in the unrectified image, with final % white pixels on the right.


p = 0.7



It looks like a classification threshold of q = 0.1 (minimum 10% white pixels to be a striped ball) will distinguish the two groups, although it would be ideal to tune the thresholds based on more data.


q = 0.1





If you run into issues with shadowed balls using this method, you also can try rescaling each ball's brightnesses before thresholding (so that the brightnesses span the full range 0, 1), which should make the method less dependent on the absolute brightness.





I'll try this out next week and make some updates on the topic. If someone else has some ideas at setting the ball ID or sth then feel free to share.
– Jakub Boruk
Aug 11 at 5:51





For ball ID you can maybe get away with just finding the dominant hue of each ball's pixels (convert to HSV, take a saturation-weighted average of the hue values), then sorting balls by their hue values to get a canonical ordering (since regardless of the lighting, the relative hues should be in the same order). You would need special cases for the white/black balls, though. A more powerful option is to use histogram intersection (mpatacchiola.github.io/blog/2016/11/12/…), or just compute histogram feature vectors and train an SVM.
– Ollin Boer Bohan
Aug 11 at 17:15





Oh! I mean using threshold (docs.opencv.org/3.4/javadoc/org/opencv/imgproc/…) with p as the threshold. I think you can count white/black pixels by using a histogram (opencv-java-tutorials.readthedocs.io/en/latest/…) with the mask argument set to be the pixels of the circle, then using the top bin as the number of white pixels and the bottom bin as the number of black pixels.
– Ollin Boer Bohan
Aug 13 at 15:34


threshold


p





The image I posted used Lightness (same as your comment). For the yellow/purple balls, you can try rescaling/normalizing the brightnesses before thresholding, or (equivalently, I think?) making the threshold adaptive (i.e. threshold = k + (1-k) * (average lightness of ball) for some k in [0,1]). In the worst case, you can do dominant hue computations first and make a lookup table that maps hue ranges -> thresholds (so, higher threshold for yellow, low threshold for purple).
– Ollin Boer Bohan
Aug 14 at 14:05



threshold = k + (1-k) * (average lightness of ball)


k





I mean I wanted to use the number of white pixels just to differentiate white and black ball. I thought that white ball will have most white pixels, and black ball least. No more questions then, I'll handle it with the method u mentioned. Thank you for help, cheers!
– Jakub Boruk
Aug 15 at 17:45






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard