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.
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
.
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);
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;
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