www.pudn.com > Photodeal.rar > Bp.h


 
#include  
#include   
#include  
#include  
#define BIGRND 32767 
 
double drnd(); 
double dpn1(); 
double squash(double x); 
double *alloc_1d_dbl(int n); 
double *alloc_1d_dbl(int n); 
double **alloc_2d_dbl(int m, int n); 
int ndigicount; //多次提取样本特征总个数 
double ** all_data_in; // 多次提取特征矩阵 
void bpnn_initialize(int seed); 
void bpnn_randomize_weights(double **w, int m, int n); 
void bpnn_zero_weights(double **w, int m, int n); 
void bpnn_layerforward(double *l1, double *l2, double **conn, int n1, int n2); 
void bpnn_output_error(double *delta, double *target, double *output, int nj); 
void bpnn_hidden_error(double* delta_h, int nh, double *delta_o, int no, double **who, double *hidden); 
void bpnn_adjust_weights(double *delta, int ndelta, double *ly, int nly, double** w, double **oldw, double eta, double momentum); 
void w_weight(double **w,int n1,int n2,char*name); 
bool r_weight(double **w,int n1,int n2,char *name); 
void w_num(int n1,int n2,int n3,char*name); 
bool r_num(int *n,char *name); 
 
double **TZTQ_24(BYTE*image ,int p,int w); 
//double **code(BYTE*image ,int *p,int w,int h,int dw); 
void BpTrain1(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); 
void BpTrain2(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); 
void BpTrain3(HDIB hDIB,int n_hidden,double min_ex,double momentum,double eta ,int width,int height); 
CString* CodeRecognize(HDIB hDIB,int width ,int height ,int n_in ,int n_hidden,int n_out); 
 
 
/*** 返回0-1的双精度随机数 ***/ 
double drnd() 
{ 
	return ((double) rand() / (double) BIGRND); 
} 
 
/*** 返回-1.0到1.0之间的双精度随机数 ***/ 
double dpn1() 
{ 
	return ((drnd() * 2.0) - 1.0); 
} 
 
double squash(double x) 
{ 
	return (1.0 / (1.0 + exp(-x))); 
} 
/*** 申请1维双精度实数数组 ***/ 
 
double *alloc_1d_dbl(int n) 
{ 
	double *new1; 
	 
	new1 = (double *) malloc ((unsigned) (n * sizeof (double))); 
	if (new1 == NULL) { 
		printf("ALLOC_1D_DBL: Couldn't allocate array of doubles\n"); 
		return (NULL); 
	} 
	return (new1); 
} 
 
/*** 申请2维双精度实数数组 ***/ 
 
double **alloc_2d_dbl(int m, int n) 
{ 
	int i; 
	double **new1; 
	 
	new1 = (double **) malloc ((unsigned) (m * sizeof (double *))); 
	if (new1 == NULL) { 
		//	printf("ALLOC_2D_DBL: Couldn't allocate array of dbl ptrs\n"); 
		return (NULL); 
	} 
	 
	for (i = 0; i < m; i++) { 
		new1[i] = alloc_1d_dbl(n); 
	} 
	 
	return (new1); 
} 
 
/*** 设置随机数种子 ***/ 
void bpnn_initialize(int seed) 
{ 
	//printf("Random number generator seed: %d\n", seed); 
	srand(seed); 
} 
 
/*** 随机初始化权值 ***/ 
void bpnn_randomize_weights(double **w, int m, int n) 
{ 
	int i, j; 
	 
	for (i = 0; i <= m; i++) { 
		for (j = 0; j <= n; j++) { 
			 
			w[i][j] = dpn1(); 
		} 
	} 
} 
/*** 0初始化权值 ***/ 
void bpnn_zero_weights(double **w, int m, int n) 
{ 
	int i, j; 
	 
	for (i = 0; i <= m; i++) { 
		for (j = 0; j <= n; j++) { 
			w[i][j] = 0.0; 
		} 
	} 
} 
 
/*********前向传输*********/ 
void bpnn_layerforward(double *l1, double *l2, double **conn, int n1, int n2) 
{ 
	double sum; 
	int j, k; 
	 
	/*** 设置阈值 ***/ 
	l1[0] = 1.0; 
	 
	/*** 对于第二层的每个神经元 ***/ 
	for (j = 1; j <= n2; j++) { 
		 
		/*** 计算输入的加权总和 ***/ 
		sum = 0.0; 
		for (k = 0; k <= n1; k++) { 
			sum += conn[k][j] * l1[k]; 
		} 
		l2[j] = squash(sum); 
	} 
} 
 
/* 输出误差 */ 
 
void bpnn_output_error(double *delta, double *target, double *output, int nj) 
{ 
	int j; 
	double o, t, errsum; 
	 
	errsum = 0.0; 
	for (j = 1; j <= nj; j++) { 
		o = output[j]; 
		t = target[j]; 
		delta[j] = o * (1.0 - o) * (t - o); 
		 
	} 
	 
} 
 
/* 隐含层误差 */ 
 
void bpnn_hidden_error(double* delta_h, int nh, double *delta_o, int no, double **who, double *hidden) 
{ 
	int j, k; 
	double h, sum, errsum; 
	 
	errsum = 0.0; 
	for (j = 1; j <= nh; j++) { 
		h = hidden[j]; 
		sum = 0.0; 
		for (k = 1; k <= no; k++) { 
			sum += delta_o[k] * who[j][k]; 
		} 
		delta_h[j] = h * (1.0 - h) * sum; 
		 
	} 
	 
} 
 
/* 调整权值 */ 
void bpnn_adjust_weights(double *delta, int ndelta, double *ly, int nly, double** w, double **oldw, double eta, double momentum) 
{ 
	double new_dw; 
	int k, j; 
	 
	ly[0] = 1.0; 
	for (j = 1; j <= ndelta; j++) { 
		for (k = 0; k <= nly; k++) { 
			new_dw = ((eta * delta[j] * ly[k]) + (momentum * oldw[k][j])); 
			w[k][j] += new_dw; 
			oldw[k][j] = new_dw; 
		} 
	} 
} 
/*******保存权值**********/ 
void w_weight(double **w,int n1,int n2,char*name) 
{ 
	int i,j; 
	double *buffer; 
	FILE *fp; 
	fp=fopen(name,"wb+"); 
	buffer=(double*)malloc((n1+1)*(n2+1)*sizeof(double)); 
	for(i=0;i<=n1;i++) 
	{ 
		for(j=0;j<=n2;j++) 
			buffer[i*(n2+1)+j]=w[i][j]; 
	} 
	fwrite((char*)buffer,sizeof(double),(n1+1)*(n2+1),fp); 
	fclose(fp); 
	free(buffer); 
} 
 
 
 
/************读取权值*************/ 
bool  r_weight(double **w,int n1,int n2,char *name) 
{ 
	int i,j; 
	double *buffer; 
	FILE *fp; 
	if((fp=fopen(name,"rb"))==NULL) 
	{ 
		::MessageBox(NULL,"无法读取权值信息",NULL,MB_ICONSTOP); 
		return (false); 
	} 
	buffer=(double*)malloc((n1+1)*(n2+1)*sizeof(double)); 
	fread((char*)buffer,sizeof(double),(n1+1)*(n2+1),fp); 
	 
	for(i=0;i<=n1;i++) 
	{ 
		for(j=0;j<=n2;j++) 
			w[i][j]=buffer[i*(n2+1)+j]; 
	} 
	fclose(fp); 
	free(buffer); 
	return(true); 
} 
 
/*****保存各层结点的数目******/ 
void w_num(int n1,int n2,int n3,char*name) 
{ 
	FILE *fp; 
	fp=fopen(name,"wb+"); 
	int *buffer; 
	buffer=(int*)malloc(3*sizeof(int)); 
	buffer[0]=n1; 
	buffer[1]=n2; 
	buffer[2]=n3; 
	fwrite((char*)buffer,sizeof(int),3,fp); 
	fclose(fp); 
	free(buffer); 
} 
 
/********读取各层结点数目*********/ 
 
bool r_num(int *n,char *name) 
{ 
	int *buffer; 
	FILE *fp; 
	buffer=(int *)malloc(3*sizeof(int)); 
	if((fp=fopen(name,"rb"))==NULL) 
	{ 
		::MessageBox(NULL,"结点参数",NULL,MB_ICONSTOP); 
		return (false); 
	} 
	fread((char*)buffer,sizeof(int),3,fp); 
	n[0]=buffer[0]; 
	n[1]=buffer[1]; 
	n[2]=buffer[2]; 
	fclose(fp); 
	free(buffer); 
	return(true); 
} 
/******************************************************** 
* 函数名称 VerticalCode() 
* 
* 参量: 
*   BYTE* lpDIBBits   -指向输入图像的象素其实位置的指针  
*   int  num          -图片中样本的个数 
*   LONG lLineByte    -输入图片每行的字节数 
*   LONG lSwidth      -预处理时归一化的宽度 
*   LONG lSheight     -预处理时归一化的长度 
* 
* 返回值: 
*   double**           -特征向量矩阵 
* 
*  函数功能 : 
*      对于输入样本提取特征向量,在这里把归一化样本的 
*	   水平和竖直方向的统计特征作为特征提取出来 
***************************************************************/ 
 
double** VerticalCode(BYTE* lpDIBBits,int num, LONG lLineByte,LONG lSwidth,LONG lSheight) 
{    
   //循环变量 
    int i,j,k; 
    BYTE* lpSrc;  
     
	//统计变量 
	int sum; 
 
    //  建立保存特征向量的二维数组 
   double **data; 
    
   // 为这个数组申请二维存储空间 
   data = alloc_2d_dbl(num,lSwidth+lSheight); 
  
   // 将归一化的样本的每个象素作为一个特征点提取出来 
 
   //逐个数据扫描 
   for(k=0;kc) c=f[i]; 
					for(i=0;i<24;i++) 
						f[i]=f[i]/c; 
     //新增六个特征 
					for(i=0;i<6;i++) 
						f[24+i]=0; 
					int x=0; 
					int y=0; 
					for(m=1;m<=3;m++) 
					{ 
						for(i=0;i<15;i++) 
 
						{ 
							lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*i; 
							x=*lpSrc; 
      lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*(i+1); 
							y=*lpSrc; 
							if((x==0) && (y==255) ) f[23+m]+=1; 
							x=y=0; 
						} 
                  for(i=0;i<29;i++) 
				  { 
	lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+i; 
							x=*lpSrc; 
      lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+(i+1); 
							y=*lpSrc; 
							if((x==0) && (y==255) ) f[26+m]+=1; 
							x=y=0; 
						} 
   lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+8*m+lLineBytes*15; 
							x=*lpSrc; 
      lpSrc=(unsigned char*)lpDIBBits+k*lSwidth+4*m*lLineBytes+29; 
							y=*lpSrc; 
							if(!x)f[23+m]+=1; 
							if(!y) f[26+m]+=1; 
							x=y=0; 
					} 
                c=f[24]; 
				for(i=25;i<30;i++) 
					if(f[i]>c) c=f[i]; 
					for(i=24;i<30;i++) 
						f[i]=f[i]/c;   
					//再新增九个特征 
 
      for(m=0;m<9;m++) 
		  f[30+m]=tz[m]; 
 
                c=f[30]; 
				for(i=30;i<39;i++) 
					if(f[i]>c) c=f[i]; 
					for(i=30;i<39;i++) 
						f[i]=f[i]/c;   
		//存储特征 
		for(i=0;i<39;i++) 
			tezheng[k][i]=f[i]; 
	} 
	 
 
//	::GlobalUnlock ((HGLOBAL)hDIB); 
	//返回特征向量矩阵的指针 
	return tezheng; 
	delete []f; 
	delete []p; 
	delete []tz; 
} 
 
/**************************************************** 
* 函数名称 BpTrain() 
*  
* 参数: 
*   double **data_in    -指向输入的特征向量数组的指针     
*	double **data_out   -指向理想输出数组的指针 
int n_in            -输入层结点的个数  
*   int n_hidden        -BP网络隐层结点的数目 
*   double min_ex       -训练时允许的最大均方误差 
*   double momentum     -BP网络的相关系数 
*   double eta          -BP网络的训练步长 
*   int num             -输入样本的个数 
* 
* 函数功能: 
*     根据输入的特征向量和期望的理想输出对BP网络尽行训练 
*     训练结束后将权值保存并将训练的结果显示出来 
********************************************************/ 
void BpTrain1(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) 
{ 
	 
	 
	 
	//循环变量    
	int i,k,l; 
	 
	//输出层结点数目 
	int  n_out=4;    
	//指向输入层数据的指针 
	double* input_unites;  
	//指向隐层数据的指针 
	double* hidden_unites; 
	//指向输出层数据的指针 
	double* output_unites;  
	//指向隐层误差数据的指针 
	double* hidden_deltas; 
	//指向输出层误差数剧的指针 
	double* output_deltas;   
	//指向理想目标输出的指针 
	double* target;     
	//指向输入层于隐层之间权值的指针 
	double** input_weights; 
	//指向隐层与输出层之间的权值的指针 
	double** hidden_weights; 
	//指向上一此输入层于隐层之间权值的指针 
	double** input_prev_weights ; 
	//指向上一此隐层与输出层之间的权值的指针 
	double** hidden_prev_weights; 
	//每次循环后的均方误差误差值  
	double ex; 
	 
	//为各个数据结构申请内存空间 
	input_unites= alloc_1d_dbl(n_in + 1); 
	hidden_unites=alloc_1d_dbl(n_hidden + 1); 
	output_unites=alloc_1d_dbl(n_out + 1); 
	hidden_deltas = alloc_1d_dbl(n_hidden + 1); 
	output_deltas = alloc_1d_dbl(n_out + 1); 
	target = alloc_1d_dbl(n_out + 1); 
	input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	 
	//为产生随机序列撒种 
	time_t t;  
	bpnn_initialize((unsigned)time(&t)); 
	 
	//对各种权值进行初始化初始化 
	bpnn_randomize_weights( input_weights,n_in,n_hidden); 
	bpnn_randomize_weights( hidden_weights,n_hidden,n_out); 
	bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); 
	bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); 
	 
	//开始进行BP网络训练 
	//这里设定最大的迭代次数为15000次 
	for(l=0;l<15000;l++)   
	{  
		//对均方误差置零 
		ex=0; 
		//对样本进行逐个的扫描 
		for(k=0;kmin_ex) 
	{ 
		 
		str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); 
		::MessageBox(NULL,str,"训练结果",NULL); 
	} 
	 
	//释放内存空间 
	 
	free(input_unites); 
	free(hidden_unites); 
	free(output_unites); 
	free(hidden_deltas); 
	free(output_deltas); 
	free(target); 
	free(input_weights); 
	free(hidden_weights); 
	free(input_prev_weights); 
	free(hidden_prev_weights); 
} 
 
///////////////////////////// 
void BpTrain2(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) 
{ 
	 
	 
	 
	//循环变量    
	int i,k,l; 
	 
	//输出层结点数目 
	int  n_out=4;    
	//指向输入层数据的指针 
	double* input_unites;  
	//指向隐层数据的指针 
	double* hidden_unites; 
	//指向输出层数据的指针 
	double* output_unites;  
	//指向隐层误差数据的指针 
	double* hidden_deltas; 
	//指向输出层误差数剧的指针 
	double* output_deltas;   
	//指向理想目标输出的指针 
	double* target;     
	//指向输入层于隐层之间权值的指针 
	double** input_weights; 
	//指向隐层与输出层之间的权值的指针 
	double** hidden_weights; 
	//指向上一此输入层于隐层之间权值的指针 
	double** input_prev_weights ; 
	//指向上一此隐层与输出层之间的权值的指针 
	double** hidden_prev_weights; 
	//每次循环后的均方误差误差值  
	double ex; 
	 
	//为各个数据结构申请内存空间 
	input_unites= alloc_1d_dbl(n_in + 1); 
	hidden_unites=alloc_1d_dbl(n_hidden + 1); 
	output_unites=alloc_1d_dbl(n_out + 1); 
	hidden_deltas = alloc_1d_dbl(n_hidden + 1); 
	output_deltas = alloc_1d_dbl(n_out + 1); 
	target = alloc_1d_dbl(n_out + 1); 
	input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	 
	//为产生随机序列撒种 
	time_t t;  
	bpnn_initialize((unsigned)time(&t)); 
	 
	//对各种权值进行初始化初始化 
	bpnn_randomize_weights( input_weights,n_in,n_hidden); 
	bpnn_randomize_weights( hidden_weights,n_hidden,n_out); 
	bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); 
	bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); 
	 
	//开始进行BP网络训练 
	//这里设定最大的迭代次数为15000次 
	for(l=0;l<15000;l++)   
	{  
		//对均方误差置零 
		ex=0; 
		//对样本进行逐个的扫描 
		for(k=0;kmin_ex) 
	{ 
		 
		str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); 
		::MessageBox(NULL,str,"训练结果",NULL); 
	} 
	 
	//释放内存空间 
	 
	free(input_unites); 
	free(hidden_unites); 
	free(output_unites); 
	free(hidden_deltas); 
	free(output_deltas); 
	free(target); 
	free(input_weights); 
	free(hidden_weights); 
	free(input_prev_weights); 
	free(hidden_prev_weights); 
} 
//////////////////////////////////////// 
void BpTrain3(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num) 
{ 
	 
	 
	 
	//循环变量    
	int i,k,l; 
	 
	//输出层结点数目 
	int  n_out=4;    
	//指向输入层数据的指针 
	double* input_unites;  
	//指向隐层数据的指针 
	double* hidden_unites; 
	//指向输出层数据的指针 
	double* output_unites;  
	//指向隐层误差数据的指针 
	double* hidden_deltas; 
	//指向输出层误差数剧的指针 
	double* output_deltas;   
	//指向理想目标输出的指针 
	double* target;     
	//指向输入层于隐层之间权值的指针 
	double** input_weights; 
	//指向隐层与输出层之间的权值的指针 
	double** hidden_weights; 
	//指向上一此输入层于隐层之间权值的指针 
	double** input_prev_weights ; 
	//指向上一此隐层与输出层之间的权值的指针 
	double** hidden_prev_weights; 
	//每次循环后的均方误差误差值  
	double ex; 
	 
	//为各个数据结构申请内存空间 
	input_unites= alloc_1d_dbl(n_in + 1); 
	hidden_unites=alloc_1d_dbl(n_hidden + 1); 
	output_unites=alloc_1d_dbl(n_out + 1); 
	hidden_deltas = alloc_1d_dbl(n_hidden + 1); 
	output_deltas = alloc_1d_dbl(n_out + 1); 
	target = alloc_1d_dbl(n_out + 1); 
	input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	 
	//为产生随机序列撒种 
	time_t t;  
	bpnn_initialize((unsigned)time(&t)); 
	 
	//对各种权值进行初始化初始化 
	bpnn_randomize_weights( input_weights,n_in,n_hidden); 
	bpnn_randomize_weights( hidden_weights,n_hidden,n_out); 
	bpnn_zero_weights(input_prev_weights, n_in,n_hidden ); 
	bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out ); 
	 
	//开始进行BP网络训练 
	//这里设定最大的迭代次数为15000次 
	for(l=0;l<15000;l++)   
	{  
		//对均方误差置零 
		ex=0; 
		//对样本进行逐个的扫描 
		for(k=0;kmin_ex) 
	{ 
		 
		str.Format("迭代%d次,平均误差%.4f\n请调整参数重新训练吧!",l,ex); 
		::MessageBox(NULL,str,"训练结果",NULL); 
	} 
	 
	//释放内存空间 
	 
	free(input_unites); 
	free(hidden_unites); 
	free(output_unites); 
	free(hidden_deltas); 
	free(output_deltas); 
	free(target); 
	free(input_weights); 
	free(hidden_weights); 
	free(input_prev_weights); 
	free(hidden_prev_weights); 
} 
 
/******************************************* 
* 函数名称 
* CodeRecognize() 
* 参量 
*  double **data_in     -指向待识别样本特征向量的指针 
*  int num              -待识别的样本的个数  
*  int n_in             -Bp网络输入层结点的个数               
*  int n_hidden         -Bp网络隐层结点的个数 
*  int n_out            -Bp网络输出层结点的个数 
* 函数功能:   
*    读入输入样本的特征相量并根据训练所得的权值  
*    进行识别,将识别的结果写入result.txt  
****************************************/ 
 
CString* CodeRecognize(double **data_in, int num ,int n_in,int n_hidden,int n_out) 
{ 
		//循环变量 
	int i,k; 
	// 指向识别结果的指针  
	int *recognize; 
	//为存放识别的结果申请存储空间 
	recognize=(int*)malloc(num*sizeof(int)); 
	CString Charac[4]={"京","晋","粤",""}; 
	CString Num[3]={"0","2","4"}; 
	CString Letter[3]={"K","E","A"}; 
	//指向输入层数据的指针 
	double* input_unites;   
	//指向隐层数据的指针 
	double* hidden_unites; 
	//指向输出层数据的指针 
	double* output_unites;  
	//指向输入层于隐层之间权值的指针 
	double** input_weights; 
	//指向隐层与输出层之间的权值的指针 
	double** hidden_weights; 
	//为各个数据结构申请内存空间 
	input_unites= alloc_1d_dbl(n_in + 1); 
	hidden_unites=alloc_1d_dbl(n_hidden + 1); 
	output_unites=alloc_1d_dbl(n_out + 1); 
	input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1); 
	hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1); 
	 
	 
 
	//逐个样本扫描 
	for(k=0;k0.55) 
				 
				result+=(int)pow(2,double(4-i)); 
			} 
			else if(k==1) 
			{ 
                if(output_unites[i]>0.36) 
				 
				result+=(int)pow(2,double(4-i)); 
			} 
			else 
			{ 
               if(output_unites[i]>0.4) 
				 
				result+=(int)pow(2,double(4-i)); 
			} 
		} 
		 
		//如果判定的结果小于等于9,认为合理 
		if(result<=9) 
			recognize[k]=result; 
		//如果判定的结果大于9,认为不合理将结果定位为一个特殊值20 
		if(result>9) 
			recognize[k]=20; 
	} 
	 
 
	 
	//将识别的结果显示出来 
	CString str; 
	CString* str1=new CString; 
	for(i=0;i