当使用c#或imagemagick时,有3个选项时如何确定文档的背景色

问题描述

|| 我目前正在开发一个必须处理扫描表格的应用程序。我的应用程序的任务之一是确定要扫描的表格类型。表格有3种可能的类型,每种背景都有独特的背景色。可能的3种颜色是红色/粉红色,绿色和蓝色。我遇到的问题是,我的尝试无法区分绿色和蓝色形式。 这是绿色和蓝色示例文件链接: http://dl.dropBox.com/u/686228/Image0037.JPG http://dl.dropBox.com/u/686228/Image0038.JPG 我正在使用C#.net应用程序和ImageMagick完成我需要执行的某些任务。 目前,我正在获取扫描表格的颜色减少的直方图,并尝试确定表格中的颜色。但是我的应用无法依赖于区分绿色和蓝色。 任何建议或更明智的方法将不胜感激。 谢谢, 埃里克     

解决方法

        我发现这很有趣,并对其进行了更深入的研究。 在如何计算位图的平均rgb颜色值中找到的获取位图平均颜色的代码存在一些问题,例如某些无效的转换和红色/蓝色通道被交换。这是固定版本:
private System.Drawing.Color CalculateAverageColor(Bitmap bm)
{
    int width = bm.Width;
    int height = bm.Height;
    int red = 0;
    int green = 0;
    int blue = 0;
    int minDiversion = 15; // drop pixels that do not differ by at least minDiversion between color values (white,gray or black)
    int dropped = 0; // keep track of dropped pixels
    long[] totals = new long[] { 0,0 };
    int bppModifier = bm.PixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb ? 3 : 4; // cutting corners,will fail on anything else but 32 and 24 bit images

    BitmapData srcData = bm.LockBits(new System.Drawing.Rectangle(0,bm.Width,bm.Height),ImageLockMode.ReadOnly,bm.PixelFormat);
    int stride = srcData.Stride;
    IntPtr Scan0 = srcData.Scan0;

    unsafe
    {
        byte* p = (byte*)(void*)Scan0;

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int idx = (y * stride) + x * bppModifier;
                red = p[idx + 2];
                green = p[idx + 1];
                blue = p[idx];
                if (Math.Abs(red - green) > minDiversion || Math.Abs(red - blue) > minDiversion || Math.Abs(green - blue) > minDiversion)
                {
                    totals[2] += red;
                    totals[1] += green;
                    totals[0] += blue;
                }
                else
                {
                    dropped++;
                }
            }
        }
    }

    int count = width * height - dropped;
    int avgR = (int)(totals[2] / count);
    int avgG = (int)(totals[1] / count);
    int avgB = (int)(totals[0] / count);

    return System.Drawing.Color.FromArgb(avgR,avgG,avgB);
}
但是,在输入图像上运行此功能后,它们都会返回一些难以区分的灰色,正如Will A在评论中所预期的那样,这就是为什么我要从计算中删除不具有差异的任何颜色R,G和B之间至少15。 有趣的是,所谓的蓝色处方扫描的G和B平均值相等(R:214,G:237,B:237)。但是,绿色处方扫描导致G和B的值之间有很大的差异(18)(R:202,G:232,B:214),因此这可能是您应该考虑的问题。例如:
if (color.G - color.B > 15) { form.Type = FormTypes.GreenForm }
    ,        工作流程概述: 将图像转换为HSL / HSV色彩空间 建立H通道的直方图 直方图应在蓝色/绿色通道中显示一个清晰的峰值(至少对于您的样本而言) 如果不够鲜明,您可以使用某种方法对直方图投票进行加权,以减少白色区域的影响(例如,在HSV颜色空间中,按S加权)。     ,        我还没有尝试过,但是如何将图像调整为1x1像素(应该“平均”所有像素),然后检查该像素的色相以查看它是否最接近红色,蓝色或绿色。 编辑 我没有安装ImageMagik,所以我用GetThumbnailImage破解了它:
private static bool ThumbnailCallback()
{
    return false;
}

static void Main(string[] args)
{
    var blueImage = Image.FromFile(\"blue.jpg\").GetThumbnailImage(1,1,new Image.GetThumbnailImageAbort(ThumbnailCallback),IntPtr.Zero);
    var blueBitmap = new Bitmap(blueImage);
    var blueHue = blueBitmap.GetPixel(0,0).GetHue();

    var greenImage = Image.FromFile(\"green.jpg\").GetThumbnailImage(1,IntPtr.Zero);
    var greenBitmap = new Bitmap(greenImage);
    var greenHue = greenBitmap.GetPixel(0,0).GetHue();
}
使用您的图像,我得到的
blueHue
值为169.0909(其中,真正的蓝色为180)和
greenHue
等于140(纯绿色为120,青色为150)。 红色表格应位于0或360附近。 我知道您已经找到了答案-只是想我给您一个替代方法。