Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implementation of Laplacian of Gaussion Edge Detection Algorithm using C#

0.00/5 (No votes)
18 Jun 2009 1  
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.

// 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.

// 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.

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.

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here