Коридор (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}]
Автор: alizar