DSP

基于Haar小波变换和KNN算法的DSP人脸识别

2019-07-13 11:39发布

这学期上了一门课叫DSP实验,学会了使用C5509A芯片,并且做了一系列实验,最后一个大PJ是使用DSP进行人脸识别。 基本思想是首先对人脸照片进行变换提取特征,最后在利用某种分类器对特征分类,用以决定属于哪一个人,最后再进行识别,计算准确度,这个项目主要是为了训练我们对于DSP的熟练情况和使用情况,同时了解一些小波变换和分类方法,仅用来学习,对于正确率没有要求,所以最后做好后准确率大概70%左右,也不算高。 首先我们小组利用的是harr小波变换进行特征提取 先简单说一下harr小波变换的原理: 小波变换(wavelettransform,WT)是一种新的变换分析方法,它继承和发展了短时傅立叶变换局部化的思想,同时又克服了窗口大小不随频率变化等缺点,能够提供一个随频率改变的“时间-频率”窗口,是进行信号时频分析和处理的理想工具。它的主要特点是通过变换能够充分突出问题某些方面的特征,能对时间(空间)频率的局部化分析,通过伸缩平移运算对信号(函数)逐步进行多尺度细化,最终达到高频处时间细分,低频处频率细分,能自动适应时频信号分析的要求,从而可聚焦到信号的任意细节,解决了Fourier变换的困难问题 哈尔函数是由Haar提出的一种正交完备函数系;是一种既反映整体又反映局部的函数;它是小波变换中的典型小波,; 哈尔变换和小波变换适用非平稳信号的分析与处理。 哈尔变换的特点: (1) 具有尺度和位移两个特性; (2) 变换范围窄; (3) 其变换特性与图像中的边界或线条的特性十分接近,因此图像中的边缘和线条经哈尔变换后,会产生较大的变换系数,而其它区划的变换系数小。 因为DSP上直接进行小波变换的源码比较少,因此我们先从matlab入手,找到了部分matlab的harr变换源码 先了解harr变换的一维代码: function out=selfdwt(in,J) % 完成J尺度Haar小波变换 % in 是输入信号 % out 是输出的小波系数 %h0,h1是相应的小波和尺度向量 h0=[1/sqrt(2),1/sqrt(2)]; h1=[-1/sqrt(2),1/sqrt(2)]; out=zeros(size(in)); m=size(in);%此处的m为一向量 x=length(in); k=0; l=0; Wl=in; for i=1:J %=================此处对应于高频部分,结果中抽取偶数的点===================== Wh=conv(h1,Wl);%卷积函数 for j=1:(length(h1)+length(Wl)-1) if mod(j,2)==0%mod函数求j/2的模,相当于求余数,且余数一定是整数 k=k+1; out(round(x/2)+k)=Wh(j);%round是四舍五入函数,因为这里x一定是整数,所以roundx/2相当于如果x为偶数则为x/2,奇数则为x/2+1 end end %============================================================================ %===============下面对应于低频部分,结果中抽取偶数点========================= Wl1=conv(h0,Wl); for j=1:(length(h0)+length(Wl)-1) if mod(j,2)==0 l=l+1; out(l)=Wl1(j); end end %=========================================================================== x=round(x/2); m=round(m/2); Wl=zeros(m); for j=1:x Wl(j)=out(j); end k=0; l=0; end 利用这个函数可以得到对二维图像进行harr变换的代码: %对一幅图像I进行M尺度的小波变换 I=imread('s1.bmp'); M=1;% M----小波变换的尺度 I1=double(I);%强制转换类型为double型,I为512*512*3的像素数组 [m,n]=size(I);%m=128,n=128 Iout=zeros(size(I));%生成512*512*3的全零矩阵 W1=zeros(size(I));%生成512*512*3的全零矩阵 %=============Haar wavelete transform================== W1=I1;%W1=像素数组 for k=1:M%进行两次迭代 for i=1:n%对所有列进行变换 W1(:,i)=selfdwt(W1(:,i),1);%对列进行变换 end for i=1:m%对所有行进行变换 W1(i,:)=selfdwt(W1(i,:),1);%对行进行变换 end for i=1:m%输出值 for j=1:n Iout(i,j)=W1(i,j); end end m=m/2;%m=256 n=n/2;%m=256*3 W1=zeros(m,n);%生成第一次得出的结果 for i=1:m for j=1:m W1(i,j)=Iout(i,j); end end end %====================================================== %========================scaling归一化======================= [m,n]=size(I);%m=512,n=1536 min=0; for i=1:m for j=1:n if(Iout(i,j)max) max=Iout1(i,j); end end end%找出Iout1中的最大值 if(max>255) Iout1=(Iout1*(255/max)).*2; end%保证每个值的大小在0-255之间 %====================================================== Iout1(:,256)=255; Iout1(256,:)=255; Iout1(1:256,128)=255; Iout1(128,1:256)=255; Iout1(1:128,64)=255; Iout1(64,1:128)=255;%画分割线 figure imshow(uint8(Iout.*28)) title('uncaling') figure imshow(uint8(Iout1)) title('after scaling') %Iout2=imidwt2(Iout,M);
调试的过程中要修改imdwt1.m文件中的第二行的图像名,图像放在与源码相同的目录下。 而分类器我们想要用的是KNN分类器,KNN分类器的原理和实现都非常简单,原理如下: 邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。 kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 下图中,绿 {MOD}圆要被决定赋予哪个类,是红 {MOD}三角形还是蓝 {MOD}四方形?如果K=3,由于红 {MOD}三角形所占比例为2/3,绿 {MOD}圆将被赋予红 {MOD}三角形那个类,如果K=5,由于蓝 {MOD}四方形比例为3/5,因此绿 {MOD}圆被赋予蓝 {MOD}四方形类。 K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。 KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。 确定了算法之后,主要由三个工作,第一是把matlab的harr变换代码改成C语言代码,第二是写出KNN分类器,第三是把这两个结合起来。中间过程不说了,代码贴出来供大家学习。 /******************************************宏定义begin************************************************/ #define IMAGEWIDTH 32//图像宽度 #define IMAGEHEIGHT 32//图像高度 #define LENGTH 32//图像进行一维harr变换时的长度,相当于图像宽度和高度 //来自例程文件,说明哪些图片 #define MODEPHOTO00 1 #define MODEPHOTO01 2 #define MODEPHOTO02 3 #define MODEPHOTO03 4 #define MODEPHOTO04 5 #define MODEPHOTO05 6 #define MODEPHOTO06 7 #define MODEPHOTO07 8 #define MODEPHOTO10 9 #define MODEPHOTO11 10 #define MODEPHOTO12 11 #define MODEPHOTO13 12 #define MODEPHOTO14 13 #define MODEPHOTO15 14 #define MODEPHOTO16 15 #define MODEPHOTO17 16 #define MODEPHOTO20 17 #define MODEPHOTO21 18 #define MODEPHOTO22 19 #define MODEPHOTO23 20 #define MODEPHOTO24 21 #define MODEPHOTO25 22 #define MODEPHOTO26 23 #define MODEPHOTO27 24 #define MODEPHOTO30 25 #define MODEPHOTO31 26 #define MODEPHOTO32 27 #define MODEPHOTO33 28 #define MODEPHOTO34 29 #define MODEPHOTO35 30 #define MODEPHOTO36 31 #define MODEPHOTO37 32 #define MODEPHOTO40 33 #define MODEPHOTO41 34 #define MODEPHOTO42 35 #define MODEPHOTO43 36 #define MODEPHOTO44 37 #define MODEPHOTO45 38 #define MODEPHOTO46 39 #define MODEPHOTO47 40 //#define TESTMATRIX 101 #define TRAINPHOTO00 101 #define TRAINPHOTO01 102 #define TRAINPHOTO02 103 #define TRAINPHOTO10 104 #define TRAINPHOTO11 105 #define TRAINPHOTO12 106 #define TRAINPHOTO20 107 #define TRAINPHOTO21 108 #define TRAINPHOTO22 109 #define TRAINPHOTO30 110 #define TRAINPHOTO31 111 #define TRAINPHOTO32 112 #define TRAINPHOTO40 113 #define TRAINPHOTO41 114 #define TRAINPHOTO42 115 #define GRAYBARLEVEL 16 /******************************************宏定义end************************************************/ void InitImage(unsigned int nMode,unsigned char *pImage,int nWidth,int nHeight); void conv(float* f,float* g,float* y,int length); void haarone(float *input,float *output,int length); void FloatImage(unsigned char *pImage,float *qImage,int nWidth,int nHeight); void UcharImage(float *pImage,unsigned char *qImage,int nWidth,int nHeight); void AddImage(float *pImage,int nWidth,int nHeight); void CopyImage(float *pImage,float *qImage,int nWidth,int nHeight); void MinImage(float *pImage,float *qImage,int nWidth,int nHeight); void MaxImage(float *pImage,float *qImage,int nWidth,int nHeight); unsigned int imageIndex[5][8]; unsigned int trainIndex[5][3]; unsigned char dbImage[IMAGEWIDTH*IMAGEHEIGHT];//输入图像 float outImage[IMAGEWIDTH][IMAGEHEIGHT];//输出图像 float changeImage[IMAGEWIDTH][IMAGEHEIGHT];//中间变量1 float nextImage[IMAGEWIDTH][IMAGEHEIGHT];//中间变量2 float endImage[IMAGEWIDTH/2][IMAGEHEIGHT/2]; int label[40]={1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5}; //unsigned char outcharImage[IMAGEWIDTH][IMAGEHEIGHT];//输出图像 //unsigned char changecharImage[IMAGEWIDTH][IMAGEHEIGHT];//中间变量1 //unsigned char nextcharImage[IMAGEWIDTH][IMAGEHEIGHT];//中间变量2 //定义所有图像的Harr特征数组 unsigned char endcharImage[40][IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char trainImage[15][IMAGEWIDTH/2][IMAGEHEIGHT/2]; /* unsigned char endcharImage00[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage01[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage02[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage03[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage04[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage05[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage06[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage07[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage10[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage11[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage12[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage13[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage14[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage15[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage16[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage17[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage20[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage21[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage22[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage23[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage24[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage25[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage26[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage27[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage30[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage31[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage32[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage33[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage34[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage35[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage36[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage37[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage40[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage41[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage42[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage43[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage44[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage45[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage46[IMAGEWIDTH/2][IMAGEHEIGHT/2]; unsigned char endcharImage47[IMAGEWIDTH/2][IMAGEHEIGHT/2]; */ float index[LENGTH]; float outdex[LENGTH]; int result[5][3]; int main() { int i,j,m,n; int a,b; int raw,col;//定义行和列变量 m=1; n=101; raw=IMAGEWIDTH; col=IMAGEHEIGHT; for(i=0;i<5;i++) for(j=0;j<8;j++) { imageIndex[i][j]= m; m++; }//设置图像索引数组 for(a=0;a<5;a++) for(b=0;b<8;b++) { InitImage(imageIndex[a][b],dbImage,IMAGEWIDTH,IMAGEHEIGHT);//读入图像 FloatImage(dbImage,*changeImage,IMAGEWIDTH,IMAGEHEIGHT);//强制转换为float型 for(i=0;i 这个是主函数,首先的宏代表的是不同的图片,MODEPHOTO的40张是训练的图片,TRAINPHOTO的15张是测试的图片,所以最后只要看这15张有几张是满足要求的即可。下方是一些函数的声明,InitImage用来读取图片,conv是卷积运算,harrone是一维harr百年换,FloatImage将unsigned char型的图片数组转化为Float型,UcharImage将float型转化为unsigned char型,AddImage是对图像的像素值做放大,CopyImage将一个图像数组复制到另一个数组中,MinImage和MaxImage分别限定图像的像素最大值和最小值。 要注意所有全局变量的定义要放在main函数外,否则DSP会报错 全局变量中imageIndex代表训练的图像的标签,5组,每组8张正好40张,trainIndex代表测试的图片的标签,5组每组3张正好15张,进入main函数后,首先让训练的40张图分别对应1-40这40个数字,然后分别对没张图片做harr变换,提取出特征值存入三维数组中。接着对测试的15张图片进行同样的操作。最后利用KNN的函数得出结果存在result数组中,按理说result的结果应该为111,222,333,444,555则是完全正确的,若不对可以计算正确率。 所有的函数定义如下: #include /******************************************宏定义begin************************************************/ #define IMAGEWIDTH 32//图像宽度 #define IMAGEHEIGHT 32//图像高度 #define LENGTH 32//图像进行一维harr变换时的长度,相当于图像宽度和高度 //来自例程文件,说明哪些图片 #define MODEPHOTO00 1 #define MODEPHOTO01 2 #define MODEPHOTO02 3 #define MODEPHOTO03 4 #define MODEPHOTO04 5 #define MODEPHOTO05 6 #define MODEPHOTO06 7 #define MODEPHOTO07 8 #define MODEPHOTO10 9 #define MODEPHOTO11 10 #define MODEPHOTO12 11 #define MODEPHOTO13 12 #define MODEPHOTO14 13 #define MODEPHOTO15 14 #define MODEPHOTO16 15 #define MODEPHOTO17 16 #define MODEPHOTO20 17 #define MODEPHOTO21 18 #define MODEPHOTO22 19 #define MODEPHOTO23 20 #define MODEPHOTO24 21 #define MODEPHOTO25 22 #define MODEPHOTO26 23 #define MODEPHOTO27 24 #define MODEPHOTO30 25 #define MODEPHOTO31 26 #define MODEPHOTO32 27 #define MODEPHOTO33 28 #define MODEPHOTO34 29 #define MODEPHOTO35 30 #define MODEPHOTO36 31 #define MODEPHOTO37 32 #define MODEPHOTO40 33 #define MODEPHOTO41 34 #define MODEPHOTO42 35 #define MODEPHOTO43 36 #define MODEPHOTO44 37 #define MODEPHOTO45 38 #define MODEPHOTO46 39 #define MODEPHOTO47 40 //#define TESTMATRIX 101 #define TRAINPHOTO00 101 #define TRAINPHOTO01 102 #define TRAINPHOTO02 103 #define TRAINPHOTO10 104 #define TRAINPHOTO11 105 #define TRAINPHOTO12 106 #define TRAINPHOTO20 107 #define TRAINPHOTO21 108 #define TRAINPHOTO22 109 #define TRAINPHOTO30 110 #define TRAINPHOTO31 111 #define TRAINPHOTO32 112 #define TRAINPHOTO40 113 #define TRAINPHOTO41 114 #define TRAINPHOTO42 115 #define GRAYBARLEVEL 16 /******************************************宏定义end************************************************/ /******************************************函数定义begin************************************************/ /*以下两个函数来自例程文件,读入一张图片并存到一个一维数组中*/ void ReadImage(unsigned char *pImage,char *cFileName,int nWidth,int nHeight); void InitImage(unsigned int nMode,unsigned char *pImage,int nWidth,int nHeight) { switch ( nMode ) { case MODEPHOTO00: ReadImage(pImage,"..\learn\01\s1.bmp",nWidth,nHeight); break; case MODEPHOTO01: ReadImage(pImage,"..\learn\01\s2.bmp",nWidth,nHeight); break; case MODEPHOTO02: ReadImage(pImage,"..\learn\01\s3.bmp",nWidth,nHeight); break; case MODEPHOTO03: ReadImage(pImage,"..\learn\01\s4.bmp",nWidth,nHeight); break; case MODEPHOTO04: ReadImage(pImage,"..\learn\01\s5.bmp",nWidth,nHeight); break; case MODEPHOTO05: ReadImage(pImage,"..\learn\01\s6.bmp",nWidth,nHeight); break; case MODEPHOTO06: ReadImage(pImage,"..\learn\01\s7.bmp",nWidth,nHeight); break; case MODEPHOTO07: ReadImage(pImage,"..\learn\01\s8.bmp",nWidth,nHeight); break; case MODEPHOTO10: ReadImage(pImage,"..\learn\02\s1.bmp",nWidth,nHeight); break; case MODEPHOTO11: ReadImage(pImage,"..\learn\02\s2.bmp",nWidth,nHeight); break; case MODEPHOTO12: ReadImage(pImage,"..\learn\02\s3.bmp",nWidth,nHeight); break; case MODEPHOTO13: ReadImage(pImage,"..\learn\02\s4.bmp",nWidth,nHeight); break; case MODEPHOTO14: ReadImage(pImage,"..\learn\02\s5.bmp",nWidth,nHeight); break; case MODEPHOTO15: ReadImage(pImage,"..\learn\02\s6.bmp",nWidth,nHeight); break; case MODEPHOTO16: ReadImage(pImage,"..\learn\02\s7.bmp",nWidth,nHeight); break; case MODEPHOTO17: ReadImage(pImage,"..\learn\02\s8.bmp",nWidth,nHeight); break; case MODEPHOTO20: ReadImage(pImage,"..\learn\03\s1.bmp",nWidth,nHeight); break; case MODEPHOTO21: ReadImage(pImage,"..\learn\03\s2.bmp",nWidth,nHeight); break; case MODEPHOTO22: ReadImage(pImage,"..\learn\03\s3.bmp",nWidth,nHeight); break; case MODEPHOTO23: ReadImage(pImage,"..\learn\03\s4.bmp",nWidth,nHeight); break; case MODEPHOTO24: ReadImage(pImage,"..\learn\03\s5.bmp",nWidth,nHeight); break; case MODEPHOTO25: ReadImage(pImage,"..\learn\03\s6.bmp",nWidth,nHeight); break; case MODEPHOTO26: ReadImage(pImage,"..\learn\03\s7.bmp",nWidth,nHeight); break; case MODEPHOTO27: ReadImage(pImage,"..\learn\03\s8.bmp",nWidth,nHeight); break; case MODEPHOTO30: ReadImage(pImage,"..\learn\04\s1.bmp",nWidth,nHeight); break; case MODEPHOTO31: ReadImage(pImage,"..\learn\04\s2.bmp",nWidth,nHeight); break; case MODEPHOTO32: ReadImage(pImage,"..\learn\04\s3.bmp",nWidth,nHeight); break; case MODEPHOTO33: ReadImage(pImage,"..\learn\04\s4.bmp",nWidth,nHeight); break; case MODEPHOTO34: ReadImage(pImage,"..\learn\04\s5.bmp",nWidth,nHeight); break; case MODEPHOTO35: ReadImage(pImage,"..\learn\04\s6.bmp",nWidth,nHeight); break; case MODEPHOTO36: ReadImage(pImage,"..\learn\04\s7.bmp",nWidth,nHeight); break; case MODEPHOTO37: ReadImage(pImage,"..\learn\04\s8.bmp",nWidth,nHeight); break; case MODEPHOTO40: ReadImage(pImage,"..\learn\05\s1.bmp",nWidth,nHeight); break; case MODEPHOTO41: ReadImage(pImage,"..\learn\05\s2.bmp",nWidth,nHeight); break; case MODEPHOTO42: ReadImage(pImage,"..\learn\05\s3.bmp",nWidth,nHeight); break; case MODEPHOTO43: ReadImage(pImage,"..\learn\05\s4.bmp",nWidth,nHeight); break; case MODEPHOTO44: ReadImage(pImage,"..\learn\05\s5.bmp",nWidth,nHeight); break; case MODEPHOTO45: ReadImage(pImage,"..\learn\05\s6.bmp",nWidth,nHeight); break; case MODEPHOTO46: ReadImage(pImage,"..\learn\05\s7.bmp",nWidth,nHeight); break; case MODEPHOTO47: ReadImage(pImage,"..\learn\05\s8.bmp",nWidth,nHeight); break; case TRAINPHOTO00: ReadImage(pImage,"..\train\01\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO01: ReadImage(pImage,"..\train\01\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO02: ReadImage(pImage,"..\train\01\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO10: ReadImage(pImage,"..\train\02\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO11: ReadImage(pImage,"..\train\02\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO12: ReadImage(pImage,"..\train\02\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO20: ReadImage(pImage,"..\train\03\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO21: ReadImage(pImage,"..\train\03\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO22: ReadImage(pImage,"..\train\03\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO30: ReadImage(pImage,"..\train\04\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO31: ReadImage(pImage,"..\train\04\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO32: ReadImage(pImage,"..\train\04\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO40: ReadImage(pImage,"..\train\05\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO41: ReadImage(pImage,"..\train\05\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO42: ReadImage(pImage,"..\train\05\s11.bmp",nWidth,nHeight); break; /* case TRAINPHOTO00: ReadImage(pImage,"..\train\01\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO01: ReadImage(pImage,"..\train\01\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO02: ReadImage(pImage,"..\train\01\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO10: ReadImage(pImage,"..\train\02\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO11: ReadImage(pImage,"..\train\02\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO12: ReadImage(pImage,"..\train\02\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO20: ReadImage(pImage,"..\train\03\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO21: ReadImage(pImage,"..\train\03\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO22: ReadImage(pImage,"..\train\03\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO30: ReadImage(pImage,"..\train\04\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO31: ReadImage(pImage,"..\train\04\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO32: ReadImage(pImage,"..\train\04\s11.bmp",nWidth,nHeight); break; case TRAINPHOTO40: ReadImage(pImage,"..\train\05\s9.bmp",nWidth,nHeight); break; case TRAINPHOTO41: ReadImage(pImage,"..\train\05\s10.bmp",nWidth,nHeight); break; case TRAINPHOTO42: ReadImage(pImage,"..\train\05\s11.bmp",nWidth,nHeight); break; */ default: break; } } void ReadImage(unsigned char *pImage,char *cFileName,int nWidth,int nHeight) { int j; unsigned char *pWork; FILE *fp; if ( fp=fopen(cFileName,"rb" ) ) { fseek(fp,1078L,SEEK_SET); pWork=pImage+(nHeight-1)*nWidth; for ( j=0;jlength) k = length; for(n=0;n!=k+1;n++){ sum+=(f[n]*g[k-n]); } return sum; } void conv(float* f,float* g,float* y,int length) { int k; for(k=0;k255.0) { *pImage=255.0; } if(*pImage<0.0) { *pImage=0.0; } } } } /*把以个数组中的内容复制到另一个数组(相当于把一幅图像复制到另一个数组中,允许一维数组复制到二维数组)*/ void CopyImage(float *pImage,float *qImage,int nWidth,int nHeight) { int i,j; float *pWork; pWork=pImage; for ( i=0;imax) max=*pWork; } } //printf(" max=%f ",max); pWork=pImage; if(max>=255.0) { for ( i=0;i KNN分类器的函数定义如下: #include "KNN.h" float MaxVecLoc(float* vec, int n_vecNum, int* loc) //计算数组中的最大值,返回值为最大值,并且参数中的指针loc指向最大值的位置 { int i; float maxn=vec[0]; *loc=0; for (i=0;ilmax) lmax=l[i]; } for(i=0;i<5;i++) { if(l[i]==lmax) index= i+1; } return index; } float distance(unsigned char *test, unsigned char *train)//已修改 //////////////////////////////////////////////////////////////////////////////////////////////////////// // // 求 vector1=(x1,x2,...,xn)和vector2=(y1,y2,...,yn)的欧几里德距离 // //////////////////////////////////////////////////////////////////////////////////////////////////////// { float dist; float sum=0.0; int i,j; for (i=0;i<16;i++) for (j=0;j<16;j++) { sum+=(*test-*train)*(*test-*train); test++; train++; } dist=sqrt(sum); return dist; } int KNNclassify(unsigned char* testPerFeature/*单个测试样本(1个)*/,unsigned char trainFeatureMaxtix[][16][16]/*训练样本集(40个训练样本)*/, int* label) //单个测试样本所属类别 { int i,loc=0,predictResult=0; float dist=0.0; //K_KNN=5 float K_Neighbor_dist[K_KNN];//存储该测试样本最邻近的K_KNN个训练样本 unsigned char K_Neighbor_Index[K_KNN];//存储该测试样本最邻近的K_KNN个训练样本是哪个 int K_Neighbor_Label[K_KNN]={0};// for (i=0;i KNN分类器的头文件定义如下: #include #include #include #define K_KNN 6 #define MAXKNN 100000000000 float distance(unsigned char *test, unsigned char *train); int KNNclassify(unsigned char* testPerFeature,unsigned char trainFeatureVec[][16][16], int* label); float MaxVecLoc(float* vec, int n_vecNum, int* loc); int label_most(int* labels); 最后的项目文件可以到这个地址下载: http://download.csdn.net/detail/shenda123/9401703