Edge detection with sobel operator/mask - g00se - May 17, 2011 01:38 AM
Hi. I'm trying to write little program that is able to detect edges. But it's not working correctly. I want to detect edges and get orientation (angle) of this egdes. So I'm using Sobel Mask/Operator to do this.
The Sobel operator performs a 2-D spatial gradient measurement on an image. Typically it is used to find the approximate absolute gradient magnitude at each point in an input grayscale image. The Sobel edge detector uses a pair of 3x3 convolution masks, one estimating the gradient in the x-direction (columns) and the other estimating the gradient in the y-direction (rows).
Masks are:
Gx:
-1 0 1
-2 0 2
-1 0 1
Gy:
1 2 1
0 0 0
-1 -2 -1
My code looks like this:
Code:
NSBitmapImageRep *bitmapImageRep = [[NSBitmapImageRep alloc] initWithData:[loadedImage TIFFRepresentation]];
NSInteger width = [bitmapImageRep pixelsWide];
NSInteger height = [bitmapImageRep pixelsHigh];
int Gx[3][3];
int Gy[3][3];
int col = 0;
int row = 0;
int sumX, sumY;
int SUM;
int I, J;
// Sobel Mask, Gx
Gx[0][0]=-1; Gx[0][1]=0; Gx[0][2]=1;
Gx[1][0]=-2; Gx[1][1]=0; Gx[1][2]=2;
Gx[2][0]=-1; Gx[2][1]=0; Gx[2][2]=1;
// Sobel Mask, Gy
Gy[0][0]=1; Gy[0][1]=2; Gy[0][2]=1;
Gy[1][0]=0; Gy[1][1]=0; Gy[1][2]=0;
Gy[2][0]=-1; Gy[2][1]=-2; Gy[2][2]=-1;
//
unsigned char *pixels;
NSBitmapImageRep *bitmap2;
NSGraphicsContext *context;
pixels = malloc(width * height);
bitmap2 = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &pixels
pixelsWide: width
pixelsHigh: height
bitsPerSample: 8
samplesPerPixel: 1
hasAlpha: NO
isPlanar: NO
colorSpaceName: NSCalibratedWhiteColorSpace
bitmapFormat: 0
bytesPerRow: width
bitsPerPixel: 8];
context = [NSGraphicsContext graphicsContextWithBitmapImageRep: bitmap2];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: context];
[bitmapImageRep drawInRect: NSMakeRect(0, 0, width, height)];
[NSGraphicsContext restoreGraphicsState];
//
/*-----------------------------------
Sobel Mask Algorithm
-----------------------------------*/
for(col=0; col<width-1; col++) {
for(row=0; row<height-1; row++) {
sumX = 0;
sumY = 0;
// Image boundaries
/*if (height==0)
SUM=0;
else if (width==0)
SUM=0;
else {*/
// Gradient X
/*for(I=-1; I<=1; I++) {
for(J=-1; J<=1; J++) {
sumX += pixels[(row+I)*width + (col+J)]*Gx[I+1][J+1];
//sumX += pixels[row][col]*Gx[I+1][J+1];
//pixels[(row*width + col)] = pixels[(row*width + col)]*Gx[I+1][J+1];
}
}*/
/*
// Gradient Y
for(I=-1; I<=1; I++) {
for(J=-1; J<=1; J++) {
sumY += pixels[row*width + col]*Gy[I+1][J+1];
}
}*/
// Gradient
//SUM = sqrt(pow((double)sumX, 2.0) + pow((double)sumY, 2.0));
//pixels[(row*width + col)] = 255 - SUM;
pixels[(row*width + col)] = abs( (pixels[((row+1)*width + (col-1))] + 2*pixels[((row+1)*width + col)] + pixels[((row+1)*width + (col+1))]) - (pixels[((row-1)*width + (col-1))] + 2*pixels[((row-1)*width + col)] + pixels[((row+1)*width + (col+1))] ));
}
}
producedImage = [[NSImage alloc] init];
[producedImage addRepresentation:bitmap2];
[bitmap2 release];
[processedImage setImage: producedImage];
In above code there are two methods to apply this mask. One is commented:
Code:
// Gradient X
/*for(I=-1; I<=1; I++) {
for(J=-1; J<=1; J++) {
sumX += pixels[(row+I)*width + (col+J)]*Gx[I+1][J+1];
//sumX += pixels[row][col]*Gx[I+1][J+1];
//pixels[(row*width + col)] = pixels[(row*width + col)]*Gx[I+1][J+1];
}
}*/
/*
// Gradient Y
for(I=-1; I<=1; I++) {
for(J=-1; J<=1; J++) {
sumY += pixels[row*width + col]*Gy[I+1][J+1];
}
}*/
// Gradient
//SUM = sqrt(pow((double)sumX, 2.0) + pow((double)sumY, 2.0));
Second one:
Code:
pixels[(row*width + col)] = abs( (pixels[((row+1)*width + (col-1))] + 2*pixels[((row+1)*width + col)] + pixels[((row+1)*width + (col+1))]) - (pixels[((row-1)*width + (col-1))] + 2*pixels[((row-1)*width + col)] + pixels[((row+1)*width + (col+1))] ));
is commonly used approximation. But when using first or second way i receive this:
![[Image: processedlena.th.png]](http://img821.imageshack.us/img821/7042/processedlena.th.png)
Can someone help me with this problem?
RE: Edge detection with sobel operator/mask - g00se - May 17, 2011 05:46 AM
Slowly forward. I added some simple code
Code:
if (SUM>255)
SUM=255;
else if (SUM<0)
SUM=0;
after
Code:
SUM = abs(sumX) + abs(sumY);
and I receive something closer to what I'm looking for
![[Image: zrzutekranu20110517godz.th.png]](http://img35.imageshack.us/img35/5759/zrzutekranu20110517godz.th.png)
But still it's not properly done edge detection.
RE: Edge detection with sobel operator/mask - SethWillits - May 18, 2011 01:13 PM
Wrote this up quickly... (first time I've done it as well)
![[Image: upshot_RoJ9vM2R.jpg]](http://sethwillits.com/temp/upshot/upshot_RoJ9vM2R.jpg)
Code:
uint8_t Convolute(const char * src, int x, int y);
int Convolute2(const char * src, int x, int y, int G[]);
int Gx[] = { -1, 0, 1, -2, 0, 2, -1, 0, 1 };
int Gy[] = { -1, -2, -1, 0, 0, 0, 1, 2, 1 };
#define SRC(__x, __y) (*(src + (__y) * 256 + (__x)))
uint8_t Convolute(const char * src, int x, int y)
{
int xx = Convolute2(src, x, y, Gx);
int yy = Convolute2(src, x, y, Gy);
int r = sqrt(xx * xx + yy * yy);
return (uint8_t)MAX(0, MIN(255, r));
}
int Convolute2(const char * src, int x, int y, int G[])
{
int center = SRC(x, y);
int v[9];
int r = 0;
v[0] = (x > 0 && y > 0) ? SRC(x - 1, y - 1) : center;
v[1] = ( y > 0) ? SRC(x , y - 1) : center;
v[2] = (x < 255 && y > 0) ? SRC(x + 1, y - 1) : center;
v[3] = (x > 0 ) ? SRC(x - 1, y ) : center;
v[4] = center;
v[5] = (x < 255 ) ? SRC(x + 1, y ) : center;
v[6] = (x > 0 && y < 255) ? SRC(x - 1, y + 1) : center;
v[7] = ( y < 255) ? SRC(x , y + 1) : center;
v[8] = (x < 255 && y < 255) ? SRC(x + 1, y + 1) : center;
r += (G[0] * v[0]) + (G[1] * v[1]) + (G[2] * v[2]) +
(G[3] * v[3]) + (G[4] * v[4]) + (G[5] * v[5]) +
(G[6] * v[6]) + (G[7] * v[7]) + (G[8] * v[8]);
return r;
}
- (PNMImage *)findEdges:(PNMImage *)image;
{
NSMutableData * data = [NSMutableData dataWithLength:256*256];
const char * src = [image.originalData bytes];
char * dst = [data mutableBytes];
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
*(dst + y * 256 + x) = Convolute(src, x, y);
}
}
return [[[PNMImage alloc] initWithData:data type:PNMGrayscaleImageType pixelsWide:256 pixelsHigh:256 maximumValue:255] autorelease];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
PNMImage * image = [PNMImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"lena" ofType:@"pgm"]];
PNMImage * edges = [self findEdges:image];
[imageView1 setImage:image.image];
[imageView2 setImage:edges.image];
}
RE: Edge detection with sobel operator/mask - g00se - May 19, 2011 09:32 AM
Ok, mine also is working now. Some novice mistake - calculated value I should store in new matrix, not write it directly to image matrix.
RE: Edge detection with sobel operator/mask - SethWillits - May 19, 2011 10:41 AM
So what are you doing with this filtered image, now?
RE: Edge detection with sobel operator/mask - g00se - May 20, 2011 12:23 AM
This little program was to test sobel mask. I will use it in program to fingerprint recognition. Grad_x and grad_y will be used to get orientation diagram.
|