Pre-processing before digit recognition with KNN classifier
现在我正在尝试使用OpenCV创建数字识别系统。Web中有许多文章和示例(甚至在StackOverflow中)。我决定使用knn分类器,因为这个解决方案在web中最流行。我发现了一个手写数字的数据库,其中有一组60k个例子,错误率小于5%。
我使用本教程作为如何使用OpenCV处理此数据库的示例。我使用的技术和测试数据完全相同(
- 为7。
- 和被认为是5。
- 和被确认为1。
- 为8。
等等(如果需要,我可以上传所有图片)。
正如你所看到的,所有的数字都有很好的质量,很容易被人识别。
所以我决定在分类之前做一些预处理。从mnist数据库站点的表中,我发现人们正在使用去纸、噪声消除、模糊和像素移动技术。不幸的是,几乎所有的文章链接都被破坏了。所以我决定自己做这样的预处理,因为我已经知道怎么做了。
现在,我的算法如下:
我认为在我的情况下不需要脱皮,因为所有的数字都是正常旋转的。我也不知道如何找到一个直角。在这之后,我得到了这些图像:
- 也是1
- 是3(不是以前的5)
- 为5(非8)
- 为7(利润!)
所以,这样的预处理对我有点帮助,但我需要更好的结果,因为在我看来,这些数字应该毫无问题地被识别出来。
有人能给我一些关于预处理的建议吗?谢谢你的帮助。
P.S.我可以上传我的源代码(C++)。
我意识到我的错误-这不是连通与预处理在所有(的davidbrown和约翰@ @)。使用的数据集从一handwritten学院数字印刷(capitalized)。我不喜欢在网上搜索数据库,所以我决定创建自己的。我有我的数据库上传到谷歌。
在这里你可以怎么使用它(列车和主分类表):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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); } |
5 &;6,7,9 1 &;&;八是公认的为一类,因为中央点是非常相似的。这个呢?
- 应用连通分量标记位的方法。因此,真正的边界和边界图像进行作物数过。那么,你想要更多的正确的工作区和中央点是标准化。
- 然后分为两个位的horizontally配件。(例如你想界划分后有两个"8")
As a result,"9"、"8"更可识别的现代建筑物的工作人员"5"和"6"。上下配件配件将是相同的,但不同的。
我可以给你一个更好的答案需要比你自己的答案,但我想以一个建议。你可以提高你的数字识别系统在以下的方式:
在白色和黑色的应用补丁的骨架化过程。
这之后,将距离变换。
在这种方式,你可以提高分类器的结果是不准确的,当数为中心或他们是不完全一样的,morphologically说。