Files
AI-on-the-edge-device/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp
michael 4cd8cad83d test5
2026-01-20 23:43:45 +01:00

1307 lines
52 KiB
C++

#include "defines.h"
#include <math.h>
#include <iomanip>
#include <sys/types.h>
#include <sstream> // std::stringstream
#include "esp_log.h"
#include "ClassFlowCNNGeneral.h"
#include "MainFlowControl.h"
#include "ClassControllCamera.h"
#include "CTfLiteClass.h"
#include "ClassLogFile.h"
static const char *TAG = "CNN";
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
{
cnn_model_file = "";
model_x_size = 1;
model_y_size = 1;
CNNGoodThreshold = 0.0;
ListFlowControll = NULL;
previousElement = NULL;
isLogImageSelect = false;
CNNType = _cnntype;
flowpostalignment = _flowalign;
imagesRetention = 5;
disabled = false;
}
std::vector<double> ClassFlowCNNGeneral::getMeterValues(int _number = 0)
{
std::vector<double> meterValues;
if (GENERAL[_number]->ROI.size() == 0)
{
return meterValues;
}
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
if (CNNType == Digit)
{
meterValues.push_back(GENERAL[_number]->ROI[_roi]->result_klasse);
}
else
{
meterValues.push_back(GENERAL[_number]->ROI[_roi]->result_float);
}
}
return meterValues;
}
std::string ClassFlowCNNGeneral::getReadout(int _number = 0, bool _extendedResolution, int prev, float _before_narrow_Analog, float AnalogToDigitTransitionStart)
{
std::string result = "";
if (GENERAL[_number]->ROI.size() == 0)
{
return result;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout _number=" + std::to_string(_number) + ", _extendedResolution=" + std::to_string(_extendedResolution) + ", prev=" + std::to_string(prev));
if (CNNType == Analogue || CNNType == Analogue100)
{
float number = GENERAL[_number]->ROI[GENERAL[_number]->ROI.size() - 1]->result_float;
int result_after_decimal_point = ((int)floor(number * 10.0f) + 10) % 10;
prev = PointerEvalAnalog(GENERAL[_number]->ROI[GENERAL[_number]->ROI.size() - 1]->result_float, prev);
result = std::to_string(prev);
if (_extendedResolution)
{
result = result + std::to_string(result_after_decimal_point);
}
for (int _roi = GENERAL[_number]->ROI.size() - 2; _roi >= 0; --_roi)
{
prev = PointerEvalAnalog(GENERAL[_number]->ROI[_roi]->result_float, prev);
result = std::to_string(prev) + result;
}
return result;
}
if (CNNType == Digit)
{
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
if ((GENERAL[_number]->ROI[_roi]->result_klasse >= 0) && (GENERAL[_number]->ROI[_roi]->result_klasse < 10))
{
result = result + std::to_string(GENERAL[_number]->ROI[_roi]->result_klasse);
}
else
{
result = result + "N";
}
}
return result;
}
if ((CNNType == DoubleHyprid10) || (CNNType == Digit100))
{
float number = GENERAL[_number]->ROI[GENERAL[_number]->ROI.size() - 1]->result_float;
// NaN?
if ((number >= 0.0f) && (number < 10.0f))
{
// is only set if it is the first digit (no analogue before!)
if (_extendedResolution)
{
int result_after_decimal_point = ((int)floor(number * 10.0f)) % 10;
int result_before_decimal_point = ((int)floor(number)) % 10;
result = std::to_string(result_before_decimal_point) + std::to_string(result_after_decimal_point);
prev = result_before_decimal_point;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) result_before_decimal_point=" + std::to_string(result_before_decimal_point) + ", result_after_decimal_point=" + std::to_string(result_after_decimal_point) + ", prev=" + std::to_string(prev));
}
else
{
if (_before_narrow_Analog >= 0.0f)
{
prev = PointerEvalHybrid(GENERAL[_number]->ROI[GENERAL[_number]->ROI.size() - 1]->result_float, _before_narrow_Analog, prev, true, AnalogToDigitTransitionStart);
}
else
{
prev = PointerEvalHybrid(GENERAL[_number]->ROI[GENERAL[_number]->ROI.size() - 1]->result_float, prev, prev);
}
// is necessary because a number greater than 9.994999 returns a 10! (for further details see check in PointerEvalHybrid)
if ((prev >= 0) && (prev < 10))
{
result = std::to_string(prev);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100) prev=" + std::to_string(prev));
}
else
{
result = "N";
}
}
}
else
{
result = "N";
if (_extendedResolution && (CNNType != Digit))
{
result = "NN";
}
}
for (int _roi = GENERAL[_number]->ROI.size() - 2; _roi >= 0; --_roi)
{
if ((GENERAL[_number]->ROI[_roi]->result_float >= 0.0f) && (GENERAL[_number]->ROI[_roi]->result_float < 10.0f))
{
prev = PointerEvalHybrid(GENERAL[_number]->ROI[_roi]->result_float, GENERAL[_number]->ROI[_roi + 1]->result_float, prev);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(DoubleHyprid10) - roi_" + std::to_string(_roi) + "prev= " + std::to_string(prev));
result = std::to_string(prev) + result;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(DoubleHyprid10) - roi_" + std::to_string(_roi) + "result= " + result);
}
else
{
prev = -1;
result = "N" + result;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(result_float < 0 /'N') - roi_" + std::to_string(_roi) + "result_float=" + std::to_string(GENERAL[_number]->ROI[_roi]->result_float));
}
}
return result;
}
return result;
}
/**
* @brief Determines the number of an ROI in connection with previous ROI results
*
* @param number: is the current ROI as float value from recognition
* @param number_of_predecessors: is the last (lower) ROI as float from recognition
* @param eval_predecessors: is the evaluated number. Sometimes a much lower value can change higer values
* example: 9.8, 9.9, 0.1
* 0.1 => 0 (eval_predecessors)
* The 0 makes a 9.9 to 0 (eval_predecessors)
* The 0 makes a 9.8 to 0
* @param Analog_Predecessors false/true if the last ROI is an analog or digit ROI (default=false)
* runs in special handling because analog is much less precise
* @param digitAnalogTransitionStart start of the transitionlogic begins on number_of_predecessor (default=9.2)
*
* @return int the determined number of the current ROI
*/
int ClassFlowCNNGeneral::PointerEvalHybrid(float number, float number_of_predecessors, int eval_predecessors, bool Analog_Predecessors, float digitAnalogTransitionStart)
{
int result = -1;
int result_after_decimal_point = ((int)floor(number * 10.0f)) % 10;
int result_before_decimal_point = ((int)(floor(number) + 10.0f)) % 10;
if (eval_predecessors < 0)
{
// on first digit is no spezial logic for transition needed
// we use the recognition as given. The result is the int value of the recognition
// add precisition of 2 digits and round before trunc
// a number greater than 9.994999 is returned as 10, this leads to an error during the decimal shift because the NUMBERS[j]->ReturnRawValue is one digit longer.
// To avoid this, an additional test must be carried out, see "if ((CNNType == DoubleHyprid10) || (CNNType == Digit100))" check in getReadout()
result = (int)(trunc(round((float)((int)(number + 10.0f) % 10) * 100.0f)) / 100.0f);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybrid - No predecessor - Result = " + std::to_string(result) + " number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors) + " eval_predecessors = " + std::to_string(eval_predecessors) + " Digit_Uncertainty = " + std::to_string(Digit_Uncertainty));
return result;
}
if (Analog_Predecessors)
{
result = PointerEvalAnalogToDigit(number, number_of_predecessors, eval_predecessors, digitAnalogTransitionStart);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybrid - Analog predecessor, evaluation over PointerEvalAnalog = " + std::to_string(result) + " number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors) + " eval_predecessors = " + std::to_string(eval_predecessors) + " Digit_Uncertainty = " + std::to_string(Digit_Uncertainty));
return result;
}
if ((number_of_predecessors >= (float)Digit_Transition_Area_Predecessor) && (number_of_predecessors <= (10.0f - (float)Digit_Transition_Area_Predecessor)))
{
// no digit change, because predecessor is far enough away (0+/-DigitTransitionRangePredecessor) --> number is rounded
// Band around the digit --> Round off, as digit reaches inaccuracy in the frame
if ((result_after_decimal_point <= DigitBand) || (result_after_decimal_point >= (10 - DigitBand)))
{
result = ((int)(round(number) + 10.0f)) % 10;
}
else
{
result = ((int)(trunc(number) + 10.0f)) % 10;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybrid - NO analogue predecessor, no change of digits, as pre-decimal point far enough away = " + std::to_string(result) + " number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors) + " eval_predecessors = " + std::to_string(eval_predecessors) + " Digit_Uncertainty = " + std::to_string(Digit_Uncertainty));
return result;
}
// Zero crossing at the predecessor has taken place (! evaluation via Prev_value and not number!) --> round up here (2.8 --> 3, but also 3.1 --> 3)
if (eval_predecessors <= 1)
{
// We simply assume that the current digit after the zero crossing of the predecessor
// has passed through at least half (x.5)
if (result_after_decimal_point > 5)
{
// The current digit does not yet have a zero crossing, but the predecessor does..
result = (result_before_decimal_point + 1) % 10;
}
else
{
// Act. digit and predecessor have zero crossing
result = result_before_decimal_point % 10;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybrid - NO analogue predecessor, zero crossing has taken placen = " + std::to_string(result) + " number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors) + " eval_predecessors = " + std::to_string(eval_predecessors) + " Digit_Uncertainty = " + std::to_string(Digit_Uncertainty));
return result;
}
// remains only >= 9.x --> no zero crossing yet --> 2.8 --> 2,
// and from 9.7(DigitTransitionRangeLead) 3.1 --> 2
// everything >=x.4 can be considered as current number in transition. With 9.x predecessor the current
// number can still be x.6 - x.7.
// Preceding (else - branch) does not already happen from 9.
if (Digit_Transition_Area_Forward >= number_of_predecessors || result_after_decimal_point >= 4)
{
// The current digit, like the previous digit, does not yet have a zero crossing.
result = result_before_decimal_point % 10;
}
else
{
// current digit precedes the smaller digit (9.x). So already >=x.0 while the previous digit has not yet
// has no zero crossing. Therefore, it is reduced by 1.
result = (result_before_decimal_point + 9) % 10;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybrid - O analogue predecessor, >= 9.5 --> no zero crossing yet = " + std::to_string(result) + " number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors) + " eval_predecessors = " + std::to_string(eval_predecessors) + " Digit_Uncertainty = " + std::to_string(Digit_Uncertainty) + " result_after_decimal_point = " + std::to_string(result_after_decimal_point));
return result;
}
int ClassFlowCNNGeneral::PointerEvalAnalogToDigit(float number, float numeral_preceder, int eval_predecessors, float AnalogToDigitTransitionStart)
{
int result = -1;
int result_after_decimal_point = ((int)floor(number * 10.0f)) % 10;
int result_before_decimal_point = ((int)(floor(number) + 10.0f)) % 10;
bool roundedUp = false;
// Within the digit inequalities
// Band around the digit --> Round off, as digit reaches inaccuracy in the frame
if ((result_after_decimal_point >= (int)(10.0f - ((float)Digit_Uncertainty * 10.0f))) || (eval_predecessors <= 4 && result_after_decimal_point >= 6))
{
// or digit runs after (analogue =0..4, digit >=6)
result = (int)(round(number) + 10.0f) % 10;
roundedUp = true;
// before/ after decimal point, because we adjust the number based on the uncertainty.
result_after_decimal_point = ((int)floor(result * 10.0f)) % 10;
result_before_decimal_point = ((int)(floor(result) + 10.0f)) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigit - Digit Uncertainty - Result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder: " + std::to_string(numeral_preceder) + " erg before comma: " + std::to_string(result_before_decimal_point) + " erg after comma: " + std::to_string(result_after_decimal_point));
}
else
{
result = (int)((int)(trunc(number) + 10.0f)) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigit - NO digit Uncertainty - Result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder));
}
// No zero crossing has taken place.
// Only eval_predecessors used because numeral_preceder could be wrong here.
// numeral_preceder<=0.1 & eval_predecessors=9 corresponds to analogue was reset because of previous analogue that are not yet at 0.
if ((eval_predecessors >= 6 && (numeral_preceder > AnalogToDigitTransitionStart || numeral_preceder <= 0.2) && roundedUp))
{
result = ((result_before_decimal_point + 10) - 1) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigit - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " eerg after comma = " + std::to_string(result_after_decimal_point));
}
return result;
}
int ClassFlowCNNGeneral::PointerEvalAnalog(float number, int numeral_preceder)
{
int result = -1;
if (numeral_preceder == -1)
{
result = (int)floor(number);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalog - No predecessor - Result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
return result;
}
float number_min = number - ((float)Analog_error / 10.0f);
float number_max = number + ((float)Analog_error / 10.0f);
if ((int)floor(number_max) - (int)floor(number_min) != 0)
{
if (numeral_preceder <= (int)Analog_error)
{
result = ((int)(floor(number_max) + 10.0f)) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalog - number ambiguous, correction upwards - result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
return result;
}
if (numeral_preceder >= (10 - (int)Analog_error))
{
result = ((int)(floor(number_min) + 10.0f)) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalog - number ambiguous, downward correction - result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
return result;
}
}
result = ((int)(floor(number) + 10.0f)) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalog - number unambiguous, no correction necessary - result = " + std::to_string(result) + " number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
return result;
}
bool ClassFlowCNNGeneral::ReadParameter(FILE *pfile, std::string &aktparamgraph)
{
aktparamgraph = trim_string_left_right(aktparamgraph);
if (aktparamgraph.size() == 0)
{
if (!GetNextParagraph(pfile, aktparamgraph))
{
return false;
}
}
if ((to_upper(aktparamgraph).compare("[ANALOG]") != 0) && (to_upper(aktparamgraph).compare(";[ANALOG]") != 0) &&
(to_upper(aktparamgraph).compare("[DIGIT]") != 0) && (to_upper(aktparamgraph).compare(";[DIGIT]") != 0) &&
(to_upper(aktparamgraph).compare("[DIGITS]") != 0) && (to_upper(aktparamgraph).compare(";[DIGITS]") != 0))
{
// Paragraph passt nicht
return false;
}
if (aktparamgraph[0] == ';')
{
disabled = true;
while (getNextLine(pfile, &aktparamgraph) && !isNewParagraph(aktparamgraph))
;
ESP_LOGD(TAG, "[Analog/Digit] is disabled!");
return true;
}
std::vector<std::string> splitted;
while (getNextLine(pfile, &aktparamgraph) && !isNewParagraph(aktparamgraph))
{
splitted = split_line(aktparamgraph);
if (splitted.size() > 1)
{
std::string _param = to_upper(splitted[0]);
if (_param == "ROIIMAGESLOCATION")
{
imagesLocation = "/sdcard" + splitted[1];
isLogImage = true;
}
else if (_param == "LOGIMAGESELECT")
{
LogImageSelect = splitted[1];
isLogImageSelect = true;
}
else if (_param == "ROIIMAGESRETENTION")
{
if (is_string_numeric(splitted[1]))
{
imagesRetention = std::stoi(splitted[1]);
}
}
else if (_param == "MODEL")
{
cnn_model_file = splitted[1];
}
else if (_param == "CNNGOODTHRESHOLD")
{
if (is_string_numeric(splitted[1]))
{
CNNGoodThreshold = std::stof(splitted[1]);
}
}
else if (splitted.size() >= 5)
{
general *_general = GetGENERAL(splitted[0], true);
roi *new_roi = _general->ROI[_general->ROI.size() - 1];
if (is_string_numeric(splitted[1]) && is_string_numeric(splitted[2]) && is_string_numeric(splitted[3]) && is_string_numeric(splitted[4]))
{
new_roi->pos_x = std::stoi(splitted[1]);
new_roi->pos_y = std::stoi(splitted[2]);
new_roi->delta_x = std::stoi(splitted[3]);
new_roi->delta_y = std::stoi(splitted[4]);
}
else
{
new_roi->pos_x = 0;
new_roi->pos_y = 0;
new_roi->delta_x = 30;
new_roi->delta_y = 30;
}
new_roi->ccw = false;
if (splitted.size() >= 6)
{
new_roi->ccw = alphanumeric_to_boolean(splitted[5]);
}
new_roi->result_float = -1;
new_roi->image = NULL;
new_roi->image_org = NULL;
}
}
}
if (!getNetworkParameter())
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "An error occured on setting up the Network -> Disabling it!");
disabled = true; // An error occured, disable this CNN!
return false;
}
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
GENERAL[_number]->ROI[_roi]->image = new CImageBasis("ROI " + GENERAL[_number]->ROI[_roi]->name, model_x_size, model_y_size, model_channel);
GENERAL[_number]->ROI[_roi]->image_org = new CImageBasis("ROI " + GENERAL[_number]->ROI[_roi]->name + " original", GENERAL[_number]->ROI[_roi]->delta_x, GENERAL[_number]->ROI[_roi]->delta_y, 3);
}
}
return true;
}
general *ClassFlowCNNGeneral::FindGENERAL(std::string _name_number)
{
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
if (GENERAL[_number]->name == _name_number)
{
return GENERAL[_number];
}
}
return NULL;
}
general *ClassFlowCNNGeneral::GetGENERAL(std::string _name, bool _create = true)
{
std::string _number_sequence, _roi_name;
int _pospunkt = _name.find_first_of(".");
if (_pospunkt > -1)
{
_number_sequence = _name.substr(0, _pospunkt);
_roi_name = _name.substr(_pospunkt + 1, _name.length() - _pospunkt - 1);
}
else
{
_number_sequence = "default";
_roi_name = _name;
}
general *_ret = NULL;
for (int i = 0; i < GENERAL.size(); ++i)
{
if (GENERAL[i]->name == _number_sequence)
{
_ret = GENERAL[i];
}
}
// not found and should not be created
if (!_create)
{
return _ret;
}
if (_ret == NULL)
{
_ret = new general;
_ret->name = _number_sequence;
GENERAL.push_back(_ret);
}
roi *new_roi = new roi;
new_roi->name = _roi_name;
_ret->ROI.push_back(new_roi);
ESP_LOGD(TAG, "GetGENERAL - GENERAL %s - roi %s - ccw: %d", _number_sequence.c_str(), _roi_name.c_str(), new_roi->ccw);
return _ret;
}
std::string ClassFlowCNNGeneral::getHTMLSingleStep(std::string host)
{
std::vector<HTMLInfo *> html_info;
std::string result = "<p>Found ROIs: </p> <p><img src=\"" + host + "/img_tmp/alg_roi.jpg\"></p>\n";
result = result + "Analog Pointers: <p> ";
html_info = GetHTMLInfo();
for (int i = 0; i < html_info.size(); ++i)
{
std::stringstream stream;
stream << std::fixed << std::setprecision(1) << html_info[i]->val;
std::string temp_string = stream.str();
result = result + "<img src=\"" + host + "/img_tmp/" + html_info[i]->filename + "\"> " + temp_string;
delete html_info[i];
}
html_info.clear();
return result;
}
bool ClassFlowCNNGeneral::doFlow(std::string time_value)
{
if (disabled)
{
return true;
}
if (!doAlignAndCut(time_value))
{
return false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow after alignment");
doNeuralNetwork(time_value);
RemoveOldLogs();
return true;
}
bool ClassFlowCNNGeneral::doAlignAndCut(std::string time_value)
{
if (disabled)
{
return true;
}
CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
ESP_LOGD(TAG, "General %d - Align&Cut", _roi);
caic->CutAndSave(GENERAL[_number]->ROI[_roi]->pos_x, GENERAL[_number]->ROI[_roi]->pos_y, GENERAL[_number]->ROI[_roi]->delta_x, GENERAL[_number]->ROI[_roi]->delta_y, GENERAL[_number]->ROI[_roi]->image_org);
if (Camera.SaveAllFiles)
{
if (GENERAL[_number]->name == "default")
{
GENERAL[_number]->ROI[_roi]->image_org->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
else
{
GENERAL[_number]->ROI[_roi]->image_org->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
}
GENERAL[_number]->ROI[_roi]->image_org->Resize(model_x_size, model_y_size, GENERAL[_number]->ROI[_roi]->image);
if (Camera.SaveAllFiles)
{
if (GENERAL[_number]->name == "default")
{
GENERAL[_number]->ROI[_roi]->image->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
else
{
GENERAL[_number]->ROI[_roi]->image->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
}
}
}
return true;
}
void ClassFlowCNNGeneral::DrawROI(CImageBasis *Image)
{
if (Image->ImageOkay())
{
if (CNNType == Analogue || CNNType == Analogue100)
{
int r = 0;
int g = 255;
int b = 0;
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
{
for (int _roi = 0; _roi < GENERAL[_ana]->ROI.size(); ++_roi)
{
Image->drawRect(GENERAL[_ana]->ROI[_roi]->pos_x, GENERAL[_ana]->ROI[_roi]->pos_y, GENERAL[_ana]->ROI[_roi]->delta_x, GENERAL[_ana]->ROI[_roi]->delta_y, r, g, b, 1);
Image->drawEllipse((int)(GENERAL[_ana]->ROI[_roi]->pos_x + GENERAL[_ana]->ROI[_roi]->delta_x / 2), (int)(GENERAL[_ana]->ROI[_roi]->pos_y + GENERAL[_ana]->ROI[_roi]->delta_y / 2), (int)(GENERAL[_ana]->ROI[_roi]->delta_x / 2), (int)(GENERAL[_ana]->ROI[_roi]->delta_y / 2), r, g, b, 2);
Image->drawLine((int)(GENERAL[_ana]->ROI[_roi]->pos_x + GENERAL[_ana]->ROI[_roi]->delta_x / 2), (int)GENERAL[_ana]->ROI[_roi]->pos_y, (int)(GENERAL[_ana]->ROI[_roi]->pos_x + GENERAL[_ana]->ROI[_roi]->delta_x / 2), (int)(GENERAL[_ana]->ROI[_roi]->pos_y + GENERAL[_ana]->ROI[_roi]->delta_y), r, g, b, 2);
Image->drawLine((int)GENERAL[_ana]->ROI[_roi]->pos_x, (int)(GENERAL[_ana]->ROI[_roi]->pos_y + GENERAL[_ana]->ROI[_roi]->delta_y / 2), (int)GENERAL[_ana]->ROI[_roi]->pos_x + GENERAL[_ana]->ROI[_roi]->delta_x, (int)(GENERAL[_ana]->ROI[_roi]->pos_y + GENERAL[_ana]->ROI[_roi]->delta_y / 2), r, g, b, 2);
}
}
}
else
{
for (int _dig = 0; _dig < GENERAL.size(); ++_dig)
{
for (int _roi = 0; _roi < GENERAL[_dig]->ROI.size(); ++_roi)
{
Image->drawRect(GENERAL[_dig]->ROI[_roi]->pos_x, GENERAL[_dig]->ROI[_roi]->pos_y, GENERAL[_dig]->ROI[_roi]->delta_x, GENERAL[_dig]->ROI[_roi]->delta_y, 0, 0, (255 - _dig * 100), 2);
}
}
}
}
}
bool ClassFlowCNNGeneral::getNetworkParameter(void)
{
if (disabled)
{
return true;
}
std::string temp_cnn = "/sdcard" + cnn_model_file;
temp_cnn = format_filename(temp_cnn);
ESP_LOGD(TAG, "%s", temp_cnn.c_str());
CTfLiteClass *tflite = new CTfLiteClass;
if (!tflite->LoadModel(temp_cnn))
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnn_model_file + " -> Init aborted!");
LogFile.WriteHeapInfo("getNetworkParameter-LoadModel");
delete tflite;
return false;
}
if (!tflite->MakeAllocate())
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tflite model -> Init aborted!");
LogFile.WriteHeapInfo("getNetworkParameter-MakeAllocate");
delete tflite;
return false;
}
if (CNNType == AutoDetect)
{
tflite->GetInputDimension(false);
model_x_size = tflite->ReadInputDimenstion(0);
model_y_size = tflite->ReadInputDimenstion(1);
model_channel = tflite->ReadInputDimenstion(2);
int anz_output_dimensions = tflite->GetAnzOutPut();
switch (anz_output_dimensions)
{
case 2:
CNNType = Analogue;
ESP_LOGD(TAG, "TFlite-Type set to Analogue");
break;
case 10:
CNNType = DoubleHyprid10;
ESP_LOGD(TAG, "TFlite-Type set to DoubleHyprid10");
break;
case 11:
CNNType = Digit;
ESP_LOGD(TAG, "TFlite-Type set to Digit");
break;
// case 20:
// CNNType = DigitHyprid10;
// ESP_LOGD(TAG, "TFlite-Type set to DigitHyprid10");
// break;
// case 22:
// CNNType = DigitHyprid;
// ESP_LOGD(TAG, "TFlite-Type set to DigitHyprid");
// break;
case 100:
if (model_x_size == 32 && model_y_size == 32)
{
CNNType = Analogue100;
ESP_LOGD(TAG, "TFlite-Type set to Analogue100");
}
else
{
CNNType = Digit100;
ESP_LOGD(TAG, "TFlite-Type set to Digit");
}
break;
default:
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite does not fit the firmware (outout_dimension=" + std::to_string(anz_output_dimensions) + ")");
}
}
delete tflite;
return true;
}
// wird von "bool ClassFlowCNNGeneral::doFlow(std::string time_value)" aufgerufen
bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time_value)
{
if (disabled)
{
return false;
}
std::string cnn_model = "/sdcard" + cnn_model_file;
cnn_model = format_filename(cnn_model);
ESP_LOGD(TAG, "%s", cnn_model.c_str());
CTfLiteClass *tflite = new CTfLiteClass;
if (!tflite->LoadModel(cnn_model))
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnn_model_file + " -> Exec aborted this round!");
LogFile.WriteHeapInfo("doNeuralNetwork-LoadModel");
delete tflite;
return false;
}
if (!tflite->MakeAllocate())
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tfilte model -> Exec aborted this round!");
LogFile.WriteHeapInfo("doNeuralNetwork-MakeAllocate");
delete tflite;
return false;
}
std::string logPath = CreateLogFolder(time_value);
std::vector<NumberPost *> numbers = flowctrl.getNumbers();
time_t _imagetime; // in seconds
time(&_imagetime);
localtime(&_imagetime);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _imagetime: " + std::to_string(_imagetime));
// For each NUMBER
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Processing Number '" + GENERAL[_number]->name + "'");
int start_roi = 0;
if ((numbers[_number]->useMaxFlowRate) && (numbers[_number]->PreValueValid) && (numbers[_number]->timeStampLastValue == numbers[_number]->timeStampLastPreValue))
{
int _AnzahlDigit = numbers[_number]->AnzahlDigit;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _AnzahlDigit: " + std::to_string(_AnzahlDigit));
int _AnzahlAnalog = numbers[_number]->AnzahlAnalog;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _AnzahlAnalog: " + std::to_string(_AnzahlAnalog));
float _MaxFlowRate = (numbers[_number]->MaxFlowRate / 60); // in unit/minutes
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _MaxFlowRate: " + std::to_string(_MaxFlowRate));
float _LastPreValueTimeDifference = (float)((difftime(_imagetime, numbers[_number]->timeStampLastPreValue)) / 60); // in minutes
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _LastPreValueTimeDifference: " + std::to_string(_LastPreValueTimeDifference) + " minutes");
std::string _PreValue_old = std::to_string((float)numbers[_number]->PreValue);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _PreValue_old: " + _PreValue_old);
////////////////////////////////////////////////////
std::string _PreValue_new1 = std::to_string((float)numbers[_number]->PreValue + (_MaxFlowRate * _LastPreValueTimeDifference));
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _PreValue_new1: " + _PreValue_new1);
std::string _PreValue_new2 = std::to_string((float)numbers[_number]->PreValue - (_MaxFlowRate * _LastPreValueTimeDifference));
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _PreValue_new2: " + _PreValue_new2);
////////////////////////////////////////////////////
// is necessary because there are always 6 numbers after the DecimalPoint due to float
int _CorrectionValue = 0;
int _pospunkt = _PreValue_old.find_first_of(".");
if (_pospunkt > -1)
{
_CorrectionValue = _PreValue_old.length() - _pospunkt;
_CorrectionValue = _CorrectionValue - numbers[_number]->Nachkomma;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _CorrectionValue: " + std::to_string(_CorrectionValue));
int _PreValue_len = ((int)_PreValue_old.length() - _CorrectionValue);
if (numbers[_number]->ExtendedResolution)
{
_PreValue_len = _PreValue_len - 1;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doNeuralNetwork, _PreValue_len(without DecimalPoint and ExtendedResolution): " + std::to_string(_PreValue_len));
////////////////////////////////////////////////////
// (+) Find out which Numbers should not change
int _DecimalPoint1 = 0;
int _NumbersNotChanged1 = 0;
while ((_PreValue_old.length() > _NumbersNotChanged1) && (_PreValue_old[_NumbersNotChanged1] == _PreValue_new1[_NumbersNotChanged1]))
{
if (_PreValue_old[_NumbersNotChanged1] == '.')
{
_DecimalPoint1 = 1;
}
_NumbersNotChanged1++;
}
_NumbersNotChanged1 = _NumbersNotChanged1 - _DecimalPoint1;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Number of ROIs that should not change: " + std::to_string(_NumbersNotChanged1));
if ((_AnzahlDigit + _AnzahlAnalog) > _PreValue_len)
{
_NumbersNotChanged1 = _NumbersNotChanged1 + ((_AnzahlDigit + _AnzahlAnalog) - _PreValue_len);
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Number of ROIs that should not change(corrected): " + std::to_string(_NumbersNotChanged1));
////////////////////////////////////////////////////
// (-) Find out which Numbers should not change
int _NumbersNotChanged2 = _NumbersNotChanged1;
if (numbers[_number]->AllowNegativeRates)
{
int _DecimalPoint2 = 0;
while ((_PreValue_old.length() > _NumbersNotChanged2) && (_PreValue_old[_NumbersNotChanged2] == _PreValue_new2[_NumbersNotChanged2]))
{
if (_PreValue_old[_NumbersNotChanged2] == '.')
{
_DecimalPoint2 = 1;
}
_NumbersNotChanged2++;
}
_NumbersNotChanged2 = _NumbersNotChanged2 - _DecimalPoint2;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Number of ROIs that should not change: " + std::to_string(_NumbersNotChanged2));
if ((_AnzahlDigit + _AnzahlAnalog) > _PreValue_len)
{
_NumbersNotChanged2 = _NumbersNotChanged2 + ((_AnzahlDigit + _AnzahlAnalog) - _PreValue_len);
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Number of ROIs that should not change(corrected): " + std::to_string(_NumbersNotChanged2));
}
////////////////////////////////////////////////////
int start_digit_new = 0;
int start_analog_new = 0;
int _NumbersNotChanged = min(_NumbersNotChanged1, _NumbersNotChanged2);
if (_NumbersNotChanged <= _AnzahlDigit)
{
// The change already takes place at the digit ROIs
start_digit_new = (_AnzahlDigit - _NumbersNotChanged);
start_digit_new = (_AnzahlDigit - start_digit_new);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "From the " + std::to_string(start_digit_new) + " th digit ROI is evaluated");
}
else
{
// The change only takes place at the analog ROIs
start_digit_new = _AnzahlDigit;
start_analog_new = (_AnzahlAnalog - (_NumbersNotChanged - _AnzahlDigit));
start_analog_new = (_AnzahlAnalog - start_analog_new);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "From the " + std::to_string(start_analog_new) + " th analog ROI is evaluated");
}
////////////////////////////////////////////////////
if (CNNType == Digit || CNNType == Digit100 || CNNType == DoubleHyprid10)
{
start_roi = start_digit_new;
}
else if (CNNType == Analogue || CNNType == Analogue100)
{
start_roi = start_analog_new;
}
}
// For each ROI
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ROI #" + std::to_string(_roi) + " - TfLite");
switch (CNNType)
{
case Analogue:
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Analogue");
tflite->LoadInputImageBasis(GENERAL[_number]->ROI[_roi]->image);
tflite->Invoke();
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Analogue - After Invoke");
float _value1 = tflite->GetOutputValue(0);
float _value2 = tflite->GetOutputValue(1);
float _result = fmod((atan2(_value1, _value2) / (M_PI * 2.0f) + 2.0f), 1.0f);
if (GENERAL[_number]->ROI[_roi]->ccw)
{
_result = 10.0f - (_result * 10.0f);
}
else
{
_result = _result * 10.0f;
}
if (_roi >= start_roi)
{
GENERAL[_number]->ROI[_roi]->result_float = _result;
}
GENERAL[_number]->ROI[_roi]->raw_result_float = _result;
if ((_result < 0.0f) || (_result >= 10.0f))
{
GENERAL[_number]->ROI[_roi]->isReject = true;
}
else
{
GENERAL[_number]->ROI[_roi]->isReject = false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "General result (Analog) - roi_" + std::to_string(_roi) + ": " + std::to_string(GENERAL[_number]->ROI[_roi]->raw_result_float));
ESP_LOGD(TAG, "General result (Analog) - roi_%i - ccw: %d - %f", _roi, GENERAL[_number]->ROI[_roi]->ccw, GENERAL[_number]->ROI[_roi]->raw_result_float);
if (isLogImage)
{
std::string _image_name = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name;
if (isLogImageSelect)
{
if (LogImageSelect.find(GENERAL[_number]->ROI[_roi]->name) != std::string::npos)
{
LogImage(logPath, _image_name, &GENERAL[_number]->ROI[_roi]->raw_result_float, NULL, time_value, GENERAL[_number]->ROI[_roi]->image_org);
}
}
}
}
break;
case Digit:
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Digit");
int _result = tflite->GetClassFromImageBasis(GENERAL[_number]->ROI[_roi]->image);
if (_roi >= start_roi)
{
GENERAL[_number]->ROI[_roi]->result_klasse = _result;
}
GENERAL[_number]->ROI[_roi]->raw_result_klasse = _result;
if ((_result < 0) || (_result >= 10))
{
GENERAL[_number]->ROI[_roi]->isReject = true;
}
else
{
GENERAL[_number]->ROI[_roi]->isReject = false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "General result (Digit) - roi_" + std::to_string(_roi) + ": " + std::to_string(GENERAL[_number]->ROI[_roi]->raw_result_klasse));
ESP_LOGD(TAG, "General result (Digit) - roi_%i: %d", _roi, GENERAL[_number]->ROI[_roi]->raw_result_klasse);
if (isLogImage)
{
std::string _image_name = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name;
if (isLogImageSelect)
{
if (LogImageSelect.find(GENERAL[_number]->ROI[_roi]->name) != std::string::npos)
{
LogImage(logPath, _image_name, NULL, &GENERAL[_number]->ROI[_roi]->raw_result_klasse, time_value, GENERAL[_number]->ROI[_roi]->image_org);
}
}
}
}
break;
case DoubleHyprid10:
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: DoubleHyprid10");
tflite->LoadInputImageBasis(GENERAL[_number]->ROI[_roi]->image);
tflite->Invoke();
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "DoubleHyprid10 - After Invoke");
int _num = tflite->GetOutClassification(0, 9);
int _numplus = (_num + 1) % 10;
int _numminus = (_num - 1 + 10) % 10;
float _value = tflite->GetOutputValue(_num);
float _valueplus = tflite->GetOutputValue(_numplus);
float _valueminus = tflite->GetOutputValue(_numminus);
float _result = (float)_num - _valueminus / (_value + _valueminus);
float _fit = _value + _valueminus;
if (_valueplus > _valueminus)
{
_result = (float)_num + _valueplus / (_valueplus + _value);
_fit = _value + _valueplus;
}
std::string temp_bufer = "DoubleHyprid10 - _num (plus, minus): " + std::to_string(_num) + " (" + std::to_string(_numplus) + ", " + std::to_string(_numminus) + ")";
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, temp_bufer);
temp_bufer = "DoubleHyprid10 - _val (plus, minus): " + std::to_string(_value) + " (" + std::to_string(_valueplus) + ", " + std::to_string(_valueminus) + ")";
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, temp_bufer);
temp_bufer = "DoubleHyprid10 - _result: " + std::to_string(_result) + ", _fit: " + std::to_string(_fit);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, temp_bufer);
float _result_save_file = _result;
if (_fit < CNNGoodThreshold)
{
GENERAL[_number]->ROI[_roi]->isReject = true;
_result = -1;
temp_bufer = "DoubleHyprid10 - Value Rejected due to Threshold (Fit: " + std::to_string(_fit) + ", Threshold: " + std::to_string(CNNGoodThreshold) + ")";
LogFile.WriteToFile(ESP_LOG_WARN, TAG, temp_bufer);
}
else
{
GENERAL[_number]->ROI[_roi]->isReject = false;
}
if (GENERAL[_number]->ROI[_roi]->ccw)
{
}
if (_roi >= start_roi)
{
GENERAL[_number]->ROI[_roi]->result_float = _result;
}
GENERAL[_number]->ROI[_roi]->raw_result_float = _result;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Result General(DoubleHyprid10) - roi_" + std::to_string(_roi) + ": " + std::to_string(GENERAL[_number]->ROI[_roi]->raw_result_float));
ESP_LOGD(TAG, "Result General(DoubleHyprid10) - roi_%i: %f", _roi, GENERAL[_number]->ROI[_roi]->raw_result_float);
if (isLogImage)
{
std::string _image_name = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name;
if (isLogImageSelect)
{
if (LogImageSelect.find(GENERAL[_number]->ROI[_roi]->name) != std::string::npos)
{
LogImage(logPath, _image_name, &_result_save_file, NULL, time_value, GENERAL[_number]->ROI[_roi]->image_org);
}
}
}
}
break;
case Digit100:
case Analogue100:
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Digit100 or Analogue100");
tflite->LoadInputImageBasis(GENERAL[_number]->ROI[_roi]->image);
tflite->Invoke();
int _num = tflite->GetOutClassification();
float _result = 0.0f;
if (GENERAL[_number]->ROI[_roi]->ccw)
{
_result = 10.0f - ((float)_num / 10.0f);
}
else
{
_result = (float)_num / 10.0f;
}
if (_roi >= start_roi)
{
GENERAL[_number]->ROI[_roi]->result_float = _result;
}
GENERAL[_number]->ROI[_roi]->raw_result_float = _result;
if ((_result < 0.0f) || (_result >= 10.0f))
{
GENERAL[_number]->ROI[_roi]->isReject = true;
}
else
{
GENERAL[_number]->ROI[_roi]->isReject = false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Result General(Digit100 or Analogue100) - roi_" + std::to_string(_roi) + ": " + std::to_string(GENERAL[_number]->ROI[_roi]->raw_result_float));
ESP_LOGD(TAG, "Result General(Digit100 or Analogue100) - roi_%i - ccw: %d - %f", _roi, GENERAL[_number]->ROI[_roi]->ccw, GENERAL[_number]->ROI[_roi]->raw_result_float);
if (isLogImage)
{
std::string _image_name = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name;
if (isLogImageSelect)
{
if (LogImageSelect.find(GENERAL[_number]->ROI[_roi]->name) != std::string::npos)
{
LogImage(logPath, _image_name, &GENERAL[_number]->ROI[_roi]->raw_result_float, NULL, time_value, GENERAL[_number]->ROI[_roi]->image_org);
}
}
}
}
break;
default:
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CNN Type: unknown");
}
break;
}
}
}
delete tflite;
return true;
}
bool ClassFlowCNNGeneral::isExtendedResolution(int _number)
{
if (CNNType == Digit)
{
return false;
}
return true;
}
std::vector<HTMLInfo *> ClassFlowCNNGeneral::GetHTMLInfo(void)
{
std::vector<HTMLInfo *> result;
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
ESP_LOGD(TAG, "Image: %d", (int)GENERAL[_number]->ROI[_roi]->image);
if (GENERAL[_number]->ROI[_roi]->image)
{
if (GENERAL[_number]->name == "default")
{
GENERAL[_number]->ROI[_roi]->image->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
else
{
GENERAL[_number]->ROI[_roi]->image->SaveToFile(format_filename("/sdcard/img_tmp/" + GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name + ".jpg"));
}
}
HTMLInfo *temp_info = new HTMLInfo;
if (GENERAL[_number]->name == "default")
{
temp_info->filename = GENERAL[_number]->ROI[_roi]->name + ".jpg";
temp_info->filename_org = GENERAL[_number]->ROI[_roi]->name + ".jpg";
}
else
{
temp_info->filename = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name + ".jpg";
temp_info->filename_org = GENERAL[_number]->name + "_" + GENERAL[_number]->ROI[_roi]->name + ".jpg";
}
if (CNNType == Digit)
{
temp_info->val = (float)GENERAL[_number]->ROI[_roi]->raw_result_klasse;
}
else
{
temp_info->val = GENERAL[_number]->ROI[_roi]->raw_result_float;
}
temp_info->image = GENERAL[_number]->ROI[_roi]->image;
temp_info->image_org = GENERAL[_number]->ROI[_roi]->image_org;
result.push_back(temp_info);
}
}
return result;
}
int ClassFlowCNNGeneral::getNumberGENERAL(void)
{
return GENERAL.size();
}
std::string ClassFlowCNNGeneral::getNameGENERAL(int _number)
{
if (_number < GENERAL.size())
{
return GENERAL[_number]->name;
}
return "GENERAL DOES NOT EXIST";
}
general *ClassFlowCNNGeneral::GetGENERAL(int _number)
{
if (_number < GENERAL.size())
{
return GENERAL[_number];
}
return NULL;
}
void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numbers)
{
for (int _number = 0; _number < GENERAL.size(); ++_number)
{
std::string _name = GENERAL[_number]->name;
bool found = false;
for (int _roi = 0; _roi < (*_name_numbers).size(); ++_roi)
{
if ((*_name_numbers)[_roi] == _name)
{
found = true;
}
}
if (!found)
{
(*_name_numbers).push_back(_name);
}
}
}
std::string ClassFlowCNNGeneral::getReadoutRawString(int _number)
{
std::string temp_string = "";
if (_number >= GENERAL.size() || GENERAL[_number] == NULL || GENERAL[_number]->ROI.size() == 0)
{
return temp_string;
}
for (int _roi = 0; _roi < GENERAL[_number]->ROI.size(); ++_roi)
{
if (CNNType == Analogue || CNNType == Analogue100)
{
if ((GENERAL[_number]->ROI[_roi]->raw_result_float < 0.0f) || (GENERAL[_number]->ROI[_roi]->raw_result_float >= 10.0f))
{
temp_string = temp_string + ",N";
}
else
{
temp_string = temp_string + "," + round_output(GENERAL[_number]->ROI[_roi]->raw_result_float, 1);
}
}
else if (CNNType == Digit)
{
if ((GENERAL[_number]->ROI[_roi]->raw_result_klasse < 0) || (GENERAL[_number]->ROI[_roi]->raw_result_klasse >= 10))
{
temp_string = temp_string + ",N";
}
else
{
temp_string = temp_string + "," + round_output(GENERAL[_number]->ROI[_roi]->raw_result_klasse, 0);
}
}
else if ((CNNType == DoubleHyprid10) || (CNNType == Digit100))
{
if ((GENERAL[_number]->ROI[_roi]->raw_result_float < 0.0f) || (GENERAL[_number]->ROI[_roi]->raw_result_float >= 10.0f))
{
temp_string = temp_string + ",N";
}
else
{
temp_string = temp_string + "," + round_output(GENERAL[_number]->ROI[_roi]->raw_result_float, 1);
}
}
}
return temp_string;
}