从位图中删除所有颜色的色调

时间:2018-03-31 03:20:54

标签: c# image image-processing c#-4.0 ocr

你好我试图消除保存在位图中的图像的所有橙色色调,我需要在图像中用tesseract进行OCR,扫描文档的橙色似乎阻碍了文本中产生错误的过程,我尝试用photoshop删除橙色I,使OCR和效果完美,主要问题是像素不是全部相同的颜色,它们是橙色但是颜色不同

Bitmap modificar = new Bitmap("imagenamodificar.png");
        for (int ycount2 = 0; ycount2 < modificar.Height; ycount2++)
        {
            for (int xcount2 = 0; xcount2 < modificar.Width; xcount2++)
            {
                if (modificar.GetPixel(xcount2, ycount2) == Color.Orange)
                {
                    modificar.SetPixel(xcount2, ycount2, Color.White);
                }
            }
        }

此代码绝对没有任何内容,图像保持不变。

然后我发现要与像素(0,0)进行比较,因为它总是我想要消除的颜色。

Bitmap modificar = new Bitmap("imagenamodificar.png");
        for (int ycount2 = 0; ycount2 < modificar.Height; ycount2++)
        {
            for (int xcount2 = 1; xcount2 < modificar.Width; xcount2++)
            {
                if (modificar.GetPixel(xcount2, ycount2) == modificar.GetPixel(0,0))
                {
                    modificar.SetPixel(xcount2, ycount2, Color.White);
                }
            }
        }

但问题是它只删除了一小部分,橙色像素仍然存在,因为正如我之前提到的,并非所有橙色调都相同,有人能想到什么吗?

1 个答案:

答案 0 :(得分:2)

以下是一些可以帮助您的关键点

  1. 不要使用GetPixel SetPixel,这是非常慢的
  2. 为了提高速度,最好使用unsafe指针访问,并致电lockbits获取Pinned Array
  3. 您可能希望使用阈值来确定特定像素颜色是否接近您要删除的颜色
  4. 可以通过以下方法计算简单的颜色阈值(您也可以在Hue上计算)

    <强>鉴于

    • threshold有些int
    • 源颜色
    • 像素颜色

    <强>阈值

    var thresh = threshold * threshold;
    
    // decode the RBG from the image Pointer
    var r = ((*p >> 16) & 255) - sR;
    var g = ((*p >> 8) & 255) - sG;
    var b = ((*p >> 0) & 255) - sB;
    
    // compare it against the threshold
    if (r * r + g * g + b * b > thresh)
       continue;
    
      

    注意 TaW 在评论中给出的链接非常有助于确定色彩距离。

    使用lockbits访问 Scanlines Pin 我们的内存

    Bitmap.LockBits Method (Rectangle, ImageLockMode, PixelFormat)

      

    将位图锁定到系统内存中。

    <强>代码

    private static unsafe void ConvertImage(string fromPath, string toPath, Color source, Color targetColor, double threshold)
    {
       var thresh = threshold * threshold;
       var target = targetColor.ToArgb();
    
       using (var bmp = new Bitmap(fromPath))
       {   
          // lock the array for direct access
          var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
          // Convert the source to rgb
          int sR = source.R, sG = source.G, sB = source.B;
          // store the max length so we don't have to recalculate it
          var length = (int*)data.Scan0 + bmp.Height * bmp.Width;
    
          for (var p = (int*)data.Scan0; p < length; p++)           
          {
    
             // get the rgb Distance
             var r = ((*p >> 16) & 255) - sR;
             var g = ((*p >> 8) & 255) - sG;
             var b = ((*p >> 0) & 255) - sB;
    
             // compare it against the threshold
             if (r * r + g * g + b * b > thresh)
                continue;
             // poke the target color in
             *p = target;
          }
    
          // unlock the bitmap
          bmp.UnlockBits(data);
          bmp.Save(toPath);
       }
    }
    

    <强>用法

    ConvertImage(@"d:\test.jpg", @"D:\result.bmp", Color.FromArgb(247, 107, 1), Color.Black, 25);
    
      

    注意:我正在使用jpg色轮,因此它不是那么干净

    原始图片

    enter image description here

    门槛25

    enter image description here

    阈值75

    enter image description here

    门槛150

    enter image description here

    橙色测试阈值75

    enter image description here

    enter image description here

    unsafe (C# Reference)

      

    unsafe关键字表示不安全的上下文,这是必需的   涉及指针的任何操作

    Unsafe Code and Pointers (C# Programming Guide)

      

    在公共语言运行库(CLR)中,不安全代码被称为   无法验证的代码。 C#中的不安全代码不一定是危险的;它   只是CLR无法验证其安全性的代码。 CLR会   因此,只有在完全信任的情况下才执行不安全的代码   部件。如果您使用不安全的代码,您有责任确保   您的代码不会引入安全风险或指针错误。