利用opencv识别数字思路篇

Home / C++ MrLee 2016-10-27 4356

看了一些数字识别的文章,研究了一翻得到一些心得,这里就不保留完全写上来!
博主原来做游戏辅助也有数字识别,当时用的是特征码技术,这种技术识别2D的数字还是非常准确的,因为2D游戏数字像素点很纯,比如字体是纯白色,然后R,G,B都是255,那我只取255,255,255指定区域的所有像素,然后生成一个数字特征码,比如0就是"62226"表示0,"02810"表示1,"43333"表示2,这个特征码就是图片像素的宽和高中取得对应坐标的白色像素点。
但如果用于有锯齿或者有渐变的游戏数字就识别不了了,因为这个针对性太强了,一对一。不过也不怕,也有解决方案。我们可以把数字二值化,然后取得各数字的像素和,0~9的像素和各不一样,后期就按这个像素和来判断是哪个数字。这种方法不仅高效,而且准确性也相当不错。当然前提是字体和大小都一样,如果不一样的话,那肯定也不自然不准了。
思想就这些,实现方法百度一查就一大堆,我这里就不写了。几十行代码的事儿!
void COpenCv::IdenNumer(void)
{
	//数字识别流程处理,方案:首先二值化取出所有的数字,然后切割每个一数字,
	//求每个数字的像素平方和(就是所有像素总和)去对应模板数字的总和,相差最小的应该就是对应的数字了
	IplImage* src = cvLoadImage("20131112221252453.png",CV_LOAD_IMAGE_GRAYSCALE);//CV_LOAD_IMAGE_GRAYSCALE加载灰度图
	//对大于dThreshold的像素值进行截断,大于dThreshold则为255,不大于dThreshold的为原值
	cvThreshold(src,src,0,255,CV_THRESH_OTSU);//二值化处理CV_THRESH_OTSU适用于局部颜色色差大
	//接下来找到轮廓
	CvMemStorage *pStore = cvCreateMemStorage();//创建一个内存存储器
	CvSeq *pOut = NULL;//CvSeq本身就是一个可增长的序列,不是固定的序列
	cvFindContours(src,pStore,&pOut,sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);//从二值位图找轮廓
	//cvFindContours(img,pStore,&pOut,sizeof(CvContour),CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	//填充所有轮廓
	cvDrawContours(src, pOut, CV_RGB(255,255,255),CV_RGB(255,255,255), 2, CV_FILLED, 8, cvPoint(0, 0));
	vector<Mimg> vec;
	while(pOut)
	{
		CvRect rect = cvBoundingRect(pOut,0);
		//绘制出每个数字的轮廓
		//cvRectangle(src, cvPoint(rect.x, rect.y), cvPoint(rect.x + rect.width, rect.
		//	y + rect.height),CV_RGB(255,255,255), 1, 1, 0);
		cvSetImageROI(src,rect);
		IplImage* dst = cvCreateImage(cvSize(rect.width,rect.height),src->depth,src->nChannels);
		cvCopy(src,dst);
		cvResetImageROI(src);
		Mimg img = {rect,dst};
		vec.push_back(img);
		pOut = pOut->h_next;//下一个值
	}
	//这里按坐标从左到右排序
	std::sort(vec.begin(),vec.end(),SortFunc);//排序
	for (vector<Mimg>::iterator it=vec.begin();it!=vec.end();it++)
	{
		//从左右到识别
	}
	cvReleaseMemStorage(&pStore);
	pStore = NULL;
	//cvShowImage("",src);
	cvReleaseImage(&src);
}

 

本文链接:https://www.it72.com/11137.htm

推荐阅读
最新回复 (0)
返回