图像模式识别之神经网络

#include "cv.h"
#include "highgui.h"
#include "utils.h"

#include<stack>

using namespace cv;
using namespace std;

#define PI 3.1415926
#define RADIAN(angle) ((angle)*PI/180.0)

//输入层到隐含层权值
double w[5][10]={{1.0087,-0.8205,0.05389,-0.0496,0.9122,0.9529,-0.1164,-1.159,0.1164,0.459},
				{0.7202,-0.1687,0.5822,1.0328,0.9833,0.8660,-0.8655,-0.2271,0.3685,-0.4271},
				{1.0656,1.3893,-0.4942,1.5207,-1.1254,-0.5841,0.9143,-1.2891,0.0143,0.2891},
				{-0.8710,-0.9764,-1.6356,0.3952,-0.5716,-1.1786,-1.3949,0.6398,0.3949,0.0998},
				{1.0087,-0.8205,0.05389,-0.0496,0.9122,0.9529,-0.1164,-1.159,0.4864,0.759}};
//隐含层到输出层权值
double w1[10][4]={{0.6762,-0.9607,-0.8025,0.0909},{0.3626,-0.2410,-0.5382,-0.7611},{0.6636,0.0056,-0.2765,-0.3734},
{0.4189,-0.1422,0.0956,0.3097},{-0.3908,-0.6207,0.4534,0.4855},{-0.6131,0.3644,0.2213,0.4040},{-0.1964,0.0792,-0.3945,0.0833},
{-0.6983,0.3958,-0.8677,0.4007},{0.6762,-0.9607,-0.8025,0.0909},{0.3626,-0.2410,-0.5382,-0.7611}};
//隐含层阈值
double b1[10]={-0.1293,1.06167,-0.0801,-0.1915,0.8152,0.0592,-0.7001,0.4053,0.7274,-0.1563};
//输出层阈值
double b2[4]={0.4712,-.2923,0.6773,0.4197};
//输入层到隐含层的权值学习率
double rate_w=0.05;
//隐含层到输出层的权值学习率
double rate_w1=0.047;
//隐含层阈值学习率
double rate_b1=0.05;
//输出层阈值学习率
double rate_b2=0.047;

struct pattern
{
	int number; //该类型数字样品个数
	double feature[200][25];//该类型数字样品特征,每个特征为25维
	pattern()
	{
		number=0;
	}
};

struct Position
{
	int bottom;
	int top;
	int left;
	int right;
};

pattern ptns[10]; //一共10个数字
double testsample[25]; //手写数字的特征 25维

//判断手写数字可否保存为cls类别的一个样品 同一类别不能有重复
bool savable(int cls)
{
	for(int i=0;i<ptns[cls].number;i++)
	{
		bool flag=true;
		for(int j=0;j<25;j++)
			flag&=(fabs(ptns[cls].feature[i][j]-testsample[j])<0.0000001 ? true:false);
		if(flag) return false;
	}

	return true;
}

//将手写数字保存为cls类别中的一个样品
void Save(int cls)
{
	for(int i=ptns[cls].number;i>0;i--)
		for(int j=0;j<25;j++)
			ptns[cls].feature[i][j]=ptns[cls].feature[i-1][j];

	for(int j=0;j<25;j++)
		ptns[cls].feature[0][j]=testsample[j];

	ptns[cls].number++;
}

//计算手写数字的在图片中出现的位置
Position GetPosition(Mat& mat)
{
	int M=mat.rows;
	int N=mat.cols;

	bool flag=false;
	int i,j;
	Position ret;

	//top
	for(i=0;i<M-1;i++)
	{
		flag=false;
		for(j=0;j<N;j++)
		{
			if(mat.at<uchar>(i,j)<128)
			{
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	ret.top=i;

	//bottom
	for(i=M-1;i>0;i--)
	{
		flag=false;
		for(j=0;j<N;j++)
		{
			if(mat.at<uchar>(i,j)<128)
			{
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	ret.bottom=i;

	//left
	for(j=0;j<N-1;j++)
	{
		flag=false;
		for(i=0;i<M;i++)
		{
			if(mat.at<uchar>(i,j)<128)
			{
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	ret.left=j;

	for(j=N-1;j>0;j--)
	{
		flag=false;
		for(i=0;i<M;i++)
		{
			if(mat.at<uchar>(i,j)<128)
			{
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	ret.right=j;

	return ret;
}

double Cal(int row,int col,Position pos,Mat& mat)
{
	int w,h;
	w=(pos.right-pos.left)/5;
	h=(pos.bottom-pos.top)/5;

	int count=0;

	for(int i=pos.top+row*h;i<pos.top+(row+1)*h;i++)
	{
		for(int j=pos.left+col*w;j<pos.left+(col+1)*w;j++)
		{
			if(mat.at<uchar>(i,j)<128)
				count++;
		}
	}
	return ((double)count)/(w*h);
}
//将手写数字特征保存在变量testsample中
void SetFeature(Mat& mat,Position pos)
{
	for(int i=0;i<5;i++)
	{
		for(int j=0;j<5;j++)
		{
			testsample[5*i+j]=Cal(i,j,pos,mat);
		}
	}
}

//神经网络
void train(double p[][5],double t[][4],int samplenum)
{
	double x[5],yd[4];
	double x1[10],o1[10],o2[4],x2[4];
	double error=0.00001;
	for(int n=0;n<samplenum;n++)
	{
		for(int i=0;i<5;i++)
			x[i]=p[n][i];
		for(int i=0;i<4;i++)
			yd[i]=t[n][i];

		//构造每个样本的输入和输出标准
		for(int j=0;j<10;j++)
		{
			o1[j]=0;
			for(int i=0;i<5;i++)
				o1[j]+=w[i][j]*x[i];
			x1[j]=1.0/(1+exp(-o1[j]-b1[j]));
		}

		for(int j=0;j<4;j++)
		{
			o2[j]=0.0;
			for(int i=0;i<10;i++)
				o2[j]+=w1[i][j]*x1[i];
			x2[j]=1.0/(1.0+exp(-o2[j]-b2[j]));
		}

		//计算误差
		double e;
		double qq[4],tjpt[4];
		double pp[10];
		for(int i=0;i<4;i++)
		{
			e=0.0;
			//希望输出误差与实际输出的偏差
			qq[i]=(yd[i]-x2[i])*x2[i]*(1-x2[i]);
			//均方差
			e+=fabs(yd[i]-x2[i])*fabs(yd[i]-x2[i]);
			//下一次隐含层到输出层之间的新权值
			for(int j=0;j<10;j++)
				w1[j][i]+=(rate_w1*qq[i]*x1[j]);
			e=sqrt(e);
			if(e<error)
				tjpt[i]=1;
		}
		for(int i=0;i<10;i++)
		{
			pp[i]=0.0;
			for(int j=0;j<4;j++)
				pp[i]+=qq[j]*w1[i][j];
			pp[i]=pp[i]*x1[i]*(1-x1[i]);
			//下一次输入层到隐含层之间的新权值
			for(int j=0;j<5;j++)
				w[j][i]+=rate_w*pp[i]*x[j];
		}

		for(int k=0;k<4;k++)
			b2[k]+=rate_b2*qq[k];
		for(int j=0;j<10;j++)
			b1[j]+=rate_b1*pp[j];
	}
}

void sim(double *psim,double* output)
{
	double x[5];
	for(int i=0;i<5;i++)
		x[i]=psim[i];
	double o1[10],x1[10];
	for(int j=0;j<10;j++)
	{
		o1[j]=0.0;
		for(int i=0;i<5;i++)
			o1[j]+=w[i][j]*x[i];
		x1[j]=1.0/(1.0+exp(-o1[j]-b1[j]));
	}
	double o2[4],x2[4];
	for(int k=0;k<4;k++)
	{
		o2[k]=0.0;
		for(int j=0;j<10;j++)
			o2[k]+=w1[j][k]*x1[j];
		x2[k]=1.0/(1.0+exp(-o2[k]-b2[k]));
	}

	for(int k=0;k<4;k++)
		output[k]=x2[k];
}

int main()
{
	//读取图像
	Mat image;

	//样本库特征提取
	int cls;
	char filename[100]="a.txt";
	char filePath[100];
	FILE* fp=fopen(filename,"r");
	while(fscanf(fp,"%d%s",&cls,filePath))
	{
		if(cls==-1)
			break;
		Mat image=imread(filePath,CV_LOAD_IMAGE_GRAYSCALE);
		Position pos=GetPosition(image);
		SetFeature(image,pos);
		if(savable(cls))
			Save(cls);
	}
	fclose(fp);

	image=imread("testsample.png",CV_LOAD_IMAGE_GRAYSCALE);
	//计算手写数字的位置
	Position pos=GetPosition(image);
	//计算手写数字的特征
	SetFeature(image,pos);

	printf("%d\n",Fisher());
	//cvNamedWindow("test",CV_WINDOW_AUTOSIZE);
	//imshow("test",image);

	waitKey(0);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值