Simple example source of math recognition for Android using Java
/*! | |
* @brief simple example source of math recognition | |
* @date 2020/01/16 | |
* @file MathSimpleExampleActivity.java | |
* @author SELVAS AI | |
* | |
* Copyright 2020. SELVAS AI Inc. All Rights Reserved. | |
*/ | |
package com.selvasai.handwriting.math; | |
import android.app.Activity; | |
import android.os.Bundle; | |
import android.util.Log; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.Locale; | |
import com.selvy.spmath.DHWR; | |
public class MathSimpleExampleActivity extends Activity { | |
public final static String TAG = "HWR"; | |
final int MAX_CANDIDATES = 10; | |
private DHWR.Ink mInk; | |
private DHWR.Setting mSetting; | |
private DHWR.Result mResult; | |
// points of '\frac{2x+4}{5y-2}' | |
// -1, 0 : end of stroke | |
// -1, -1 : end of ink | |
// (x0, y0), (x1, y1), ... (-1, 0) ... (xn, yn) .... (-1, 0), (-1, -1) | |
final int[] ink_fraction = {383, 614, 325, 755, 338, 759, 373, 759, 392, 772, 353, 808, 318, | |
825, 320, 805, -1, 0, 348, 691, 351, 688, 358, 676, 397, 668, 427, 667, 433, 663, -1, 0, | |
528, 642, 533, 647, 524, 654, 506, 696, 503, 729, 515, 726, 528, 711, 561, 671, 586, | |
648, 585, 657, 572, 701, 563, 736, 545, 810, 518, 860, 498, 865, 478, 849, 480, 822, | |
515, 783, 535, 769, 587, 744, 620, 735, 631, 732, 642, 732, 644, 733, -1, 0, 714, 691, | |
712, 685, 750, 684, 771, 679, 778, 678, -1, 0, 880, 665, 891, 660, 926, 655, 938, 659, | |
958, 680, 940, 706, 923, 719, 883, 743, 876, 750, 892, 752, 933, 749, 979, 744, 999, | |
743, 1023, 743, 1003, 744, -1, 0, 193, 531, 206, 526, 258, 529, 316, 528, 384, 524, 418, | |
522, 500, 520, 575, 519, 604, 518, 661, 517, 715, 516, 752, 515, 798, 512, 852, 508, | |
873, 508, 915, 505, 961, 502, 979, 501, 1023, 500, 1055, 500, 1070, 499, 1100, 497, | |
1135, 495, 1146, 493, 1163, 492, 1152, 490, 1131, 487, -1, 0, 302, 341, 340, 342, 365, | |
355, 369, 379, 327, 416, 313, 427, 304, 436, 337, 430, 362, 424, 414, 410, 430, 406, | |
423, 406, -1, 0, 444, 337, 450, 337, 479, 319, 509, 325, 511, 347, 492, 386, 481, 405, | |
465, 428, 472, 414, -1, 0, 537, 292, 534, 292, 512, 303, 498, 337, 500, 378, 520, 419, | |
529, 429, 548, 445, 555, 452, 558, 453, -1, 0, 607, 374, 613, 369, 660, 371, 728, 364, | |
761, 356, 760, 349, -1, 0, 688, 316, 686, 318, 681, 331, 690, 388, 693, 407, 696, 426, | |
697, 423, -1, 0, 842, 292, 851, 296, 849, 311, 830, 354, 821, 376, 827, 391, 861, 398, | |
926, 402, 985, 401, 995, 400, 989, 398, -1, 0, 959, 281, 941, 293, 916, 337, 890, 401, | |
869, 458, 864, 479, 866, 488, -1, 0, -1, -1}; | |
// points of '\sqrt{144}+\sqrt{1728}' | |
final int[] ink_square_root = {376, 665, 375, 659, 383, 680, 394, 704, 405, 717, 410, 691, 411, | |
666, 408, 566, 404, 495, 410, 450, 413, 437, 419, 429, 449, 427, 498, 436, 602, 440, | |
759, 428, 824, 421, 859, 418, 857, 428, -1, 0, 516, 571, 509, 580, 513, 625, 519, 648, | |
526, 644, -1, 0, 624, 545, 627, 545, 627, 553, 594, 582, 562, 604, 567, 609, 606, 605, | |
657, 596, 670, 588, -1, 0, 613, 555, 612, 553, 620, 569, 624, 616, 630, 634, 635, 632, | |
-1, 0, 728, 547, 729, 548, 695, 580, 671, 597, 672, 601, 716, 601, 775, 594, 786, 590, | |
-1, 0, 739, 541, 728, 562, 729, 606, 733, 642, 743, 654, -1, 0, 1063, 519, 1054, 536, | |
1058, 577, 1060, 597, -1, 0, 1023, 563, 1032, 558, 1087, 553, 1117, 552, -1, 0, 1315, | |
620, 1319, 620, 1343, 652, 1360, 672, 1361, 650, 1359, 570, 1363, 484, 1365, 424, 1370, | |
413, 1391, 412, 1454, 415, 1519, 413, 1685, 397, 1816, 382, 1910, 377, 1980, 386, 1963, | |
394, -1, 0, 1506, 512, 1493, 512, 1499, 556, 1504, 592, 1509, 608, 1513, 602, -1, 0, | |
1586, 505, 1586, 511, 1573, 560, 1560, 549, 1564, 534, 1586, 506, 1614, 497, 1635, 525, | |
1637, 554, 1624, 617, 1618, 639, 1617, 641, 1623, 632, -1, 0, 1714, 542, 1731, 516, | |
1778, 519, 1792, 561, 1778, 578, 1735, 595, 1713, 593, 1733, 587, 1753, 584, 1811, 579, | |
1838, 578, -1, 0, 1925, 527, 1925, 520, 1906, 470, 1886, 476, 1877, 525, 1885, 576, | |
1873, 615, 1852, 617, 1862, 561, 1907, 535, 1942, 531, 1959, 542, -1, 0, -1, -1}; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
copyResourceToStorage(); | |
initEngine(); | |
testFraction(); | |
testSquareRoot(); | |
destroyEngine(); | |
} | |
private void copyResourceToStorage() { | |
String path = "hdb"; | |
String[] fileList = null; | |
try { | |
fileList = getAssets().list(path); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
if (fileList == null) { | |
return; | |
} | |
for (String file : fileList) { | |
try { | |
String filePath = (path + "/" + file); | |
try { | |
FileInputStream fis = openFileInput(file); | |
fis.close(); | |
} catch (FileNotFoundException e) { | |
InputStream is = getAssets().open(filePath); | |
final int bufferSize = is.available(); | |
byte[] buffer = new byte[bufferSize]; | |
int readSize = is.read(buffer); | |
is.close(); | |
if (readSize > 0) { | |
FileOutputStream fos = openFileOutput(file, Activity.MODE_PRIVATE); | |
fos.write(buffer); | |
fos.close(); | |
} | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
private void makeInputEvent(DHWR.Ink ink, int[] inputs) { | |
DHWR.InkClear(ink.GetHandle()); | |
int i = 0; | |
while (true) { | |
if (inputs[i] == -1 && inputs[i + 1] == -1) { // if end of inks | |
break; | |
} else if (inputs[i] == -1 && inputs[i + 1] == 0) { // if end of stroke | |
DHWR.EndStroke(ink.GetHandle()); | |
} else { | |
DHWR.AddPoint(ink.GetHandle(), inputs[i], inputs[i + 1]); | |
} | |
i += 2; | |
} | |
} | |
private String getCandidates(DHWR.Result result) { | |
StringBuilder candidates = new StringBuilder(); | |
boolean exit = false; | |
int resultSize = result.size(); | |
if (resultSize < 1) { | |
return "result empty"; | |
} | |
for (int i = 0; i < MAX_CANDIDATES; i++) { | |
for (int j = 0; j < resultSize; j++) { | |
DHWR.Line line = result.get(j); | |
for (int k = 0; k < line.size(); k++) { | |
DHWR.Block block = line.get(k); | |
if (block.candidates.size() <= i) { | |
exit = true; | |
break; | |
} | |
candidates.append(String.format(Locale.US, " [%d] ", i + 1)); | |
candidates.append(block.candidates.get(i)); | |
if (k + 1 < line.size()) { | |
candidates.append(" "); | |
} | |
} | |
if (exit) { | |
break; | |
} | |
if (j + 1 < result.size()) { | |
candidates.append("\n"); | |
} | |
} | |
if (exit) { | |
break; | |
} | |
candidates.append("\n"); | |
} | |
return candidates.toString(); | |
} | |
private void printResult(String title, int status) { | |
if (status == DHWR.ERR_SUCCESS) { | |
Log.d(TAG, title + " ...Success"); | |
Log.d(TAG, "Recognized Text:\n" + getCandidates(mResult)); | |
} else { | |
Log.d(TAG, title + " ...Failed" + " (" + status + ")"); | |
} | |
} | |
private int initEngine() { | |
final int MAX_VERSION_LENGTH = 64; | |
char[] version = new char[MAX_VERSION_LENGTH]; | |
DHWR.GetRevision(version); | |
final String filesPath = getFilesDir().getAbsolutePath(); | |
int status = DHWR.Create(filesPath + "/" + "license.key"); | |
DHWR.SetExternalResourcePath(filesPath.toCharArray()); | |
mInk = new DHWR.Ink(); | |
mSetting = new DHWR.Setting(); | |
mResult = new DHWR.Result(); | |
DHWR.SetRecognitionMode(mSetting.GetHandle(), DHWR.MULTICHAR); | |
DHWR.SetCandidateSize(mSetting.GetHandle(), MAX_CANDIDATES); | |
Log.d(TAG, "SDK Version: " + String.valueOf(version).trim()); | |
Log.d(TAG, "Initialize Engine ..." + (status == DHWR.ERR_SUCCESS ? "Success" : "Failed")); | |
return status; | |
} | |
private int destroyEngine() { | |
int status = DHWR.Close(); | |
Log.d(TAG, "Destroy Engine ..." + (status == DHWR.ERR_SUCCESS ? "Success" : "Failed")); | |
return status; | |
} | |
private int testFraction() { | |
DHWR.ClearLanguage(mSetting.GetHandle()); | |
DHWR.AddLanguage(mSetting.GetHandle(), DHWR.DLANG_MATH_MIDDLE_EXPANSION, DHWR.DTYPE_MATH_EX); | |
DHWR.SetAttribute(mSetting.GetHandle()); | |
makeInputEvent(mInk, ink_fraction); | |
int status = DHWR.Recognize(mInk, mResult); | |
printResult("Fraction Test", status); | |
return status; | |
} | |
private int testSquareRoot() { | |
DHWR.ClearLanguage(mSetting.GetHandle()); | |
DHWR.AddLanguage(mSetting.GetHandle(), DHWR.DLANG_MATH_MIDDLE_EXPANSION, DHWR.DTYPE_MATH_EX); | |
DHWR.SetAttribute(mSetting.GetHandle()); | |
makeInputEvent(mInk, ink_square_root); | |
int status = DHWR.Recognize(mInk, mResult); | |
printResult("Square root Test", status); | |
return status; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment