i am working on a single cell image to detect the nucleus.
Logic used-
1. i am detecting the darkest pixel in the cell(which in most cases belongs to the nucleus)
2. using canny edge detection to detect the edges.(low threshold=0, high threshold=0, sigma=3)
3. threshold with a value of 1 and make all the edges white in colour.
4. Starting from the darkest pixel, i traverse all the neighbours till i reach the nearest edge.
This works for most cases and detects the nucleus well.
But, sometimes, the edge detection does not form a fully closed curve around the nucleus and leaves a gap at few areas. so when i traverse thru neighbor pixels, the pointer crosses the required area thru the small gaps and goes into other parts of the image.
i want a solution that will form closed curves, i.e fill up the gaps in the edges.
i tried the dilating the image and then eroding it. it closes some curves but not all.
unsafe public Bitmap execute2(Bitmap inputImage, Bitmap temp)
{
BitmapData inputImageData = inputImage.LockBits(new Rectangle(0, 0, inputImage.Width, inputImage.Height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
byte* inputImagePtr = (byte*)(void*)inputImageData.Scan0.ToPointer();
BitmapData tempData = temp.LockBits(new Rectangle(0, 0, inputImage.Width, inputImage.Height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
byte* tempPtr = (byte*)(void*)tempData.Scan0.ToPointer();
int i, j;
Point maxIntensity = new Point();
Point curr = new Point();
Point neigh = new Point();
Byte max = 255;
Stack<Point> points = new Stack<Point>();
Stack<Point> check = new Stack<Point>();
for (i = 0; i < temp.Height; i++)
{
for (j = 0; j < temp.Width; j++)
{
if (inputImagePtr[i * temp.Width + j] != 255)
{
if (inputImagePtr[i * temp.Width + j] < max && tempPtr[i * temp.Width + j]!=255)
{
max = inputImagePtr[i * temp.Width + j];
maxIntensity.X = j;
maxIntensity.Y = i;
}
}
}
}
int width = temp.Width;
int height = temp.Height;
points.Push(maxIntensity);
while (points.Count != 0)
{
curr = points.Pop();
if (tempPtr[curr.Y * width + curr.X] != 255 && curr.X > 0 && curr.X < width - 1 && curr.Y > 0 && curr.Y < height - 1)
{
neigh.X = curr.X - 1;
neigh.Y = curr.Y;
if (check.Contains(neigh) == false)
{
points.Push(neigh);
check.Push(neigh);
inputImagePtr[neigh.Y * width + neigh.X] = 0;
}
neigh.X = curr.X + 1;
neigh.Y = curr.Y;
if (check.Contains(neigh) == false)
{
points.Push(neigh);
check.Push(neigh);
inputImagePtr[neigh.Y * width + neigh.X] = 0;
}
neigh.X = curr.X;
neigh.Y = curr.Y - 1;
if (check.Contains(neigh) == false)
{
points.Push(neigh);
check.Push(neigh);
inputImagePtr[neigh.Y * width + neigh.X] = 0;
}
neigh.X = curr.X;
neigh.Y = curr.Y + 1;
if (check.Contains(neigh) == false)
{
points.Push(neigh);
check.Push(neigh);
inputImagePtr[neigh.Y * width + neigh.X] = 0;
}
}
}
inputImage.UnlockBits(inputImageData);
temp.UnlockBits(tempData);
return inputImage;
}
inputImage- original grayscale image with white background
temp- after canny, dilation, erosion (black background, white edges)