В этом примере показано, как обнаружить области в изображении, которые содержат текст. Это - общая задача, выполняемая на неструктурированных сценах. Неструктурированные сцены являются изображениями, которые содержат неопределенные или случайные сценарии. Например, вы можете автоматически обнаруживать и распознавать текст из захваченного видео, чтобы предупредить водителя о дорожном знаке. Это отличается от структурированных сцен, которые содержат известные сценарии, где положение текста известно заранее.
Сегментация текста от неструктурированной сцены значительно помогает с дополнительными задачами, такими как оптическое распознавание символов (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] Чен, Хойчжун, и др. "Устойчивое текстовое Обнаружение в Естественных Изображениях с Улучшенными Ребром Максимально Устойчивыми Экстремальными областями". Обработка изображений (ICIP), 2 011 18-х Международных конференций IEEE по вопросам. IEEE, 2011.
[2] Гонсалес, Альваро, и др. "Текстовое местоположение в комплексных изображениях". Распознавание образов (ICPR), 2 012 21-х Международных конференций по вопросам. IEEE, 2012.
[3] Литий, Яо и Хучуэн Лу. "Текстовое обнаружение сцены через ширину штриха". Распознавание образов (ICPR), 2 012 21-х Международных конференций по вопросам. IEEE, 2012.
[4] Нейман, Лукаш и Иржи Матас. "Текстовая локализация сцены в реальном времени и распознавание". Компьютерное зрение и Распознавание образов (CVPR), 2 012 Конференций по IEEE по. IEEE, 2012.