引言
二十一世纪刚刚开始,就进入了光电产业飞速发展的时代,传统的成像技术渐渐的被数字传感器取代,像素这个词慢慢的被更多的人熟悉,像素代表着一部数字照相机在单位面积上能表示的点数,像素越高,表明相机拍摄下来的照片越清晰。现在的集成电路技术已经可以将镜头和光线传感器集成到一个小的芯片上,镜头的生产技术一直是国外领先,国内滞后,现在国内的光电产业处于发展初期,在未来几年中将快速发展起来,尤其是在苏州这个外资众多的地方,技术先进的企业正在这里茁壮成长。
在镜头的生产过程中,除了在生产环境重要防尘、防静电之外,测试环节非常重要,依靠人的肉眼去观察一个镜头上有没有脏点,或者CMOS传感器上有没有坏点,是不现实的,必须依靠计算机来完成测试任务。本课题就是针对手机摄像头的质量检测而设计的,收集摄像头一般是针孔式摄像机,具有体积小,成本低,携带方便的特点。软件中实现的三个图像算法,可以基本上解决质量检测的难题。
对于国内来说,目前尚没有成熟的镜头质量检测软件,在检测的时候需要解决实时传输,速度等重要问题,而且衡量镜头质量的参数非常多,所以对于开发人员来说,不仅需要知道计算机方面的知识,而且在电子和光学方面都要非常的熟悉。在这样的环境下,我决定写一个类似功能的软件,来填补这个空白区域。
在本系统中,可以实现视频的实时显示,随机抓取一帧数据,用3个非常重要的测试算法:MTF,SHADING , PARTICLE, 可以对镜头的质量做出准确,客观的评价。对于进行手机摄像头量产的公司来说,是一个非常有用的工具。
图 1系统框图 图 2模块流程图
1.系统构成及硬件介绍
如图1所示,系统选用的硬件电路上有两个主要芯片,光线传感器(CMOS sensor)和Cypress 公司的EZ-USB FX2芯片。
CMOS sensor的主要作用是将光信号转化为电信号,并量化为二进制数据传输给EZ-USB FX2芯片进行打包,是测试系统的目标。
软件系统使用了可视化的开发环境:Visual Studio 6 结合 Microsoft发布的开发包DirectShow,DirectShow软件系统的结构上按照软件工程的思想进行设计。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。运用DirectShow,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等等,使得多媒体数据的回放变得轻而易举。更值得一提的是,DirectShow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。
2.软件系统的设计
2.1 需求分析
本系统的主要模块如下所示(如图 2):
在线下载(烧入)模块:完成传感器的配置。
动态检测设备模块:根据系统中的视频设备的数量,动态调整视频设备列表。
视频捕捉模块:将视频从传感器捕捉到内存中并显示。
动态抓取模块:在视频的显示过程中,可以抓取其中的一帧图像并存储。
图像分析模块:实现测试的MTF,SHADING,PARTICLE三个算法。
界面控制模块:根据摄像头的像素,自动调整显示窗口的大小,自适应显示分辨率。
2.2 模块实现
主要模块类及其说明
CcaptureVideo:视频显示和控制类,完成与Windows驱动程序的交互,并将视频数据保存到内存中。CsampleGrabberCB:视频捕捉类,可以将视频流中的一帧数据抓取到指定的内存区域,供分析算法使用。CdialogAnalyse:图像分析窗口类,实现分析图像的三个算法,并将分析结果显示在本窗口中。CcameraShowAndTestDlg:程序主窗口,显示视频流,控制整个程序的运行。
2.2.1 视频的实时显示功能的实现:
视频流的控制操作在CcaptureVideo类中完成,在该类中,使用了DirectShow组件中的ICaptureGraphBuilder2、IbaseFilter、IgraphBuilder、IvideoWindow等类来建立显示链路。
视频流从摄像头到显示过程的部分程序实现如下:
HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
m_bIsActived = true; //是否已创建CCaptureVideo对象标志
HRESULT hr;
//初始化过滤器管理器
hr = InitCaptureGraphBuilder();
if(FAILED(hr))
{
AfxMessageBox("Failed to get video interfaces!");
return hr;
}。。。。。。。
BindFilter(iDeviceID, &m_pBF); // 绑定设备到过滤器
teInstance( CLSID_SampleGrabber ); //创建抓取过滤器
。。。。。。
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
//设置视频格式
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
ype = MEDIATYPE_Video;
e = MEDIASUBTYPE_RGB24; //OR RGB32
hr = m_pGrabber->SetMediaType(&mt);
m_pGB->AddFilter( pGrabBase, L"Grabber" ); 添加抓取过滤器
m_pGrabber->GetConnectedMediaType( &mt ); //设置所连接设备的媒体类型
。。。。。。
hr = m_pMC->Run();//显示视频
。。。。。。
}
2.2.2 消息传递传送图像数据
视频的显示和抓取均是在主窗口中完成的,而算法的分析是在一个叫“算法分析”的字窗体中完成,因此必须将主窗口中捕捉到的一帧数据,传送到子窗体中进行处理,分析算法
运行完毕后还需要反馈到主窗体中,在Windows环境中,需要用消息实现。
在CdialogAnalyse的头文件中加入消息声明[3]:(程序略)
3.核心算法
MTF 表现了一个镜头对所摄物体对比度(contrast)的再现能力。光学中对于正弦条纹对比度的定义是V = (Imax - Imin) / (Imax + Imin),Imax和Imin是指亮度,(这儿人们用矩
形条纹,也一样)。那么MTF就是成像前后此对比度的比:
MTF = Vo / Vi
MTF值和条纹密度(空间频率,lp/mm)的关系是:条纹越密,MTF 越低。条纹密到一定程度时,镜头的分辨能力达到极限,MTF值趋近于零。这一极限情况到达得越晚,表明镜头的分辨力越高。
MTF测试的要求
MTF测试须满足如下要求:
图象数据中取5块测试区域(四角区域和中心区域)将每个区域中的Y (亮度信号)与一个标准亮度值进行比较,大于标准值的Y定为Ymax,同样小的就定为Ymin
计算每块区域的平均Ymax 和 Ymin
MTF值 = (平均Ymax – 平均Ymin)/(平均Ymax + 平均Ymin)
把算得的MTF值 和 标准MTF值进行比较,并将比较结果在应用软件中得到反映
MTF测试源程序
void getMTF(float * ShadingMtf,int pixbyte, int pixrow, int pixwidth, BYTE **nimage, float lightref, int nlightwidth, int nlightrow)
{
//获得5个区域的MTF值
ShadingMtf[0]=getoneMTF(pixbyte,pixrow,pixwidth,nimage,lightref,1,nlightwidth,nlightrow);
ShadingMtf[1]=getoneMTF(pixbyte,pixrow,pixwidth,nimage,lightref,2,nlightwidth,nlightrow);
ShadingMtf[2]=getoneMTF(pixbyte,pixrow,pixwidth,nimage,lightref,3,nlightwidth,nlightrow);
ShadingMtf[3]=getoneMTF(pixbyte,pixrow,pixwidth,nimage,lightref,4,nlightwidth,nlightrow);
ShadingMtf[4]=getoneMTF(pixbyte,pixrow,pixwidth,nimage,lightref,5,nlightwidth,nlightrow);
}
3.1 SHADING(亮度分析)
Shading测试的要求
Shading测试须满足如下要求:
一帧图象取5块区域(四角区域和中心区域)
分别计算每块区域的Y(亮度信号)的平均值,
将四角区域的计算结果分别和中心进行比较:Y角 / Y中心
将计算得到的数值与用户自定义的标准值进行比较
把比较结果在应用软件端得到反映
Shading测试源程序略
3.2 PARTICLE(脏点检测)
Particle测试的要求
Particle测试须满足如下要求
根据用户需求,从视频流中截取一帧图象数据,单独对该数据进行脏点及油点的分析
将抓获的数据中的Y值和用户设定的脏点标准值进行比较,小于标准值的设为一不良点,当连续的不良点达到规定的数目,即定为脏点。如果Y值大于脏点标准值,小于油点标准值,应将该点也设为一不良点,当连续的不良点达到油点规定的数目,即定为油点将脏点或油点出现的地点,在应用软件中圈出来,并且指出相应脏点或油点的数目
Particle部分测试源程序
bool getParticle(int noil,int ndirty,int pixbyte,float frefPDirty,float frefPOil,BYTE **nimage,int nlightwidth, int nlightrow)
{
int i=0;
int j=0;
int blockpix=100;//此值分块
int checkfield=1;//检测污点的时候,规定连续点的间隔数。(一般为1,则为8领域检测)
int intervalpix=0;////如果脏点或油点的连续个数是一个的,就用此值分块
bool intervalref=true;
int *getparameter0;
int m=0;
int oilm=0;///油块的个数
int dirtym=0;//脏块的个数
checkplace dirtyclust[100],oilclust[100];
/* struct pixplace
{
int npix;
int pixlifthighx;
int pixlifthighy;
int pixrightlowx;
int pixrightlowy;
} m_nDirtyPlace[10] ,m_nOilPlace[10];
int m_nDirtyCount;
int m_nOilCount;
/*//////去除有污点的区域,不需要再检测
for (m=0;m
{
if((i>=dirtyclust[m].pixleftx)&&
(i<=dirtyclust[m].pixrightx))
////进入了有污点的区域
{
if (j==dirtyclust[m].pixlefty)
{
j=j+dirtyclust[m].pixrighty;
}
}
}
*//////////////////////////去除有污点的区域,有待测试时候再考虑。
}//////j循环
if (intervalref)
intervalref=false;
else
intervalref=true;
}///////i循环
/////赋值
m_nDirtyCount=dirtym;
m_nOilCount=oilm;
for(i=0;i
{
m_nDirtyPlace[i].pixn=dirtyclust[i].pixn;
m_nDirtyPlace[i].pixleftx=dirtyclust[i].pixleftx;
m_nDirtyPlace[i].pixlefty=dirtyclust[i].pixlefty;
m_nDirtyPlace[i].pixrightx=dirtyclust[i].pixrightx;
m_nDirtyPlace[i].pixrighty=dirtyclust[i].pixrighty;
}
for(i=0;i
{
m_nOilPlace[i].pixn=oilclust[i].pixn;
m_nOilPlace[i].pixleftx=oilclust[i].pixleftx;
m_nOilPlace[i].pixlefty=oilclust[i].pixlefty;
m_nOilPlace[i].pixrightx=oilclust[i].pixrightx;
m_nOilPlace[i].pixrighty=oilclust[i].pixrighty;
}
return 1;
}
4.结果与分析
4.1 测试界面
SHADING和PARTICLE算法的测试界面和结果如图 3、图 4和图 5所示
4.2 测试结果
经测试,MTF和SHADING算法可以准确地分析出不同颜色区域的MTF值和亮度值,PARTICLE可以准确地找到图像中的脏点,并将之改成肉眼容易识别的绿色,使测试人员可以快速的发现。
图 3 SHADING分析界面
图 4 脏点检测之前
图 5 脏点检测之后
参考文献:
[1]陆其明,《DirectShow开发指南》[M],北京:清华大学出版社,2003年12月
[2](美)Kate GreGory,《Visual C++6开发使用手册》[M],北京:机械工业出版社,1999年2月
[3]张志强,《Windows编程技术》[M],北京:机械工业出版社,2003年7月
中国论文网(www.lunwen.net.cn)免费学术期刊论文发表,目录,论文查重入口,本科毕业论文怎么写,职称论文范文,论文摘要,论文文献资料,毕业论文格式,论文检测降重服务。