多媒体制作技术大作业Word格式文档下载.docx
《多媒体制作技术大作业Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《多媒体制作技术大作业Word格式文档下载.docx(18页珍藏版)》请在冰豆网上搜索。
#include"
cv.h"
highgui.h"
intmain(intargc,char**argv)
{
IplImage*src;
if(argc==2&
&
(src=cvLoadImage(argv[1],1))!
=0){
//计算HSV(hue色度saturation饱和度value亮度)并分解成为不同的平面
IplImage*hsv=cvCreateImage(cvGetSize(src),8,3);
cvCvtColor(src,hsv,CV_BGR2HSV);
//可以更改为CV_BGR2GRAY,可以自己尝试一下
cvNamedWindow("
src"
CV_WINDOW_AUTOSIZE);
cvShowImage("
src);
dst"
hsv);
cvWaitKey(0);
return0;
}
}
(ii)高斯滤波平滑处理函数CVSmooth()
在数字图像处理中,由于受到成像方法的限制,图像中的边缘、细节特征等重要信息常湮没于噪声信号中,给图像的后继处理带来很大的影响。
因此对含噪声图像进行适当的预处理是图像处理中的一个重要问题,对于改善图像质量具有重要的意义。
图像去噪是图像预处理中一项应用比较广泛的技术,其作用是为了提高图像的信噪比,突出图像的期望区域
各种方法的图像平滑
voidcvSmooth(constCvArr*src,CvArr*dst,intsmoothtype=CV_GAUS
SIAN,intparam1=3,intparam2=0,doubleparam3=0);
其中:
src输入图像.dst输出图像.smoothtype平滑方法:
.
(1)CV_BLUR_NO_SCALE(简单不带尺度变换的模糊)-对每个象素领域param1×
param2求和。
如果邻域大小是变化的,可以事先利用函数cvIntegral计算积分图像。
(2)CV_BLUR(simpleblur)-对每个象素邻域param1×
param2求和并做尺度变换1/(param1•param2).
(3)CV_GAUSSIAN(gaussianblur)-对图像进行核大小为param1×
param2的高斯卷积
(4)CV_MEDIAN(medianblur)-发现邻域param1×
param1的中值(i.e.邻域是方的).
(5)CV_BILATERAL(双滤波)-应用双向3x3滤波,彩色sigma=param1,空间sigma=param2.关于双向滤波,
param1:
平滑操作的第一个参数.
param2:
平滑操作的第二个参数param2为零对应简单的尺度变换和高斯模糊。
param3:
对应高斯参数的Gaussiansigma(标准差).如果为零,这由下面的核尺寸计算。
函数cvSmooth可使用上面任何一种方法平滑图像。
每一种方法都有自己的特点以及局限。
(iii)用于对图像的边缘检测(采用canny算法)。
1.Canny边缘检测基本原理
(1)图象边缘检测必须满足两个条件:
一能有效地抑制噪声;
二必须尽量精确确定边缘的位置。
(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。
这就是Canny边缘检测算子。
(3)类似与Marr(LoG)边缘检测方法,也属于先平滑后求导数的方法。
2.voidcvCanny(constCvArr*image,CvArr*edges,doublethreshold1,doublethreshold2,intaperture_size=3);
其中threshold1:
第一个阈,threshold2:
第二个阈值,aperture_sizeSobel:
算子内核大小.函数cvCanny采用Canny算法发现输入图像的边缘而且在输出图像中标识这些边缘。
threshold1和threshold2当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
3.在opencv中文论坛上我们可以找到关于Canny算法的详细过程
#include"
cxcore.h"
intmain(intargc,char**argv)
{
IplImage*pImg=NULL;
//声明IplImage指针
IplImage*pCannyImg=NULL;
char*filename;
filename="
F:
\\练习\\VC6.0\\opencv\\1.jpg"
;
pImg=cvLoadImage(filename,1);
//载入图像,强制转化为Gray
if((pImg=cvLoadImage(filename,0))!
=0){
pCannyImg=cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);
cvCanny(pImg,pCannyImg,50,150,3);
1);
//创建窗口
cvNamedWindow("
canny"
1);
cvShowImage("
pImg);
//显示图像
cvShowImage("
pCannyImg);
//等待按键
cvDestroyWindow("
);
//销毁窗口
//释放图像
cvReleaseImage(&
pImg);
cvReleaseImage(&
pCannyImg);
}
return-1;
图1Canny算法处理后
(iv)cvSetImageROI()函数
cvSetImageROI()函数基于给定的矩形设置感兴趣区域,也就是从图片中找到我们需要的部分。
voidcvSetImageROI(IplImage*image,CvRectrect);
函数cvSetImageROI基于给定的矩形设置图像的ROI(感兴趣区域).如果ROI是NULL并且参数RECT的值不等于整个图像,ROI被分配.不像COI,大多数的OpenCV函数支持ROI并且处理它就像它是一个分离的图像(例如,所有的像素坐标从ROI的左上角或左下角(基于图像的结构)计算。
下面用一段代码来说明cvSetImageROI函数:
stdio.h"
intmain()
{
IplImage*img=cvLoadImage("
F:
\\练习\\VC6.0\\opencv\\1.jpg"
);
IplImage*img1=cvLoadImage("
\\练习\\VC6.0\\opencv\\2.jpg"
cvSetImageROI(img1,cvRect(0,0,256,256));
//设置img1的ROI区域
cvResize(img,img1);
//缩放img图像,并将数据拷贝到img1
cvResetImageROI(img1);
//这句是必须的,在img1的ROI区域显示img
img1"
img1);
cvDestroyAllWindows();
}
图2处理前图3处理后
3、程序的运行与实现
本程序采用的是一种很简单的识别方法,即将分割出的字符与模板想比较,得到结果图像后检测图像中非零像素的个数,当个数最少时即判定为匹配图像。
因为模板的大小是22*14的,所以需要将所得分割字符统一大小,之后再相比较,检测最小值。
具体实现方面还是让我痛苦了一段时间,如何用循环实现字符自动匹配和字符的显示比较的困难。
后来我采用的方法是建立字符串数组存储模板图片的文件名,利用数组来自动匹配,显示方面我采用将汉字分成若干个SWITCH语句,利用数组中的数字表示汉字序数,不同的序数执行不同的分支程序。
图4原图像
图5分割结果
三、实验感想
我的这套车牌识别系统是基于opencv建立的,在网上虽然有很多matlab的识别程序,但真正用opencv而非直接使用VC识别的系统很少,所以我采用的方法是在借鉴matlab程序的思路的基础上,自己搭建一个VC平台,其中的模块很多是在网上找的,但他们之间的连接和搭配,以及一些方法的选择也加入了我自己的想法。
通过这次的大作业,我对于图像处理课上讲授的内容有了更深的理解,对一些算法的应用有了更深的感受,比如开闭操作、投影直方图和最佳全局阈值等,而且在这个过程中,也熟悉了opencv和VC的编程方法,真的是收益良多。
四、附录
源代码
#include<
cv.h>
cxcore.h>
highgui.h>
iostream>
usingnamespacestd;
#pragmacomment(lib,"
cv.lib"
)
cxcore.lib"
highgui.lib"
#defineT27
#defineT12
#defineS(image,x,y)((uchar*)(image->
imageData+image->
widthStep*(y)))[(x)]//S
voidmain()
IplImage*pImg8u=NULL;
//灰度图
IplImage*pImg8uSmooth=NULL;
//高斯滤波后的图
IplImage*pImgCanny=NULL;
//二值化的图
IplImage*pImgHist=NULL;
//直方图
inthist_size=155;
floatrange_0[]={0,256};
float*ranges[]={range_0};
inti,j,bin_w;
floatmax_value,min_value;
intmin_dx,max_dx;
introw_start,row_end;
//用来记录车牌开始,结束行
intcol_start,col_end;
//用来记录车牌开始,结束列
intcount=0;
//用来记录行或列的白点个数
src=cvLoadImage("
8.jpg"
-1);
pImg8uSmooth=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
pImg8u=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
pImgCanny=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,pImg8u,CV_RGB2GRAY);
//灰度化
cvSmooth(pImg8u,pImg8uSmooth,CV_GAUSSIAN,3,0,0);
//高斯滤波
cvCanny(pImg8uSmooth,pImgCanny,100,200,3);
//二值化
row_start=0;
row_end=0;
col_start=0;
col_end=0;
introw[120];
intcol[340];
intk;
k=0;
boolflag=false;
for(j=0;
j<
pImgCanny->
height;
j++)//找到上行开始
count=0;
for(i=0;
i<
width-1;
i++)
{
if(S(pImgCanny,i,j)!
=S(pImgCanny,i+1,j))//统计行跳数
count++;
if(count>
T)
{
row[k]=j;
k++;
break;
}
}
for(i=0;
k;
i++)//从上边开始,3行连续时认为是起始行
if((row[i]==row[i+1]-1)&
(row[i+1]==row[i+2]-1)){
row_start=row[i];
break;
cout<
<
"
thestartrow:
row_start<
endl;
cvLine(pImg8u,cvPoint(0,row_start),cvPoint(src->
width,row_start),cvScalar(255,0,0),1,8,0);
for(i=k-1;
i>
row_start;
i--)//从下边开始,3行连续时认为是起始行
if((row[i]==row[i-1]+1)&
(row[i-1]==row[i-2]+1)){
row_end=row[i];
theendrow:
row_end<
cvLine(pImg8u,cvPoint(0,row_end),cvPoint(src->
width,row_end),cvScalar(255,0,0),1,8,0);
flag=false;
for(i=10;
width;
i++)//找到左列开始
for(j=row_start;
row_end;
j++)
if(S(pImgCanny,i,j)==255)
T1)
col_start=i;
flag=true;
if(flag)break;
thestartcol:
col_start<
cvLine(pImg8u,cvPoint(col_start,row_start),cvPoint(col_start,row_end),cvScalar(255,0,0),1,8,0);
for(i=pImgCanny->
width-10;
col_start;
i--)//找到右列开始
col_end=i;
theendcol:
col_end<
cvLine(pImg8u,cvPoint(col_end,row_start),cvPoint(col_end,row_end),cvScalar(255,0,0),1,8,0);
CvRectROI_rect;
//获得图片感兴趣区域
ROI_rect.x=col_start;
ROI_rect.y=row_start;
ROI_rect.width=col_end-col_start;
ROI_rect.height=row_end-row_start;
IplImage*pImg8uROI=NULL;
//感兴趣的图片
cvSetImageROI(pImg8u,ROI_rect);
pImg8uROI=cvCreateImage(cvSize(ROI_rect.width,ROI_rect.height),IPL_DEPTH_8U,1);
cvCopy(pImg8u,pImg8uROI);
cvResetImageROI(pImg8u);
intnWidth=409;
//(409,90)分别为感兴趣图像的宽度与高度
intnHeight=90;
IplImage*pImgResize=NULL;
//归一化的灰度图
pImgResize=cvCreateImage(cvSize(nWidth,nHeight),IPL_DEPTH_8U,1);
cvResize(pImg8uROI,pImgResize,CV_INTER_LINEAR);
//线性插值
intnCharWidth=45;
intnSpace=12;
7;
i++)//得到每个字符的双边界
switch(i){
case0:
case1:
col[i*2]=i*nCharWidth+i*nSpace;
col[i*2+1]=(i+1)*nCharWidth+i*nSpace;
case2:
case3:
case4:
case5:
case6:
col[i*2]=i*nCharWidth+i*nSpace+22;
col[i*2+1]=(i+1)*nCharWidth+i*nSpace+22;
14;
i++)//画出每个字符的区域
cvLine(pImgResize,cvPoint(col[i],0),cvPoint(col[i],nHeight),cvScalar(255,0,0),1,8,0);
IplImage*pImgCharOne=NULL;
IplImage*pImgCharTwo=NULL;
IplImage*pImgCharThree=NULL;
IplImage*pImgCharFour=NULL;
IplImage*pImgCharFive=NULL;
IplImage*pImgCharSix=NULL;
IplImage*pImgCharSeven=NULL;
pImgCharOne=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharTwo=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharThree=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharFour=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharFive=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharSix=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
pImgCharSeven=cvCreateImage(cvSize(nCharWidth,nHeight),IPL_DEPTH_8U,1);
CvRectROI_rect1;
ROI_rect1.x=col[0];
ROI_rect1.y=0;
ROI_rect1.width=nCharWidth;
ROI_rect1.height=nHeight;
cvSetImageROI(pImgResize,ROI_rect1);
cvCopy(pImgResize,pImgCharOne,NULL);
//获取第1个字符
cvResetImageROI(pImgResize);
ROI_rect1.x=col[2];
ROI_r