自动检测与识别自然图像中的文本

这个例子显示了如何检测包含文本的图像中的区域。这是非结构化场景进行的一项共同任务。非结构化场景是包含不确定的或随机的场景图像。例如,你可以从捕获的视频自动检测和识别的文字来提醒有关交通标志的驱动程序。这比结构化场景,其含有其中文本的位置事先已知的已知方案不同。

从非结构化场景分割文本大大有助于其他任务,如光学字符识别(OCR)。在此实例中的自动文本检测算法检测到大量的文本区域候补的和逐步去除那些不太可能包含文本。

第1步:检测候选文本区使用MSER

MSER特征检测器可以很好地查找文本区域[1]。它对文本很有效,因为文本的一致颜色和高对比度导致稳定的强度配置文件。

使用detectMSERFeatures函数查找图像中的所有区域并绘制这些结果。注意,在文本旁边检测到许多非文本区域。

colorImage = imread (“handicapSign.jpg”);I = rgb2gray(colorImage);检测MSER区域。[mserRegions,mserConnComp] = detectMSERFeatures(I,...'RegionAreaRange',[200 8000]“ThresholdDelta”,4);图imshow(我)抱情节(mserRegions'showPixelList',真实,'showEllipses'、假)标题(“女士地区”)保持

步骤2:基于基本的几何属性删除非文本区域

虽然MSER算法挑选出大部分的文字,也检测到图像中不是文字许多其他稳定的区域。您可以使用基于规则的方法来除去非文本区域。例如,文本的几何性质可以用于过滤出使用简单的阈值的非文本区域。或者,您可以使用机器学习方法训练文本对非文本分类。典型地,这两种方法的组合来产生更好的效果[4]。此示例使用一个简单的基于规则的方法来基于几何特性滤波器非文本区域。

有几种几何性质是良好的文本和非文本区[2,3]之间进行鉴别,其中包括:

  • 纵横比

  • 偏心

  • 欧拉数

  • 程度

  • 密实度

采用regionprops测量其中的一些属性,然后根据它们的属性值删除区域。

%用途regionprops测量MSER性能mserStats = regionprops(mserConnComp,'BoundingBox的'“偏心”...“密实”“程度”“欧拉”“图像”);使用包围框数据计算纵横比。bbox = vertcat (mserStats.BoundingBox);w = bbox (: 3);h = bbox (: 4);aspectRatio = w / h;阈值数据,以确定要删除哪些区域。这些阈值%,可能需要调整为其他图像。filterIdx =的aspectRatio”> 3;filterIdx = filterIdx |[mserStats.Eccentricity]> 0.995;filterIdx = filterIdx |[mserStats.Solidity] <0.3;filterIdx = filterIdx |[mserStats.Extent] <0.2 |[mserStats.Extent]> 0.9;filterIdx = filterIdx |[mserStats.EulerNumber] <-4;%删除地区mserStats(filterIdx)= [];mserRegions(filterIdx)= [];%显示剩余区域图imshow(我)抱情节(mserRegions'showPixelList',真实,'showEllipses'、假)标题(“基于几何属性删除非文本区域后”)保持

第3步:根据笔划宽度变化除去非文本区域

用于文本和非文本之间判别另一个常见度量是笔划宽度。笔划宽度是曲线和线,使一个字符的宽度的量度。文本区域倾向于具有小冲程宽度变化,而非文本区域往往有较大的变化。

为了帮助理解笔画宽度如何可以用来除去非文本区域,估计检测的MSER区域之一的笔画宽度。您可以通过使用距离变换和二进制细化操作[3]这样做。

%获取的区域的二值图像,并且垫,以避免边界效应%在笔画宽度计算期间。.Image regionImage = mserStats (6);regionImage = padarray(regionImage, [1 1]);计算描边宽度图像。distanceImage = bwdist (~ regionImage);skeletonImage = bwmorph (regionImage,'瘦',INF);strokeWidthImage = distanceImage;strokeWidthImage(〜skeletonImage)= 0;%旁显示笔划宽度图像的区域的图像。图副区(1,2,1)于imagesc(regionImage)标题(“地区形象”)副区(1,2,2)于imagesc(strokeWidthImage)标题(“笔划宽度图片”

在上面显示的图像中,请注意边框宽度图像在大部分区域的变化非常小。这表明该区域更可能是文本区域,因为组成该区域的直线和曲线都具有相似的宽度,这是人类可读文本的一个共同特征。

为了使用笔画宽度变化来使用阈值去除非文本区域,整个区域的变化必须量化为一个单一的度量,如下所示:

计算笔画宽度变化度量strokeWidthValues = distanceImage(skeletonImage);strokeWidthMetric = STD(strokeWidthValues)/平均值(strokeWidthValues);

然后,阈值可以被应用,以除去非文本区域。请注意,此阈值可能需要用不同的字体样式的图像调整。

%阈值的笔划宽度的变化度量strokeWidthThreshold = 0.4;strokeWidthFilterIdx = strokeWidthMetric> strokeWidthThreshold;

上述过程必须分别应用于每个检测到的MSER区域。下面的for循环处理所有区域,然后显示使用笔画宽度变化删除非文本区域的结果。

%过程中的剩余区域j = 1:numel(mserStats) regionImage = mserStats(j).Image;regionImage = padarray(regionImage, [1 1], 0);distanceImage = bwdist (~ regionImage);skeletonImage = bwmorph (regionImage,'瘦',INF);strokeWidthValues = distanceImage(skeletonImage);strokeWidthMetric = STD(strokeWidthValues)/平均值(strokeWidthValues);strokeWidthFilterIdx(J)= strokeWidthMetric> strokeWidthThreshold;结束%根据笔画宽度变化移除区域mserRegions(strokeWidthFilterIdx)= [];mserStats(strokeWidthFilterIdx)= [];%显示剩余区域图imshow(我)抱情节(mserRegions'showPixelList',真实,'showEllipses'、假)标题(“删除非文本区域之后基于笔划宽度变异”)保持

步骤4:合并文本区域以获得最终的检测结果

此时,所有的检测结果都由单独的文本字符组成。要将这些结果用于识别任务(如OCR),必须将单个文本字符合并到单词或文本行中。这使得识别图像中的实际单词成为可能,这些单词包含了比单个字符更有意义的信息。例如,识别字符串“EXIT”与单个字符{“X”、“E”、“T”、“I”}的集合,这些字符在没有正确排序的情况下丢失了单词的含义。

将单个文本区域合并到单词或文本行中的一种方法是,首先找到相邻的文本区域,然后在这些区域周围形成一个包围框。若要查找邻近区域,请展开前面计算的边界框regionprops。这使得邻近的文本区域的边界框重叠,使得属于同一字或文本行的一部分文本区域形成重叠的包围盒的链。

%获取边界的所有地区盒bboxes = vertcat(mserStats.BoundingBox);从[X Y宽度高度]%转换边界框格式到[XMIN YMIN%XMAX YMAX]格式以方便使用。XMIN = bboxes(:,1);YMIN = bboxes(:,2);XMAX = XMIN + bboxes(:,3) -  1;YMAX = YMIN + bboxes(:,4) -  1;%的少量展开边界框。expansionAmount = 0.02;XMIN =(1-expansionAmount)* XMIN;YMIN =(1-expansionAmount)* YMIN;XMAX =(1 + expansionAmount)* XMAX;YMAX =(1 + expansionAmount)* YMAX;%剪辑的边界框为图像边界内XMIN = MAX(XMIN,1);YMIN = MAX(YMIN,1);XMAX =分钟(XMAX,大小(I,2));YMAX =分钟(YMAX,大小(I,1));%显示扩展边界框expandedBBoxes = [xmin ymin xmax-xmin+1 ymax-ymin+1];IExpandedBBoxes = insertShape (colorImage,'长方形',expandedBBoxes,“线宽”,3);图imshow(IExpandedBBoxes)标题(扩展边框文本

现在,重叠的包围盒可以被合并在一起,以形成围绕单个单词或文本行的单个边界框。要做到这一点,计算所有的包围盒对之间的重合度。这种量化,这样就可以通过寻找非零重叠比率找到相邻的文本区域的组中的所有对文本区域之间的距离。一旦成对交叠比率计算,应使用找到所有由非零重叠率“连接”的文本区域。

使用bboxOverlapRatio函数来计算成对交叠比率对所有的扩展边界框,然后使用找到所有的连通区域。

%计算重叠率overlapRatio = bboxOverlapRatio(expandedBBoxes,expandedBBoxes);%设定边界框和其本身之间为零,以重叠率%简化图形表示。N =尺寸(overlapRatio,1);overlapRatio(1:N + 1:N ^ 2)= 0;%创建图表G =图表(overlapRatio);%找到图中连接的文本区域componentIndices = conncomp(克);

输出conncomp是索引来对每个边界框所属的连接的文本区域。使用这些指数通过计算各个边框组成每个连接的组件的最小值和最大值,以多个相邻边界框合并成一个单一的边框。

根据最小和最大尺寸合并盒子。XMIN = accumarray(componentIndices',XMIN,[],@Min);YMIN = accumarray(componentIndices',YMIN,[],@Min);XMAX = accumarray(componentIndices',XMAX,[],@Max);YMAX = accumarray(componentIndices',YMAX,[],@Max);%构成合并使用[X Y宽度高度]格式的边界框。textBBoxes = [XMIN YMIN XMAX-XMIN + 1 YMAX-YMIN + 1];

最后,在显示最终的检测结果之前,通过删除仅由一个文本区域组成的边界框来抑制假文本检测。这删除了不太可能是实际文本的孤立区域,因为文本通常是在组(单词和句子)中找到的。

%删除边界仅包含一个文本区框numRegionsInGroup = histcounts(componentIndices);textBBoxes(numRegionsInGroup == 1,:) = [];%显示最终文本检测结果。ITextRegion = insertShape (colorImage,'长方形',textBBoxes,“线宽”,3);图imshow(ITextRegion)标题(“发现文本”

步骤5:使用OCR识别检测到的文本

检测文本区域后,使用光学字符识别函数可识别每个边框内的文本。注意,在不首先查找文本区域的情况下光学字符识别功能将是相当多的嘈杂。

ocrtxt = OCR(I,textBBoxes);[ocrtxt.Text]
ANS = 'HANDICIXPPED PARKING特板REQUIRED UNAUTHORIZED车辆可TOWED AT业主EXPENSE'

这个例子说明,你如何检测使用MSER特征检测器先找到候选文本区域的图像中的文本,然后将它描述了如何使用几何测量删除所有的非文本区域。这个例子的代码是用于开发更强大的文本检测算法一个很好的起点。注意,如果没有进一步增强该实施例中可以产生各种其他图像的合理的结果,例如,posters.jpg或licensePlates.jpg。

参考

[1]陈,回中,等。“强大的文本检测与边缘增强后的最大稳定极值区域自然的图像。”图像处理(ICIP),2011第18届IEEE国际会议。IEEE,2011。

[2]冈萨雷斯,阿尔瓦罗等。“复杂图像中的文本位置。”模式识别(ICPR),2012第21届国际会议上。IEEE,2012。

[3]李瑶,和Huchuan路。“通过笔划宽度场景文本检测”。模式识别(ICPR),2012第21届国际会议上。IEEE,2012。

[4]诺伊曼的Lukas,和伊日麦塔斯。“实时场景文本定位和识别。”计算机视觉和模式识别(CVPR),2012年IEEE会议。IEEE,2012。