Локальное пороговое значение или бинаризация текста на изображении

Я разрабатываю приложение для извлечения текста на С# в разных условиях освещения.

Моя проблема в том, что иногда на изображении бывают разные уровни яркости, например:

http://i.imgur.com/NJ2XTrn.png?1

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

Я ищу алгоритм/фрагмент/функцию или что-то еще, что может применить правильный порог/бинаризацию к изображению.

Я основал этот BradleyLocalThresholding в AForge. , лучше, чем другие неадаптивные методы, но теряют некоторые детали. (например, G на изображении становится O)

Кто-нибудь может предложить мне лучший способ?


person Univers3    schedule 30.04.2013    source источник
comment
Вы пробовали играть с процентом «t»? Возможно, вы могли бы попробовать несколько значений и использовать консенсус относительно того, какая это буква. Отказ от ответственности: я никогда не занимался реальной обработкой изображений и только читал комментарии к ссылке, которую вы разместили.   -  person Cemafor    schedule 01.05.2013
comment
Лучшее значение t, которое я пробовал, взять большинство букв хорошо, НО «G» становится «O» (так что добавьте слишком много), а «L» становится «I» (поэтому вычтите слишком много). Я играл с размером окна, но безрезультатно.   -  person Univers3    schedule 01.05.2013


Ответы (3)


да, используйте niblack (opencv имеет его как функцию) - в основном он использует локальное среднее значение для построения переменной theshold. это лучше всего работает для OCR. в зависимости от разрешения изображения вы также можете бикубически повышать дискретизацию в 2 или 3 раза ДО порогового значения.

person morishuz    schedule 30.04.2013
comment
Привет, можете ли вы показать, где в OpenCV находятся функции niblack или бикубической upsamle ?? Я искал в его документации в Интернете, но безрезультатно. - person Univers3; 01.05.2013
comment
cv::adaptiveThreshold() с использованием типа ADAPTIVE_THRESH_MEAN и изменение размера с использованием cv::resize с типом INTER_CUBIC - person morishuz; 01.05.2013

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

  1. Произвольно выберите начальный порог оценки T (обычно как среднее значение).
  2. Сегментируйте сигнал, используя T, что даст две группы: G1, состоящая из всех точек со значениями‹=T, и G2, состоящая из точек со значением>T.
  3. Вычислите среднее расстояние между точками G1 и T и точками G2 и T.
  4. Вычислить новое пороговое значение T=(M1+M2)/2
  5. Повторяйте шаги со 2 по 4, пока изменение T не станет достаточно меньшим.

Хитрость заключается не в том, чтобы применить его ко всему изображению, а в том, чтобы разбить изображение на блоки (например) 5x5 и применить его к блокам по отдельности, что даст вам:

введите здесь описание изображения

Ниже приведена реализация на R, которую, я уверен, вы сможете воспроизвести.

getT = function(y){
  t = mean(y)

  mu1 = mean(y[y>=t])
  mu2 = mean(y[y 1){
      cmu1 = mean(y[y>=t])
      cmu2 = mean(y[y 1 & cmu1 == mu1 & cmu2 == mu2){
      print(paste('done t=', t))
      return(t)
      break;
    }else{
      mu1 = cmu1 
      mu2 = cmu2
      t = (mu1 + mu2)/2
      print(paste('new t=', t))
    }
    i = i+1
  }
}


r = seq(1, nrow(image), by=5)
c = seq(1, ncol(image), by=5)
r[length(r)] = nrow(image)
c[length(c)] = ncol(image)
y = image
for(i in 2:length(r) ){
  for(j in 2:length(c) ){
    block = image[r[i-1]:r[i], c[j-1]:c[j]]
    t = getT(block)
    y[r[i-1]:r[i], c[j-1]:c[j]] = (block>t)+0
  }
}

display(y)
person Omar Wagih    schedule 02.05.2013
comment
Очень хороший пример, но я не думаю, что этого достаточно для надежного распознавания символов. Результаты, которые у меня есть с BradleyLocalThreshold, на данный момент намного лучше. - person Univers3; 04.05.2013
comment
Справедливо :-) Есть ли причина, по которой изображения такого низкого качества? - person Omar Wagih; 04.05.2013
comment
Я согласен, качество изображения слишком низкое, возможно, его можно было бы улучшить с помощью простых усилий, изменив методы захвата. - person Ilya Evdokimov; 04.05.2013

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

person denver    schedule 01.05.2013
comment
Коррекция освещенности также использует локальное усреднение, поэтому ничем не отличается от niblack, за исключением того, что требует дополнительного шага. так что на самом деле нет смысла, если единственное, что вы ищете, это текст с OCR. - person morishuz; 02.05.2013
comment
Подсветку можно применять в режиме макросъемки, поскольку искажения по всему изображению постепенные и непрерывные. Это может неравномерно уменьшить дисперсию в локальной области до применения адаптивного порога. - person denver; 02.05.2013