Как определить цвет фона документа, когда есть 3 варианта, используя c # или imagemagick - PullRequest
4 голосов
/ 30 мая 2011

В настоящее время я занимаюсь разработкой приложения, которое должно обрабатывать отсканированные формы.Одной из задач моего приложения является определение типа сканируемой формы.Существует 3 возможных типа форм с уникальным цветом фона для идентификации каждого вида.Возможны 3 цвета: красный / розовый, зеленый и синий.Проблема, которую я имею, состоит в том, что мои попытки не в состоянии различить зеленую и синюю формы.Вот ссылки на зеленый и синий примеры файлов:

http://dl.dropbox.com/u/686228/Image0037.JPG

http://dl.dropbox.com/u/686228/Image0038.JPG

Я использую C # .net Application и ImageMagick для некоторых задач, которые мне нужнывыполнить.

В настоящее время я получаю гистограмму уменьшенного цвета моей отсканированной формы и пытаюсь определить, какие цвета находятся в форме.Но мое приложение не может различить зеленые и синие.

Любой совет или, возможно, более разумный подход будут с благодарностью приняты.

Спасибо,

Эрик

Ответы [ 3 ]

8 голосов
/ 31 мая 2011

Я нашел это довольно интересным и углубился в него немного глубже.

Код для получения среднего цвета растрового изображения, найденный в Как рассчитать средние значения цвета 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, 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, 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);
}

Запуск этой функции на ваших входных изображениях, однако, возвратил некоторый неразличимый сероватый цвет для них обоих, как уже ожидалось Уиллом А в комментариях, поэтому яm отбрасывает любые цвета из расчета, которые не имеют разницы не менее 15 между R, G и B.

Интересно то, что предположительно синее сканирование по рецепту усредняет равные значения для G и B ( R: 214, G: 237, B: 237 ).Однако сканирование по зеленому рецепту привело к большой разнице (18) между значениями G и B ( R: 202, G: 232, B: 214 ), так что это может бытьВы должны смотреть в.Пример:

if (color.G - color.B > 15) { form.Type = FormTypes.GreenForm }
3 голосов
/ 30 мая 2011

Схема рабочего процесса:

  • Преобразование изображения в цветовое пространство HSL / HSV
  • Построение гистограммы канала H
  • Гистограмма должна показывать четкий пик (для вашегосэмплы по крайней мере) в сине-зеленом канале

Если это не достаточно различимо, вы можете взвешивать голоса гистограммы чем-то, чтобы уменьшить влияние белых областей (например, в цветовом пространстве HSV, вес наS).

0 голосов
/ 30 мая 2011

Я не пробовал это, но как насчет изменения размера изображения до 1x1 пикселя (который должен «усреднять» все пиксели), а затем проверьте оттенок этого пикселя, чтобы увидеть, является ли он ближе к красному, синему или зеленому .

EDIT

У меня не установлен 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, 1, new Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
    var greenBitmap = new Bitmap(greenImage);
    var greenHue = greenBitmap.GetPixel(0, 0).GetHue();
}

Используя ваши изображения, я получил значение blueHue 169,0909 (где истинный синий будет 180), а greenHue равно 140 (чистый зеленый - 120, голубой - 150).

Красные формы должны быть где-то около 0 или 360.

Я знаю, что вы уже нашли ответ - просто подумал, что я дам вам альтернативу.

...