一个简单的Apriltag,数字,动物水果分类器
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单的Apriltag,数字,动物水果分类器相关的知识,希望对你有一定的参考价值。
简 介: 对于全国大学生智能车竞赛竞赛室内视觉AI组用于识别Apriltag,数字,动物以及水果任务,本文提出了基于图片像素的HSV空间的统计值,建立了一个简单的大类分类器。利用这个分类器可以非常精确的在第一时间吧图片分成Apriltag,数字以及彩色图片(动物和水果),然后在利用不同的识别模型进一步识别。
由于这个过程应用了对于图片库的先验知识,一方面可以继续应用原来已经建立好的Apriltag、数字、动物以及水果识别模型,另一方面也可以提高整个识别的效率。
关键词
: 智能车竞赛,室内视觉AI,分类器,机器视觉
§01 简单分类器
一、应用背景
在第十六届全国大学生智能车竞赛全国总决赛中,为了适应 线上总决赛 的要求, 室内视觉AI组的比赛采用了 赛道积分与识别积分分离 的比赛形式,这样可以保证比赛过程中更加的紧凑高效。
▲ 图1.1 智能车在识别图片任务
为了避免人工对于识别过程的干预,整个识别过程是由计算机随机给出Apriltag,数字,动物以及水果图片,由参赛车模自动根据拍摄的照片给出识别结果。
由于之前的比赛,Apriltag,数字,动物以及水果分别位于赛道的不同位置,Apriltag位于赛道上,数字位于三岔路口,动物和水果则位于赛道两旁。所以智能车模可以预先根据车模所处在赛道的不同位置,指导摄像头所拍摄的图片中的种类分别属于哪一大类。然后在分别调取不同的识别模型和算法来进一步处理图片。
在新的比赛模式下,所有的图片都是随机出现,因此,需要预先判断图片属于哪一大类,然后才能够调取原来的识别模型。那么改如何设计一个简单的分类算法,将获取的图片先划分到三大类(Apriltag,数字以及动物与水果)呢?
本文下面就讨论一个利用图片的像素颜色来进行分类的简单算法。
二、原始数据
1、数据库来源
在 第十六届智能汽车竞赛AI视觉组分赛区数据集发布 给出了应用在智能车竞赛中的四类图片的数据集合以及下载的方式。
-
智能车竞赛数据集合:
-
AprilTag:25h9 系列 0 ~ 9
数字:0 ~ 9
动物图片:五个子类:牛(93)、狗(101)、猪(88)、猫(99)、马(95)
水果图片: 橙子(86)、榴莲(75)、苹果(88)、葡萄(89)、香蕉(93)
数据库总体数量 927 张图片。
▲ 图1.2.1 Apriltag图片
▲ 图1.2.2 数字图片
▲ 图1.2.3 水果-桔子
▲ 图1.2.4 动物-牛图片
2、数据库存储目录
AprilTtag码
Tag25h9_0.png
Tag25h9_1.png
Tag25h9_2.png
Tag25h9_3.png
Tag25h9_4.png
Tag25h9_5.png
Tag25h9_6.png
Tag25h9_7.png
Tag25h9_8.png
Tag25h9_9.png
动物
├─牛
├─狗
├─猪
├─猫
└─马
数字
0.png
1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png
水果
├─榴莲
├─橙子
├─苹果
├─葡萄
└─香蕉
from headm import *
alldir = r'D:\\Temp\\ALL'
subdirstr = ['ApriTtag码', '数字', '动物', '水果']
animalstr = '狗,马,猫,牛,猪'
fruitstr = '橙子,榴莲,苹果,葡萄,香蕉'
animalsub = animalstr.split(',')
fruitsub = fruitstr.split(',')
def subfile(sub):
dirname = os.path.join(alldir, sub)
files = [os.path.join(alldir, sub, f) for f in os.listdir(dirname) if f[-3:]=='png']
return files
allfile = []
allfile.extend(subfile(subdirstr[0]))
allfile.extend(subfile(subdirstr[1]))
for s in animalsub:
substr = '动物\\\\%s'%s
allfile.extend(subfile(substr))
for s in fruitsub:
substr = '水果\\\\%s'%s
allfile.extend(subfile(substr))
printf(len(allfile))
三、图片颜色
1、基本识别方案
为了建立一个非常简单的Apriltag,数字、动物和水果的分类器,需要:
- 结合已知先验知识,借助于简化的模式识别的方法建立分类器;
- 抛开对于图片内的形态识别特征,转换使用基于像素的统计规律,这样可以大大提高检测速度;
因此,计划使用图片的颜色空间的统计特性来区分三类。主要利用原则:
- 由于Apriltag,数字都是黑白的图片;利用这一点可以用于区分水果与动物;
- Apriltag与数字在黑白的占空比方面不同,可以利用图片的灰度分布统计来,或者平均灰度来区分这两类。
2、图片的RGB转换HSV
根据黑白图片与参赛图片之间关系,可以把Apriltag,数字分布与动物水果进行区分。为了有效区分彩色图片与黑白图片,则需要将图片从 RGB转换到HSV空间。 在HSV(Hue, Saturation, Value)中, S 分量表示色彩的保护度,也就是颜色距离白色与纯色之间的差异度量。通常取0% ~ 100%, S值越大颜色就越饱和。
▲ 图1.3.2.1 图片的RGB
▲ 图1.3.2.2 Apriltag RGB图片
在 Python Math: Convert RGB color to HSV color 给出了RGB转换到HSV计算公式。
那么,
H
,
S
,
V
H,S,V
H,S,V的计算公式如下:
V
=
C
max
V = C_{\\max }
V=Cmax
下面给出了数字图片以及动物与水果对应的S分量的分布。可以看到黑白图片的S分量大都分布在0附近,而普通的彩色图片对应的S分量分布具有很多很大的数值。
▲ 图1.3.4 黑白图片 4 对应的S的分布
▲ 图1.3.3 不同的彩色图片对应的S分量的分布
3、利用平均色饱和度区分彩色与黑白图片
计算图片的色保护平均值:
S
a
v
e
r
a
g
e
=
∑
i
,
j
S
(
i
,
j
)
N
S_{average} = {{\\sum\\limits_{i,j}^{} {S\\left( {i,j} \\right)} } \\over N}
Saverage=Ni,j∑S(i,j)
-
其中:
-
S(i,j)
: 图片每个像素的色饱和值
N
:图片的像素个数
对于907张动物与水果的平均色饱和度值得分布如下图所示:
▲ 图1.3.3.1 动物与水果平均S值
如果取一个阈值 S min S_{\\min } Smin作为区别黑白 与彩色图片的阈值, S min S_{\\min } Smin越大,对于黑白图片的误判成彩色图片概率就越低,但对于彩色图片误判成黑白图片的概率就越大。
下图给出了使用S平均值判断彩色图片时,随着阈值的增加,正确率的变化:
▲ 图1.3.3.2 阈值与彩色图片判断正确率
可以看到当阈值取10的时候,判断黑白照片与彩色照片的正确率大约为95%,当阈值取20的时候,正确率已经下降到90%以下了。
由于使用摄像头摄取图片的时候,存在一定的图片白平衡失真,上面色饱和阈值不能够设置太高,否则就会使得黑白图片被误判成彩色图片。
下面是色饱和度小于10的动物与水果图片,共有39张,可以看到它们的确都接近于灰色图片,或者图片中动物的比例较小,大部分为背景白色。
▲ 图1.3.3.4 色饱和度小于10的图片
4、图片灰度
如果仅仅通过色保护度来区分黑白图片(Apriltag, 数字)与彩色照片(动物和水果)会存在比较大的误差。下面还可以通过图片的灰度分布差异来进一步区分黑白图与彩色图片。
下面是对于所有平均色饱和度小于20的图片绘制出他们亮度分布(V值),可以看到他们具有一个很大的特点,就是除了亮度值非常大(对应背景白色)之外,还存着一定数量的灰度值分布。
▲ 图1.3.4.1 色保护度小于20的图片亮度值分布
而对比黑色图片(Apriltag,数字)图片的亮度分布,可以看到它的分布主要集中在最高值与最低值,中间分布很少。因此,可以利用这个差异进一步区分黑白图片与彩色图片。
▲ 图1.3.4.2 黑白图的亮度值分布
对于平均色饱和小于20(总共有41张图片),计算它的次级亮度平均值:
V a v e r a g e = 1 N 1 ∑ V ( i , j ) < 230 V ( i , j ) V_{average} = {1 \\over {N_1 }}\\sum\\limits_{V\\left( {i,j} \\right) < 230}^{} {V\\left( {i,j} \\right)} Vaverage=N11V(i,j)<230∑V(i,j)
在上面公式中的230是相对于亮度最高位255时所设定的阈值,把所有不是最高亮度,也就是背景像素之外的像素亮度(V值)相加,再除以这些像素个数 N 1 N_1 N1,所得到的次级亮度平均值的分布如下图所示:
▲ 图1.3.4.3 灰度平均值
下面是对20张黑白图(Apriltag,数字)利用计算的次级亮度平均值的分布。可以看到它们的值都小于20。
▲ 图1.3.4.4 所有黑白(Apriltag, 数字)图片的次级亮度平均值分布
如果取35作为阈值,使用次级亮度平均值来区分黑白图与彩色图片,可以达到100%的正确率。
五、利用S,V区分设置分类器
为了提高分类器的适应性,可以考虑联合图片的S,V来区分黑白图与彩色图。计算图片的平均色饱和度值 S a v e S_{ave} Save以及次级平均亮度值 V a v e V_{ave} Vave。选择两个合适的阈值: S T S_T ST以及 V T V_T VT,对于同时满足: S a v e < S T , V a v e < V T S_{ave} < S_T ,\\,\\,V_{ave} < V_T Save<ST,Vave<VT
判断为黑白图(AprilTag,数字),否则就是彩色图(动物和水果)。
直接对于数据集合的图片来说, S T = 20 , V T = 60 S_T = 20,\\,\\,\\,V_T = 60 ST=20,VT=60,就可以获得100%的正确率。
选择 S T , V T S_T ,V_T ST,VT,以及用于计算次级亮度值的阈值需要根据实际摄像头图片数据进行调整。
六、区分Apriltag与数字
根据图片的平均色保护度以及次级平均亮度可以将黑白图片与动物水果图片区分开来。那么如何区分Apriltag与数字呢?
如果对于前面给出的APriltag 和数字亮度值的分布来看,可以看到Apriltag的黑色背景值比白色背景多,而数字则恰好反过来,它的白色背景像素多余黑色背景像素。利用这一点差异,可以对于黑白图片中的黑色像素(也就是V值低于图片平均灰度的像素)的个数进行统计,如果黑色像素的个数高于所有像素个数的50%,则是Apriltag图片,反之则是数字图片。
※ 算法总结 ※
对于全国大学生智能车竞赛竞赛室内视觉AI组用于识别Apriltag,数字,动物以及水果任务,本文提出了基于图片像素的HSV空间的统计值,建立了一个简单的大类分类器。利用这个分类器可以非常精确的在第一时间吧图片分成Apriltag,数字以及彩色图片(动物和水果),然后在利用不同的识别模型进一步识别。
由于这个过程应用了对于图片库的先验知识,一方面可以继续应用原来已经建立好的Apriltag、数字、动物以及水果识别模型,另一方面也可以提高整个识别的效率。
对于本文前面提到的算法中的阈值,需要根据实际采集到的图片进行进一步优化,使得最终的识别效率达到最高。
▲ 图4.1 我的智能车看到图片识别就像这只鸽子一样
※ 附件程序
from headm import *
from PIL import Image
import cv2
alldir = r'D:\\Temp\\ALL'
subdirstr = ['ApriTtag码', '数字', '动物', '水果']
animalstr = '狗,马,猫,牛,猪'
fruitstr = '橙子,榴莲,苹果,葡萄,香蕉'
animalsub = animalstr.split(',')
fruitsub = fruitstr.split(',')
def subfile(sub):
dirname = os.path.join(alldir, sub)
files = [os.path.join(alldir, sub, f) for f in os.listdir(dirname) if f[-3:]=='png']
return files
allfile = []
allfile.extend(subfile(subdirstr[0]))
allfile.extend(subfile(subdirstr[1]))
markdim = []
markdim.extend([0]*10)
markdim.extend([1]*10)
for s in animalsub:
substr = '动物\\\\%s'%s
ssf = subfile(substr)
allfile.extend(ssf)
printff(s, len(ssf))
markdim.extend([2]*(len(allfile)-len(markdim)))
for s in fruitsub:
substr = '水果\\\\%s'%s
ssf = subfile(substr)
allfile.extend(ssf)
printff(s, len(ssf))
markdim.extend([3]*(len(allfile)-len(markdim)))
pltgif = PlotGIF()
grayfile = tspload('grayfile', 'grayfile')
def img2colorhist(imagefile):
printf(imagefile)
img = Image.open(imagefile)
imghsv = img.convert('HSV')
imgdata = array(Image.Image.getdata(imghsv))
H = imgdata[:,0]
S = imgdata[:,1]
V = imgdata[:,2]
plt.clf()
plt.subplot(1,2,1)
plt.hist(V)
plt利用LeNet识别十种动物和水果