Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recognize a red ball's position in an image with JavaScript?

Say I have this image:

enter image description here

I'd like to recognize the position of the red ball in the image, I could measure the size of the ball(in pixel) in ahead.

I know that I could draw the image to a canvas, then I could get the pixel color data with context.getImageData, but then what should I do? which algorithm sould I use? I'm new to image processing, thanks a lot.

like image 969
wong2 Avatar asked May 07 '12 12:05

wong2


1 Answers

Here's code dedicated to getting that ball position. The output position will logged to the console so have your JS console open! This code has some values in it that you can play with. I chose some that work for your image such as the rough diameter of the ball being 14 pixels and the threshold for each colour component.

I saved the image as "test.jpg" but you can change the code to the correct image path on line 11.

<!DOCTYPE html>
<html>
    <body>
        <canvas width="800" height="600" id="testCanvas"></canvas>
        <script type="text/javascript">
            var img = document.createElement('img');
            img.onload = function () {
                console.log(getBallPosition(this));
            };
            img.src = 'test.jpg';

            function getBallPosition(img) {
                var canvas = document.getElementById('testCanvas'),
                    ctx = canvas.getContext('2d'),
                    imageData,
                    width = img.width,
                    height = img.height,
                    pixelData,
                    pixelRedValue,
                    pixelGreenValue,
                    pixelBlueValue,
                    pixelAlphaValue,
                    pixelIndex,
                    redThreshold = 128,
                    greenThreshold = 40,
                    blueThreshold = 40,
                    alphaThreshold = 180,
                    circleDiameter = 14,
                    x, y,
                    count,
                    ballPosition,
                    closestBallCount = 0,
                    closestBallPosition;

                // Draw the image to the canvas
                canvas.width = width;
                canvas.height = height;
                ctx.drawImage(img, 0, 0);

                // Get the image data
                imageData = ctx.getImageData(0, 0, width, height);
                pixelData = imageData.data;

                // Find the ball!
                for (y = 0; y < height; y++) {
                    // Reset the pixel count
                    count = 0;

                    // Loop through the pixels on this line
                    for (x = 0; x < width; x++) {
                        // Set the pixel data starting point
                        pixelIndex = (y * width * 4) + (x * 4);

                        // Grab the red pixel value
                        pixelRedValue = pixelData[pixelIndex];
                        pixelGreenValue = pixelData[pixelIndex + 1];
                        pixelBlueValue = pixelData[pixelIndex + 2];
                        pixelAlphaValue = pixelData[pixelIndex + 3];

                        // Check if the value is within out red colour threshold
                        if (pixelRedValue >= redThreshold && pixelGreenValue <= greenThreshold && pixelBlueValue <= blueThreshold && pixelAlphaValue >= alphaThreshold) {
                            count++;
                        } else {
                            // We've found a pixel that isn't part of the red ball
                            // so now check if we found any red data
                            if (count === circleDiameter) {
                                // We've found our ball
                                return {
                                    x: x - Math.floor(circleDiameter / 2),
                                    y: y
                                };
                            } else {
                                // Any data we found was not our ball
                                if (count < circleDiameter && count > closestBallCount) {
                                    closestBallCount = count;
                                    closestBallPosition = {
                                        x: x - Math.floor(circleDiameter / 2),
                                        y: y
                                    };
                                }
                                count = 0;
                            }
                        }
                    }
                }

                return closestBallPosition;
            }
        </script>
    </body>
</html>
like image 107
Rob Evans Avatar answered Oct 14 '22 08:10

Rob Evans