[DEV] better version

This commit is contained in:
Edouard DUPIN 2016-08-29 22:55:00 +02:00
parent a6f9f546a4
commit 4e0c1db793
4 changed files with 188 additions and 49 deletions

View File

@ -18,16 +18,18 @@
dollar::EnginePPlus::EnginePPlus(): dollar::EnginePPlus::EnginePPlus():
m_PPlusDistance(0.10f), m_PPlusDistance(0.10f),
m_PPlusExcludeDistance(0.2*0.2), m_PPlusExcludeDistance(0.2*0.2),
m_scaleKeepRatio(false) { m_scaleKeepRatio(false),
m_penalityNotLinkRef(0.1),
m_penalityNotLinkSample(0.1) {
} }
void dollar::EnginePPlus::setPPlusDistance(float _value) { void dollar::EnginePPlus::setPPlusDistance(float _value) {
if (_value*_value == m_PPlusDistance) { if (_value == m_PPlusDistance) {
return; return;
} }
m_PPlusDistance = _value*_value; m_PPlusDistance = _value;
for (auto &it: m_gestures) { for (auto &it: m_gestures) {
if (it == nullptr) { if (it == nullptr) {
continue; continue;
@ -37,18 +39,18 @@ void dollar::EnginePPlus::setPPlusDistance(float _value) {
} }
float dollar::EnginePPlus::getPPlusDistance() { float dollar::EnginePPlus::getPPlusDistance() {
return std::sqrt(m_PPlusDistance); return m_PPlusDistance;
} }
void dollar::EnginePPlus::setPPlusExcludeDistance(float _value) { void dollar::EnginePPlus::setPPlusExcludeDistance(float _value) {
if (_value == m_PPlusExcludeDistance) { if (_value*_value == m_PPlusExcludeDistance) {
return; return;
} }
m_PPlusExcludeDistance = _value; m_PPlusExcludeDistance = _value*_value;
} }
float dollar::EnginePPlus::getPPlusExcludeDistance() { float dollar::EnginePPlus::getPPlusExcludeDistance() {
return m_PPlusExcludeDistance; return std::sqrt(m_PPlusExcludeDistance);
} }
void dollar::EnginePPlus::setScaleKeepRatio(bool _value) { void dollar::EnginePPlus::setScaleKeepRatio(bool _value) {
if (_value == m_scaleKeepRatio) { if (_value == m_scaleKeepRatio) {
@ -67,6 +69,78 @@ bool dollar::EnginePPlus::getScaleKeepRatio() {
return m_scaleKeepRatio; return m_scaleKeepRatio;
} }
void dollar::EnginePPlus::setPenalityNotLinkRef(float _value) {
m_penalityNotLinkRef = _value;
}
float dollar::EnginePPlus::getPenalityNotLinkRef() {
return m_penalityNotLinkRef;
}
void dollar::EnginePPlus::setPenalityNotLinkSample(float _value) {
m_penalityNotLinkSample = _value;
}
float dollar::EnginePPlus::getPenalityNotLinkSample() {
return m_penalityNotLinkSample;
}
float dollar::EnginePPlus::calculatePPlusDistanceSimple(const std::vector<vec2>& _points,
const std::vector<vec2>& _reference,
std::vector<std::pair<int32_t, int32_t>>& _dataDebug) {
std::vector<float> distance; // note: use square distance (faster, we does not use std::sqrt())
distance.resize(_points.size(), MAX_FLOAT);
// point Id that is link on the reference.
std::vector<int32_t> usedId;
usedId.resize(_points.size(), -1);
for (size_t iii=0; iii<_points.size(); iii++) {
float bestDistance = MAX_FLOAT;
int32_t kkkBest = -1;
for (size_t kkk=0; kkk<_reference.size(); ++kkk) {
float dist = (_points[iii]-_reference[kkk]).length2();
if (dist < bestDistance) {
bestDistance = dist;
kkkBest = kkk;
}
}
if (kkkBest != -1) {
// reject the distance ... if too big ...
if (bestDistance <= m_PPlusExcludeDistance) {
usedId[iii] = kkkBest;
distance[iii] = bestDistance;
//DOLLAR_INFO("set new link: " << iii << " with " << kkkBest << " d=" << bestDistance);
}
}
}
double fullDistance = 0;
int32_t nbTestNotUsed = 0;
int32_t nbReferenceNotUsed = 0;
// now we count the full distance use and the number of local gesture not use
for (auto &it : distance) {
if (it < 100.0) {
fullDistance += it;
} else {
nbTestNotUsed++;
}
}
// we count the number of point in the gesture reference not used:
for (auto &it : usedId) {
if (it == -1) {
nbReferenceNotUsed++;
}
}
// now we add panality:
fullDistance += float(nbTestNotUsed)* m_penalityNotLinkSample;
fullDistance += float(nbReferenceNotUsed)* m_penalityNotLinkRef;
for (size_t kkk=0; kkk<usedId.size(); ++kkk) {
if (usedId[kkk] != -1) {
_dataDebug.push_back(std::make_pair(kkk, usedId[kkk]));
}
}
DOLLAR_DEBUG("test distance : " << fullDistance << " nbTestNotUsed=" << nbTestNotUsed << " nbReferenceNotUsed=" << nbReferenceNotUsed);
return fullDistance;
}
float dollar::EnginePPlus::calculatePPlusDistance(const std::vector<vec2>& _points, float dollar::EnginePPlus::calculatePPlusDistance(const std::vector<vec2>& _points,
@ -132,8 +206,8 @@ float dollar::EnginePPlus::calculatePPlusDistance(const std::vector<vec2>& _poin
} }
} }
// now we add panality: // now we add panality:
fullDistance += float(nbTestNotUsed)* 0.1f; fullDistance += float(nbTestNotUsed)* m_penalityNotLinkSample;
fullDistance += float(nbReferenceNotUsed)* 0.1f; fullDistance += float(nbReferenceNotUsed)* m_penalityNotLinkRef;
for (size_t kkk=0; kkk<usedId.size(); ++kkk) { for (size_t kkk=0; kkk<usedId.size(); ++kkk) {
if (usedId[kkk] != -1) { if (usedId[kkk] != -1) {
@ -239,9 +313,20 @@ dollar::Results dollar::EnginePPlus::recognize2(const std::vector<std::vector<ve
//DOLLAR_ERROR("Reference path with no Value"); //DOLLAR_ERROR("Reference path with no Value");
continue; continue;
} }
int32_t nbStrokeSample = _strokes.size();
int32_t nbStrokeRef = gesture->getPath().size();
/*
if (nbStrokeSample != nbStrokeRef) {
continue; //==> must have the same number of stroke ...
}
*/
float distance = MAX_FLOAT; float distance = MAX_FLOAT;
std::vector<std::pair<int32_t, int32_t>> dataPair; std::vector<std::pair<int32_t, int32_t>> dataPair;
distance = calculatePPlusDistance(points, gesture->getEnginePoints(), dataPair); distance = calculatePPlusDistance(points, gesture->getEnginePoints(), dataPair);
//distance = calculatePPlusDistanceSimple(points, gesture->getEnginePoints(), dataPair);
if (nbStrokeRef != nbStrokeSample) {
distance += 0.1f*float(std::abs(nbStrokeRef-nbStrokeSample));
}
//storeSVG("out_dollar/lib/recognizePPlus/" + gesture->getName() + "_" + etk::to_string(gesture->getId()) + ".svg", gesture, _strokes, points, dataPair, m_scaleKeepRatio); //storeSVG("out_dollar/lib/recognizePPlus/" + gesture->getName() + "_" + etk::to_string(gesture->getId()) + ".svg", gesture, _strokes, points, dataPair, m_scaleKeepRatio);
for (size_t kkk=0; kkk<m_nbResult; ++kkk) { for (size_t kkk=0; kkk<m_nbResult; ++kkk) {
if (distance < bestDistance[kkk]) { if (distance < bestDistance[kkk]) {

View File

@ -31,6 +31,16 @@ namespace dollar {
public: public:
void setScaleKeepRatio(bool _value); void setScaleKeepRatio(bool _value);
bool getScaleKeepRatio(); bool getScaleKeepRatio();
protected:
float m_penalityNotLinkRef;
public:
void setPenalityNotLinkRef(float _value);
float getPenalityNotLinkRef();
protected:
float m_penalityNotLinkSample;
public:
void setPenalityNotLinkSample(float _value);
float getPenalityNotLinkSample();
protected: protected:
std::vector<ememory::SharedPtr<dollar::GesturePPlus>> m_gestures; //!< List of all loaded gesture in the engine std::vector<ememory::SharedPtr<dollar::GesturePPlus>> m_gestures; //!< List of all loaded gesture in the engine
public: public:
@ -42,6 +52,9 @@ namespace dollar {
float calculatePPlusDistance(const std::vector<vec2>& _points, float calculatePPlusDistance(const std::vector<vec2>& _points,
const std::vector<vec2>& _reference, const std::vector<vec2>& _reference,
std::vector<std::pair<int32_t, int32_t>>& _dataDebug); std::vector<std::pair<int32_t, int32_t>>& _dataDebug);
float calculatePPlusDistanceSimple(const std::vector<vec2>& _points,
const std::vector<vec2>& _reference,
std::vector<std::pair<int32_t, int32_t>>& _dataDebug);
}; };
} }

View File

@ -5,7 +5,7 @@
*/ */
#include <iostream> #include <iostream>
#include <dollar/Engine.h> #include <dollar/EnginePPlus.h>
#include <dollar/tools.h> #include <dollar/tools.h>
#include <etk/etk.h> #include <etk/etk.h>
@ -17,7 +17,12 @@ void usage(const std::string& _progName) {
TEST_PRINT("usage:"); TEST_PRINT("usage:");
TEST_PRINT(" " << _progName << " [option] reference_gesture corpus_path"); TEST_PRINT(" " << _progName << " [option] reference_gesture corpus_path");
TEST_PRINT(" [option]"); TEST_PRINT(" [option]");
TEST_PRINT(" -h --help Display this help"); TEST_PRINT(" -h --help Display this help");
TEST_PRINT(" --keep_ratio Keep aspect ratio for the form recognition");
TEST_PRINT(" --dist-check=flaot distance between points in the system recognition");
TEST_PRINT(" --dist-excl=flaot distance to exclude a point in a pathern matching ...");
TEST_PRINT(" --penal-ref=float Penality for reference when not connected");
TEST_PRINT(" --penal-sample=float Penality for sample when not connected");
TEST_PRINT(" parameters (must be here)"); TEST_PRINT(" parameters (must be here)");
TEST_PRINT(" reference_gesture Path of the reference gestures"); TEST_PRINT(" reference_gesture Path of the reference gestures");
TEST_PRINT(" corpus_path Path of the corpus files"); TEST_PRINT(" corpus_path Path of the corpus files");
@ -25,6 +30,12 @@ void usage(const std::string& _progName) {
bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus); bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus);
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 penalityRef = 0.1;
static float penalitySample = 0.1;
int main(int _argc, const char *_argv[]) { int main(int _argc, const char *_argv[]) {
// init etk log system and file interface: // init etk log system and file interface:
etk::init(_argc, _argv); etk::init(_argc, _argv);
@ -37,6 +48,34 @@ int main(int _argc, const char *_argv[]) {
usage(_argv[0]); usage(_argv[0]);
return 0; return 0;
} }
if (arg == "--keep_ratio") {
keepAspectRatio = true;
continue;
}
if (etk::start_with(arg,"--dist-ref=") == true) {
std::string val(&arg[11]);
distanceReference = etk::string_to_float(val);
TEST_PRINT("configure distanceReference=" << distanceReference);
continue;
}
if (etk::start_with(arg,"--dist-excl=") == true) {
std::string val(&arg[12]);
distanceExclude = etk::string_to_float(val);
TEST_PRINT("configure distanceExclude=" << distanceExclude);
continue;
}
if (etk::start_with(arg,"--penal-ref=") == true) {
std::string val(&arg[12]);
penalityRef = etk::string_to_float(val);
TEST_PRINT("configure penalityRef=" << penalityRef);
continue;
}
if (etk::start_with(arg,"--penal-sample=") == true) {
std::string val(&arg[15]);
penalityRef = etk::string_to_float(val);
TEST_PRINT("configure penalitySample=" << penalitySample);
continue;
}
if( arg[0] == '-' if( arg[0] == '-'
&& arg[1] == '-') { && arg[1] == '-') {
// subLibrary usage ... // subLibrary usage ...
@ -134,8 +173,12 @@ void annalyseResult(std::map<std::string, std::vector<std::pair<dollar::Results,
bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus) { bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus) {
// declare a Gesture (internal API) // declare a Gesture (internal API)
dollar::Engine reco; dollar::EnginePPlus reco;
reco.setScaleKeepRatio(false); reco.setScaleKeepRatio(keepAspectRatio);
reco.setPPlusDistance(distanceReference);
reco.setPPlusExcludeDistance(distanceExclude);
reco.setPenalityNotLinkRef(penalityRef);
reco.setPenalityNotLinkSample(penalitySample);
TEST_PRINT("---------------------------------------------------------------------------"); TEST_PRINT("---------------------------------------------------------------------------");
TEST_PRINT("-- Load Gestures: " << _srcGesture); TEST_PRINT("-- Load Gestures: " << _srcGesture);
TEST_PRINT("---------------------------------------------------------------------------"); TEST_PRINT("---------------------------------------------------------------------------");
@ -167,7 +210,7 @@ bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus) {
std::vector<std::string> path = etk::split(it, '/'); std::vector<std::string> path = etk::split(it, '/');
std::string filename = path[path.size()-1]; std::string filename = path[path.size()-1];
TEST_PRINT("Test '" << label << "' type=" << type << " " << filename); TEST_PRINT("Test '" << label << "' type=" << type << " " << filename);
dollar::Results res = reco.recognize(listPoints, "$P+"); dollar::Results res = reco.recognize(listPoints);
agregateResults[label+" "+type].push_back(std::make_pair(res,it)); agregateResults[label+" "+type].push_back(std::make_pair(res,it));

View File

@ -5,7 +5,7 @@
*/ */
#include <iostream> #include <iostream>
#include <dollar/Engine.h> #include <dollar/EnginePPlus.h>
#include <dollar/tools.h> #include <dollar/tools.h>
#include <etk/etk.h> #include <etk/etk.h>
@ -18,12 +18,13 @@ void usage(const std::string& _progName) {
TEST_PRINT(" " << _progName << " [option] corpus_path"); TEST_PRINT(" " << _progName << " [option] corpus_path");
TEST_PRINT(" "); TEST_PRINT(" ");
TEST_PRINT(" [option]"); TEST_PRINT(" [option]");
TEST_PRINT(" -h --help Display this help"); TEST_PRINT(" -h --help Display this help");
TEST_PRINT(" --keep_ratio Keep aspect ratio for the form recognition"); TEST_PRINT(" --keep_ratio Keep aspect ratio for the form recognition");
TEST_PRINT(" --dist-check=flaot distance between points in the system recognition"); TEST_PRINT(" --dist-check=flaot distance between points in the system recognition");
TEST_PRINT(" --dist-excl=flaot distance to exclude points in the check algo"); TEST_PRINT(" --dist-excl=flaot distance to exclude a point in a pathern matching ...");
TEST_PRINT(" --group-size=flaot size of the distance between point to stop grouping in one form"); TEST_PRINT(" --group-size=flaot size of the distance between point to stop grouping in one form");
TEST_PRINT(" --mode=string mode of reco"); TEST_PRINT(" --penal-ref=float Penality for reference when not connected");
TEST_PRINT(" --penal-sample=float Penality for sample when not connected");
TEST_PRINT(" "); TEST_PRINT(" ");
TEST_PRINT(" parameters (must be here)"); TEST_PRINT(" parameters (must be here)");
TEST_PRINT(" corpus_path Path of the corpus files"); TEST_PRINT(" corpus_path Path of the corpus files");
@ -35,16 +36,11 @@ void usage(const std::string& _progName) {
bool testCorpus(const std::string& _srcCorpus); bool testCorpus(const std::string& _srcCorpus);
static bool keepAspectRatio = false; static bool keepAspectRatio = false;
static float distanceReference = 0.1; // distance of the gesture reference [0.02, 0.3] static float distanceReference = 0.1f; // distance of the gesture reference [0.02, 0.3]
static float distanceCheck = 0.1; // distance of the test points [0.02, 0.3] static float distanceExclude = 0.2f; // distance of the exclusion point [0.1, 1.0]
static float distanceExclude = 0.2; // distance of the exclusion point [0.1, 1.0] static float distanceGroupLimiting = 1.0f; // square distance of the grouping genereation
static float distanceGroupLimiting = 1.0; // square distance of the grouping genereation static float penalityRef = 0.1;
static std::string modeReco = "P+"; static float penalitySample = 0.1;
setScaleKeepRatio();
setPPlusDistance(distanceReference); // to generate reference gesture
setPPlusDistance(distanceCheck); // to generate test gesture
int main(int _argc, const char *_argv[]) { int main(int _argc, const char *_argv[]) {
// init etk log system and file interface: // init etk log system and file interface:
@ -68,14 +64,6 @@ int main(int _argc, const char *_argv[]) {
TEST_PRINT("configure distanceReference=" << distanceReference); TEST_PRINT("configure distanceReference=" << distanceReference);
continue; continue;
} }
// TODO: Must not be different ...
if (etk::start_with(arg,"--dist-check=") == true) {
std::string val(&arg[13]);
distanceCheck = etk::string_to_float(val);
distanceReference = distanceCheck;
TEST_PRINT("configure distanceCheck=" << distanceCheck);
continue;
}
if (etk::start_with(arg,"--dist-excl=") == true) { if (etk::start_with(arg,"--dist-excl=") == true) {
std::string val(&arg[12]); std::string val(&arg[12]);
distanceExclude = etk::string_to_float(val); distanceExclude = etk::string_to_float(val);
@ -88,10 +76,16 @@ int main(int _argc, const char *_argv[]) {
TEST_PRINT("configure distanceGroupLimiting=" << distanceGroupLimiting); TEST_PRINT("configure distanceGroupLimiting=" << distanceGroupLimiting);
continue; continue;
} }
if (etk::start_with(arg,"--mode=") == true) { if (etk::start_with(arg,"--penal-ref=") == true) {
std::string val(&arg[7]); std::string val(&arg[12]);
modeReco = val; penalityRef = etk::string_to_float(val);
TEST_PRINT("configure modeReco=" << modeReco); TEST_PRINT("configure penalityRef=" << penalityRef);
continue;
}
if (etk::start_with(arg,"--penal-sample=") == true) {
std::string val(&arg[15]);
penalityRef = etk::string_to_float(val);
TEST_PRINT("configure penalitySample=" << penalitySample);
continue; continue;
} }
if ( arg[0] == '-' if ( arg[0] == '-'
@ -176,6 +170,8 @@ bool testCorpus(const std::string& _srcCorpus) {
} }
} }
} }
// remove generation path ...
etk::FSNodeRemove("out_dollar/generate-form");
//listOfElementInCorpus.clear(); //listOfElementInCorpus.clear();
//listOfElementInCorpus.push_back("slash"); //listOfElementInCorpus.push_back("slash");
@ -219,14 +215,15 @@ bool testCorpus(const std::string& _srcCorpus) {
generateFile("out_dollar/generate-form/pre_generate/" + itTypeOfCorpusFileName + "_FULL.svg", listPath, ""); generateFile("out_dollar/generate-form/pre_generate/" + itTypeOfCorpusFileName + "_FULL.svg", listPath, "");
} }
for (size_t iii=0; iii<fileFiltered.size(); ++iii) { for (size_t iii=0; iii<fileFiltered.size(); ++iii) {
dollar::Gesture gest; ememory::SharedPtr<dollar::GesturePPlus> gest = ememory::makeShared<dollar::GesturePPlus>();
std::vector<std::vector<vec2>> listPoints = dollar::loadPoints(fileFiltered[iii]); std::vector<std::vector<vec2>> listPoints = dollar::loadPoints(fileFiltered[iii]);
gest.set(itTypeOfCorpus, 0, listPoints); gest->set(itTypeOfCorpus, 0, listPoints);
gest.configure(10, 8, false, distanceReference, keepAspectRatio); dollar::EnginePPlus reco;
dollar::Engine reco;
reco.setScaleKeepRatio(keepAspectRatio); reco.setScaleKeepRatio(keepAspectRatio);
reco.setPPlusDistance(distanceCheck); reco.setPPlusDistance(distanceReference);
reco.setPPlusExcludeDistance(distanceExclude); reco.setPPlusExcludeDistance(distanceExclude);
reco.setPenalityNotLinkRef(penalityRef);
reco.setPenalityNotLinkSample(penalitySample);
reco.addGesture(gest); reco.addGesture(gest);
std::vector<std::string> path = etk::split(fileFiltered[iii], '/'); std::vector<std::string> path = etk::split(fileFiltered[iii], '/');
std::string filename = path[path.size()-1]; std::string filename = path[path.size()-1];
@ -237,7 +234,7 @@ bool testCorpus(const std::string& _srcCorpus) {
continue; continue;
} }
listPoints = dollar::loadPoints(fileFiltered[jjj]); listPoints = dollar::loadPoints(fileFiltered[jjj]);
dollar::Results res = reco.recognize(listPoints, "$" + modeReco); dollar::Results res = reco.recognize(listPoints);
results[iii][jjj] = res.getConfidence(); results[iii][jjj] = res.getConfidence();
results[jjj][iii] = res.getConfidence(); results[jjj][iii] = res.getConfidence();
path = etk::split(fileFiltered[jjj], '/'); path = etk::split(fileFiltered[jjj], '/');
@ -312,6 +309,7 @@ bool testCorpus(const std::string& _srcCorpus) {
} }
} }
// enable/disable grouping auto ... // enable/disable grouping auto ...
// TODO : Check if it is possible ...
if (false) { if (false) {
float lastValue = 0.0; float lastValue = 0.0;
linkIds.clear(); linkIds.clear();