2012-09-17 1 views
1

Область:Как заменить тональные вариации одного и того же цвета на C# Bitmap?

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

Ссылка на captcha может быть найдена here. Освежающий даст вам еще один капчу.

Причина:

Я знаю, что большинство людей считает, что это неправильно, чтобы возиться с каптчами так здесь я защищаясь. Это будет использоваться только для знания/самостоятельной задачи. Для этих изображений не планируется никакого другого использования.

Проблема:

После изучения этих изображений на некоторое время, я понял, что хорошо было бы Подход заменить цвета: «белый и желтый» в «Color.Black», и любой другой цвет следует заменить на «Color.White».

После этого я просто «инвертирую» цвета, приводя меня к выходу, который я хочу.

Пример кода:

В этом коде я пытаюсь заменить цвет «черный» каждое изображение для Skyblue Pixel.

 WebRequests wr = new WebRequests(); // My class to handle WebRequests 
     Bitmap bmp; 
     string url = "http://www.fazenda.rj.gov.br/projetoCPS/codigoImagem"; 

     bmp = wr.GetBitmap (url); 

     for (int i = 1; i < bmp.Height ; i++) 
     { 
      for (int j = 1 ; j < bmp.Width ; j++) 
      { 
       if (bmp.GetPixel(j,i).Equals(Color.Black)) 
       { 
        bmp.SetPixel(j,i, Color.SkyBlue); 
       } 
      } 
     } 

Этот код не работает вообще, я не знаю, почему, но ни один пиксель не становится заменен в этом примере.

Вопрос:

Как я могу сделать эту работу? Что мне здесь не хватает?

Кроме того, идеальным сценарием для меня было бы «уменьшить» цветовой палитру этого изображения до «основных» цветов, что значительно облегчило бы мою работу здесь.

Я уже пробовал AForge Framework, который я использую для уменьшения цветов, но он вообще не работает, результат не тот, который я ожидал.

Что я могу сделать здесь, чтобы правильно преобразовать это изображение?

Спасибо заранее,

Марчелло Линс.

+0

капча Я вижу, содержит желтый «Q» и «C» и черный «Q», но и белый «W» и белый «C», что ваш подход исчезнет до черного. – LSerni

+0

Они не исчезнут, так как фон серый, никогда черный. Я хотел бы, чтобы все персонажи имели один и тот же цвет, и поскольку цвета символов могут быть только «белыми, желтыми и черными», я получаю все черные символы, а каждый другой цвет будет рассматриваться как задний план. –

ответ

1

Причина, по которой ваш алгоритм не работает, заключается в том, что вы ищете точное соответствие . Но черный на изображении не очень черный из-за артефактов сжатия JPEG; в трех CAPTCHAS, которые я загрузил, не было ни одного черного (0, 0, 0) пикселей. Ближайшее значение было (0, 0, 4), которое выглядит черным, но нет.

Приближенный подход был бы:

  • Убрать все серые (каналы, отличающиеся друг от друга менее чем на 5%), имеющей средний канал ниже 220 с серой. Это убивает тонкие линии lightgray, а также большую часть артефактов звонка (JPEG) на сером фоне.
  • Замените все пиксели, в которых красный, зеленый или синий канал больше, чем на 25% выше , и два других канала с серым. Это позаботится о красных, зеленых и блюзовых, а также о большинстве их звонких артефактов.
  • Запустите простой despeckle, чтобы удалить все пиксели nongray, окруженные пятью серыми и никакими другими пикселями одного цвета в пределах 20%.

В конце этого процесса фон является серым, все оставшиеся пикселы негрей являются символами.

Некоторые полезные функции:

// Very basic (and CIE-incorrect) check 
public static int isGray(Color c) 
{ 
    if (Math.Abs(c.R - c.G) > 5 * 2.55) return 0; // Not gray. R and G too different 
    if (Math.Abs(c.R - c.B) > 5 * 2.55) return 0; 
    if (Math.Abs(c.G - c.B) > 5 * 2.55) return 0; 
    return 1; 
} 

// the blind man's test for shading :-) 
public static int isShadeOfRed(Color c) 
{ 
    if (4*c.R < 5*c.G) return 0; // Red not strong enough in respect to green 
    if (4*c.R < 5*c.B) return 0; // Red not strong enough in respect to blue 
    return 1; // Red is stronger enough than green and blue to be called "shade of red" 
} 

// (shades of green and blue left as an exercise) 

// Very basic (and CIE-incorrect) check 
public static int areSameColor(Color a, Color b) 
{ 
    if (Math.Abs(a.R - b.R) > 5 * 2.55) return 0; 
    if (Math.Abs(a.G - b.G) > 5 * 2.55) return 0; 
    if (Math.Abs(a.B - b.B) > 5 * 2.55) return 0; 
    return 1; // "more or less" the same color 
} 

// This is more or less pseudo code... 
public static int isNoise(int x, int y) 
{ 
    if ((x < 1) || (y < 1)) return 0; // or maybe "return 1" 
    if ((x+1 >= bmp.Width)||(y+1 >= bmp.Height)) return 0; 
    pix = bmp.GetPixel(x,y); 
    for (i = -1; i <= 1; i++) 
     for (j = -1; j <= 1; j++) 
     { 
      if ((i == 0) && (j == 0)) continue; 
      test = bmp.GetPixel(x+i, y+j); 
      if (isGray(test)) grays++; 
      if (isSameColor(pix, test)) same++; 
     } 
    // Pixel surrounded by grays, and has no neighbours of the same colour 
    // (who knows, maybe we could skip gray calculation and check altogether?) 
    // is noise. 
    if ((grays == 5) && (same == 0)) 
     return 1; 
    return 0; 
} 

// NOTE: do not immediately set to gray pixels found to be noise, for their neighbours 
// will be calculated using the new gray pixel. Damage to image might result. 
// Use a copy of bmp instead. 
+0

Просто, чтобы проверить, проверили? –

+0

С парой CAPTCHA, да. Но вы можете поэкспериментировать с этими порогами - например, «220». Я думаю, что это может быть поднято. Кроме того, это зависит от OCR, используемого позже: я остановил despeckling на пяти серых, потому что в противном случае это отсекало черты характера. Возможно, четыре или шесть дают лучший конечный результат. – LSerni

+0

@Iserni большое спасибо. Я дам ему попробовать в ближайшее время:) –

 Смежные вопросы

  • Нет связанных вопросов^_^