若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/86612009
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
项目中有手写输入识别需求,转而研究手写输入算法。
zinnia是一个开源的手写识别库,采用C++实现,具有手写识别,学习以及文字模型数据制作转换等功能,且该库拥有较好的可移植性。
zinnia手写输入为用户笔画坐标作为一系列坐标数据,并输出按SVM置信度排序的n个最佳字符。
zinnia库具备以下特点:
下载地址:https://github.com/taku910/zinnia
(zinnia主页所指下载地址已经404…)
提供csdn下载地址:https://download.csdn.net/download/qq21497936/10934234
就这么轻松愉快的编译完了,如下图:
将其模块化,参照jpeglib的模块化方法:https://blog.csdn.net/qq21497936/article/details/86155043
为了给zinnia提供识别的基础数据,需要制作训练数据,训练数据用S表达式编写。一般而言,更多数据会产生更好的质量。到目前为止,百日草只支持批量训练,涉及到3个应用,如下:
(character (value あ) (width 300) (height 300) (strokes ((54 58)(249 68)) ((147 10)(145 201)(182 252)) ((224 103)(149 230)(82 240)(53 204)(86 149)(182 139)(240 172)(248 224)(228 250))))
(character (value い) (width 300) (height 300) (strokes ((56 63)(43 213)(67 259)(94 243)) ((213 66)(231 171)(208 217))))
(character (value う) (width 300) (height 300) (strokes ((102 35)(187 45)) ((73 121)(167 105)(206 139)(198 211)(135 275))))
(character (value え) (width 300) (height 300) (strokes ((140 19)(162 38)) ((62 105)(208 100)(51 263)(128 205)(188 268)(260 252))))
(character (value お) (width 300) (height 300) (strokes ((64 94)(240 98)) ((148 35)(159 129)(140 199)(105 247)(64 228)(101 161)(192 161)(222 223)(189 257)) ((223 49)(253 89))))
得到模型文件data.mode(二进制),至于多生成得data.mode.txt(文本文件)是一种独立于体系结构得格式,zinnia只能添加二进制文件,但是截图对比预留出来,以后也许用得到呢?
实际与模型文件格式类似,只是少了“(value う)”这一段,如下:
(character (width 300) (height 300) (strokes ((54 58)(249 68)) ((147 10)(145 201)(182 252)) ((224 103)(149 230)(82 240)(53 204)(86 149)(182 139)(240 172)(248 224)(228 250))))
(character (width 300) (height 300) (strokes ((56 63)(43 213)(67 259)(94 243)) ((213 66)(231 171)(208 217))))
(character (width 300) (height 300) (strokes ((102 35)(187 45)) ((73 121)(167 105)(206 139)(198 211)(135 275))))
(character (width 300) (height 300) (strokes ((140 19)(162 38)) ((62 105)(208 100)(51 263)(128 205)(188 268)(260 252))))
(character (width 300) (height 300) (strokes ((64 94)(240 98)) ((148 35)(159 129)(140 199)(105 247)(64 228)(101 161)(192 161)(222 223)(189 257)) ((223 49)(253 89))))
zinnia.exe -m data.model test.txt
使用模型”data.model”(二进制,非文本的),输入的文件为”test.txt”
由此,我们可以看出zinnia库识别的特点,应该是相似度,相似度越高越在前面,越低在越后面,那么风马牛不相及也有个相似度(负数),应该都能输出,我们取前面一部分(约5-10个)就好了,其实也可以取相似度,我们仔细查看识别出的数据特点,分析如下图:
所以根据数据特点,果断给这个下定义,认为就是相似度(阅读代码实际也是,相似得分)。
参照jpeglib测试demo:https://blog.csdn.net/qq21497936/article/details/86155043
参照jpeglib测试demo:https://blog.csdn.net/qq21497936/article/details/86155043
#include
#include "zinnia.h"
static const char *input =
"(character (width 1000)(height 1000)"
"(strokes ((243 273)(393 450))((700 253)(343 486)(280 716)(393 866)(710 880))))";
#pragma comment(lib, "libzinnia.lib")
int main(int argc, char **argv) {
zinnia::Recognizer *recognizer = zinnia::Recognizer::create();
if (!recognizer->open("D:\\compile\\zinnia\\Demo\\Debug\\data.model"))
{
std::cerr << recognizer->what() << std::endl;
return -1;
}
// 第一次识别(输入文件)
zinnia::Character *character = zinnia::Character::create();
if (!character->parse(input)) {
std::cerr << character->what() << std::endl;
return -1;
}
{
zinnia::Result *result = recognizer->classify(*character, 1);
if (!result)
{
std::cerr << recognizer->what() << std::endl;
return -1;
}
for (size_t i = 0; i < result->size(); ++i)
{
std::cout << "parse input i = " << i
<< " result = " << result->value(i)
<< "\t score = " << result->score(i) << std::endl;
}
delete result;
}
// 第二次识别(函数输入特征点)
character->clear();
character->set_width(300);
character->set_height(300);
character->add(0, 51, 29);
character->add(0, 117, 41);
character->add(1, 99, 65);
character->add(1, 219, 77);
character->add(2, 27, 131);
character->add(2, 261, 131);
character->add(3, 129, 17);
character->add(3, 57, 203);
character->add(4, 111, 71);
character->add(4, 219, 173);
character->add(5, 81, 161);
character->add(5, 93, 281);
character->add(6, 99, 167);
character->add(6, 207, 167);
character->add(6, 189, 245);
character->add(7, 99, 227);
character->add(7, 189, 227);
character->add(8, 111, 257);
character->add(8, 189, 245);
{
zinnia::Result *result = recognizer->classify(*character, 1);
if (!result)
{
std::cerr << recognizer->what() << std::endl;
return -1;
}
for (size_t i = 0; i < result->size(); ++i)
{
std::cout << "parase input i = " << i
<< " result = " << result->value(i)
<< "\t score = " << result->score(i) << std::endl;
}
delete result;
}
delete character;
delete recognizer;
getchar();
return 0;
}
如下图,模型只有5个,所以不准,框架搭好,下一步节主要研究数据模型:
https://download.csdn.net/download/qq21497936/10934243
(略)
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/86612009