[DEV] better recognition
This commit is contained in:
parent
1b1992a301
commit
aaceff37cb
@ -54,7 +54,8 @@ static float pathDistance(const std::vector<vec2>& _path1, const std::vector<vec
|
|||||||
}
|
}
|
||||||
|
|
||||||
dollar::Engine::Engine():
|
dollar::Engine::Engine():
|
||||||
m_PPlusDistance(0.10f) {
|
m_PPlusDistance(0.10f),
|
||||||
|
m_scaleKeepRatio(false) {
|
||||||
m_numPointsInGesture = 128;
|
m_numPointsInGesture = 128;
|
||||||
DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ...");
|
DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ...");
|
||||||
setRotationInvariance(false);
|
setRotationInvariance(false);
|
||||||
@ -68,7 +69,7 @@ void dollar::Engine::setNumberPointInGesture(size_t _value) {
|
|||||||
m_numPointsInGesture = _value;
|
m_numPointsInGesture = _value;
|
||||||
DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ...");
|
DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ...");
|
||||||
for (auto &it: m_gestures) {
|
for (auto &it: m_gestures) {
|
||||||
it.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance);
|
it.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance, m_scaleKeepRatio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +77,34 @@ size_t dollar::Engine::getNumberPointInGesture() {
|
|||||||
return m_numPointsInGesture;
|
return m_numPointsInGesture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dollar::Engine::setPPlusDistance(float _value) {
|
||||||
|
if (_value == m_PPlusDistance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_PPlusDistance = _value;
|
||||||
|
for (auto &it: m_gestures) {
|
||||||
|
it.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance, m_scaleKeepRatio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float dollar::Engine::getPPlusDistance() {
|
||||||
|
return m_PPlusDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dollar::Engine::setScaleKeepRatio(bool _value) {
|
||||||
|
if (_value == m_scaleKeepRatio) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_scaleKeepRatio = _value;
|
||||||
|
for (auto &it: m_gestures) {
|
||||||
|
it.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance, m_scaleKeepRatio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dollar::Engine::getScaleKeepRatio() {
|
||||||
|
return m_scaleKeepRatio;
|
||||||
|
}
|
||||||
|
|
||||||
float dollar::Engine::distanceAtBestAngle(const std::vector<vec2>& _points, const std::vector<vec2>& _reference) {
|
float dollar::Engine::distanceAtBestAngle(const std::vector<vec2>& _points, const std::vector<vec2>& _reference) {
|
||||||
float startRange = -m_angleRange;
|
float startRange = -m_angleRange;
|
||||||
float endRange = m_angleRange;
|
float endRange = m_angleRange;
|
||||||
@ -177,17 +206,17 @@ static float calculatePPlusDistance(const std::vector<vec2>& _points,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kkkBest != -1) {
|
if (kkkBest != -1) {
|
||||||
if (bestDistance > 0.2*0.2) {
|
// reject the distance ... if too big ...
|
||||||
// reject the distance ...
|
if (bestDistance <= 0.2*0.2) {
|
||||||
}
|
int32_t previous = usedId[kkkBest];
|
||||||
int32_t previous = usedId[kkkBest];
|
usedId[kkkBest] = iii;
|
||||||
usedId[kkkBest] = iii;
|
distance[iii] = bestDistance;
|
||||||
distance[iii] = bestDistance;
|
//DOLLAR_INFO("set new link: " << iii << " with " << kkkBest << " d=" << bestDistance);
|
||||||
//DOLLAR_INFO("set new link: " << iii << " with " << kkkBest << " d=" << bestDistance);
|
if (previous != -1) {
|
||||||
if (previous != -1) {
|
//DOLLAR_INFO(" Reject : " << previous);
|
||||||
//DOLLAR_INFO(" Reject : " << previous);
|
distance[previous] = MAX_FLOAT;
|
||||||
distance[previous] = MAX_FLOAT;
|
iii = previous-1;
|
||||||
iii = previous-1;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,7 +305,7 @@ bool dollar::Engine::loadGesture(const std::string& _filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dollar::Engine::addGesture(Gesture _gesture) {
|
void dollar::Engine::addGesture(Gesture _gesture) {
|
||||||
_gesture.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance);
|
_gesture.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation, m_PPlusDistance, m_scaleKeepRatio);
|
||||||
m_gestures.push_back(std::move(_gesture));
|
m_gestures.push_back(std::move(_gesture));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +338,7 @@ dollar::Results dollar::Engine::recognize(const std::vector<std::vector<vec2>>&
|
|||||||
|
|
||||||
dollar::Results dollar::Engine::recognizeN(const std::vector<std::vector<vec2>>& _strokes, const std::string& _method) {
|
dollar::Results dollar::Engine::recognizeN(const std::vector<std::vector<vec2>>& _strokes, const std::string& _method) {
|
||||||
std::vector<vec2> points = dollar::combineStrokes(_strokes);
|
std::vector<vec2> points = dollar::combineStrokes(_strokes);
|
||||||
points = dollar::normalizePath(points, m_numPointsInGesture, m_paramterIgnoreRotation);
|
points = dollar::normalizePath(points, m_numPointsInGesture, m_paramterIgnoreRotation, m_scaleKeepRatio);
|
||||||
vec2 startv = dollar::getStartVector(points, m_numPointsInGesture/RATIO_START_VECTOR);
|
vec2 startv = dollar::getStartVector(points, m_numPointsInGesture/RATIO_START_VECTOR);
|
||||||
std::vector<vec2> vector = normalyse(points);
|
std::vector<vec2> vector = normalyse(points);
|
||||||
// Keep maximum 5 results ...
|
// Keep maximum 5 results ...
|
||||||
@ -393,7 +422,7 @@ dollar::Results dollar::Engine::recognizeN(const std::vector<std::vector<vec2>>&
|
|||||||
|
|
||||||
dollar::Results dollar::Engine::recognizeP(const std::vector<std::vector<vec2>>& _strokes) {
|
dollar::Results dollar::Engine::recognizeP(const std::vector<std::vector<vec2>>& _strokes) {
|
||||||
std::vector<vec2> points = dollar::combineStrokes(_strokes);
|
std::vector<vec2> points = dollar::combineStrokes(_strokes);
|
||||||
points = dollar::normalizePath(points, m_numPointsInGesture, m_paramterIgnoreRotation);
|
points = dollar::normalizePath(points, m_numPointsInGesture, m_paramterIgnoreRotation, m_scaleKeepRatio);
|
||||||
// Keep maximum 5 results ...
|
// Keep maximum 5 results ...
|
||||||
float bestDistance[MAX_RESULT_NUMBER];
|
float bestDistance[MAX_RESULT_NUMBER];
|
||||||
int32_t indexOfBestMatch[MAX_RESULT_NUMBER];
|
int32_t indexOfBestMatch[MAX_RESULT_NUMBER];
|
||||||
@ -456,10 +485,11 @@ dollar::Results dollar::Engine::recognizeP(const std::vector<std::vector<vec2>>&
|
|||||||
|
|
||||||
|
|
||||||
static void storeSVG(const std::string& _fileName,
|
static void storeSVG(const std::string& _fileName,
|
||||||
const dollar::Gesture& gesture,
|
const dollar::Gesture& gesture,
|
||||||
const std::vector<std::vector<vec2>>& _strokes,
|
const std::vector<std::vector<vec2>>& _strokes,
|
||||||
const std::vector<vec2>& _points,
|
const std::vector<vec2>& _points,
|
||||||
std::vector<std::pair<int32_t, int32_t>> _links) {
|
std::vector<std::pair<int32_t, int32_t>> _links,
|
||||||
|
bool _keepAspectRatio) {
|
||||||
std::string data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
|
std::string data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
|
||||||
data += "<svg height=\"100\" width=\"100\">\n";
|
data += "<svg height=\"100\" width=\"100\">\n";
|
||||||
for (auto &itLines : gesture.getPath()) {
|
for (auto &itLines : gesture.getPath()) {
|
||||||
@ -476,7 +506,7 @@ static void storeSVG(const std::string& _fileName,
|
|||||||
data += "\"\n";
|
data += "\"\n";
|
||||||
data += " />\n";
|
data += " />\n";
|
||||||
}
|
}
|
||||||
for (auto &itLines : dollar::scaleToOne(_strokes)) {
|
for (auto &itLines : dollar::scaleToOne(_strokes, _keepAspectRatio)) {
|
||||||
data += " <polyline fill=\"none\" stroke=\"purple\" stroke-opacity=\"0.8\" stroke-width=\"2\"\n";
|
data += " <polyline fill=\"none\" stroke=\"purple\" stroke-opacity=\"0.8\" stroke-width=\"2\"\n";
|
||||||
data += " points=\"";
|
data += " points=\"";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@ -513,7 +543,7 @@ static void storeSVG(const std::string& _fileName,
|
|||||||
|
|
||||||
|
|
||||||
dollar::Results dollar::Engine::recognizePPlus(const std::vector<std::vector<vec2>>& _strokes) {
|
dollar::Results dollar::Engine::recognizePPlus(const std::vector<std::vector<vec2>>& _strokes) {
|
||||||
std::vector<vec2> points = dollar::normalizePathToPoints(_strokes, m_PPlusDistance);
|
std::vector<vec2> points = dollar::normalizePathToPoints(_strokes, m_PPlusDistance, m_scaleKeepRatio);
|
||||||
// Keep maximum 5 results ...
|
// Keep maximum 5 results ...
|
||||||
float bestDistance[MAX_RESULT_NUMBER];
|
float bestDistance[MAX_RESULT_NUMBER];
|
||||||
int32_t indexOfBestMatch[MAX_RESULT_NUMBER];
|
int32_t indexOfBestMatch[MAX_RESULT_NUMBER];
|
||||||
@ -536,7 +566,7 @@ dollar::Results dollar::Engine::recognizePPlus(const std::vector<std::vector<vec
|
|||||||
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);
|
||||||
storeSVG("out_dollar/lib/recognizePPlus/" + gesture.getName() + "_" + etk::to_string(gesture.getId()) + ".svg", gesture, _strokes, points, dataPair);
|
//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<MAX_RESULT_NUMBER; ++kkk) {
|
for (size_t kkk=0; kkk<MAX_RESULT_NUMBER; ++kkk) {
|
||||||
if (distance < bestDistance[kkk]) {
|
if (distance < bestDistance[kkk]) {
|
||||||
if (kkk == 0) {
|
if (kkk == 0) {
|
||||||
|
@ -17,6 +17,15 @@ namespace dollar {
|
|||||||
class Engine {
|
class Engine {
|
||||||
protected:
|
protected:
|
||||||
float m_PPlusDistance;
|
float m_PPlusDistance;
|
||||||
|
public:
|
||||||
|
void setPPlusDistance(float _value);
|
||||||
|
float getPPlusDistance();
|
||||||
|
protected:
|
||||||
|
bool m_scaleKeepRatio; // when rescale the path, keep the aspect ration for processing
|
||||||
|
public:
|
||||||
|
void setScaleKeepRatio(bool _value);
|
||||||
|
bool getScaleKeepRatio();
|
||||||
|
protected:
|
||||||
float m_angleRange;
|
float m_angleRange;
|
||||||
bool m_paramterIgnoreRotation; //!< Ignore the start rotation of the gesture
|
bool m_paramterIgnoreRotation; //!< Ignore the start rotation of the gesture
|
||||||
public:
|
public:
|
||||||
|
@ -90,7 +90,6 @@ bool dollar::Gesture::loadJSON(const std::string& _fileName) {
|
|||||||
m_name = doc["value"].toString().get();
|
m_name = doc["value"].toString().get();
|
||||||
m_subId = doc["sub-id"].toNumber().getU64(),
|
m_subId = doc["sub-id"].toNumber().getU64(),
|
||||||
m_path = loadPointsJson(doc);
|
m_path = loadPointsJson(doc);
|
||||||
m_path = dollar::scaleToOne(m_path);
|
|
||||||
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
|
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -110,7 +109,6 @@ bool dollar::Gesture::loadSVG(const std::string& _fileName) {
|
|||||||
it2.setY(it2.y()*-1);
|
it2.setY(it2.y()*-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_path = dollar::scaleToOne(m_path);
|
|
||||||
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
|
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -151,7 +149,7 @@ void dollar::Gesture::storeJSON(const std::string& _fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dollar::Gesture::storeSVG(const std::string& _fileName, bool _storeDot) {
|
void dollar::Gesture::storeSVG(const std::string& _fileName, bool _storeDot) {
|
||||||
std::vector<std::vector<vec2>> strokes = dollar::scaleToOne(m_path);
|
std::vector<std::vector<vec2>> strokes = dollar::scaleToOne(m_path, true);
|
||||||
std::string data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
|
std::string data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
|
||||||
data += "<svg height=\"100\" width=\"100\">\n";
|
data += "<svg height=\"100\" width=\"100\">\n";
|
||||||
for (auto &itLines : strokes) {
|
for (auto &itLines : strokes) {
|
||||||
@ -185,23 +183,25 @@ void dollar::Gesture::set(const std::string& _name, uint32_t _subId, std::vector
|
|||||||
m_engineVector.clear();
|
m_engineVector.clear();
|
||||||
m_engineStartV.clear();
|
m_engineStartV.clear();
|
||||||
m_enginePoints.clear();
|
m_enginePoints.clear();
|
||||||
|
m_path2.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dollar::Gesture::configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation, float _distance) {
|
void dollar::Gesture::configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation, float _distance, bool _keepAspectRatio) {
|
||||||
m_enginePath.clear();
|
m_enginePath.clear();
|
||||||
m_engineVector.clear();
|
m_engineVector.clear();
|
||||||
m_engineStartV.clear();
|
m_engineStartV.clear();
|
||||||
m_enginePoints.clear();
|
m_enginePoints.clear();
|
||||||
|
m_path2 = dollar::scaleToOne(m_path, _keepAspectRatio);
|
||||||
// Generates dots:
|
// Generates dots:
|
||||||
m_enginePoints = dollar::normalizePathToPoints(m_path, _distance);
|
m_enginePoints = dollar::normalizePathToPoints(m_path, _distance, _keepAspectRatio);
|
||||||
DOLLAR_VERBOSE("create " << m_enginePoints.size() << " points");
|
DOLLAR_VERBOSE("create " << m_enginePoints.size() << " points");
|
||||||
// for debug only
|
// for debug only
|
||||||
storeSVG("out_dollar/lib/gestures/" + m_name + "_" + etk::to_string(m_subId) + ".svg", true);
|
//storeSVG("out_dollar/lib/gestures/" + m_name + "_" + etk::to_string(m_subId) + ".svg", true);
|
||||||
// Simplyfy paths
|
// Simplyfy paths
|
||||||
std::vector<std::vector<vec2>> uniPath = dollar::makeReferenceStrokes(m_path);
|
std::vector<std::vector<vec2>> uniPath = dollar::makeReferenceStrokes(m_path);
|
||||||
// normalize paths
|
// normalize paths
|
||||||
for (auto &it : uniPath) {
|
for (auto &it : uniPath) {
|
||||||
std::vector<vec2> val = dollar::normalizePath(it, _nbSample, _ignoreRotation);
|
std::vector<vec2> val = dollar::normalizePath(it, _nbSample, _ignoreRotation, _keepAspectRatio);
|
||||||
m_enginePath.push_back(val);
|
m_enginePath.push_back(val);
|
||||||
// calculate start vector:
|
// calculate start vector:
|
||||||
vec2 startv = dollar::getStartVector(val, _startAngleIndex);
|
vec2 startv = dollar::getStartVector(val, _startAngleIndex);
|
||||||
|
@ -14,6 +14,7 @@ namespace dollar {
|
|||||||
std::string m_name;
|
std::string m_name;
|
||||||
uint32_t m_subId;
|
uint32_t m_subId;
|
||||||
std::vector<std::vector<vec2>> m_path;
|
std::vector<std::vector<vec2>> m_path;
|
||||||
|
std::vector<std::vector<vec2>> m_path2;
|
||||||
public:
|
public:
|
||||||
Gesture();
|
Gesture();
|
||||||
bool load(const std::string& _filename);
|
bool load(const std::string& _filename);
|
||||||
@ -32,10 +33,10 @@ namespace dollar {
|
|||||||
return m_subId;
|
return m_subId;
|
||||||
}
|
}
|
||||||
const std::vector<std::vector<vec2>>& getPath() const {
|
const std::vector<std::vector<vec2>>& getPath() const {
|
||||||
return m_path;
|
return m_path2;
|
||||||
}
|
}
|
||||||
std::vector<std::vector<vec2>>& getPath() {
|
std::vector<std::vector<vec2>>& getPath() {
|
||||||
return m_path;
|
return m_path2;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::vector<vec2>> m_enginePath; // Singulized path with every conbinaison
|
std::vector<std::vector<vec2>> m_enginePath; // Singulized path with every conbinaison
|
||||||
@ -44,7 +45,7 @@ namespace dollar {
|
|||||||
std::vector<vec2> m_enginePoints;
|
std::vector<vec2> m_enginePoints;
|
||||||
public:
|
public:
|
||||||
// Configure the reference gesture for recognition...
|
// Configure the reference gesture for recognition...
|
||||||
void configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation, float _distance);
|
void configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation, float _distance, bool _keepAspectRatio);
|
||||||
size_t getEngineSize() const {
|
size_t getEngineSize() const {
|
||||||
return m_enginePath.size();
|
return m_enginePath.size();
|
||||||
}
|
}
|
||||||
|
@ -52,18 +52,23 @@ std::vector<vec2> dollar::scaleToOne(const std::vector<vec2>& _points, bool _kee
|
|||||||
dollar::Rectangle box(_points);
|
dollar::Rectangle box(_points);
|
||||||
std::vector<vec2> out;
|
std::vector<vec2> out;
|
||||||
vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y());
|
vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y());
|
||||||
|
vec2 offset(0,0);
|
||||||
if (_keepAspectRation == true) {
|
if (_keepAspectRation == true) {
|
||||||
float val = 1;
|
float val = 1;
|
||||||
if (box.getSize().x() > 0) {
|
offset = box.getSize() * val;
|
||||||
|
if (box.getSize().x() > box.getSize().y()) {
|
||||||
val = 1.0f/box.getSize().x();
|
val = 1.0f/box.getSize().x();
|
||||||
|
offset = vec2(0.0f, (1.0f-offset.y())*0.5f);
|
||||||
} else {
|
} else {
|
||||||
val = 1.0f/box.getSize().y();
|
val = 1.0f/box.getSize().y();
|
||||||
|
offset = vec2((1.0f-offset.x())*0.5f, 0.0f);
|
||||||
}
|
}
|
||||||
scale = vec2(val,val);
|
scale = vec2(val,val);
|
||||||
}
|
}
|
||||||
for (auto &it : _points) {
|
for (auto &it : _points) {
|
||||||
vec2 tmp = it - box.getPos();
|
vec2 tmp = it - box.getPos();
|
||||||
tmp *= scale;
|
tmp *= scale;
|
||||||
|
//tmp += offset;
|
||||||
out.push_back(tmp);
|
out.push_back(tmp);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@ -73,12 +78,16 @@ std::vector<std::vector<vec2>> dollar::scaleToOne(const std::vector<std::vector<
|
|||||||
dollar::Rectangle box(_points);
|
dollar::Rectangle box(_points);
|
||||||
std::vector<std::vector<vec2>> out;
|
std::vector<std::vector<vec2>> out;
|
||||||
vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y());
|
vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y());
|
||||||
|
vec2 offset(0,0);
|
||||||
if (_keepAspectRation == true) {
|
if (_keepAspectRation == true) {
|
||||||
float val = 1;
|
float val = 1;
|
||||||
if (box.getSize().x() > 0) {
|
offset = box.getSize() * val;
|
||||||
|
if (box.getSize().x() > box.getSize().y()) {
|
||||||
val = 1.0f/box.getSize().x();
|
val = 1.0f/box.getSize().x();
|
||||||
|
offset = vec2(0.0f, (1.0f-offset.y())*0.5f);
|
||||||
} else {
|
} else {
|
||||||
val = 1.0f/box.getSize().y();
|
val = 1.0f/box.getSize().y();
|
||||||
|
offset = vec2((1.0f-offset.x())*0.5f, 0.0f);
|
||||||
}
|
}
|
||||||
scale = vec2(val,val);
|
scale = vec2(val,val);
|
||||||
}
|
}
|
||||||
@ -87,6 +96,7 @@ std::vector<std::vector<vec2>> dollar::scaleToOne(const std::vector<std::vector<
|
|||||||
for (auto &itPoint : it) {
|
for (auto &itPoint : it) {
|
||||||
vec2 tmp = itPoint - box.getPos();
|
vec2 tmp = itPoint - box.getPos();
|
||||||
tmp *= scale;
|
tmp *= scale;
|
||||||
|
//tmp += offset;
|
||||||
stroke.push_back(tmp);
|
stroke.push_back(tmp);
|
||||||
}
|
}
|
||||||
out.push_back(stroke);
|
out.push_back(stroke);
|
||||||
@ -204,19 +214,19 @@ std::vector<vec2> dollar::normalyse(const std::vector<vec2>& _points) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<vec2> dollar::normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation) {
|
std::vector<vec2> dollar::normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation, bool _keepAspectRatio) {
|
||||||
_points = dollar::resample(_points, _nbSample);
|
_points = dollar::resample(_points, _nbSample);
|
||||||
if (_ignoreRotation == true) {
|
if (_ignoreRotation == true) {
|
||||||
_points = rotateToZero(_points);
|
_points = rotateToZero(_points);
|
||||||
}
|
}
|
||||||
_points = scaleToOne(_points);
|
_points = scaleToOne(_points, _keepAspectRatio);
|
||||||
return translateBariCenterToZero(_points);
|
return translateBariCenterToZero(_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<vec2> dollar::normalizePathToPoints(std::vector<std::vector<vec2>> _points, float _distance) {
|
std::vector<vec2> dollar::normalizePathToPoints(std::vector<std::vector<vec2>> _points, float _distance, bool _keepAspectRatio) {
|
||||||
// Scale point to (0.0,0.0) position and (1.0,1.0) size
|
// Scale point to (0.0,0.0) position and (1.0,1.0) size
|
||||||
_points = dollar::scaleToOne(_points);
|
_points = dollar::scaleToOne(_points, _keepAspectRatio);
|
||||||
std::vector<vec2> out;
|
std::vector<vec2> out;
|
||||||
for (auto &it : _points) {
|
for (auto &it : _points) {
|
||||||
if (it.size() == 0) {
|
if (it.size() == 0) {
|
||||||
|
@ -47,7 +47,7 @@ namespace dollar {
|
|||||||
* @param[in] _keepAspectRation Keep the aspect ratio of the scaling
|
* @param[in] _keepAspectRation Keep the aspect ratio of the scaling
|
||||||
* @return modify points
|
* @return modify points
|
||||||
*/
|
*/
|
||||||
std::vector<vec2> scaleToOne(const std::vector<vec2>& _points, bool _keepAspectRation=false);
|
std::vector<vec2> scaleToOne(const std::vector<vec2>& _points, bool _keepAspectRation=true);
|
||||||
/**
|
/**
|
||||||
* @brief Scale the list of point in a 1.0*1.0 box started at 0.0*0.0
|
* @brief Scale the list of point in a 1.0*1.0 box started at 0.0*0.0
|
||||||
* @param[in] _points input path
|
* @param[in] _points input path
|
||||||
@ -98,18 +98,20 @@ namespace dollar {
|
|||||||
* @param[in] _points List of points in the path
|
* @param[in] _points List of points in the path
|
||||||
* @param[in] _nbSample Number of element to resample
|
* @param[in] _nbSample Number of element to resample
|
||||||
* @param[in] _ignoreRotation Ignore start rotation of the algorithm
|
* @param[in] _ignoreRotation Ignore start rotation of the algorithm
|
||||||
|
* @param[in] _keepAspectRatio Keep Aspect ratio when scaling to the correct size (1.0,1.0) (it will be centered)
|
||||||
* @return new list of points
|
* @return new list of points
|
||||||
*/
|
*/
|
||||||
std::vector<vec2> normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation);
|
std::vector<vec2> normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation, bool _keepAspectRatio);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Transform the path to be comparable, resample the path with a specific number of sample, and limit size at 1.0 square center around 0
|
* @brief Transform the path to be comparable, resample the path with a specific number of sample, and limit size at 1.0 square center around 0
|
||||||
* @note The difference with @ref normalizePath is thet we do not combinethe path together, that permit to not have unneded point between strokes...
|
* @note The difference with @ref normalizePath is thet we do not combinethe path together, that permit to not have unneded point between strokes...
|
||||||
* @param[in] _points List of points in the path
|
* @param[in] _points List of points in the path
|
||||||
* @param[in] _distance Distance between points
|
* @param[in] _distance Distance between points
|
||||||
|
* @param[in] _keepAspectRatio Keep Aspect ratio when scaling to the correct size (1.0,1.0) (it will be centered)
|
||||||
* @return new list of points
|
* @return new list of points
|
||||||
*/
|
*/
|
||||||
std::vector<vec2> normalizePathToPoints(std::vector<std::vector<vec2>> _points, float _distance);
|
std::vector<vec2> normalizePathToPoints(std::vector<std::vector<vec2>> _points, float _distance, bool _keepAspectRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ 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::Engine reco;
|
||||||
|
reco.setScaleKeepRatio(false);
|
||||||
TEST_PRINT("---------------------------------------------------------------------------");
|
TEST_PRINT("---------------------------------------------------------------------------");
|
||||||
TEST_PRINT("-- Load Gestures: " << _srcGesture);
|
TEST_PRINT("-- Load Gestures: " << _srcGesture);
|
||||||
TEST_PRINT("---------------------------------------------------------------------------");
|
TEST_PRINT("---------------------------------------------------------------------------");
|
||||||
@ -153,6 +154,7 @@ bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus) {
|
|||||||
// "label_type" ==> list of (result, file test name)
|
// "label_type" ==> list of (result, file test name)
|
||||||
std::map<std::string, std::vector<std::pair<dollar::Results, std::string>>> agregateResults;
|
std::map<std::string, std::vector<std::pair<dollar::Results, std::string>>> agregateResults;
|
||||||
int32_t nbRecognise = 0;
|
int32_t nbRecognise = 0;
|
||||||
|
int32_t nbRecognise2 = 0;
|
||||||
int32_t nbtested = 0;
|
int32_t nbtested = 0;
|
||||||
for (auto &it : files) {
|
for (auto &it : files) {
|
||||||
std::string label;
|
std::string label;
|
||||||
@ -180,15 +182,20 @@ bool testCorpus(const std::string& _srcGesture, const std::string& _srcCorpus) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (res.getName() == label) {
|
if (res.getName() == label) {
|
||||||
nbRecognise ++;
|
nbRecognise++;
|
||||||
|
nbRecognise2++;
|
||||||
TEST_INFO(" " << res.getName() << " score=" << res.getConfidence());
|
TEST_INFO(" " << res.getName() << " score=" << res.getConfidence());
|
||||||
} else {
|
} else if (etk::toupper(res.getName()) == etk::toupper(label)) {
|
||||||
|
nbRecognise2++;
|
||||||
|
TEST_WARNING(" " << res.getName() << " score=" << res.getConfidence());
|
||||||
|
}else {
|
||||||
TEST_ERROR(" " << res.getName() << " score=" << res.getConfidence());
|
TEST_ERROR(" " << res.getName() << " score=" << res.getConfidence());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
annalyseResult(agregateResults);
|
annalyseResult(agregateResults);
|
||||||
TEST_PRINT("Recognise: " << nbRecognise << " / " << nbtested << " ==> " << (float(nbRecognise) / float(nbtested) * 100.0f) << " %");
|
TEST_PRINT("Recognise: " << nbRecognise << " / " << nbtested << " ==> " << (float(nbRecognise) / float(nbtested) * 100.0f) << " %");
|
||||||
|
TEST_PRINT("Recognise (a==A): " << nbRecognise2 << " / " << nbtested << " ==> " << (float(nbRecognise2) / float(nbtested) * 100.0f) << " %");
|
||||||
// All is done corectly
|
// All is done corectly
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,11 @@ bool testCorpus(const std::string& _srcCorpus) {
|
|||||||
}
|
}
|
||||||
//listOfElementInCorpus.clear();
|
//listOfElementInCorpus.clear();
|
||||||
//listOfElementInCorpus.push_back("z");
|
//listOfElementInCorpus.push_back("z");
|
||||||
|
// Value to stop grouping in the same element ...
|
||||||
|
float groupSize = 1.0;
|
||||||
|
groupSize = 1.0;
|
||||||
|
bool keepAspectRatio = false;
|
||||||
|
|
||||||
TEST_PRINT(" will done for: " << listOfElementInCorpus);
|
TEST_PRINT(" will done for: " << listOfElementInCorpus);
|
||||||
for (auto &itTypeOfCorpus : listOfElementInCorpus) {
|
for (auto &itTypeOfCorpus : listOfElementInCorpus) {
|
||||||
TEST_PRINT("---------------------------------------------------------------------------");
|
TEST_PRINT("---------------------------------------------------------------------------");
|
||||||
@ -141,19 +146,28 @@ bool testCorpus(const std::string& _srcCorpus) {
|
|||||||
it.resize(fileFiltered.size(), OUT_OF_RANGE);
|
it.resize(fileFiltered.size(), OUT_OF_RANGE);
|
||||||
}
|
}
|
||||||
// Generate Full Files:
|
// Generate Full Files:
|
||||||
|
std::string itTypeOfCorpusFileName = itTypeOfCorpus;
|
||||||
|
if (itTypeOfCorpusFileName == "/") {
|
||||||
|
itTypeOfCorpusFileName = "slash";
|
||||||
|
} else if (itTypeOfCorpusFileName == "\\") {
|
||||||
|
itTypeOfCorpusFileName = "back-slash";
|
||||||
|
} else if (itTypeOfCorpusFileName == "?") {
|
||||||
|
itTypeOfCorpusFileName = "question";
|
||||||
|
}
|
||||||
{
|
{
|
||||||
std::vector<std::string> listPath;
|
std::vector<std::string> listPath;
|
||||||
for (size_t iii=0; iii<fileFiltered.size(); ++iii) {
|
for (size_t iii=0; iii<fileFiltered.size(); ++iii) {
|
||||||
listPath.push_back(fileFiltered[iii]);
|
listPath.push_back(fileFiltered[iii]);
|
||||||
}
|
}
|
||||||
generateFile("out_dollar/generate-form/pre_generate/" + itTypeOfCorpus + "_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;
|
dollar::Gesture gest;
|
||||||
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, 0.1);
|
gest.configure(10, 8, false, 0.1, keepAspectRatio);
|
||||||
dollar::Engine reco;
|
dollar::Engine reco;
|
||||||
|
reco.setScaleKeepRatio(keepAspectRatio);
|
||||||
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];
|
||||||
@ -177,9 +191,7 @@ bool testCorpus(const std::string& _srcCorpus) {
|
|||||||
TEST_PRINT("---------------------------------------------------------------------------");
|
TEST_PRINT("---------------------------------------------------------------------------");
|
||||||
int32_t residualValues = fileFiltered.size();
|
int32_t residualValues = fileFiltered.size();
|
||||||
int32_t subId = 1;
|
int32_t subId = 1;
|
||||||
// Value to stop grouping in the same element ...
|
|
||||||
float groupSize = 1.0;
|
|
||||||
groupSize = 1.0;
|
|
||||||
while (residualValues > 0) {
|
while (residualValues > 0) {
|
||||||
std::vector<int32_t> countMinimum;
|
std::vector<int32_t> countMinimum;
|
||||||
countMinimum.resize(fileFiltered.size(), 0);
|
countMinimum.resize(fileFiltered.size(), 0);
|
||||||
@ -201,6 +213,10 @@ bool testCorpus(const std::string& _srcCorpus) {
|
|||||||
}
|
}
|
||||||
if (bestId == -1) {
|
if (bestId == -1) {
|
||||||
TEST_ERROR("No more elements ... residualValues=" << residualValues);
|
TEST_ERROR("No more elements ... residualValues=" << residualValues);
|
||||||
|
|
||||||
|
// TODO : Add the rest of the elements ...
|
||||||
|
|
||||||
|
|
||||||
//==> Exit loop
|
//==> Exit loop
|
||||||
residualValues = 0;
|
residualValues = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -279,22 +295,28 @@ bool testCorpus(const std::string& _srcCorpus) {
|
|||||||
results[jjj][linkIds[iii]] = OUT_OF_RANGE;
|
results[jjj][linkIds[iii]] = OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (linkIds.size() <= 3) {
|
||||||
|
TEST_ERROR("Group is too small ... residualValues=" << residualValues);
|
||||||
|
// TODO : Add the rest of the elements ...
|
||||||
|
//==> Exit loop
|
||||||
|
residualValues = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
residualValues -= (linkIds.size() +1);
|
residualValues -= (linkIds.size() +1);
|
||||||
|
|
||||||
TEST_DEBUG("Generate output files (SVG with all added path in one file)");
|
TEST_DEBUG("Generate output files (SVG with all added path in one file)");
|
||||||
// Generate Files:
|
// Generate Files:
|
||||||
std::vector<std::string> listPath;
|
std::vector<std::string> listPath;
|
||||||
for (size_t iii=0; iii<linkIds.size(); ++iii) {
|
for (size_t iii=0; iii<linkIds.size(); ++iii) {
|
||||||
listPath.push_back(fileFiltered[linkIds[iii]]);
|
listPath.push_back(fileFiltered[linkIds[iii]]);
|
||||||
}
|
}
|
||||||
generateFile("out_dollar/generate-form/pre_generate/" + itTypeOfCorpus + "_" + etk::to_string(subId) + ".svg", listPath, fileFiltered[bestId]);
|
generateFile("out_dollar/generate-form/pre_generate/" + itTypeOfCorpusFileName + "_" + etk::to_string(subId) + ".svg", listPath, fileFiltered[bestId]);
|
||||||
TEST_DEBUG("Generate output file (corpus ...)");
|
TEST_DEBUG("Generate output file (corpus ...)");
|
||||||
// declare a Gesture (internal API)
|
// declare a Gesture (internal API)
|
||||||
dollar::Gesture ref;
|
dollar::Gesture ref;
|
||||||
ref.set(itTypeOfCorpus, subId, dollar::loadPoints(fileFiltered[bestId]));
|
ref.set(itTypeOfCorpus, subId, dollar::loadPoints(fileFiltered[bestId]));
|
||||||
// Store gesture with his extention type:
|
// Store gesture with his extention type:
|
||||||
ref.store("out_dollar/generate-form/corpus/" + itTypeOfCorpus + "_" + etk::to_string(subId) + ".json");
|
ref.store("out_dollar/generate-form/corpus/" + itTypeOfCorpusFileName + "_" + etk::to_string(subId) + ".json");
|
||||||
ref.store("out_dollar/generate-form/corpus_svg/" + itTypeOfCorpus + "_" + etk::to_string(subId) + ".svg");
|
ref.store("out_dollar/generate-form/corpus_svg/" + itTypeOfCorpusFileName + "_" + etk::to_string(subId) + ".svg");
|
||||||
|
|
||||||
|
|
||||||
// Increment subId...
|
// Increment subId...
|
||||||
|
Loading…
x
Reference in New Issue
Block a user