Вот еще альтернативное решение вашей проблемы, смоделировав ваш вопрос как «проблему оптимизации пути». Хотя это сложнее, чем простое решение для бинаризации и затем кривой, на практике оно более надежно.
С очень высокого уровня, мы должны рассматривать это изображение как график, где
каждый пиксель изображения является узлом на этом графике
каждый узел связан с некоторыми другими узлами, известными как соседи, и это определение соединения часто называют топологией этого графа.
каждый узел имеет вес (особенность, стоимость, энергия или как вы хотите его назвать), отражая вероятность того, что этот узел находится в оптимальной центральной линии, которую мы ищем.
До тех пор, пока мы можем смоделировать эту вероятность, ваша задача поиска «осевых линий границ» переходит к задаче поиска локальных оптимальных путей на графе , которые могут быть эффективно решены с помощью динамического программирования, например, алгоритма Витерби.
Вот некоторые плюсы принятия этого подхода:
все ваши результаты будут непрерывными (в отличие от порогового метода, который может разбить одну центральную линию на части)
много свобод для построения такого графа, вы можете выбрать различные функции и топологию графа.
Ваши результаты являются оптимальными в смысле оптимизации пути
Ваше решение будет более устойчивым к шуму, поскольку пока шум равномерно распределяется между всеми пикселями, эти оптимальные пути остаются стабильными.
Вот короткая демонстрация вышеуказанной идеи. Поскольку я не использую какие-либо предварительные знания для определения возможных начальных и конечных узлов, я просто декодирую по каждому возможному начальному узлу.
Для нечетких окончаний это вызвано тем, что мы ищем оптимальные пути для всех возможных конечных узлов. В результате, хотя для некоторых узлов, расположенных в темных областях, выделенный путь все еще остается локально оптимальным.
Для нечеткого пути вы можете сгладить его после того, как найдете его, или использовать некоторые сглаженные функции вместо необработанной интенсивности.
Можно восстановить частичные пути, изменив начальный и конечный узлы.
Нетрудно обрезать эти нежелательные локальные оптимальные пути. Потому что у нас есть вероятность всех путей после декодирования Витерби, и вы можете использовать различные предшествующие знания (например, мы видим, что нам нужен только один оптимальный путь для тех, кто использует один и тот же источник).
Для более подробной информации, вы можете обратиться к статье.
Wu, Y.; Zha, S.; Cao, H.; Liu, D., & Natarajan, P. (2014, February). A Markov Chain Line Segmentation Method for Text Recognition. In IS&T/SPIE 26th Annual Symposium on Electronic Imaging (DRR), pp. 90210C-90210C.
Вот небольшой фрагмент кода Python, который используется для создания приведенного выше графика.
import cv2
import numpy as np
from matplotlib import pyplot
# define your image path
image_path = ;
# read in an image
img = cv2.imread( image_path, 0 );
rgb = cv2.imread( image_path, -1 );
# some feature to reflect how likely a node is in an optimal path
img = cv2.equalizeHist( img ); # equalization
img = img - img.mean(); # substract DC
img_pmax = img.max(); # get brightest intensity
img_nmin = img.min(); # get darkest intensity
# express our preknowledge
img[ img > 0 ] *= +1.0 / img_pmax;
img[ img = 1 :
prev_idx = vt_path[ -1 ].astype('int');
vt_path.append( path_buffer[ prev_idx, time ] );
time -= 1;
vt_path.reverse();
vt_path = np.asarray( vt_path ).T;
# plot found optimal paths for every 7 of them
pyplot.imshow( rgb, 'jet' ),
for row in range( 0, h, 7 ) :
pyplot.hold(True), pyplot.plot( vt_path[row,:], c=np.random.rand(3,1), lw = 2 );
pyplot.xlim( ( 0, w ) );
pyplot.ylim( ( h, 0 ) );