去除斑点 - 从图像中去除斑点或点 [英] Despeckle - Remove spots or dots from the image

查看:359
本文介绍了去除斑点 - 从图像中去除斑点或点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Winforms。在我的表格中,我有一个显示黑白图像的图片框。我还有一个按钮,如果你点击它,该按钮将删除图像上的斑点/点。当图像尺寸不大时,它会快速消除斑点。如果图像很大,则需要一段时间。此外,有时这个函数会从它认为是一个点的图像中删除一些单词。如何提高此功能的性能,更准确地去除斑点或点基本上去除图像?



更新
经过研究,我发现这个图书馆似乎很有希望提出这个问题:





图片信息



这里要注意的是它是黑白图像 - 位深度1





我的代码

  private int [] mask = new int [9]; 
private void remove_spot_btn_Click(object sender,EventArgs e)
{
Bitmap img = new Bitmap(pictureBox1.Image);
颜色c;

for(int ii = 0; ii< img.Width; ii ++)
{
for(int jj = 0; jj< img.Height; jj ++)
{

if(ii - 1> = 0&& jj - 1> = 0)
{
c = img.GetPixel(ii - 1 ,jj - 1);
mask [0] = Convert.ToInt16(c.R);
}
else
{
mask [0] = 0;
}

if(jj - 1> = 0&& ii + 1< img.Width)
{
c = img.GetPixel(ii + 1,jj - 1);
mask [1] = Convert.ToInt16(c.R);
}
else
mask [1] = 0;

if(jj - 1> = 0)
{
c = img.GetPixel(ii,jj - 1);
mask [2] = Convert.ToInt16(c.R);
}
else
mask [2] = 0;

if(ii + 1< img.Width)
{
c = img.GetPixel(ii + 1,jj);
mask [3] = Convert.ToInt16(c.R);
}
else
mask [3] = 0;

if(ii - 1> = 0)
{
c = img.GetPixel(ii - 1,jj);
mask [4] = Convert.ToInt16(c.R);
}
else
mask [4] = 0;

if(ii - 1> = 0&& jj + 1< img.Height)
{
c = img.GetPixel(ii - 1,jj + 1);
mask [5] = Convert.ToInt16(c.R);
}
else
mask [5] = 0;

if(jj + 1< img.Height)
{
c = img.GetPixel(ii,jj + 1);
mask [6] = Convert.ToInt16(c.R);
}
else
mask [6] = 0;


if(ii + 1< img.Width&& jj + 1< img.Height)
{
c = img.GetPixel(ii + 1,jj + 1);
mask [7] = Convert.ToInt16(c.R);
}
else
mask [7] = 0;
c = img.GetPixel(ii,jj);
mask [8] = Convert.ToInt16(c.R);
Array.Sort(mask);
int mid = mask [4];
img.SetPixel(ii,jj,Color.FromArgb(mid,mid,mid));
}
}

pictureBox1.Image = img;
MessageBox.Show(Complete);
}


解决方案

正如您所知,使用 AForge.NET 是一个好主意(您只需将其添加为nuget)。我建议你使用它的中位数过滤器通常用于去噪(请参阅维基百科中的中位数过滤器)。



AForge需要24bpp的RGB图像,所以你需要先在你的示例中转换它,但这里有一个代码似乎在它上面工作得很好的例子:

  //使用(var bmp = LoadForFiltering(@C:\ temp\Testing-Image3)将文件加载为24bpp RGB 
。 tif))
{
var filter = new Median();

//运行过滤器
filter.ApplyInPlace(bmp);

//将文件保存回来(这里,我用png作为输出格式)
bmp.Save(@C:\ temp\Testing-Image3.png);
}


private static Bitmap LoadForFiltering(string filePath)
{
var bmp =(Bitmap)Bitmap.FromFile(filePath);
if(bmp.PixelFormat == PixelFormat.Format24bppRgb)
return bmp;

尝试
{
//来自AForge的示例代码
if(bmp.PixelFormat == PixelFormat.Format16bppGrayScale || Bitmap.GetPixelFormatSize(bmp.PixelFormat)> 32)
抛出新的NotSupportedException(不支持的图像格式);

返回AForge.Imaging.Image.Clone(bmp,PixelFormat.Format24bppRgb);
}
最后
{
bmp.Dispose();
}
}

如果你真的需要高性能,那么你可以去例如,对于NVidia CUDA / NPP(直接使用GPU),这是更多的工作,而不是C#直接支持(当然需要NVidia卡)。相关问题: 2D CUDA中值滤波器优化和CUDA白皮书:< a href =http://www.nvidia.com/content/nvision2008/tech_presentations/Game_Developer_Track/NVISION08-Image_Processing_and_Video_with_CUDA.pdf =nofollow noreferrer>使用CUDA的图像处理和视频算法


I'm using Winforms. In my form I have a picturebox that displays a black and white image. I also have a button that if you click it, the button will remove spots / dots on the images. When the image dimension is not big it removes the spots quickly. If the image is large it takes a while. Also sometimes this function removes some of the words from the image it thinks its a spot. How can I improve the performance of this function and more accurately remove the spots or dots basically despeckle the image?

Update Upon research I found this library that seemed promising for this question:

http://www.aforgenet.com/framework/docs/html/cdf93487-0659-e371-fed9-3b216efb6954.htm

Link for spotted image: http://www.filedropper.com/testing-image3

Image Example

Note image in link has a bigger version of this:

Image Information

The thing to note here is that it is a black and white image - Bit Depth 1

My Code

    private int[] mask = new int[9];
    private void remove_spot_btn_Click(object sender, EventArgs e)
    {
        Bitmap img = new Bitmap(pictureBox1.Image);
        Color c;

        for (int ii = 0; ii < img.Width; ii++)
        {
            for (int jj = 0; jj < img.Height; jj++)
            {

                if (ii - 1 >= 0 && jj - 1 >= 0)
                {
                    c = img.GetPixel(ii - 1, jj - 1);
                    mask[0] = Convert.ToInt16(c.R);
                }
                else
                {
                    mask[0] = 0;
                }

                if (jj - 1 >= 0 && ii + 1 < img.Width)
                {
                    c = img.GetPixel(ii + 1, jj - 1);
                    mask[1] = Convert.ToInt16(c.R);
                }
                else
                    mask[1] = 0;

                if (jj - 1 >= 0)
                {
                    c = img.GetPixel(ii, jj - 1);
                    mask[2] = Convert.ToInt16(c.R);
                }
                else
                    mask[2] = 0;

                if (ii + 1 < img.Width)
                {
                    c = img.GetPixel(ii + 1, jj);
                    mask[3] = Convert.ToInt16(c.R);
                }
                else
                    mask[3] = 0;

                if (ii - 1 >= 0)
                {
                    c = img.GetPixel(ii - 1, jj);
                    mask[4] = Convert.ToInt16(c.R);
                }
                else
                    mask[4] = 0;

                if (ii - 1 >= 0 && jj + 1 < img.Height)
                {
                    c = img.GetPixel(ii - 1, jj + 1);
                    mask[5] = Convert.ToInt16(c.R);
                }
                else
                    mask[5] = 0;

                if (jj + 1 < img.Height)
                {
                    c = img.GetPixel(ii, jj + 1);
                    mask[6] = Convert.ToInt16(c.R);
                }
                else
                    mask[6] = 0;


                if (ii + 1 < img.Width && jj + 1 < img.Height)
                {
                    c = img.GetPixel(ii + 1, jj + 1);
                    mask[7] = Convert.ToInt16(c.R);
                }
                else
                    mask[7] = 0;
                c = img.GetPixel(ii, jj);
                mask[8] = Convert.ToInt16(c.R);
                Array.Sort(mask);
                int mid = mask[4];
                img.SetPixel(ii, jj, Color.FromArgb(mid, mid, mid));
            }
        }

        pictureBox1.Image = img;
        MessageBox.Show("Complete");
    }

解决方案

As you found out, using AForge.NET is a good idea (you just have to add it as a nuget). I suggest you use its Median filter which is often used for denoising (see Median Filter in wikipedia).

AForge needs 24bpp RGB images, so you need to convert it first in your sample case, but here is an example of code that seems to work quite well on it:

  // load the file as 24bpp RGB
  using (var bmp = LoadForFiltering(@"C:\temp\Testing-Image3.tif"))
  {
      var filter = new Median();

      // run the filter 
      filter.ApplyInPlace(bmp);

      // save the file back (here, I used png as the output format)
      bmp.Save(@"C:\temp\Testing-Image3.png");
  }


  private static Bitmap LoadForFiltering(string filePath)
  {
      var bmp = (Bitmap)Bitmap.FromFile(filePath);
      if (bmp.PixelFormat == PixelFormat.Format24bppRgb)
          return bmp;

      try
      {
          // from AForge's sample code
          if (bmp.PixelFormat == PixelFormat.Format16bppGrayScale || Bitmap.GetPixelFormatSize(bmp.PixelFormat) > 32)
              throw new NotSupportedException("Unsupported image format");

          return AForge.Imaging.Image.Clone(bmp, PixelFormat.Format24bppRgb);
      }
      finally
      {
          bmp.Dispose();
      }
  }

If you really need high performance, then you could go for NVidia CUDA/NPP (using directly the GPU) for example but this is more work, not directly supported from C# (and requires an NVidia card of course). Related question here: 2D CUDA median filter optimization and a white paper on CUDA here : Image Processing and Video Algorithms with CUDA

这篇关于去除斑点 - 从图像中去除斑点或点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆