详细设计说明书.docx
- 文档编号:28495810
- 上传时间:2023-07-15
- 格式:DOCX
- 页数:15
- 大小:76.34KB
详细设计说明书.docx
《详细设计说明书.docx》由会员分享,可在线阅读,更多相关《详细设计说明书.docx(15页珍藏版)》请在冰豆网上搜索。
详细设计说明书
疲劳驾驶检测系统
详细设计说明书
2015年3月13日
1.引言2
1.1编写目的2
1.2背景3
1.3定义3
1.4参考资料3
2.程序系统的结构4
3.详细设计6
3.1程序简单描述6
3.2整体结构7
3.3性能7
3.4输入输出项7
3.5算法7
3.5.1人脸检测算法7
3.5.2Otus最佳阈值图像分割法8
3.5.3RobertCross边缘检测9
3.6主要类的说明以及xml配置文件9
3.7存储分配16
3.8注释16
3.9测试计划16
3.10尚未解决的问题16
1.引言
1.1编写目的
此说明书在概要设计的基础上,对基于人眼的疲劳检测终端各个模块,程序分别进行了实现层面上的要求和说明。
在以下的详细设计报告中将对在本阶段中队系统所做的所有详细设计进行说明。
主要工作包括:
根据软件需求说明书所描述的数据,功能,运行,性能,需求,并依照概要设计说明书所确定的处理流程、总体设计、软件系统的结构设计,逐个模块的程序描述(包括各模块的功能、性能、输入、输出、算法、程序逻辑、接口等)。
软件开发小组的产品实现成员应该阅读和参考此说明书,从而进行代码的编写,测试。
1.2背景
说明:
A、待开发系统的名称:
不规范驾驶检测系统
B、开发者:
孙艳强陈浩倪四飞
用户:
驾驶员或者是汽车厂商以及交通管理部门
C、项目开发背景:
学生工程实践选题
1.3定义
1、android-opencv:
这是一个在android操作系统上的Opencv开源库,本系统的开发中用到了该库,加快了开发的效率,降低了开发成本。
2、系统:
待开发的不规范驾驶检测系统
1.4参考资料
《软件工程概论》
《软件文档编写》
《android应用程序设计》
《java基础》
《opencv教程》
《andorid-opencv手册—网页版》
2.程序系统的结构
本待开发的系统采用的软件层次框图如下图所示:
在前期的方案确定的时候,采用的是基于android操作系统的OpencV开源库,因此只需要将编译好的OpenCV库导入到开发环境中即可进行开发,因此本系统的主要开发工作集中在应用程序的设计部分。
有
获取一帧图像
图像预处理
人脸定位
人眼和嘴巴定位
给予警示
结束
计数
开始
有摄像头
打开摄像头
在项目的概要设计中,确定的具体的软件的主流程方案如下图所示。
没达到
在人眼状态的判断过程中具体的步骤如下图所示。
3.详细设计
为了完成系统所需要的功能,我们设计了一个类来实现:
FdActivity
说明如下:
FdActivity:
该类是作为程序的主界面类,在该类中,将surfaceview占据了整个界面,在该类中主要重写了onCreate()、onPause()、onDestroy()、onCameraViewStarted()、onCameraViewStopped()、onCameraFrame()、onCreateOptionsMenu()、onOptionsItemSelected()、
函数具体的分析参见程序的具体描述部分;
onCameraFrame()函数:
在系统实时监测驾驶员的头像数据的时候,需要显示当前的帧率,该类就是负责帧率的显示的类,该类中,主要是实现了以下的几个功能:
从一帧图片中计算人眼的区域
绘制人眼的区域
3.1程序简单描述
打开摄像头,实时采集脸部的帧数据,图像进行灰度变化,首先进行预处理,将背景噪声以及图像中的突刺变化去除,防止影响后面的图形计算精度;利用Opencv中的已有函数接口进行人脸和人眼的定位,在将人眼的轮廓提取出来,这里面的用的方法:
Otus和RobertCross边缘检测。
利用最大垂直距离进行是否闭合的判定,组后再利用PERCLOS原理进行疲劳状态的判断。
3.2整体结构
见概要设计说明书
3.3性能
实时性:
能基本实现实时性的要求
对人脸的判断准确度:
95%以上
眼睛的判断准确度:
90%以上
疲劳识别:
80%以上
3.4输入输出项
输入的数据是:
摄像头采集的实时数据
输出是:
预警声音
3.5算法
3.5.1人脸检测算法
传统的检测人脸分方法有很多种:
基于肤色的分离、基于统计模型、或者是PCA方法,但是这些方法识别的时间较长,并且准确率不高,在本文中,采用的是OpenCV中非常成功的基于Haar-Like特征的Adaboost算法。
人脸检测分成两步:
首先是训练过程产生分类器文件,再是利用分类器进行人脸检测过程[4]。
训练过程:
(1)准备正负样本,正样本是需要检测的目标(正脸),负样本是不含正样本特征的任何目标;
(2)利用CreatSample程序准备正样本集;(3)利用Haar-Training程序训练得到分类器特征xml文件。
检测过程:
利用android-OpenCV中的分类器构建函数去加载该特征xml文件,利用分类器本身的成员函数[4,5]:
detectMultiScale(Matimage,List
其函数各参数的意义:
Image:
需要进行目标检测的区域.
Object:
将检测到的目标标记在矩形框中.
scaleFactor:
代表图像的缩放因子.
Minneighbors:
指定每个候选矩阵至少包含的邻近元素个数.
Flag:
标志位,默认为0.
Minsize:
最小的检测窗口,如果该值设置过小,将会导致图像的计算量较大。
3.5.2Otus最佳阈值图像分割法
当系统成功标记处人眼部的区域后,需要进行二值化处理,从而实现眼部提取。
但是由于图像的灰度值对光线很敏感,固定的阈值势必无法满足要求,本文采用的是基于Otsu算法的二值化处理。
Otsu算法,又被称为最大类间法,是一种自适应的图像分割技术,它是根据最小二乘原理推导出来的,根据光线强度的不同,阈值会随之变化,能得到最优的阈值[7],其基本原理如下:
将直方图在某一阈值进行分割成两组,称为“前景”和“背景”,当被分成的两组的方差最大时候,该阈值就是最佳分割阈值。
方差是灰度均匀分布的一种度量,值越大,说明构成图像两部分的差别越大,当部分“前景”错分为“背景”或者“背景”错分为“前景”的时候,都会导致方差变小,因此最大类间法意味着错分的概率最小。
对于图像直方图,不妨假设其灰度级为0~m,像素点个数为N,针对某一个分割阈值t,那么整个图像被分割成两部分,0~t称为“前景”,而t+1~m称为“背景”。
“前景”的权重为Wf,均值设为Mf,方差为Df,“背景”的权重为Wb,均值设为Mb,方差为Db。
图像的整体的方差公式如式3所式。
(3)
Otsu的最终目的就是要求出D的最大值来,从而得到最优的分割阈值。
3.5.3RobertCross边缘检测
边缘是图像灰度值变化剧烈的位置,因此包含了大量的有用信息,常用的边缘检测包含很多,比如:
RobertCross边缘检测,Canny边缘检测,Prewitt边缘检测,Sobel检测。
但是这些方法中唯有RobertCross计算方便简单、快速,容易在实时系统中实现,本系统中采用的就是该检测方法,根据任意一对互相垂直方向上像素点的差分来计算梯度的原理[8,9],采用对角线方向相邻像素灰度差。
如式4所示:
(4)
G代表的是计算之后的灰度值,而f代表的是原始图像的灰度值。
虽然Robert检测速度很快,但是其缺点也是很明显的,对噪声敏感,并且边缘不是很光滑。
3.6主要类的说明以及xml配置文件
在上面的概述中,我们初步说明了在该系统的实现过程中需要实现的几个类。
在这里我们详细的说明。
//思路:
详细写出每个类的每个函数接口的作用以及用法
FdActivity:
继承Activity,实现了整个应用程序的界面,在该类中主要是定义了两个菜单选项,分别是mItemFace50,mItemFace40,这是选择图像的范围的两个选项,分别对应着50%和40%。
重写onCreate函数,将fdview作为界面加载的部分。
重写onCreateOptionsMenu()函数,将两个菜单选项加入到菜单中;
重写onOptionsItemSelected函数,当在屏幕上点击对应的item时,将会自动进行item的选择;
Init函数接口是用来进行帧率计算的初始化函数,在该函数中主要实现获取当前的时间--getTickFrequency,以及初始化绘制的文字的颜色信息(blue)以及大小(50)
Measure()函数是计算帧率的主要函数,获得当前的时间,减去在init函数中的初始时间,获得这段图像处理的时间,帧率的计算如下:
doublefps=step*freq/(time-prevFrameTime)
再将其按照固定的格式进行输出:
DecimalFormat("0.00");
Draw函数:
就是指在画布上进行绘制的函数:
canvas.drawText(strfps,20+offsetx,10+50+offsety,paint)
抽象基类MyCvViewBase的设计:
这个类主要是为了下面的的具体的fdview类服务的,在该类中,我们是实现了surfaceholder.callback的接口以及runable接口,这样该类就可以作为一个单独的线程去运行了,从而实现了多线程的功能。
在该类的构造函数MyCvViewBase中,我们需要获得holder,添加callback接口,进行FpsMeter的构建。
因为是实现了surfaceholder.callback的接口,因此需要重写三个函数,分别是surfacecreated,surfacechanged,surfacedestroyed。
三个函数中分别要实现的功能:
Surfacecreated()这个是在surface刚建立的时候就调用回调函数,在这个函数中,我们需要打开摄像头,在Android-OpenCV中,打开摄像头的接口的函数为mCamera=VideoCapture(ighgui.CV_CAP_ANDROID),检查是否打开,如果已经打开了,那么如下安排:
(newThread(this)).start();
否则的话直接release掉camara。
Surfacechaged()函数,是在surfacecreated回调之后进行第一次调用,在这里我们主要是获得摄像头支持的size,然后我们不断选择最优的预览size,(这部分代码是在网上参考的)。
将camara的设置成为:
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH,mFrameWidth);
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT,mFrameHeight);
surfaceDestroyed()回调函数,就是当surface消失的时候进行回调的,因此,这里面我们需要做一些资源的释放的操作,比如说camera释放。
作为抽象的基类,我们为子类提供的接口是:
protectedabstractBitmapprocessFrame(intflag,VideoCapturecapture);
该接口在子类中进行图像处理时详细的设计。
(参见Fdview设计)
我们在该抽象基类中实现了runnable接口,因此还需要实现run函数;
首先需要完成对计量帧率的对象的初始化工作。
下面的就是不断的while循环,进行图像的处理工作:
首先从摄像头中回去实时的数据帧,该部分的接口是:
mCamera.grab(),[mCameras是上面打开的摄像头]然后进行图像的处理processFrame,返回bmp对象,进行帧率的计量,锁住画布--mHolder.lockCanvas(),进行绘画,解锁画布。
Bmp图像的回收。
Fdview类的设计:
该类主要是继承了抽象基类MyCvViewBase,因此主要在这一部分中,需要实现的接口函数,
protectedBitmapprocessFrame(intflag,VideoCapturecapture)
构造函数中需要实现的是:
获取xml文件资源context.getResources().openRawResource(R.raw.haarcascade_frontalface_alt);进行xml文件的读写,利用该xml文件进行分类器对象的初始化,分类器对象在OpenCV中是实现目标检测的对象,是由特征文件xml进行构造的。
在该软件中需要定位人脸,人嘴和人眼,因此需要以下几个xml文件,分别是:
haarcascade_frontalface_alt.xml以及haarcascade_mcs_mouth.xml,haarcascade_righteye_2splits.xml,haarcascade_lefteye_2splits.xml文件,识别率高达95%以上,是OpenCV中自带的已经训练好的分类器特征文件。
重写surfacechanged()函数,主要是初始化了mat数据,mat可以看成是二维的保存图像的矩阵,是OpenCV中自带的数据格式。
实现processFrame接口函数,在该部分主要是关于图像处理的接口函数,是整个软件的核心函数:
首先是解析出摄像头的RGB以及灰度图像格式:
capture.retrieve(mRgba,Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
capture.retrieve(mGray,Highgui.CV_CAP_ANDROID_GREY_FRAME);
进行预处理过程:
主要是进行直方图的均衡化过程,OpenCV自带接口:
Imgproc.equalizeHist();
利用OpenCV中自带的目标识别的函数mCascade.detectMultiScale[说明:
mCascade是人脸的分类器对象]进行图像中目标的检测,我们首先需要定位到人脸部,并且将人脸在图像中标记出来。
(绿色的标记)
如果人脸不是空的,那么开始将人脸设置成为感兴趣区域,在该区域中进行人眼的检测,,同样的还是有eyedectcade.detectMultiScale()[说明:
eyedetectcade是人眼的分类器对象],如果眼睛找到了,我们将其中一只眼睛标记出来,用来进行图像处理,因为基本而言,人眼都是堆对称的,一只眼睛的状态可以代表人眼目前的状态,将该区域进行Otsu二值化处理,以及RobertCross或者是canny边缘检测来提取人眼的轮廓,canny在OpenCV中已经有固定的接口,而Otsu和RobertCross检测需要自己去实现。
子啊利用最大的垂直距离进行扫描,当最大的垂直距离小于40%的标记高度的时候判断是闭合状态。
附上关于Otsu以及RobertCross边缘检测的代码:
publicMatRobert(Matmat){//robertcross边缘检测代码
introbbertNum=0;
introw=mat.rows();
intcol=mat.cols();
for(inti=1;i for(intj=1;j robbertNum=(int)Math.abs(mat.get(i,j)[0] -mat.get(i+1,j+1)[0]) +(int)Math.abs(mat.get(i+1,j)[0] -mat.get(i,j+1)[0]); if(robbertNum>50){ mat.put(i,j,255); }else{ mat.put(i,j,0); } } } returnmat; } publicintOtsu(Matmat){//Otsu算法实现: int[]histData=newint[256]; for(inti=0;i<256;i++){ histData[i]=0;//初始化为0值 } inttotal=mat.cols()*mat.rows(); for(inti=0;i for(intj=0;j inttemp=(int)mat.get(i,j)[0]; histData[temp]++; } } doublesum=0; for(intt=0;t<256;t++){ sum+=t*histData[t]; } doublesumF=0; intWB=0; intWF=0; doublevarMax=0; intthresh=0; /* *for(inti=0;i<256;i++){System.out.print(i); *System.out.println(": "+histData[i]);} */ for(intt=0;t<256;t++){ WF+=histData[t]; if(WF==0) continue; WB=total-WF; if(WB==0) break; sumF+=(double)(t*histData[t]); doublemF=sumF/WF; doublemB=(sum-sumF)/WB; doublevarBetween=WB*WF*(mB-mF)*(mB-mF); if(varBetween>varMax){ varMax=varBetween; thresh=t; } } returnthresh; } Xml文件的配置如下: 需要加入下面的权限: name="android.permission.CAMERA"/> name="android.permission.DISABLE_KEYGUARD"/> name="android.hardware.camera"/> name="android.hardware.camera.autofocus"/> 3.7存储分配 本程序在高级语言JAVA进行编码,直接的内存分配由JAVA运行时分配。 3.8注释 在代码的适当出有中文代码注释。 3.9测试计划 测试日期、测试人员安排请参考测试计划,测试用例的具体内容,请参考测试说明。 3.10尚未解决的问题 1、目前实现的帧率较低,仅能达到6-7帧/s的水平,还远远达不到“实 时”的要求,需要对算法进行优化。 2、在对人眼进行定位的时候,精度不够高,带着眼镜的时候会将眼镜的 边框带入,影响最大的垂直距离的计算,从而影响到PERCLOS的计算精 度。 3、没能实现“自动跟踪”人眼,需要保持固定的距离才能进行人眼的定位。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详细 设计 说明书