/** @file * @author Edouard DUPIN * @copyright 2016, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #include #include #include #include #include #include #include static bool keepAspectRatio = false; static float distanceReference = 0.1f; // distance of the gesture reference [0.02, 0.3] static float distanceExclude = 0.2f; // distance of the exclusion point [0.1, 1.0] static float distanceGroupLimiting = 1.0f; // square distance of the grouping genereation static float penalityRef = 0.1; static float penalitySample = 0.1; static float penalityAspectRatio = 0.2; //!< ==> result += delta aspect ratio * penality void usage(const etk::String& _progName) { TEST_PRINT("usage:"); TEST_PRINT(" " << _progName << " [option] corpus_path"); TEST_PRINT(" "); TEST_PRINT(" [option]"); TEST_PRINT(" -h --help Display this help"); TEST_PRINT(" --keep_ratio Keep aspect ratio for the form recognition (default:" + etk::toString(keepAspectRatio) + ")"); TEST_PRINT(" --dist-check=flaot Distance between points in the system recognition (default:" + etk::toString(distanceReference) + ")"); TEST_PRINT(" --dist-excl=flaot Distance to exclude a point in a pathern matching ... (default:" + etk::toString(distanceExclude) + ")"); TEST_PRINT(" --group-size=flaot Size of the distance between point to stop grouping in one form (default:" + etk::toString(distanceGroupLimiting) + ")"); TEST_PRINT(" --penal-ref=float Penality for reference when not connected (default:" + etk::toString(penalityRef) + ")"); TEST_PRINT(" --penal-sample=float Penality for sample when not connected (default:" + etk::toString(penalitySample) + ")"); TEST_PRINT(" --penal-aspect-ratio=float Penality for the distance of aspect ratio (default:" + etk::toString(penalityAspectRatio) + ")"); TEST_PRINT(" "); TEST_PRINT(" parameters (must be here)"); TEST_PRINT(" corpus_path Path of the corpus files"); TEST_PRINT(" "); TEST_PRINT(" The generate data is in out_dollar/xxx"); TEST_PRINT(" example:"); } bool testCorpus(const etk::String& _srcCorpus); int main(int _argc, const char *_argv[]) { // init etk log system and file interface: etk::init(_argc, _argv); etk::String srcCorpus; for (int32_t iii=1; iii<_argc; ++iii) { etk::String arg = _argv[iii]; if ( arg == "-h" || arg == "--help") { usage(_argv[0]); return 0; } if (arg == "--keep_ratio") { keepAspectRatio = true; continue; } if (etk::start_with(arg,"--dist-ref=") == true) { etk::String val(&arg[11]); distanceReference = etk::string_to_float(val); TEST_PRINT("configure distanceReference=" << distanceReference); continue; } if (etk::start_with(arg,"--dist-excl=") == true) { etk::String val(&arg[12]); distanceExclude = etk::string_to_float(val); TEST_PRINT("configure distanceExclude=" << distanceExclude); continue; } if (etk::start_with(arg,"--group-size=") == true) { etk::String val(&arg[13]); distanceGroupLimiting = etk::string_to_float(val); TEST_PRINT("configure distanceGroupLimiting=" << distanceGroupLimiting); continue; } if (etk::start_with(arg,"--penal-ref=") == true) { etk::String val(&arg[12]); penalityRef = etk::string_to_float(val); TEST_PRINT("configure penalityRef=" << penalityRef); continue; } if (etk::start_with(arg,"--penal-sample=") == true) { etk::String val(&arg[15]); penalityRef = etk::string_to_float(val); TEST_PRINT("configure penalitySample=" << penalitySample); continue; } if (etk::start_with(arg,"--penal-aspect-ratio=") == true) { etk::String val(&arg[20]); penalityAspectRatio = etk::string_to_float(val); TEST_PRINT("configure penalityAspectRatio=" << penalityAspectRatio); continue; } if ( arg[0] == '-' && arg[1] == '-') { // subLibrary usage ... continue; } if (srcCorpus == "") { srcCorpus = arg; continue; } usage(_argv[0]); return -1; } if (srcCorpus == "") { TEST_ERROR("Missing input or output"); usage(_argv[0]); return -1; } return testCorpus(srcCorpus); } void generateFile(const etk::String& _fileName, const etk::Vector& _list, const etk::String& _refName) { TEST_PRINT(" " << _fileName); etk::String data("\n"); data += "\n"; for (auto &itFile : _list) { etk::Vector> strokes = dollar::scaleToOne(dollar::loadPoints(itFile), keepAspectRatio); for (auto &itLines : strokes) { if (itLines.size() == 1) { // TODO: This is a line .... } data += " > strokes = dollar::scaleToOne(dollar::loadPoints(_refName), keepAspectRatio); for (auto &itLines : strokes) { if (itLines.size() == 1) { // TODO: This is a line .... } data += " files = path.folderGetSub(false, true, "*.json"); TEST_PRINT("corpus have " << files.size() << " files"); etk::Vector listOfElementInCorpus; for (auto &it : files) { if (etk::end_with(it, ".json") == true) { etk::Vector path = etk::split(it, '/'); etk::String elemName = etk::split(path[path.size()-1],'_')[0]; if (elemName == "slash") { elemName = "/"; }if (elemName == "back-slash") { elemName = "\\"; } if (std::find(listOfElementInCorpus.begin(), listOfElementInCorpus.end(), elemName) == listOfElementInCorpus.end()) { listOfElementInCorpus.pushBack(elemName); } } } // remove generation path ... etk::FSNodeRemove("out_dollar/generate-form"); //listOfElementInCorpus.clear(); //listOfElementInCorpus.pushBack("slash"); TEST_PRINT(" will done for: " << listOfElementInCorpus); int32_t nbElementGenerated = 0; for (auto &itTypeOfCorpus : listOfElementInCorpus) { TEST_PRINT("---------------------------------------------------------------------------"); TEST_PRINT("-- Generate FOR: '" << itTypeOfCorpus << "'"); TEST_PRINT("---------------------------------------------------------------------------"); etk::Vector fileFiltered; etk::String fileNameIt = itTypeOfCorpus; if (fileNameIt == "/") { fileNameIt = "slash"; } else if (fileNameIt == "\\") { fileNameIt = "back-slash"; } for (auto &it : files) { if (etk::end_with(it, ".json") == true) { etk::Vector path = etk::split(it, '/'); etk::String filename = path[path.size()-1]; if (etk::start_with(filename, fileNameIt + "_") == true) { fileFiltered.pushBack(it); } } } TEST_PRINT("correlation of " << fileFiltered.size() << " files"); etk::Vector> results; results.resize(fileFiltered.size()); for (auto &it : results) { it.resize(fileFiltered.size(), OUT_OF_RANGE); } // Generate Full Files: etk::String itTypeOfCorpusFileName = itTypeOfCorpus; if (itTypeOfCorpusFileName == "/") { itTypeOfCorpusFileName = "slash"; } else if (itTypeOfCorpusFileName == "\\") { itTypeOfCorpusFileName = "back-slash"; } else if (itTypeOfCorpusFileName == "?") { itTypeOfCorpusFileName = "question"; } { etk::Vector listPath; for (size_t iii=0; iii gest = ememory::makeShared(); etk::Vector> listPoints = dollar::loadPoints(fileFiltered[iii]); gest->set(itTypeOfCorpus, 0, listPoints); dollar::EnginePPlus reco; reco.setScaleKeepRatio(keepAspectRatio); reco.setPPlusDistance(distanceReference); reco.setPPlusExcludeDistance(distanceExclude); reco.setPenalityNotLinkRef(penalityRef); reco.setPenalityNotLinkSample(penalitySample); reco.setPenalityAspectRatio(penalityAspectRatio); reco.addGesture(gest); etk::Vector path = etk::split(fileFiltered[iii], '/'); etk::String filename = path[path.size()-1]; TEST_DEBUG("Test : " << fileFiltered[iii]); for (size_t jjj=0; jjj= jjj) { // same element to compare ... result will be 0 ... continue; } listPoints = dollar::loadPoints(fileFiltered[jjj]); dollar::Results res = reco.recognize(listPoints); results[iii][jjj] = res.getConfidence(); results[jjj][iii] = res.getConfidence(); path = etk::split(fileFiltered[jjj], '/'); etk::String filename2 = path[path.size()-1]; TEST_DEBUG(" " << res.getConfidence() << " " << filename2); } } TEST_PRINT("---------------------------------------------------------------------------"); TEST_PRINT("-- annalyse result to create groups: " << fileFiltered.size()); TEST_PRINT("---------------------------------------------------------------------------"); int32_t residualValues = fileFiltered.size(); int32_t subId = 1; while (residualValues > 0) { etk::Vector countMinimum; countMinimum.resize(fileFiltered.size(), 0); for (size_t iii=0; iii bestCount) { bestCount = countMinimum[iii]; bestId = iii; } } if (bestId == -1) { TEST_ERROR("No more elements ... residualValues=" << residualValues); // TODO : Add the rest of the elements ... //==> Exit loop residualValues = 0; continue; } else { TEST_INFO("find NB element : " << countMinimum[bestId] << " for ID=" << bestId); } // Order the result for the bestID ==> permit to show if it is possible to do a better case ... etk::Vector linkIds; for (size_t jjj=0; jjj> ordered; for (size_t jjj=0; jjj= OUT_OF_RANGE) { continue; } auto it = ordered.begin(); bool added = false; while (it != ordered.end()) { if (it->first > val) { ordered.insert(it, etk::makePair(val, jjj)); added = true; break; } ++it; } if (added == false) { ordered.pushBack(etk::makePair(val, jjj)); } } // enable/disable grouping auto ... // TODO : Check if it is possible ... if (false) { float lastValue = 0.0; linkIds.clear(); for (size_t jjj=0; jjj path = etk::split(fileFiltered[ordered[jjj].second], '/'); etk::String filename = path[path.size()-1]; etk::String tmppp = " "; if (jjj listPath; for (size_t iii=0; iii