[ 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
}
}
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.
No comments:
Post a Comment