Art*_*huk 13 c++ opencv image-processing image-recognition knn
现在我正在尝试使用OpenCV创建数字识别系统.WEB中有很多文章和例子(甚至在StackOverflow上).我决定使用KNN分类器,因为这个解决方案在WEB中最受欢迎.我找到了一个手写数字数据库,训练集为60k,错误率低于5%.
我使用本教程作为如何使用OpenCV使用此数据库的示例.我使用完全相同的技术和测试数据(t10k-images.idx3-ubyte)我有4%的错误率.但是当我尝试对自己的数字进行分类时,我会遇到更大的错误.例如:
被认定为7
和
被认可为5
和
被认定为1
被认可为8等等(如果需要,我可以上传所有图像).
正如您所看到的,所有数字都具有良好的质量,并且易于识别.
所以我决定在分类之前做一些预处理.从上表MNIST数据库的网站,我发现人们使用歪斜校正,去除噪声,模糊和像素移位技术.不幸的是,几乎所有文章的链接都被打破了.所以我决定自己做这样的预处理,因为我已经知道如何做到这一点.
现在,我的算法如下:
我认为在我的情况下不需要去偏移,因为所有数字通常都是旋转的.而且我也不知道如何找到合适的旋转角度.所以在这之后我得到了这些图像:
也是1
是3(以前不是5)
是5(不是8)
是7(利润!)所以,这样的预处理对我有所帮助,但我需要更好的结果,因为在我看来,这些数字应该被认可而没有问题.
任何人都可以通过预处理给我任何建议吗?谢谢你的帮助.
PS我可以上传我的源代码(c ++)代码.
我意识到我的错误 - 它根本与预处理无关(感谢@DavidBrown和@John)。我使用手写的数字数据集而不是打印的(大写的)。我在网上没有找到这样的数据库,所以我决定自己创建一个。我已将我的数据库上传到Google Drive。
以下是如何使用它(训练和分类):
int digitSize = 16;
//returns list of files in specific directory
static vector<string> getListFiles(const string& dirPath)
{
vector<string> result;
DIR *dir;
struct dirent *ent;
if ((dir = opendir(dirPath.c_str())) != NULL)
{
while ((ent = readdir (dir)) != NULL)
{
if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0 )
{
result.push_back(ent->d_name);
}
}
closedir(dir);
}
return result;
}
void DigitClassifier::train(const string& imagesPath)
{
int num = 510;
int size = digitSize * digitSize;
Mat trainData = Mat(Size(size, num), CV_32FC1);
Mat responces = Mat(Size(1, num), CV_32FC1);
int counter = 0;
for (int i=1; i<=9; i++)
{
char digit[2];
sprintf(digit, "%d/", i);
string digitPath(digit);
digitPath = imagesPath + digitPath;
vector<string> images = getListFiles(digitPath);
for (int j=0; j<images.size(); j++)
{
Mat mat = imread(digitPath+images[j], 0);
resize(mat, mat, Size(digitSize, digitSize));
mat.convertTo(mat, CV_32FC1);
mat = mat.reshape(1,1);
for (int k=0; k<size; k++)
{
trainData.at<float>(counter*size+k) = mat.at<float>(k);
}
responces.at<float>(counter) = i;
counter++;
}
}
knn.train(trainData, responces);
}
int DigitClassifier::classify(const Mat& img) const
{
Mat tmp = img.clone();
resize(tmp, tmp, Size(digitSize, digitSize));
tmp.convertTo(tmp, CV_32FC1);
return knn.find_nearest(tmp.reshape(1, 1), 5);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4338 次 |
| 最近记录: |