В этом примере показано, как обнаружить области в изображении, которые содержат текст. Это обычная задача, выполняемая на неструктурированных сценах. Неструктурированные сцены являются изображениями, которые содержат неопределенные или случайные сценарии. Например, вы можете автоматически обнаруживать и распознавать текст из захваченного видео, чтобы предупредить драйвер о дорожном знаке. Это отличается от структурированных сцен, которые содержат известные сценарии, где положение текста известно заранее.
Сегментация текста из неструктурированной сцены очень помогает с дополнительными задачами, такими как оптическое распознавание символов (OCR). Алгоритм автоматического обнаружения текста в этом примере обнаруживает большое количество кандидатов текстовых областей и постепенно удаляет те, которые с меньшей вероятностью содержат текст.
Детектор функций MSER хорошо работает для нахождения текстовых областей [1]. Он хорошо работает для текста, потому что последовательный цвет и высокая контрастность текста приводят к стабильным профилям интенсивности.
Используйте detectMSERFeatures
функция, чтобы найти все области в изображении и построить эти результаты. Заметьте, что рядом с текстом обнаружено много нетекстовых областей.
colorImage = imread('handicapSign.jpg'); I = im2gray(colorImage); % Detect MSER regions. [mserRegions, mserConnComp] = detectMSERFeatures(I, ... 'RegionAreaRange',[200 8000],'ThresholdDelta',4); figure imshow(I) hold on plot(mserRegions, 'showPixelList', true,'showEllipses',false) title('MSER regions') hold off
Несмотря на то, что алгоритм MSER выбирает большую часть текста, он также обнаруживает многие другие стабильные области в изображении, которые не являются текстом. Можно использовать подход, основанный на правилах, для удаления нетекстовых областей. Для примера геометрические свойства текста могут использоваться для фильтрации нетекстовых областей с помощью простых порогов. Кроме того, можно использовать подход машинного обучения для обучения классификатора текста и нетекста. Как правило, комбинация двух подходов дает лучшие результаты [4]. Этот пример использует простой подход на основе правил для фильтрации нетекстовых областей на основе геометрических свойств.
Существует несколько геометрических свойств, которые хороши для различения текстовых и нетекстовых областей [2,3], включая:
Соотношение сторон
Оригинальность
Число Эйлера
Степень
Основательность
Использование regionprops
чтобы измерить несколько из этих свойств и затем удалить области на основе значений их свойств.
% Use regionprops to measure MSER properties mserStats = regionprops(mserConnComp, 'BoundingBox', 'Eccentricity', ... 'Solidity', 'Extent', 'Euler', 'Image'); % Compute the aspect ratio using bounding box data. bbox = vertcat(mserStats.BoundingBox); w = bbox(:,3); h = bbox(:,4); aspectRatio = w./h; % Threshold the data to determine which regions to remove. These thresholds % may need to be tuned for other images. filterIdx = aspectRatio' > 3; filterIdx = filterIdx | [mserStats.Eccentricity] > .995 ; filterIdx = filterIdx | [mserStats.Solidity] < .3; filterIdx = filterIdx | [mserStats.Extent] < 0.2 | [mserStats.Extent] > 0.9; filterIdx = filterIdx | [mserStats.EulerNumber] < -4; % Remove regions mserStats(filterIdx) = []; mserRegions(filterIdx) = []; % Show remaining regions figure imshow(I) hold on plot(mserRegions, 'showPixelList', true,'showEllipses',false) title('After Removing Non-Text Regions Based On Geometric Properties') hold off
Другой распространенной метрикой, используемой для различения текста и нетекста, является ширина штриха. Ширина штриха-это мера ширины кривых и линий, образующих символ. Текстовые области, как правило, имеют небольшие вариации ширины штриха, в то время как нетекстовые области, как правило, имеют большие изменения.
Чтобы помочь понять, как ширина штриха может использоваться, чтобы удалить нетекстовые области, оцените ширину штриха одной из обнаруженных областей MSER. Вы можете сделать это с помощью преобразования расстояния и бинарной операции утончения [3].
% Get a binary image of the a region, and pad it to avoid boundary effects % during the stroke width computation. regionImage = mserStats(6).Image; regionImage = padarray(regionImage, [1 1]); % Compute the stroke width image. distanceImage = bwdist(~regionImage); skeletonImage = bwmorph(regionImage, 'thin', inf); strokeWidthImage = distanceImage; strokeWidthImage(~skeletonImage) = 0; % Show the region image alongside the stroke width image. figure subplot(1,2,1) imagesc(regionImage) title('Region Image') subplot(1,2,2) imagesc(strokeWidthImage) title('Stroke Width Image')
На изображениях, показанных выше, заметьте, что изображение ширины штриха имеет очень мало изменений в большей части области. Это указывает, что область с большей вероятностью является текстовой областью, потому что линии и кривые, образующие область, все имеют одинаковые ширины, что является общей характеристикой читаемого человеком текста.
В порядок использования вариаций ширины штриха для удаления нетекстовых областей с помощью порога значения изменение по всей области должно быть количественно определено в одну метрику следующим образом:
% Compute the stroke width variation metric
strokeWidthValues = distanceImage(skeletonImage);
strokeWidthMetric = std(strokeWidthValues)/mean(strokeWidthValues);
Затем может быть применен порог для удаления нетекстовых областей. Обратите внимание, что это пороговое значение может потребовать настройки для изображений с различными стилями шрифта.
% Threshold the stroke width variation metric
strokeWidthThreshold = 0.4;
strokeWidthFilterIdx = strokeWidthMetric > strokeWidthThreshold;
Процедура, показанная выше, должна применяться отдельно к каждой обнаруженной области MSER. В следующем цикле for-loop обрабатываются все области, а затем показываются результаты удаления нетекстовых областей с помощью вариаций ширины штриха.
% Process the remaining regions for j = 1:numel(mserStats) regionImage = mserStats(j).Image; regionImage = padarray(regionImage, [1 1], 0); distanceImage = bwdist(~regionImage); skeletonImage = bwmorph(regionImage, 'thin', inf); strokeWidthValues = distanceImage(skeletonImage); strokeWidthMetric = std(strokeWidthValues)/mean(strokeWidthValues); strokeWidthFilterIdx(j) = strokeWidthMetric > strokeWidthThreshold; end % Remove regions based on the stroke width variation mserRegions(strokeWidthFilterIdx) = []; mserStats(strokeWidthFilterIdx) = []; % Show remaining regions figure imshow(I) hold on plot(mserRegions, 'showPixelList', true,'showEllipses',false) title('After Removing Non-Text Regions Based On Stroke Width Variation') hold off
На данной точке все результаты обнаружения состоят из отдельных текстовых символов. Чтобы использовать эти результаты для задач распознавания, таких как OCR, отдельные текстовые символы должны быть объединены в текстовые строки или слова. Это позволяет распознавать фактические слова в изображении, которые несут более значимую информацию, чем только отдельные символы. Например, распознавание строки 'EXIT' по сравнению с набором отдельных символов {'X', 'E', 'T', 'I'}, где значение слова теряется без правильного упорядоченного расположения.
Один из подходов для объединения отдельных текстовых областей в слова или текстовые строки состоит в том, чтобы сначала найти соседние текстовые области, а затем сформировать ограничивающий прямоугольник вокруг этих областей. Чтобы найти соседние области, разверните ограничительные рамки, вычисленные ранее с помощью regionprops
. Это заставляет ограничивающие рамки соседних текстовых областей перекрываться так, что текстовые области, которые являются частью одного и того же слова или текстовой строки, образуют цепь перекрывающихся ограничивающих рамок.
% Get bounding boxes for all the regions bboxes = vertcat(mserStats.BoundingBox); % Convert from the [x y width height] bounding box format to the [xmin ymin % xmax ymax] format for convenience. xmin = bboxes(:,1); ymin = bboxes(:,2); xmax = xmin + bboxes(:,3) - 1; ymax = ymin + bboxes(:,4) - 1; % Expand the bounding boxes by a small amount. expansionAmount = 0.02; xmin = (1-expansionAmount) * xmin; ymin = (1-expansionAmount) * ymin; xmax = (1+expansionAmount) * xmax; ymax = (1+expansionAmount) * ymax; % Clip the bounding boxes to be within the image bounds xmin = max(xmin, 1); ymin = max(ymin, 1); xmax = min(xmax, size(I,2)); ymax = min(ymax, size(I,1)); % Show the expanded bounding boxes expandedBBoxes = [xmin ymin xmax-xmin+1 ymax-ymin+1]; IExpandedBBoxes = insertShape(colorImage,'Rectangle',expandedBBoxes,'LineWidth',3); figure imshow(IExpandedBBoxes) title('Expanded Bounding Boxes Text')
Теперь перекрывающиеся ограничительные рамки могут быть объединены вместе, чтобы сформировать один ограничивающий прямоугольник вокруг отдельных слов или текстовых строк. Для этого вычислите коэффициент перекрытия между всеми ограничивающими прямоугольными парами. Это количественно определяет расстояние между всеми парами текстовых областей, так что можно найти группы соседних текстовых областей, ища ненулевые коэффициенты перекрытия. После вычисления парных коэффициентов перекрытия используйте graph
чтобы найти все текстовые области, «связанные» ненулевым коэффициентом перекрытия.
Используйте bboxOverlapRatio
функция для вычисления парных коэффициентов перекрытия для всех развернутых ограничивающих рамок, затем используйте graph
для поиска всех связанных областей.
% Compute the overlap ratio overlapRatio = bboxOverlapRatio(expandedBBoxes, expandedBBoxes); % Set the overlap ratio between a bounding box and itself to zero to % simplify the graph representation. n = size(overlapRatio,1); overlapRatio(1:n+1:n^2) = 0; % Create the graph g = graph(overlapRatio); % Find the connected text regions within the graph componentIndices = conncomp(g);
Область выхода conncomp
- индексы связанных текстовых областей, к которым принадлежит каждый ограничивающий прямоугольник. Используйте эти индексы, чтобы объединить несколько соседних ограничивающих рамок в один ограничивающий прямоугольник путем вычисления минимума и максимума отдельных ограничивающих рамок, образующих каждый связанный компонент.
% Merge the boxes based on the minimum and maximum dimensions. xmin = accumarray(componentIndices', xmin, [], @min); ymin = accumarray(componentIndices', ymin, [], @min); xmax = accumarray(componentIndices', xmax, [], @max); ymax = accumarray(componentIndices', ymax, [], @max); % Compose the merged bounding boxes using the [x y width height] format. textBBoxes = [xmin ymin xmax-xmin+1 ymax-ymin+1];
Наконец, перед показом окончательных результатов обнаружения подавьте обнаружение ложного текста путем удаления ограничивающих рамок, составленных только из одной текстовой области. Это удаляет изолированные области, которые вряд ли будут фактическим текстом, учитывая, что текст обычно встречается в группах (слова и предложения).
% Remove bounding boxes that only contain one text region numRegionsInGroup = histcounts(componentIndices); textBBoxes(numRegionsInGroup == 1, :) = []; % Show the final text detection result. ITextRegion = insertShape(colorImage, 'Rectangle', textBBoxes,'LineWidth',3); figure imshow(ITextRegion) title('Detected Text')
После обнаружения текстовых областей используйте ocr
функция для распознавания текста внутри каждого ограничивающего прямоугольника. Обратите внимание, что без предварительного нахождения текстовых областей, выхода ocr
функция была бы значительно более шумной.
ocrtxt = ocr(I, textBBoxes); [ocrtxt.Text]
ans = 'HANDICIXPPED PARKING SPECIAL PLATE REQUIRED UNAUTHORIZED VEHICLES MAY BE TOWED AT OWNERS EXPENSE '
В этом примере показано, как обнаружить текст в изображении с помощью детектора функций MSER, чтобы сначала найти текстовые области-кандидаты, а затем оно описало, как использовать геометрические измерения для удаления всех нетекстовых областей. Этот пример кода является хорошей начальной точкой для разработки более устойчивых алгоритмов обнаружения текста. Обратите внимание, что без дополнительных улучшений этот пример может привести к разумным результатам для множества других изображений, например, posters.jpg или licensePlates.jpg.
[1] Chen, Huizhong, et al. «Надежное обнаружение текста в естественных изображениях с максимально стабильнейшие экстремальнейшие области с улучшенными кромками». Обработка изображений (ICIP), 2011 18-я Международная конференция IEEE по. IEEE, 2011.
[2] Gonsalez, Alvaro, et al. «Расположение текста в сложных изображениях». Pattern Recognition (ICPR), 2012 21-я Международная конференция. IEEE, 2012.
[3] Ли, Яо и Хучуань Лу. «Обнаружение текста сцены по ширине штриха». Pattern Recognition (ICPR), 2012 21-я Международная конференция. IEEE, 2012.
[4] Нейман, Лукас и Иржи Матас. «Локализация и распознавание текста сцены в реальном времени». Компьютерное зрение and Pattern Recognition (CVPR), 2012 IEEE Conference on. IEEE, 2012.