Распознавание коридоров в тексте

Коридор (river) — совпадение пробелов по вертикали или наклонной линии в трёх и более смежных строках. Считается одним из дефектов вёрстки. Дефект устраняется довольно легко, но сложность заключается в его автоматическом обнаружении.

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



При обсуждении задачи на StackExchange было предложено два простых и эффективных решения. Возможно, кому-то они тоже окажутся полезными.

1. Открываем изображение с чёрно-белой маской nPix-by-1, где nPix примерно соответствует межстрочному интервалу, то есть количеству пикселов между строками.

opImg = imopen(bwImg,ones(13,1));

2. Обрабатываем изображение маской 1-by-mPix, где mPix — минимальная ширина коридора. Так мы избавляемся от слишком тонких линий.

opImg = imopen(opImg,ones(1,5));

3. Избавляемся от горизонтальных «коридоров», которые могут быть вызваны или отступом первой строки, или интервалом между абзацами. Также убираем «озёра» большого размера, просто наложив маску чуть больше, чем nPix-by-nPix. На этом шаге мы избавляемся также от слишком маленьких «речушек», которые имеют размер меньше, чем (nPix+2)*(mPix+2)*4, то есть примерно три строки.

%# horizontal river: just look for rows that are all true opImg(all(opImg,2),:) = false; %# open with line spacing (nPix) opImg = imopen(opImg,ones(13,1));  %# remove lakes with nPix+2 opImg = opImg & ~imopen(opImg,ones(15,15));   %# remove small fry opImg = bwareaopen(opImg,7*15*4);

4. Если нам важна не только длина, но и толщина коридора, то можно нарисовать скелет из точек, равноудалённых от границ коридора, с окраской каждой точки в соответствии с шириной коридора в этом месте.

   dt = bwdist(~opImg);    sk = bwmorph(opImg,'skel',inf);    %# prune the skeleton a bit to remove branches    sk = bwmorph(sk,'spur',7);     riversWithWidth = dt.*sk;

В Mathematica это делается с помощью эрозии и преобразования Хафа в несколько строчек кода.

(*Get Your Images*) i = Import /@ {"http://i.stack.imgur.com/4ShOW.png",                 "http://i.stack.imgur.com/5UQwb.png"};  (*Erode and binarize*) i1 = Binarize /@ (Erosion[#, 2] & /@ i);  (*Hough transform*) lines = ImageLines[#, .5, "Segmented" -> True] & /@ i1;  (*Ready, show them*) Show[#[[1]],Graphics[{Thick,Orange, Line /@ #[[2]]}]] & /@ Transpose[{i, lines}]

ссылка на оригинал статьи http://habrahabr.ru/post/170485/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *