Каковы лучшие алгоритмы для порога изображения документа в этом примере?


31

Я пытаюсь реализовать различные алгоритмы бинаризации на изображении: введите описание изображения здесь

Вот код:

clc;
clear;
x=imread('n2.jpg');     %load original image

Теперь мы изменим размеры изображений, чтобы вычислительная работа стала проще для нас позже.

size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');

z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);

% теперь мы находим среднее и стандартное отклонение, необходимые для алгоритмов niblack и% sauvola

m = mean(v(:))
s=std(v(:))
k=-.4;
value=m+ k*s;
temp=v;

% реализации алгоритма порогового определения niblack:

for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
k=kittlerMet(g);
figure;
imshow(k);
title('result by kittlerMet');

% реализации алгоритма порогового соуса

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

конец

figure;
imshow(t2);
title('result by sauvola');

Результаты, которые я получил, как показано: введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

Как вы можете видеть, результирующие изображения ухудшаются в темных местах. Может кто-нибудь предложить, как оптимизировать мой результат?


1
Можете ли вы использовать информацию о цвете, чтобы отбрасывать фон, а не только яркость?
эндолит

Уважаемый сэр / мадам. Я делаю проект по обработке изображений. Мне интересна концепция бинаризации. Пожалуйста, проверьте и исправьте кодировку ... Я беру кодировку и запускаю программу. Но при кодировании возникает какая-то ошибка ... Неопределенная функция или переменная "g". и еще одно - Ошибка в msp (строка 31) k = kittlerMet (g); .. Как ее решить ... Пожалуйста, исправьте кодировку ...
muthu

Ответы:


49

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

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

white = Closing[src, DiskMatrix[5]]

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

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

РЕДАКТИРОВАТЬ: меня попросили в комментариях объяснить, что делает операция закрытия. Это морфологическая дилатация с последующей морфологической эрозией . Расширение, по сути, перемещает структурирующий элемент в каждой позиции изображения и выбирает самый яркий пиксель под маской, таким образом:

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

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

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

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

Вот пример с различными размерами структурирующего элемента:

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

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

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

Теперь вы просто делите исходное изображение на это «белое изображение», чтобы получить изображение (почти) равномерной яркости:

whiteAdjusted = Image[ImageData[src]/ImageData[white]*0.85]

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

Это изображение теперь может быть преобразовано в двоичную форму с постоянным порогом:

Binarize[whiteAdjusted , 0.6]

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


5
Вот Это Да! Это действительно круто! Огромный +1!
Фонон

@nikie +1 Очень приятно - что именно вы подразумеваете, когда закрывающий фильтр должен быть «выбран больше, чем штрих шрифта»? Ширина или длина любой буквы? Кроме того, что на самом деле делает закрывающий фильтр? Благодарность!
Spacey

1
@ Мохаммед: я добавил небольшое пояснение к своему ответу. И да, это нелинейные операции. Общим заголовком является морфологическая обработка изображений.
Ники Эстнер

1
@nikie Неважно, максимум белый, а не черный. :-)
Спейси

1
@gdelfino: Я обычно стараюсь избегать этого, используя достаточно большую маску, и использую Clip[ImageData[white],{eps,Infinity}]там, где eps - небольшое число, чтобы быть в безопасности.
Ники Эстнер

6

Ответ Ники кажется лучшим, а также работает и приносит результаты. Так что это явный победитель.

Тем не менее, просто к документации я добавил еще одну ссылку, которая может быть очень быстрой.

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

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

Ссылка ниже подробно описывает точный метод. http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm

Этот метод будет относительно вычислительно быстрее.


Разве эти две вещи по сути не одинаковы? А именно, оценить локальное среднее значение сигнала до установления порога?
Мориц

1
@Maurits Похоже, что основными отличиями являются порядок и используемая статистика. Например, в операторах открытия / закрытия (которые состоят из дилатации и эрозии, но в другом порядке) окно сканируется растром и берется макс. (Между прочим). Однако в адаптивном пороге среднее / медиана может быть взято вместо макс.
Spacey

ОП также спросил об этом на SO , на что я ответил. Но в принципе я не думаю, что между ответами есть какая-либо разница, каждый всегда оценивает местную статистику. Если вы делаете адаптивный порог, вы также изучаете фон в процессе.
Maurits

6

Еще один способ использования полосового фильтра (в MATLAB). Игра с разницей в гауссовых параметрах может дать лучшие результаты. Процесс в основном состоит в полосовой фильтрации изображения для удаления низкочастотных фоновых пятен, нормализации до [0,1], необходимого для команды 'graythresh', порогового изображения.

Загрузите изображение и преобразуйте его в двойной оттенки серого:

I = imread('hw.jpg');
I = rgb2gray(I);
I = double(I);

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

Отфильтруйте, используя разницу гауссова ядра, и нормализуйте:

J = imgaussian(I,1.5) - imgaussian(I,0.5);
J = J - min(J(:));
J = J / max(J(:));

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

Рассчитайте порог и сделайте 010101:

T = J > graythresh(J);

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


4

Это хороший код Matlab для адаптивного определения порога: http://www.mathworks.com/matlabcentral/fileexchange/8647-local-adaptive-thresholding


Argh! Требуется набор инструментов для обработки изображений, хотя. : - /
Spacey

Верно. Извините, если у вас его нет. Но DIPImage - это бесплатный Image Tolbox для Matlab. diplib.org/documentation У него есть несколько методов для определения порога (проверьте раздел сегментации), и вы также можете выполнять все морфологические операции, такие как закрытие. У разработчика также есть блог cb.uu.se/~cris/blog/index.php/archives/tag/matlab
MyCarta

0

Я попробую эту кодировку. Но у меня нет правильного ответа ...

clc;
clear;
x=imread('base2.jpg');
size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');
z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);
m = mean(v(:))
s=std(v(:))
k=-2;
value=m+ k*s;
temp=v;
for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
% k=kittlerMet(g);
% figure;
% imshow(k);
% title('result by kittlerMet');

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

end
figure;
imshow(t2);
title('result by sauvola');

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

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


2
Если это предназначено для ответа на вопрос, пожалуйста, объясните, что вы делаете и почему.
Мэтт Л.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.