Быстрый пороговой обработки изображения

что такое быстрый и надежный способ порогового изображения с возможным размытием и неравномерной яркостью?

пример (размытие, но равномерная яркость):

enter image description here

поскольку изображение не гарантируется равномерной яркостью,невозможно использовать фиксированный порог. Адаптивный порог работает нормально, но из-за размытости он создает разрывы и искажения в функциях (здесь важными функциями являются Судоку цифры):

enter image description here

Я также попытался использовать выравнивание гистограммы (используя OpenCV

5 ответов


используя предложения вон Катона и Тераота, я уменьшил изображение, прежде чем закрыть его, а затем увеличил закрытое изображение до обычного размера. Я также пропорционально уменьшил размер ядра.

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(5,5));
Mat temp = new Mat(); 

Imgproc.resize(image, temp, new Size(image.cols()/4, image.rows()/4));
Imgproc.morphologyEx(temp, temp, Imgproc.MORPH_CLOSE, kernel);
Imgproc.resize(temp, temp, new Size(image.cols(), image.rows()));

Core.divide(image, temp, temp, 1, CvType.CV_32F); // temp will now have type CV_32F
Core.normalize(temp, image, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);

Imgproc.threshold(image, image, -1, 255, 
    Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);

изображение ниже показывает результаты бок о бок для 3 различных методов:

Left-закрытие регулярного размера (432 пикселя), размер ядра 19

закрытие среднего размера (216 пикселей), ядро размера 9

закрытие правой четверти (108 пикселей), размер ядра 5

enter image description here

качество изображения ухудшается, поскольку размер изображения, используемого для закрытия, становится меньше, но ухудшение недостаточно значительно, чтобы повлиять на алгоритмы распознавания объектов. Скорость увеличивается чуть более чем в 16 раз для закрытия четверти размера, даже при изменении размера, что предполагает, что время закрытия примерно пропорционально количеству пикселей на изображении.

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


альтернативный подход:

предполагая, что ваше намерение состоит в том, чтобы цифры были четко бинаризован ... переместите фокус на компоненты, а не на весь образ.

вот довольно простой подход:

  1. сделайте осторожную edgemap на изображении. Сначала попробуйте с параметрами для функции Canny в диапазоне от низкого порога до 0,66 * [среднее значение] и высокого порога до 1,33*[среднее значение]. (значение среднее значение greylevel).
  2. вам нужно будет немного повозиться с параметрами, чтобы получить изображение, где основные компоненты/цифры видны четко как отдельные компоненты. Почти идеально было бы достаточно на данном этапе.
  3. рассматривая каждый Канни край как подключенный компонент (т. е. использовать cvFindContours () или его аналог C++, в зависимости от того), можно оценить передний план и фоновые серые уровни и достичь порога.

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

    надеюсь, что это помогло!

Edit 1:

основываясь на порогах Canny edge, вот очень грубая идея, достаточная для точной настройки значений. The high_threshold определяет, насколько сильным должно быть ребро до его обнаружения. В принципе, ребро должно иметь градиент величина больше чем high_threshold чтобы быть обнаруженным в первую очередь. Таким образом, это делает первоначальное обнаружение ребер.

и low_threshold имеет дело с соединением близлежащих краев. Он контролирует, сколько близлежащих отключенных краев будет объединено в один край. Для лучшей идеи прочитайте "Шаг 6" из этот сайт. Попробуйте установить очень маленький low_threshold и посмотреть,как все происходит. Вы можете отказаться от этой вещи 0.66*[среднее значение], если она не работает на этих изображениях - его просто все равно правило.


мы используем Брэдли алгоритм очень похожие проблемы (в сегменте буквы от фона, с неровными света и неровного цвета фона), описан здесь: http://people.scs.carleton.ca:8008/~рот/ИИТ-публикации-ити/документы/gerh-50002.формат PDF, Вот код на C#: http://code.google.com/p/aforge/source/browse/trunk/Sources/Imaging/Filters/Adaptive+Binarization/BradleyLocalThresholding.cs?r=1360. Он работает на цельный образ, который может быть вычислен, используя integral функция использованием OpenCV. Он очень надежный и быстрый, но сам не реализован в OpenCV, но легко переносится.

другой вариант-метод adaptiveThreshold в openCV, но мы не дали ему попробовать: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold - ... Средняя версия такая же, как у bradleys, за исключением того, что она использует константу для изменения среднего значения вместо процента, что я думаю, лучше.

также, хорошая статья здесь: https://dsp.stackexchange.com/a/2504


вы можете попробовать работать на основе каждой плитки, если знаете, что у вас есть хороший урожай сетки. Работает на 9 подызображения, а не весь рис, скорее всего, приведет к более равномерной яркости на каждом фрагменте. Если ваша обрезка идеальна, вы можете даже попробовать использовать каждую цифровую ячейку отдельно; но все зависит от того, насколько надежен ваш урожай.


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

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));

в:

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(19,19));

смогите быстро пройти вверх по вашему достаточному решению с низким ударом к точности.