⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bp.h

📁 本目录主要包括:文档和两个源代 其中源代码是识别程序的
💻 H
📖 第 1 页 / 共 2 页
字号:
					b=(*lpSrc==255)?0:1;
				    tz[m]+=b;
				}
		}

		//提取第9个特征-总象素值
		for(i=0;i<lHeight;i++)
			for(j=k*width;j<(k+1)*width;j++)
			{	lpSrc=(unsigned char*)lpDIBBits + lLineBytes *  i + j;
				b=(*lpSrc==255)?0:1;
			    tz[8]+=b;
			}

		//提取第10、11个特征-水平扫描切割
			i=int(lHeight*1/3);
			for(j=k*width;j<(k+1)*width;j++)
			{	lpSrc=(unsigned char*)lpDIBBits + lLineBytes *  i + j;
				b=(*lpSrc==255)?0:1;
			    tz[9]+=b;
			}
			//
			i=int(lHeight*2/3);
			for(j=k*width;j<(k+1)*width;j++)
			{	lpSrc=(unsigned char*)lpDIBBits + lLineBytes *  i + j;
				b=(*lpSrc==255)?0:1;
			    tz[10]+=b;
			}

		//提取第12、13个特征-垂直扫描切割
			j=int(k*width+width*1/3);
			for(i=0;i<lHeight;i++)
			{	lpSrc=(unsigned char*)lpDIBBits + lLineBytes *  i + j;
				b=(*lpSrc==255)?0:1;
			    tz[11]+=b;
			}
			
			j=int(k*width+width*2/3);
			for(i=0;i<lHeight;i++)
			{	lpSrc=(unsigned char*)lpDIBBits + lLineBytes *  i + j;
				b=(*lpSrc==255)?0:1;
			    tz[12]+=b;
			}

		//存储特征
		for(i=0;i<dim;i++)
			tezheng[k][i]=tz[i];
	}

	::GlobalUnlock ((HGLOBAL)hDIB);
	//返回特征向量矩阵的指针
	return tezheng;
}

/**********************************
* 函数名称 code()
*
* 参量:
*   BYTE* lpDIBBits   -指向输入图像的象素其实位置的指针 
*   int num           -图片中样本的个数
*   LONG lLineByte    -输入图片每行的字节数
*   LONG lSwidth      -预处理时归一化的宽度
*   LONG lSheight     -预处理时归一化的长度
*
*  函数功能 :
*      对于输入样本提取特征向量,在这里把归一化样本的
*	   每一个象素都作为特征提取出来
**************************************/

double** code (BYTE* lpDIBBits,int num, LONG lLineByte,LONG lSwidth,LONG lSheight)
{   
	//循环变量
    int i,j,k;
    BYTE* lpSrc; 
	
    //  建立保存特征向量的二维数组
	double **data;
	
	// 为这个数组申请二维存储空间
	data = alloc_2d_dbl(num,lSwidth*lSheight);
	
	// 将归一化的样本的每个象素作为一个特征点提取出来
	
	//逐个数据扫描
	for(k=0;k<num;k++)  
	{ 
		//对每个数据逐行扫描
		for(i=0;i<lSheight;i++)
		{  
			//对每个数据逐列扫描
			for(j=k*lSwidth;j<(k+1)*lSwidth;j++)
			{
				
				// 指向图像第i行第j列个象素的指针
				lpSrc = lpDIBBits + i*lLineByte + j;
				
				//如果这个象素是黑色的
				if(*(lpSrc)==0)
					//将特征向量的相应位置填1
					data[k][i*lSwidth+j-k*lSwidth]=1;
				//如果这个象素是其他的   
				if(*(lpSrc)!=0)
					//将特征向量的相应位置填0
					data[k][i*lSwidth+j-k*lSwidth]=0;
				
				
			}
		}
	}
	
	return(data);  
}

/****************************************************
* 函数名称 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 BpTrain(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;k<num;k++)  
		{ 
			//将提取的样本的特征向量输送到输入层上
			for(i=1;i<=n_in;i++)
				input_unites[i] = data_in[k][i-1];
			
			//将预定的理想输出输送到BP网络的理想输出单元
			for(i=1;i<=n_out;i++)
				target[i]=data_out[k][i-1];
			
			//前向传输激活
			
			//将数据由输入层传到隐层 
			bpnn_layerforward(input_unites,hidden_unites,
				input_weights, n_in,n_hidden);
			//将隐层的输出传到输出层
			bpnn_layerforward(hidden_unites, output_unites,
				hidden_weights,n_hidden,n_out);
			
			//误差计算
			
			//将输出层的输出与理想输出比较计算输出层每个结点上的误差
			bpnn_output_error(output_deltas,target,output_unites,n_out);
			//根据输出层结点上的误差计算隐层每个节点上的误差
			bpnn_hidden_error(hidden_deltas,n_hidden, output_deltas, n_out,hidden_weights, hidden_unites);
			
			//权值调整
			//根据输出层每个节点上的误差来调整隐层与输出层之间的权值    
			bpnn_adjust_weights(output_deltas,n_out, hidden_unites,n_hidden,
				hidden_weights, hidden_prev_weights, eta, momentum); 
			//根据隐层每个节点上的误差来调整隐层与输入层之间的权值    	
			bpnn_adjust_weights(hidden_deltas, n_hidden, input_unites, n_in,
				input_weights, input_prev_weights, eta, momentum);  
			
			//误差统计		
			for(i=1;i<=n_out;i++)
				ex+=(output_unites[i]-data_out[k][i-1])*(output_unites[i]-data_out[k][i-1]);
		}
		//计算均方误差
		ex=ex/double(num*n_out);
		//如果均方误差已经足够的小,跳出循环,训练完毕  
		if(ex<min_ex)break;
	}
	
	//相关保存
	
	//保存输入层与隐层之间的权值
	w_weight(input_weights,n_in,n_hidden,"win.dat");
	//保存隐层与输出层之间的权值
	w_weight(hidden_weights,n_hidden,n_out,"whi.dat");
	
	//保存各层结点的个数
	w_num(n_in,n_hidden,n_out,"num");
	
	//显示训练结果
	
	CString str;
	if(ex<=min_ex)
	{
		str.Format ("迭代%d次,\n平均误差%.4f",l,ex);
		
		::MessageBox(NULL,str,"训练结果",NULL);
	}
	
	if(ex>min_ex)
	{
		
		str.Format("迭代%d次,平均误差%.4f\n我已经尽了最大努力了还是达不到您的要求\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 
****************************************/

void 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));
	
	//指向输入层数据的指针
	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);
	
	
	//读取权值
	if( r_weight(input_weights,n_in,n_hidden,"win.dat")==false)
		return;
	if(r_weight(hidden_weights,n_hidden,n_out,"whi.dat")==false)
		return;
	
	
	//逐个样本扫描
	for(k=0;k<num;k++)
	{ 
		//将提取的样本的特征向量输送到输入层上
		for(i=1;i<=n_in;i++)
			input_unites[i]=data_in[k][i-1];
		
		//前向输入激活
        bpnn_layerforward(input_unites,hidden_unites,
			input_weights, n_in,n_hidden);
        bpnn_layerforward(hidden_unites, output_unites,
			hidden_weights,n_hidden,n_out);
		
		//根据输出结果进行识别
		int result=0 ;
		//考察每一位的输出
		for(i=1;i<=n_out;i++)
		{
			//如果大于0.5判为1
			if(output_unites[i]>0.5)
				
				result+=(int)pow(2,double(4-i));
		}
		
		//如果判定的结果小于等于9,认为合理
		if(result<=9)
			recognize[k]=result;
		//如果判定的结果大于9,认为不合理将结果定位为一个特殊值20
		if(result>9)
			recognize[k]=20;
	}
	
	
	//将识别结果写到文本中
	FILE *fp;
	fp=fopen("result.txt","w+");
	
	for(i=0;i<num;i++)
	{  
		if(recognize[i]==20)
			fprintf(fp,"无法识别,");
		else
			fprintf(fp,"%d,",recognize[i]);
		
	}
	fclose(fp);
	
	//将识别的结果显示出来
	CString str,str1;
	for(i=0;i<num;i++)
	{
		if(recognize[i]!=20)
			str.Format("%d ",recognize[i]);
		
		if(recognize[i]==20)
			str.Format("无法识别 ");
		
		str1+=str;
	}
	
	//通知用户训练完成
	
	
	::MessageBox(NULL,str1,"识别结果",NULL);
	
	//释放存储空间
	free(input_unites);
	free(hidden_unites);
	free(output_unites);
	free(input_weights);
	free(hidden_weights);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -