无法获得具有亮点的图像的准确阈值

时间:2016-04-07 10:23:46

标签: python opencv image-processing

我试图在图像中检测到一个巨大的亮斑。我这样做的方式是,我首先将其转换为COLOR_BGR2HLS_FULL,采用绿色通道并将GuassianBlur应用于此,然后我使用THRESH_OTSU获得阈值图像然后绘制轮廓:

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)

以下是获得的图片的样子:

enter image description here

以下是所需图片的样子:

enter image description here

另外,我这样做的方式与所有相似类型的图像不一致。你有什么更好的建议吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

好吧,我得到了这个结果:

初始图像(我没有原始图像,所以我从你的绿线中删除了绿线):

enter image description here

使用GREEN频道进行处理:

enter image description here

然后使用带有方形窗口半径为32的Dilate和Erode过滤器来移除容器:

扩张后 enter image description here

腐蚀之后 enter image description here

照明抑制滤镜(或高通滤镜 - 按图像的高斯平滑除法)使图像更加清晰:

enter image description here

最后一个门槛

enter image description here

enter image description here

您也可以平滑最终的面具

enter image description here

再次使用阈值以获得更平滑的结果:

enter image description here

答案 1 :(得分:1)

不,我还没有使用任何其他修复技术去除血管。 膨胀是某个区域内的最大值,Erode是最小值。我使用Dilate和Erode半径32和HighPass半径128。

代码在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;
}