Коридор (river) — совпадение пробелов по вертикали или наклонной линии в трёх и более смежных строках, один из дефектов вёрстки. Дефект устраняется довольно легко, но сложность заключается в его автоматическом обнаружении.
Коридор появляется не только из-за специфичного расположения пробелов, но из-за формы глифов. Например, в двух текстах пробелы расположены в одинаковых местах. В первом хорошо заметны два коридора, а во втором дефекта нет.
Логично применить здесь метод с переводом текста в растровую картинку и обработкой изображения.
При обсуждении задачи на StackExchange было предложено два простых и эффективных решения. Возможно, кому-то они тоже окажутся полезными.
1. Открываем изображение с чёрно-белой маской nPix-by-1, где nPix примерно соответствует межстрочному интервалу, то есть количеству пикселов между строками.
2. Обрабатываем изображение маской 1-by-mPix, где mPix — минимальная ширина коридора. Так мы избавляемся от слишком тонких линий.
3. Избавляемся от горизонтальных «коридоров», которые могут быть вызваны или отступом первой строки, или интервалом между абзацами. Также убираем «озёра» большого размера, просто наложив маску чуть больше, чем nPix-by-nPix. На этом шаге мы избавляемся также от слишком маленьких «речушек», которые имеют размер меньше, чем (nPix+2)*(mPix+2)*4, то есть примерно три строки.
4. Если нам важна не только длина, но и толщина коридора, то можно нарисовать скелет из точек, равноудалённых от границ коридора, с окраской каждой точки в соответствии с шириной коридора в этом месте.
В Mathematica это делается с помощью эрозии и преобразования Хафа в несколько строчек кода.
Коридор появляется не только из-за специфичного расположения пробелов, но из-за формы глифов. Например, в двух текстах пробелы расположены в одинаковых местах. В первом хорошо заметны два коридора, а во втором дефекта нет.
Логично применить здесь метод с переводом текста в растровую картинку и обработкой изображения.
При обсуждении задачи на 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}]