-
-
Save selvypen/a27ca8368bde62f370effc634b4ed9de to your computer and use it in GitHub Desktop.
Simple example source of handwriting recognition for Windows using C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* @brief example source of handwriting recognition | |
* @date 2019/12/03 | |
* @file handwriting_simple_example.cpp | |
* @author SELVAS AI | |
* | |
* Copyright 2019. SELVAS AI Inc. All Rights Reserved. | |
*/ | |
#include <stdio.h> | |
#include <locale.h> | |
#include "dhwr.h" | |
#define log(...) printf(__VA_ARGS__) | |
// points of 'a' | |
// -1, 0 : end of stroke | |
// -1, -1 : end of ink | |
// (x0, y0), (x1, y1), ... (-1, 0) ... (xn, yn) .... (-1, 0), (-1, -1) | |
const int ink_a[] = {271, 97, 270, 95, 266, 94, 262, 94, 256, 94, 249, 94, 243, 96, 234, 100, 226, | |
107, 216, 118, 208, 127, 203, 137, 195, 147, 191, 156, 188, 163, 188, 169, 188, 172, 191, 175, | |
195, 176, 202, 176, 210, 176, 218, 176, 227, 173, 237, 170, 246, 166, 253, 161, 258, 156, 261, | |
153, 264, 148, 265, 144, 267, 139, 267, 135, 268, 131, 268, 128, 268, 123, 268, 122, 268, 120, | |
268, 117, 268, 116, 268, 119, 273, 126, 278, 133, 284, 140, 291, 145, 294, 150, 299, 153, 301, | |
156, 303, 159, 306, 160, 307, 163, 308, 163, -1, 0, -1, -1}; | |
// points of 'good morning' | |
const int ink_good_morning[] = {242, 382, 233, 372, 209, 385, 176, 425, 174, 438, 195, 447, 216, | |
427, 223, 411, 231, 379, 233, 382, 233, 405, 234, 456, 232, 512, 227, 534, 200, 569, 167, 569, 154, | |
543, 161, 513, 173, 500, 220, 476, 266, 464, 278, 458, 282, 458, -1, 0, 303, 398, 292, 403, 285, | |
426, 307, 437, 319, 430, 330, 397, 311, 385, 291, 391, 297, 401, -1, 0, 369, 383, 363, 386, 358, | |
415, 385, 421, 411, 402, 418, 388, 406, 370, 372, 380, 362, 402, 368, 406, -1, 0, 496, 385, 497, | |
384, 495, 377, 471, 383, 457, 391, 438, 418, 463, 424, 482, 416, 510, 386, 516, 343, 511, 315, | |
508, 302, 510, 306, 513, 336, 518, 384, 528, 419, 534, 425, 533, 419, -1, 0, 626, 365, 629, 370, | |
633, 392, 635, 405, 634, 421, 630, 420, 638, 389, 644, 378, 658, 371, 671, 393, 673, 412, 673, 416, | |
673, 409, 678, 389, 684, 378, 704, 366, 715, 377, 720, 397, 723, 409, 723, 411, 725, 409, 730, 402, | |
-1, 0, 756, 374, 750, 375, 749, 401, 776, 400, 788, 391, 797, 373, 766, 366, 750, 373, 763, 375, | |
-1, 0, 814, 350, 814, 347, 823, 358, 836, 390, 838, 406, 835, 409, 833, 397, 837, 389, 855, 368, | |
875, 356, 894, 354, 900, 355, 899, 365, -1, 0, 911, 342, 917, 357, 916, 370, 918, 398, 917, 401, | |
917, 384, 929, 351, 946, 341, 955, 354, 958, 366, 961, 389, 964, 401, 959, 380, -1, 0, 983, 327, | |
991, 326, 1005, 330, 1005, 338, -1, 0, 991, 362, 992, 366, 999, 393, 1001, 400, -1, 0, 1032, 344, | |
1039, 350, 1045, 376, 1046, 396, 1049, 388, 1053, 378, 1067, 355, 1079, 352, 1086, 374, 1092, 398, | |
1095, 404, 1097, 403, 1099, 398, -1, 0, 1146, 345, 1149, 350, 1140, 356, 1127, 375, 1142, 384, | |
1160, 359, 1155, 342, 1151, 343, 1164, 366, 1180, 403, 1181, 439, 1176, 457, 1153, 486, 1113, 488, | |
1089, 463, 1101, 443, 1116, 434, 1162, 417, 1219, 409, 1229, 416, 1228, 417, -1, 0, -1, -1}; | |
// points of '4' | |
const int ink_4[] = {273, 69, 270, 72, 267, 78, 261, 88, 253, 103, 245, 115, 236, 127, 231, 137, 227, | |
144, 226, 146, 230, 146, 238, 146, 252, 146, 271, 145, 291, 143, 313, 141, 329, 139, 341, 137, | |
352, 137, 358, 137, 362, 137, 364, 136, -1, 0, 300, 105, 300, 106, 300, 112, 298, 121, 298, 132, | |
296, 143, 296, 154, 296, 163, 296, 169, 296, 177, 296, 181, 295, 186, 295, 189, 295, 190, -1, 0, | |
-1, -1}; | |
// points of '안녕하세요' | |
const int ink_annyeonghaseyo[] = {182, 315, 185, 316, 183, 316, 182, 318, 180, 320, 173, 330, 159, | |
356, 149, 384, 149, 406, 157, 426, 175, 440, 200, 451, 230, 446, 250, 431, 259, 411, 268, 384, | |
266, 357, 258, 341, 244, 330, 229, 327, 215, 326, 204, 328, 195, 332, 192, 339, -1, 0, 357, | |
269, 355, 268, 355, 271, 354, 281, 355, 317, 359, 360, 363, 403, 365, 430, 364, 443, 362, 443, | |
-1, 0, 363, 377, 368, 370, 371, 370, 381, 370, 400, 371, 424, 376, 431, 377, -1, 0, 275, 502, | |
270, 504, 268, 508, 267, 515, 268, 527, 272, 541, 281, 556, 299, 571, 324, 575, 357, 569, 387, | |
555, 408, 533, -1, 0, 506, 301, 498, 296, 497, 302, 492, 327, 484, 364, 479, 401, 478, 432, | |
482, 453, 489, 467, 502, 470, 518, 471, 551, 468, 571, 454, 574, 450, -1, 0, 552, 334, 554, | |
319, 559, 323, 574, 320, 604, 317, 635, 315, 650, 316, 659, 320, 656, 322, -1, 0, 591, 377, | |
589, 377, 598, 375, 622, 371, 650, 363, 678, 353, 683, 348, -1, 0, 701, 300, 698, 300, 697, | |
301, 696, 307, 694, 318, 692, 347, 688, 378, 682, 412, 678, 442, 678, 449, -1, 0, 621, 515, | |
606, 520, 603, 526, 600, 536, 602, 546, 616, 558, 649, 562, 674, 556, 682, 546, 679, 538, 666, | |
531, 621, 518, 594, 526, -1, 0, 790, 282, 789, 278, 789, 279, 790, 282, 799, 288, 829, 304, | |
854, 318, 871, 330, 872, 331, -1, 0, 793, 386, 787, 383, 786, 383, 785, 384, 792, 384, 827, | |
385, 861, 385, 878, 387, -1, 0, 828, 436, 807, 448, 796, 457, 783, 471, 777, 487, 778, 501, | |
790, 506, 825, 507, 847, 496, 851, 487, 850, 477, 844, 471, 830, 465, 804, 460, 792, 459, -1, | |
0, 937, 294, 936, 290, 935, 292, 933, 298, 931, 315, 930, 359, 931, 407, 935, 453, 939, 488, | |
942, 518, 942, 536, 939, 550, 936, 554, -1, 0, 939, 408, 946, 399, 947, 402, 967, 401, 997, | |
402, 1013, 405, -1, 0, 1145, 319, 1134, 315, 1135, 318, 1129, 326, 1105, 362, 1080, 403, 1058, | |
446, 1041, 476, 1030, 496, 1030, 494, -1, 0, 1069, 430, 1071, 425, 1073, 427, 1079, 433, 1092, | |
449, 1106, 471, 1114, 486, -1, 0, 1106, 416, 1104, 404, 1116, 407, 1146, 403, 1179, 399, 1206, | |
391, 1209, 389, -1, 0, 1228, 352, 1225, 357, 1224, 361, 1222, 374, 1222, 404, 1223, 431, 1226, | |
452, 1226, 466, 1225, 463, -1, 0, 1269, 345, 1268, 343, 1267, 347, 1265, 360, 1265, 398, 1267, | |
434, 1269, 466, 1272, 484, 1276, 490, -1, 0, 1373, 342, 1369, 342, 1368, 345, 1368, 354, 1372, | |
366, 1382, 376, 1404, 385, 1431, 377, 1445, 360, 1451, 334, 1446, 321, 1432, 321, 1400, 326, | |
1369, 341, 1358, 359, 1353, 380, 1357, 402, 1363, 421, 1370, 440, 1376, 459, 1377, 479, 1374, | |
497, 1369, 509, 1363, 516, 1361, 514, -1, 0, 1426, 413, 1432, 407, 1432, 408, 1434, 416, 1429, | |
442, 1413, 476, 1388, 503, 1358, 526, 1334, 534, 1319, 536, 1318, 533, 1342, 523, 1417, 503, | |
1477, 495, 1525, 497, -1, 0, -1, -1}; | |
// points of '中囯' | |
const int ink_zhongguo[] = {54, 72, 53, 72, 52, 73, 52, 75, 52, 80, 52, 83, 52, 87, 52, 89, 52, | |
95, 52, 98, 52, 101, 51, 104, 51, 106, 51, 109, 51, 111, 51, 114, 51, 116, 51, 118, 51, | |
121, 51, 122, 51, 123, 51, 120, 51, 117, 50, 114, -1, 0, 51, 81, 52, 81, 53, 81, 54, 81, | |
55, 81, 56, 81, 59, 81, 60, 81, 64, 80, 68, 79, 71, 78, 76, 78, 81, 76, 86, 75, 96, 74, | |
99, 74, 104, 73, 110, 72, 113, 72, 117, 71, 119, 71, 123, 70, 125, 70, 127, 70, 127, 69, | |
128, 69, 129, 69, 129, 70, 129, 71, 129, 73, 129, 75, 129, 78, 129, 81, 129, 84, 129, 87, | |
129, 90, 129, 94, 129, 95, 129, 97, 129, 98, 129, 101, 129, 102, 129, 103, 129, 104, 129, | |
105, 128, 106, 127, 106, 124, 106, -1, 0, 47, 114, 48, 114, 49, 114, 50, 114, 53, 114, 55, | |
114, 56, 114, 58, 114, 61, 114, 66, 114, 70, 113, 75, 112, 82, 112, 87, 111, 96, 108, 104, | |
108, 111, 107, 119, 106, 123, 106, 126, 105, 130, 105, 131, 104, 132, 104, 133, 104, 133, | |
103, 132, 101, -1, 0, 82, 30, 82, 31, 82, 32, 82, 34, 82, 38, 82, 39, 82, 41, 82, 46, 82, | |
48, 82, 52, 82, 54, 82, 58, 82, 63, 82, 67, 82, 69, 82, 75, 82, 78, 82, 83, 82, 87, 82, | |
91, 82, 95, 82, 98, 82, 102, 82, 105, 82, 110, 82, 113, 82, 116, 82, 120, 82, 124, 82, | |
128, 82, 131, 82, 134, 82, 137, 82, 139, 82, 141, 82, 146, 82, 147, 82, 148, 82, 149, 82, | |
150, 82, 151, 82, 152, 82, 153, 82, 154, 82, 155, 82, 156, 82, 157, 81, 157, 81, 155, 81, | |
152, 81, 149, -1, 0, 165, 51, 166, 54, 166, 59, 167, 64, 167, 71, 167, 76, 167, 83, 167, | |
90, 167, 96, 167, 105, 167, 110, 167, 114, 167, 118, 167, 122, 167, 125, 167, 130, 167, | |
133, 167, 135, 167, 137, 167, 138, 167, 140, 167, 138, 167, 132, 167, 129, -1, 0, 168, | |
60, 169, 60, 170, 60, 171, 60, 174, 60, 175, 60, 176, 60, 177, 60, 178, 60, 180, 60, 181, | |
60, 185, 59, 189, 59, 193, 59, 199, 58, 205, 55, 209, 54, 211, 53, 217, 52, 220, 51, 222, | |
51, 224, 51, 225, 51, 226, 51, 227, 51, 228, 50, 229, 50, 231, 50, 232, 50, 233, 50, 234, | |
50, 235, 51, 235, 53, 235, 55, 235, 56, 237, 57, 237, 60, 237, 63, 237, 64, 238, 67, 238, | |
69, 238, 73, 238, 75, 238, 80, 238, 82, 238, 86, 238, 88, 238, 94, 238, 96, 238, 99, 238, | |
103, 238, 106, 238, 110, 238, 112, 238, 116, 238, 117, 238, 119, 238, 123, 238, 125, 238, | |
126, 238, 129, 238, 130, 238, 132, 238, 134, 238, 135, 238, 136, 238, 137, 237, 135, 234, | |
131, 231, 129, 225, 124, -1, 0, 176, 90, 177, 90, 178, 90, 179, 90, 180, 90, 181, 90, 182, | |
89, 183, 89, 185, 87, 188, 87, 190, 86, 192, 85, 194, 84, 196, 84, 197, 83, 198, 83, 199, | |
83, 200, 83, 201, 83, 202, 83, 204, 83, 205, 83, 206, 83, 206, 82, -1, 0, 180, 109, 181, | |
109, 182, 109, 183, 109, 184, 109, 186, 109, 188, 109, 190, 109, 192, 109, 197, 107, 199, | |
107, 200, 107, 202, 107, 203, 106, 205, 106, 205, 105, -1, 0, 191, 86, 192, 86, 192, 89, | |
192, 90, 193, 92, 193, 93, 193, 96, 193, 98, 193, 100, 194, 103, 194, 105, 194, 106, 194, | |
108, 194, 110, 194, 111, 194, 114, 194, 115, 194, 116, 194, 118, 194, 120, 194, 122, 194, | |
123, 194, 124, 194, 125, -1, 0, 183, 129, 184, 129, 185, 129, 186, 129, 187, 129, 188, | |
129, 190, 128, 193, 127, 195, 127, 198, 126, 201, 125, 202, 124, 206, 123, 207, 123, 209, | |
123, 210, 123, 211, 123, 212, 123, 213, 123, 213, 122, -1, 0, 218, 93, 218, 94, 219, 94, | |
220, 96, 221, 96, 221, 98, 221, 99, 223, 99, 223, 101, 224, 102, 225, 103, 225, 105, 226, | |
106, 227, 107, 227, 108, 227, 109, -1, 0, 169, 146, 170, 146, 171, 146, 172, 146, 176, 146, | |
181, 145, 187, 145, 192, 143, 197, 143, 203, 142, 206, 142, 208, 141, 210, 141, 211, 141, | |
212, 141, 213, 141, 213, 140, 214, 140, 215, 140, 216, 140, 217, 140, 218, 140, 219, 140, | |
221, 140, 223, 140, 224, 140, 225, 140, 226, 140, -1, 0, -1, -1}; | |
// points of 'ありがとう' | |
const int ink_arigatou[] = {272, 331, 265, 338, 311, 340, 400, 328, 455, 306, 470, 282, -1, 0, 354, | |
236, 342, 243, 342, 305, 357, 394, 374, 462, 386, 499, 384, 479, -1, 0, 444, 350, 435, 388, 416, | |
412, 349, 454, 299, 459, 278, 439, 325, 391, 411, 373, 457, 392, 456, 452, 451, 463, 455, 454, -1, | |
0, 569, 310, 570, 327, 571, 365, 570, 380, 569, 370, -1, 0, 619, 280, 620, 280, 632, 309, 639, 357, | |
638, 386, 620, 447, 591, 505, 585, 516, 596, 489, -1, 0, 706, 315, 705, 310, 735, 308, 794, 308, | |
827, 327, 826, 388, 808, 437, 790, 459, 785, 441, -1, 0, 816, 251, 803, 248, 772, 302, 739, 364, | |
723, 426, 723, 468, 740, 450, 747, 441, -1, 0, 839, 294, 851, 303, 859, 330, 861, 344, 858, 338, | |
-1, 0, 869, 235, 874, 240, 876, 249, 878, 263, 872, 259, -1, 0, 887, 223, 892, 227, 902, 249, 906, | |
264, -1, 0, 970, 266, 979, 288, 994, 314, 1015, 320, -1, 0, 1075, 272, 1078, 276, 1021, 338, 962, | |
391, 940, 432, 946, 458, 971, 482, 1029, 487, 1069, 475, 1090, 463, -1, 0, 1181, 234, 1223, 256, | |
1237, 262, 1249, 270, -1, 0, 1151, 336, 1146, 340, 1193, 320, 1246, 320, 1285, 337, 1290, 387, | |
1246, 448, 1203, 494, 1204, 486, -1, 0, -1, -1}; | |
const int DHWR_MAX_CANDIDATES = 10; | |
DHWRInkObject ink_obj = NULL; | |
DHWRResultObject result_obj = NULL; | |
DHWRSettingObject setting_obj = NULL; | |
void make_input_event(DHWRInkObject ink, const int* inputs) { | |
DHWRInkClear(ink); | |
int i = 0; | |
while (true) { | |
if (inputs[i + 0] == -1 && inputs[i + 1] == -1) { | |
break; | |
} else if (inputs[i + 0] == -1 && inputs[i + 1] == 0) { | |
DHWREndStroke(ink); | |
} else { | |
DHWRAddPoint(ink, inputs[i + 0], inputs[i + 1]); | |
} | |
i += 2; | |
} | |
} | |
void print_wchar(const wchar_t* result, int size) { | |
int i; | |
for (i = 0; i < size; i++) { | |
log("%C", result[i]); | |
} | |
log(" ("); | |
for (i = 0; i < size; i++) { | |
if (i != 0) { | |
log(" "); | |
} | |
log("0x%04x", result[i]); | |
} | |
log(")"); | |
} | |
void print_candidate(DHWRResultObject result) { | |
bool exit = false; | |
unsigned int length; | |
int size_line = DHWRGetLineSize(result); | |
if (size_line == 0) { | |
log("result empty\n"); | |
return; | |
} | |
for (unsigned int i = 0; i < DHWR_MAX_CANDIDATES; i++) { | |
for (int j = 0; j < size_line; j++) { | |
DHWRResultLine line = DHWRGetLine(result, j); | |
int size_block = DHWRGetBlockSize(line); | |
for (int k = 0; k < size_block; k++) { | |
DHWRResultBlock block = DHWRGetBlock(line, k); | |
if (DHWRGetCandidateSize(block) <= i) { | |
exit = true; | |
break; | |
} | |
log("[%02d] ", i + 1); | |
const wchar_t* current_cand = (const wchar_t*)(DHWRGetCandidate(block, i, &length)); | |
print_wchar(current_cand, length); | |
if (k + 1 < size_block) { | |
log(", "); | |
} | |
} | |
if (exit) { | |
break; | |
} | |
if (j + 1 < size_line) { | |
log("\n"); | |
} | |
} | |
if (exit) { | |
break; | |
} | |
log("\n"); | |
} | |
} | |
void print_result(const char *title, int status) { | |
log("\n%s ", title); | |
if (status == ERR_SUCCESS) { | |
log("...Success\n"); | |
print_candidate(result_obj); | |
} else { | |
log("...Failed (%d)\n", status); | |
} | |
} | |
int initEngine() { | |
unsigned long status = ERR_SUCCESS; | |
status = DHWRCreate("./license_key/license.key"); | |
if (ink_obj == NULL) { | |
ink_obj = DHWRCreateInkObject(); | |
} | |
if (result_obj == NULL) { | |
result_obj = DHWRCreateResultObject(); | |
} | |
if (setting_obj == NULL) { | |
setting_obj = DHWRCreateSettingObject(); | |
} | |
DHWRSetExternalResourcePath("./hdb/"); | |
DHWRSetExternalLibraryPath("./lib/"); // for chinese & thai | |
DHWRSetRecognitionMode(setting_obj, MULTICHAR); | |
DHWRSetCandidateSize(setting_obj, DHWR_MAX_CANDIDATES); | |
log("\nInitialize Engine ...%s (%ld)\n", status == ERR_SUCCESS ? "Success" : "Failed", status); | |
return status; | |
} | |
int destroyEngine() { | |
unsigned long status = ERR_SUCCESS; | |
status = DHWRClose(); | |
if (ink_obj != NULL) { | |
DHWRDestroyInkObject(ink_obj); | |
} | |
if (result_obj != NULL) { | |
DHWRDestroyResultObject(result_obj); | |
} | |
if (setting_obj != NULL) { | |
DHWRDestroySettingObject(setting_obj); | |
} | |
log("\nDestroy Engine ...%s (%ld)\n", status == ERR_SUCCESS ? "Success" : "Failed", status); | |
return status; | |
} | |
int testKorean() { | |
unsigned long status = ERR_SUCCESS; | |
DHWRClearLanguage(setting_obj); | |
DHWRAddLanguage(setting_obj, DLANG_KOREAN, (DHWR_TYPE)(DTYPE_KOREAN | DTYPE_SIGN | DTYPE_NUMERIC)); | |
DHWRSetAttribute(setting_obj); | |
make_input_event(ink_obj, ink_annyeonghaseyo); | |
status = DHWRecognize(ink_obj, result_obj); | |
print_result("Korean Test", status); | |
return status; | |
} | |
int testEnglish() { | |
unsigned long status = ERR_SUCCESS; | |
DHWRClearLanguage(setting_obj); | |
DHWRAddLanguage(setting_obj, DLANG_ENGLISH, (DHWR_TYPE)(DTYPE_UPPERCASE | DTYPE_LOWERCASE)); | |
DHWRSetAttribute(setting_obj); | |
make_input_event(ink_obj, ink_good_morning); | |
status = DHWRecognize(ink_obj, result_obj); | |
print_result("English Test", status); | |
return status; | |
} | |
int testChinese() { | |
unsigned long status = ERR_SUCCESS; | |
DHWRClearLanguage(setting_obj); | |
DHWRAddLanguage(setting_obj, DLANG_CHINA, DTYPE_SIMP); | |
DHWRSetAttribute(setting_obj); | |
make_input_event(ink_obj, ink_zhongguo); | |
status = DHWRecognize(ink_obj, result_obj); | |
print_result("Chinese Test", status); | |
return status; | |
} | |
int testJapanese() { | |
unsigned long status = ERR_SUCCESS; | |
DHWRClearLanguage(setting_obj); | |
DHWRAddLanguage(setting_obj, DLANG_JAPANESE, DTYPE_HIRAGANA); | |
DHWRSetAttribute(setting_obj); | |
make_input_event(ink_obj, ink_arigatou); | |
status = DHWRecognize(ink_obj, result_obj); | |
print_result("Japanese Test", status); | |
return status; | |
} | |
int main() { | |
setlocale(LC_ALL, ""); | |
initEngine(); | |
testKorean(); | |
testEnglish(); | |
testChinese(); | |
testJapanese(); | |
destroyEngine(); | |
return 0; | |
} |
chavito706
commented
Mar 24, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment