Click here to Skip to main content
15,886,075 members
Articles / Multimedia / GDI+

Implementation of Laplacian of Gaussion Edge Detection Algorithm using C#

Rate me:
Please Sign up or sign in to vote.
4.29/5 (5 votes)
18 Jun 2009CPOL2 min read 74.6K   5.6K   33   3
This code helps to implement LOG using C#
Edge_Detection_Code

Introduction 

The Laplacian of Gaussian filter is a convolution filter that is used to detect edges. This filter first applies a Gaussian blur, then applies the Laplacian filter and finally checks for zero crossings (i.e. when the resulting value goes from negative to positive or vice versa). The end result of this filter is to highlight edges. The operator normally takes a single graylevel image as input and produces another binary image as output. Pointers are used in the code so it is much faster.

Edge detection is a problem of fundamental importance in image analysis. In typical images, edges characterize object boundaries and are therefore useful for segmentation, registration, and identification of objects in a scene. For edge detection, there are various algorithms used like Sobel,Roberts Filter, LoG, etc.
The following links help to explain about LoG:

Using the Code

In this code, first we find the mean of image and deviation of image. Using deviation of image, we will decide threshold of image allowed to display. GetPixel and SetPixel functions have several drawbacks so we use Pointer. We access and modify a pixel value using Pointer. The next example utilizes the “unsafe” block in C#. Inside unsafe blocks, we have access to pointers from C#. The conclusion is that pointers in unsafe blocks are faster than GetPixel and SetPixel functions.

C#
// Open Bitmap for Source image & destination.
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, 
	bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData srcData = SrcImage.LockBits(new Rectangle(0, 0, SrcImage.Width, 
	SrcImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

Lock bits for source image in read only format and get BitmapData object. Lock bits for destination image in read and write format and set BitmapData.

C#
// Find mean of Image.
for (int colm = 0; colm < srcData.Height - size; colm++)
{
	byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
	
	for (int row = 0; row < srcData.Width - size; row++)
	{
		nTemp = 0.0;
		
		for (k = 0; k < size; k++)
		{
			for (l = 0; l < size; l++)
			{
				byte* tempPtr = (byte*)srcData.Scan0 + 
					((colm + l) * srcData.Stride);
				c = (tempPtr[((row + k) * offset)] + 
					tempPtr[((row + k) * offset) + 1] + 
					tempPtr[((row + k) * offset) + 2]) / 3;

				nTemp += (double)c * MASK[k, l];
			}
		}
		
		sum += nTemp;
		n++;
	}
}
mean = ((double)sum / n);

// Find deviation of Image.
for (int i = 0; i < srcData.Height - size; i++)
{
	byte* ptr = (byte*)srcData.Scan0 + (i * srcData.Stride);
	
	for (int j = 0; j < srcData.Width - size; j++)
	{
		nTemp = 0.0;
		
		for (k = 0; k < size; k++)
		{
			for (l = 0; l < size; l++)
			{
				byte* tempPtr = (byte*)srcData.Scan0 + 
						((i + l) * srcData.Stride);
				c = (tempPtr[((j + k) * offset)] + 
					tempPtr[((j + k) * offset) + 1] + 
					tempPtr[((j + k) * offset) + 2]) / 3;

				nTemp += (double)c * MASK[k, l];
			
			}
		}
		
		s = (mean - nTemp);
		d += (s * s);
	}
}

d = d / (n - 1);
d = Math.Sqrt(d);
d = d * 2;

This code is used to calculate the mean of image and deviation of image which helps to decide threshold range of image.

C#
for (int colm = mdl; colm < srcData.Height - mdl; colm++)
{
	byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
	byte* bitmapPtr = (byte*)bitmapData.Scan0 + (colm * bitmapData.Stride);

	for (int row = mdl; row < srcData.Width - mdl; row++)
	{
		nTemp = 0.0;

		min = double.MaxValue;
		max = double.MinValue;

		// Get neighbour Pixels.
		for (k = (mdl * -1); k < mdl; k++)
		{
			for (l = (mdl * -1); l < mdl; l++)
			{
				byte* tempPtr = (byte*)srcData.Scan0 + 
						((colm + l) * srcData.Stride);
				c = (tempPtr[((row + k) * offset)] + 
					tempPtr[((row + k) * offset) + 1] + 
					tempPtr[((row + k) * offset) + 2]) / 3;

				nTemp += (double)c * MASK[mdl + k, mdl + l];
			}
		}

		if (nTemp > d)
		{
			bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = 
						bitmapPtr[row * offset + 2] = 255;
		}
		else
		{
			bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = 
						bitmapPtr[row * offset + 2] = 0;
		}
	}
}

This code is used to mark identified part as white and the remaining with black pixel value. Using outer nested loops, we visit each pixel and find its neighbouring pixel using the inner FOR loop. Multiply pixel array with Mask array and add into threshold value(nTemp). After visiting all neighbour pixels, compare threshold value(nTemp) with deviation (d), put WHITE pixel if threshold value(nTemp) is greater than deviation(d) otherwise BLACK pixel.

C#
bitmap.UnlockBits(bitmapData);
SrcImage.UnlockBits(srcData);

Unlock the locked bits so that it frees bitmap object, and we can modify bitmap object in future.

Points of Interest 

Finding image deviation and Threshold using Mathematical calculation is best.

History

  • 18th June, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
I am Software developer, working on web and Windows technology. Willing to accept challengces and try to complete them.

Comments and Discussions

 
Question12 x 12 masking matrix Pin
swarnamuki26-Oct-13 6:06
swarnamuki26-Oct-13 6:06 
Generalgood work Pin
salihovic21-Oct-09 23:45
salihovic21-Oct-09 23:45 
Newscolor image segmentation Pin
hieulinhanh19-Jul-09 17:42
hieulinhanh19-Jul-09 17:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.