基于matlab的快速定位限速标志牌算法
数学实验的综合实验设计,要求使用matlab建立模型和算法,能够快速从图片中取出含有限速标志的图片区域。并截取保存为图片文件。 要求算法能够自动提取红色圆形图框区域。
一,题目分析
要定位限速标志,首先需要明白标志的特征,一个典型的限速标志如下:
该图像为一圈红色圆形区域中间包含黑色数字的形式组成,题目上要求能够自动提取红色圆形图框区域,那我们只需要想办法把这个圆弄出来。
那么基本思想如下:
- 提取出图像中的红色像素区域
- 找到这些像素区域中的圆
- 根据圆的位置对原图进行截图
对截取到的图片进行进一步判别
二,具体步骤
首先亮出例程图:
图片的读取与转化
首先需要对图片进行读取和转化。
使用imread(file)
读取图像,该函数会返回RGB图像数组:
1 | image=imread('pic/include-80.png'); |
由于RGB图像不易处理,这里需先转换为HSV图像。
关于RGB,HSV,HSL:三分钟带你快速学习RGB、HSV和HSL颜色空间
使用rgb2hsv(img)
进行转化,该函数会返回一个MxNx3的数组,对应图像的H,S,V分量。
1 | hsvImg=rgb2hsv(image);%转换到HSV空间 |
之后,需要提取出其中的红色像素点。该步骤可以使用matlab数组运算和逻辑运算,判断HSV三个域中的每个像素点是否在红色像素点数值范围,是为1,否为0,最后将三个域的数组相与运算,就得到了只有红色像素位置信息图片,顺便还进行了图像的二值化。
1 | hsvReg1=((h1<=0.056&h1>=0)|(h1>=0.740&h1<=1.0)) & s1>=0.169& s1<=1.0 &v1>=0.180&v1<=1.0;%提取红色分量 |
得到的结果如下:
图像的降噪处理
可以看到,此时图像已经可以十分清楚的看到圆环了。
之后需要对图像进行降噪处理,消除图像中像素点的很少的无效区域,便于之后对图像进行处理。
使用bwareaopen(BW,P)
删除二值化图像BW中像素量少于P的所有连通分量。可以将像素少于P的色块区域删除。
1 | hsvReg1=bwareaopen(hsvReg1,110);%110为去除像素点阙值 |
其中P的值需要根据实际情况进行选择,太大可能导致较小的图像被直接删没了,太大图像就会有很多杂点。
运行结果:
可以看到少了很多杂点。
填充平滑图像
现在我们得到了包含各种色块的图像,由于我们使用圆度进行检测,因此需要让目标色块尽可能平滑饱满,跟圆长得更加接近,减少以下情况对识别的干扰:
首先需要填充图像内部的小黑点。这里使用闭运算imclose(I,SE)
,使用结构元素 SE
对灰度或二值图像 I
执行形态学闭运算。形态学闭运算是先膨胀后腐蚀,这两种运算使用相同的结构元素。
这里补充一下关于图像开闭运算的知识:
膨胀:求局部最大值的操作
腐蚀:求局部最小值的操作
开运算
imopen()
:先腐蚀后膨胀称为开 (Open)局部的区域大小和形状由SE指定。原图经过开运算后,去除孤立的小点,毛刺和小桥(即连通两块区域的小点),而总的位置和形状不变。
闭运算
imclose()
:先膨胀后腐蚀称为闭 (Close)局部的区域大小和形状由SE指定。原图经过闭运算后,能够填平小湖(即小孔),弥合小缝隙,而总的位置和形状不变。
参考文章:开闭运算 imopen imclose
SE
可由函数strel()
生成,该函数可以生成很多类型的平面元素结构,我们只需要使用SE = strel("disk",r)
盘型结构,其他结构可以参考官方文档。
对图像进行闭运算:
1 | se=strel('disk',2);%半径为2 |
其中imfill(hsvReg1,'holes')
填充了图像中的孔,即无法通过从图像边缘填充背景来到达的一组背景像素。结果是圆环变成圆。
划分连通区域
该步骤将上图中的图块分别标记编号并求其边缘点。
使用函数[B,L]=bwboundaries(hsvReg1,'noholes')
,该函数将图像上的连通域分别标记并记录边界点在cell类型的B中,在L中储存标记后的区域。
其中指定参数noholes
将不会将hole作为新对象,而是将包括hole的整体作为一个整体。
1 | [B,L]=bwboundaries(hsvReg1,'noholes'); |
处理结果:
区分了每个连通域及其边界。
计算连通域特性
获得了不同连通域后,我们需要计算不同连通域的特性。
使用regionprops(BW,properties)
进行计算,根据properties
字符串计算标记好连通域的BW中不同连通域的不同特性,并返回结构体数组。
在该题中,我们依据图形的圆度判断是否为圆,因此我们需要求:
Centroid
:区域的质心,对应圆心Area
:实际的像素数,对应面积Circularity
:圆度,由(4*Area *pi)/(Perimeter^2)计算,由于matlab2017没有,因此直接求Perimeter
Perimeter
:围绕区域的边界,如果图像包含不连续区域,regionprops
将返回意外结果。(所以先填充平滑)
1 | stats=regionprops(L,'Area','Centroid','Perimeter'); |
提取图形中的圆
在该步骤中,我们遍历每一个连通域,求其圆度,保持圆度大于阈值threshold
的连通域的圆心,半径(由周长计算)。
1 | threshold=0.88;%圆度的阈值 |
裁剪图像
获得圆心和半径后,我们可以计算出圆所在图像区域,使用imcrop(I,rect)
进行裁剪。
rect
是一个四元素数组,第一二个元素为矩形的左上角坐标,第三个元素是矩形的长,第四个是宽。
1 | for i=1:length(cents) |
结果如下:
三,结论
本方法使用提取红色像素进行二值化,通过对二值化图像找圆的方式找到原图中的红色圆形区域,以定位限速牌。由于使用圆度进行判断,判断方法较为单一,当阈值过大,会导致变形的限速牌无法识别,当阈值过小,一些图像则会被误识别,因此还需要进行改进,以获得更加准确的方案。
目前,可以考虑对裁剪后的图像进行文字识别OCR,如果有限速的数字则可以更为准确的判断。
四,代码附录
1 | image=imread('pic/include-80.png'); |