思路:
识别的方法是获取一张测试图通过滤波,阈值分割前景与背景,边缘检测,查找轮廓,定位出数字,提取数字,由于提取的数字大小尺寸不一样且我们需要将图片的分割成5*5分块来计算欧氏距离,所以笔者统一将数字大小的尺寸规定为(250*250)然后通过计算获取的图片与样本图片进行欧氏距离计算,从而算出欧式距离最小该样本为其识别结果。
识别操作就是:
将提取的数字大小的尺寸重新定义其尺寸(250*250)后,将其分成5*5子块,则每一个子块占的像素点为:(250/5)*(250/5)= 2500个像素 然后计算每一个子块的所有像素值相加除于总的橡树点。例如计算某一个有2500个橡树的子块有1000个像素值为255 则该子块的所有的像素值相加为 255 * 1000 / 2500 为其分块的特征值。然后与样本的对应的分块进行欧式距离计算
即 得到欧式距离 与所有样本计算欧式距离,则最小的欧式距离为其识别结果
#include
#include
#include
#define N 5
using namespace cv;
using namespace std;
Mat testImage;
float getDistance(float a[N*N], float b[N*N])
{
int i;
float distance = 0;
for (i = 0; i < N*N; i++)
{
distance += (a[i] - b[i]) * (a[i] - b[i]);
}
return distance;
}
void getNumberFeature(Mat image, float a[N*N])
{
Mat temp = image.clone();
cvtColor(temp, temp, COLOR_RGB2GRAY);
blur(temp, temp, Size(3, 3));
threshold(temp, temp, 0, 255, THRESH_OTSU);
Canny(temp, temp, 3, 9, 3, true);
vector
vector
findContours(temp, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
vector
Mat temp_temp;
//其实contours.size() == 1 因为单个数字不包括10
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(contours[i], contours_poly[i], 3, false);
Rect ROI;
ROI = boundingRect(Mat(contours_poly[i]));
temp_temp.create(Size(ROI.width,ROI.height),temp.type());
temp(ROI).copyTo(temp_temp);
}
resize(temp_temp, temp_temp, Size(250, 250));
imshow("temp_temp", temp_temp);
int W, H;
W = 250;
H = 250;
for (int i = 0; i < N*N; i++)
a[i] = (float)0;
for (int i = 0; i < W; i++)
for (int j = 0; j < H; j++)
{
if (int(temp_temp.at
{
// printf("(%d,%d) = %d\n",j,i, (i / (W / 5) + j / (H / 5) * N) );
// if (i / (W / 5) + j / (H / 5) * N > 25)
// cout << "fail Erroe!" << endl;
a[i / (W / N) + j / (H / N) * N]++;
}
}
/******************************************/
for (int i = 0; i < N*N; i++)
{
a[i] = a[i] / ((W / N) * (H / N));
}
}
int getResultNumber()
{
int i;
float min;
int Number;
if (testImage.empty())
{
cout << "fail to read the test's Image!" << endl;
return false;
}
float testFeature[N*N];;
getNumberFeature(testImage, testFeature);
Mat srcImage[9];
float srcFeature[9][N*N];
/*************************读取模板图*****************************/
for (i = 0; i < 9; i++)
{
String filePath, fileName, allName;
filePath = "D:/detectNumber";
fileName = ".png";
// i+1 //
allName = filePath + "/" + format("%d", i + 1) + fileName;
srcImage[i] = imread(allName);
if (srcImage[i].empty())
{
printf("fail to read the the %d testImage!", i);
return false;
}
}
/*****************************************************************/
/*************************测试读取模板图是否成功*********************/
// for (int i = 0; i < 10; i++)
// {
// if (srcImage[i].empty())
// {
// printf("fail to read the %d testImage!", i);
// return false;
// }
// }
/*****************************************************************/
for (i = 0; i < 9; i++)
{
getNumberFeature(srcImage[i], srcFeature[i]);
}
float allDistanceValue[10] = { 0 };
/*****************************匹配操作*****************************/
for (i = 0; i < 9; i++)
{
allDistanceValue[i] = getDistance(testFeature, srcFeature[i]);
}
/******************************************************************/
Number = 0;
min = allDistanceValue[0];
for (i = 0; i < 9; i++)
{
if (min > allDistanceValue[i])
{
min = allDistanceValue[i];
Number = i;
}
}
for (i = 0; i < 9; i++)
{
printf("Distance[%d] = %f\n", i + 1, allDistanceValue[i]);
}
return Number + 1;
}
// 数字转字符串操作
string IntToStrig(int number)
{
ostringstream os;
os << number;
return os.str();
}
int main()
{
testImage = imread("D:/detectNumber/test.png");
int RusultNumber = getResultNumber();
/********************************************************图上标注操作********************************************************/
String Text;
Text = "detect Number:" + IntToStrig(RusultNumber);
Size TextSize;
int fontFace = FONT_HERSHEY_SIMPLEX;
double fontScale = 1;
int thickness = 1;
int LineType = LINE_4;
TextSize = getTextSize(Text, fontFace, fontScale, thickness, int());
putText(testImage, Text, Point(0, TextSize.height), fontFace, fontScale, Scalar(0, 0, 255), thickness, LineType, false);
/**************************************************************************************************************************/
imshow("数字识别操作", testImage);
waitKey(0);
}
效果图:
存在的问题:
①.由于数字样本图片少,不同的数字图片有可能会出现识别错误.
②.局限性在于不能检测到"数字十"