Reputation:
I'm trying to detect a huge bright blob in an image. The way I'm doing it is, I'm first converting it to COLOR_BGR2HLS_FULL
, taking the green channel and applying GuassianBlur to it like so and then I'm using THRESH_OTSU
to obtain the thresholded image and then drawing the contour:
self.result = cv2.cvtColor(self.result_array_color, cv2.COLOR_BGR2HLS_FULL)
self.result = self.result[:,:,1]
self.result = cv2.GaussianBlur(self.result,(25,25), 0)
Here's what the obtained image looks like:
And here's what the desired image should look like:
Also, my way of going about this isn't consistent with all the images of similar type. Is there a better way you could suggest?
Thank you!
Upvotes: 0
Views: 242
Reputation: 1575
No, I haven't use any other inpainting techniques to remove the vessels. Dilate is the maximum value inside some area and Erode is the minimum value. I used Dilate and Erode radius 32 and HighPass radius 128.
The code is in C# :
public byte[] Dilate(byte[] image, int width, int height, int radius)
{
byte[] temp = new byte[image.Length];
byte[] result = new byte[image.Length];
//Dilate by X
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
byte v = 0;
for (int i = x - radius; i <= x + radius; i++)
if (i >= 0 && i < width)
v = Math.Max(v, image[i + y * width]);
temp[x + y * width] = v;
}
//Dilate by Y
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
byte v = 0;
for (int i = y - radius; i <= y + radius; y++)
if (i >= 0 && i < height)
v = Math.Max(v, temp[x + i * width]);
result[x + y * width] = v;
}
return result;
}
public byte[] Erode(byte[] image, int width, int height, int radius)
{
byte[] temp = new byte[image.Length];
byte[] result = new byte[image.Length];
//Dilate by X
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
byte v = 255;
for (int i = x - radius; i <= x + radius; i++)
if (i >= 0 && i < width)
v = Math.Min(v, image[i + y * width]);
temp[x + y * width] = v;
}
//Dilate by Y
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
byte v = 255;
for (int i = y - radius; i <= y + radius; y++)
if (i >= 0 && i < height)
v = Math.Min(v, temp[x + i * width]);
result[x + y * width] = v;
}
return result;
}
public byte[] HighPass(byte[] image, int width, int height, float radius)
{
byte[] smooth = GaussSmooth(image, width, height, (byte)radius);
byte[] result = new byte[image.Length];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
result[x + y * width] = (byte)(128 + image[x + y * width] - smooth[x + y * width]);
}
return result;
}
Upvotes: 1
Reputation: 1575
Well, I got to achieve this result:
Initial image (I did not have the original one so I removed the green line from yours):
Use GREEN channel for processing:
Then use Dilate and Erode filter with square window with radius 32 to remove vessels:
The Lighting Suppression filter (or High-Pass filter - division by Gauss smooth of the image) to make image more plain:
And finally a threshold
You can also smooth the final mask
And use threshold again to obtain more smooth result:
Upvotes: 1