Видимость коридора зависит не только от расположения пробелов, но и от формы символов. Например, на двух текстах ниже пробелы расположены в одинаковых местах, но в первом коридоры хорошо заметны, а во втором дефекта нет. Поэтому логично применить здесь метод с переводом текста в растровую картинку и обработкой изображения.
При обсуждении задачи на 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/
Добавить комментарий