手写数字识别c++实现,opencv1.0

	【实验项目名称】
	手写数字特征提取方法与实现
	【实验目的】
	通过手写数字特征的提取,了解数字的特征提取方法,掌握特征匹配准则。
【实验原理】
读取标准化后的数字0~9,二值化,对每个数字进行等分区域分割,统计	每个区域内的黑色像素点的个数,即为特征初值。采用欧式距离的模板匹配			法判断数字。
【实验要求】
给定数字0-9的原始样本集合,每个数字都有10个大小为240*240的样本		图像。要求如下:
1、	将上述图像切分成标准图像库,存储为文件。
2、	对每个数字进行等分区间分割(分割区间至少大于等于10*10)
3、	给出统计结果:每个区域内的黑色像素点个数值以及占总量的百分	比,显示出计算结果。
4、	采用欧氏距离模板匹配法,给出识别结果。
5、	从统计意义上,给出每个数字的识别率。

具体步骤如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
使用vc++6.0以及opencv1.0实现,opencv需要提前进行环境配置。

// NumberReg.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "string.h"
#include "malloc.h"
#include "stdio.h"
#include<stdlib.h> 
#define M 14
#define N 14
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")
#pragma comment(lib,"cvaux.lib")
#pragma comment(lib,"cvcam.lib")
char* StandardStr(IplImage *img)//获取分块后的01字符串
{
	int wp=img->widthStep;
	char *str=(char *)malloc(M*N+1);//动态建立字符串。

	uchar *data=(uchar *)img->imageData;
	int count=0;//计数
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			if(data[2*i*wp+2*j]>127)
			{
				count++;
			}
			if(data[(2*i+1)*wp+2*j]>127)
			{
				count++;
			}
			if(data[2*i*wp+(2*j+1)]>127)
			{
				count++;
			}
			if(data[(2*i+1)*wp+(2*j+1)]>127)
			{
				count++;
			}
			if(count>1)//块里面像素值大于127的个数大于一半
			{
				str[i*M+j]='1';
			}
			else//块里面像素值大于127的个数小于一半
			{
				str[i*M+j]='0';
			}
			count=0;
		}
	
	}
	str[M*N]='\0';//字符串结尾
	return str;
}
void WriteStr(char* str,char *filename,FILE *fp,char *i,char *j)
{	
	remove(filename);
	//FILE *fp;
	if(fp==NULL)
	{
        puts("Fail to open file!");
    }
	else
	{
		char *str1=(char *)malloc(strlen(str)+3);
		strcpy(str1,i);
		strcat(str1,j);
		strcat(str1,str);
		fprintf(fp,"%s\n",str1);
	}
}
void train(int row)//获得要测试的数据
{
	remove("C:\\Users\\曹人\\Desktop\\train.txt");
	IplImage *img=0;
	FILE *fp;
	fp=fopen("C:\\Users\\曹人\\Desktop\\train.txt","a+");
	//地址
	for(int i=0;i<10;i++)
	{
		for(int j=0;j<10;j++)
		{	//获取数字0-9各10张图片
			char *address=(char *)malloc(sizeof("C:\\Users\\曹人\\Desktop\\手写数字数据集\\train-images\\")+10);
			char *a=(char *)malloc(1),*b=(char *)malloc(2);
			itoa(i,a,10);
			itoa(j+10*row,b,10);//取训练集当中的10开始的数字
			
			strcpy(address,	"C:\\Users\\曹人\\Desktop\\手写数字数据集\\train-images\\");
			strcat(address,a);
			strcat(address,"_");
			strcat(address,b);
			strcat(address,".bmp");
			img=cvLoadImage(address,0);
			WriteStr(StandardStr(img),"C:\\Users\\曹人\\Desktop\\train.txt",fp,a,b);
			free(address);
		}
	}
	fclose(fp);
}
void test()//获取标准化后数据
{
	IplImage *img=0;
	FILE *fp;
	remove("C:\\Users\\曹人\\Desktop\\test.txt");
	fp=fopen("C:\\Users\\曹人\\Desktop\\test.txt","a+");
	//地址
	for(int i=0;i<10;i++)
	{
		for(int j=10;j<100;j++)
		{	//获取数字0-9各10张图片
			char *address=(char *)malloc(sizeof("C:\\Users\\曹人\\Desktop\\手写数字数据集\\test-images\\")+10);
			char *a=(char *)malloc(1),*b=(char *)malloc(2);
			itoa(i,a,10);
			itoa(j,b,10);
			
			strcpy(address,	"C:\\Users\\曹人\\Desktop\\手写数字数据集\\test-images\\");
			strcat(address,a);
			strcat(address,"_");
			strcat(address,b);
			strcat(address,".bmp");
			img=cvLoadImage(address,0);
			WriteStr(StandardStr(img),"C:\\Users\\曹人\\Desktop\\test.txt",fp,a,b);
			free(address);
		}
	}
	fclose(fp);
}
char* ReadStr(FILE *fp,int i,int n)
{
	//FILE*fp;
	int CurrentIndex=0;
	char *StrLine=(char *)malloc(n);
	//fp = fopen(filename,"r+");
	fseek(fp,0,SEEK_SET);//指针调到最开始。
	if(fp == NULL) //判断文件是否存在及可读
    { 
        printf("error!"); 
        return NULL; 
    }
	while (!feof(fp)) 
    { 
    
        if (CurrentIndex==i)
        {
            fgets(StrLine,n,fp);  //读取一行
            printf("%s", StrLine); //输出
            return StrLine;
        }
        fgets(StrLine,n,fp); //读取一行,并定位到下一行
        CurrentIndex++;
    }
	return NULL;
}
void ShowImage(char *str)
{
	IplImage *img=cvLoadImage("C:\\Users\\曹人\\Desktop\\show.bmp",0);//存储结果的照片
	int wp=img->widthStep;
	uchar *data=(uchar *)img->imageData;
	int Inum=2;
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			data[2*i*wp+2*j]=(str[Inum]-'0')*255;//依次一个小块
			data[(2*i+1)*wp+2*j]=(str[Inum]-'0')*255;
			data[2*i*wp+(2*j+1)]=(str[Inum]-'0')*255;
			data[(2*i+1)*wp+(2*j+1)]=(str[Inum]-'0')*255;
			Inum++;
		}
	
	}
	/*for(int i=0;i<img->width;i++)
	{
		for(int j=0;j<img->height;j++)
		{
			if(data1[i*wp+j]>0)
			{
				data1[i*wp+j]=255;
			}
			printf("%d",data1[i*wp+j]/255);
		}
		printf("\n");
	}*/
	cvNamedWindow("First", 0);
	cvShowImage("First", img);
	cvWaitKey(0);	
}
double Odistance(char *num,char *rightNum)//求欧氏距离
{
	int Sq=0;
	for(int i=3;rightNum[i]!='\n';i++)
	{
		int a=num[i-1]-'0';//需要被识别的数字。
		//int a=num[i]-'0';
		int b=rightNum[i]-'0';
		Sq+=(a-b)*(a-b);
	}
	return sqrt(Sq);
}
bool JudgeImage(char *Number,FILE *fp,int n)//遍历每一个测试集的图片。
{
	double minDistance=100000.0;//记录最短欧氏距离。
	char rightNumber;//识别出的数字
	char location;//识别出的数字的位置。
	char *StrLine=(char *)malloc(n);
	fseek(fp,0,SEEK_SET);//指针调到最开始。
	if(fp == NULL) //判断文件是否存在及可读
    { 
        printf("error!"); 
        return NULL; 
    }
	while (!feof(fp)) 
    { 
        fgets(StrLine,n,fp); //读取一行,并定位到下一行
		double temp=Odistance(Number,StrLine);
		if(minDistance>temp)//当找到一个更接近的就更换原来的数。
		{
			rightNumber=StrLine[0];
			location=StrLine[1];
			minDistance=temp;
		}
    }
	if(rightNumber==Number[0])
	{
		printf("第几行%c\n",rightNumber);
		printf("第几列%c\n",location);
		return true;
	}
	printf("识别错误,识别的是%c,第%c个\n",rightNumber,location);
	return false;
}
int main(int argc, char* argv[])
{
	/*IplImage *img=0;
	//地址
	for(int i=0;i<10;i++)
	{
		for(int j=0;j<10;j++)
		{	//获取数字0-9各10张图片
			char *address=(char *)malloc(sizeof("C:\\桌面\\手写数字数据集\\train-images\\")+10);
			char *a=(char *)malloc(1),*b=(char *)malloc(1);
			itoa(i,a,10);
			itoa(j,b,10);
			
			strcpy(address,	"C:\\桌面\\手写数字数据集\\train-images\\");
			strcat(address,a);
			strcat(address,"_");
			strcat(address,b);
			strcat(address,".bmp");
			img=cvLoadImage(address,0);
			WriteStr(StandardStr(img,14,14),"C:\\桌面\\train.txt",a,b);
			free(address);
		}
	}*/
	int row=0;
	train(row);//训练集。
	test();
	/*FILE *fp;
	fp=fopen("C:\\Users\\曹人\\Desktop\\test.txt","r");
	ShowImage(ReadStr(fp,48,200));//展现需要的图片。
	fclose(fp);*/
	FILE *fpTrain;
	FILE *fpTest;
	fpTrain=fopen("C:\\Users\\曹人\\Desktop\\train.txt","r");
	fpTest=fopen("C:\\Users\\曹人\\Desktop\\test.txt","r");
	int Tnum=0;
	int i=0;
	int Dinum[11]={0};
	for(i=0;i<100;i++)
	{
		//ShowImage(ReadStr(fpTest,i,201));//展现压缩后的的图片。
		if(JudgeImage(ReadStr(fpTrain,i,202),fpTest,201))
		{
			Dinum[i/10]++;
			Tnum++;
		}
	}
	for(i=0;i<10;i++)
	{
		printf("数字%d的正确率为%d%%\n",i,Dinum[i]*10);
	}
	printf("\n\n");
	printf("总的正确率%d%%",Tnum);
	//printf("%d",JudgeImage(ReadStr(fpTrain,99,201),fpTest,200));	
	fclose(fpTrain);
	fclose(fpTest);
	/*for(int i=0;i<img->width;i++)
	{
		for(int j=0;j<img->height;j++)
		{
			if(data1[i*wp+j]>0)
			{
				data1[i*wp+j]=255;
			}
			printf("%d",data1[i*wp+j]/255);
		}
		printf("\n");
	}*/
	//cvNamedWindow("First", 0);
	//cvShowImage("First", img);
	//cvWaitKey(0);
	return 0;
}

注意文件存放的位置

附件如下链接:
https://pan.baidu.com/s/1W4CIVKlptYX00rqbx46xFA
提取码:kzcp

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个非常有趣的问题。MNIST是一个非常著名的手写数字数据集,用于测试机器学习算法的性能。在C++中,我们可以使用OpenCV库来读取和处理图像数据,并使用机器学习库(如TensorFlow)来构建数字识别模型。下面是一个基本的MNIST手写数字识别示例: 1. 首先,我们需要下载MNIST数据集,可以从官方网站下载:http://yann.lecun.com/exdb/mnist/ 2. 接下来,我们需要使用OpenCV库来读取图像数据。可以使用以下代码: ``` cv::Mat image = cv::imread("mnist_image.png", CV_LOAD_IMAGE_GRAYSCALE); ``` 这将读取图像数据并将其转换为灰度图像。 3. 然后,我们需要将图像数据转换为适合机器学习算法的格式。可以使用以下代码: ``` cv::Mat_<float> image_data = image.reshape(1, 1); image_data /= 255.0f; ``` 这将将图像数据转换为一个浮点数矩阵,并将其归一化为0到1之间的值。 4. 接下来,我们可以使用机器学习库来构建数字识别模型。这里假设我们使用TensorFlow库。可以使用以下代码: ``` tensorflow::GraphDef graph_def; tensorflow::Session* session; tensorflow::SessionOptions session_options; tensorflow::ReadBinaryProto(tensorflow::Env::Default(), "mnist_model.pb", &graph_def); session_options.config.mutable_gpu_options()->set_allow_growth(true); session = tensorflow::NewSession(session_options); tensorflow::Status status = session->Create(graph_def); ``` 这将读取预训练的数字识别模型,并创建一个TensorFlow会话。 5. 最后,我们可以使用以下代码来预测图像中的数字: ``` tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, 784})); auto input_tensor_mapped = input_tensor.tensor<float, 2>(); for (int i = 0; i < 784; i++) { input_tensor_mapped(0, i) = image_data(0, i); } std::vector<tensorflow::Tensor> output_tensors; tensorflow::Status status = session->Run({{"input", input_tensor}}, {"output"}, {}, &output_tensors); float* prediction = output_tensors[0].flat<float>().data(); ``` 这将将图像数据输入到数字识别模型中,并返回一个浮点数数组,表示每个数字的概率。我们可以选择具有最高概率的数字作为预测结果。 希望这个示例可以帮助你了解如何在C++中基于OpenCV实现MNIST手写数字识别

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值