Saturday, December 5, 2009

Programming: Java: Video Tracking: Sobel Algorithm




[ Effect of Sobel Edge Detection Shown in Yellow ]
[ and Color Detection Shown in Blue ]
Intro:
I first experimented with Video Tracking about a year ago, at the time I was programming primarily in VB.net 2008. A powerful language yes, but when it comes to graphics and "time expensive" processes, its bad side begins to shine through.

About a week ago I decided to reopen this project and give it another go, this time in Java. My reasoning? Java runs a lot faster and is much better at handling color arrays, the basis for image recognition.

Summary of technique:
There are many methods for scanning video feeds, none of them perfect. They all have there downfalls. The key of a good tracking program is to use multiple of these methods together so that one methods downfall can be picked up by another ones strong point.

After much research, the types of image recognition I chose to develop upon were:
  • Sobel Edge Detection
  • Color Recognition
  • Motion Detection 

 [ Effect of Sobel Edge Detection Shown in Yellow ]

The Sobel Algorithm:
Sobel Image Analysis is a way of scanning an image and trying to detect where the edges of objects are. This can be especially important if you are scanning high resolution video feeds by first using the Sobel Algorithm to mark points of interest in the image, negating the need to scan the entire image for color or motion.

The algorithm works by looking at each pixel of the image and comparing it to the eight pixels surrounding it. If a pixel surrounding is within a given color threshold then the point is flagged (in my program edges are flagged by a yellow point).

Sobel Example Code: Java

public void Update(BufferedImage buf) {
        img = buf; //Store the image
        int w = img.getWidth(); //Image Width
        int h = img.getHeight(); //Image Height
       
        EdgeMap= new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB); //Create Overlay
       
        for (int x = 0; x < img.getWidth(); x+=scan) { //Scan through each X of the image
            for (int y = 0; y < img.getHeight(); y+=scan) { //For each X scan through each Y of the image
               
                Color C = new Color(img.getRGB(x,y)); //Get the pixel color at the current position
                int GS = ((C.getRed() + C.getGreen() + C.getBlue()) /3); //Generate the GrayScale                                          
                //Sobel Algoritham
                boolean W = false; //Switch for whether the point is an edge
                if (x > scan && x < img.getWidth()-scan) { //Check we aren't on an X edge pixel
                    if (y > scan && y < img.getHeight()-scan) { //Check we aren't on an Y edge pixel
               
                        for (int u = -scan; u <= scan; u+=scan) { //Scan the surrounding X pixels
                            for (int v = -scan; v <= scan; v+=scan) { //For each X scan the surrounding Y pixels
                           
                                if (u != 0 && v != 0) { // Make sure we aren't checking the pixel against itself
                                    Color B = new Color(img.getRGB(x + u,y + v)); //Get the current boarding color
                                    int BS = ((B.getRed() + B.getGreen() + B.getBlue()) /3); //Generate the GrayScale
                                    if (((GS-BS) < t && (GS-BS) > -t) == false) { //Are they different enough?
                                        W = true; //If so set the switch to TRUE
                                    }
                                }
                            }
                        }
               
                    }
                }
               
                if (W == true) { //Did the pixel had at least one boarding pixel that was different?
                    EdgeMap.setRGB(x,y,EdgeColor.getRGB()); //If so then draw a yellow pixel on the overlay
                }
                //End Sobel
                           
            }
        }
}

Notes on example code:
  • The variable "scan" is an integer and refers to the accuracy of the scan. eg. scan = 1 would mean that every pixel of the image would be scanned. scan = 2 would mean every other pixel would be scanned. scan = 5 would mean every fifth pixel... ect, ect...
  • The variable "t" is an integer and refers to the Threshold for pixel comparison. This is set in the program via the Trackbar in the Top right of the Screen which allows for differences of 0 to 40.
  • My program has a separate class for displaying the image to the window, it draws the actual image first then draws what are called "overlays" on top of it. In this case the overlay is the image "EdgeMap" which is transparent everywhere except where an edge has been detected.
  • For best results, downsize your image to around 200x200 pixels before passing it to this algorithm and set "scan" to 1. If you want to scan a larger image you will need to set "scan" to a higher value to maintain performance.
I hope this helps anyone who is trying to do something in this field, it's a tricky one. Please subscribe, more like this is on the way!

    No comments: