CTfLiteClass.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "CTfLiteClass.h"
  2. #include "ClassLogFile.h"
  3. #include "Helper.h"
  4. #include "esp_log.h"
  5. #include "../../include/defines.h"
  6. #include <sys/stat.h>
  7. // #define DEBUG_DETAIL_ON
  8. static const char *TAG = "TFLITE";
  9. float CTfLiteClass::GetOutputValue(int nr)
  10. {
  11. TfLiteTensor* output2 = this->interpreter->output(0);
  12. int numeroutput = output2->dims->data[1];
  13. if ((nr+1) > numeroutput)
  14. return -1000;
  15. return output2->data.f[nr];
  16. }
  17. int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs)
  18. {
  19. if (!LoadInputImageBasis(rs))
  20. return -1000;
  21. Invoke();
  22. return GetOutClassification();
  23. }
  24. int CTfLiteClass::GetOutClassification(int _von, int _bis)
  25. {
  26. TfLiteTensor* output2 = interpreter->output(0);
  27. float zw_max;
  28. float zw;
  29. int zw_class;
  30. if (output2 == NULL)
  31. return -1;
  32. int numeroutput = output2->dims->data[1];
  33. //ESP_LOGD(TAG, "number output neurons: %d", numeroutput);
  34. if (_bis == -1)
  35. _bis = numeroutput -1;
  36. if (_von == -1)
  37. _von = 0;
  38. if (_bis >= numeroutput)
  39. {
  40. ESP_LOGD(TAG, "NUMBER OF OUTPUT NEURONS does not match required classification!");
  41. return -1;
  42. }
  43. zw_max = output2->data.f[_von];
  44. zw_class = _von;
  45. for (int i = _von + 1; i <= _bis; ++i)
  46. {
  47. zw = output2->data.f[i];
  48. if (zw > zw_max)
  49. {
  50. zw_max = zw;
  51. zw_class = i;
  52. }
  53. }
  54. return (zw_class - _von);
  55. }
  56. void CTfLiteClass::GetInputDimension(bool silent = false)
  57. {
  58. TfLiteTensor* input2 = this->interpreter->input(0);
  59. int numdim = input2->dims->size;
  60. if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim);
  61. int sizeofdim;
  62. for (int j = 0; j < numdim; ++j)
  63. {
  64. sizeofdim = input2->dims->data[j];
  65. if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim);
  66. if (j == 1) im_height = sizeofdim;
  67. if (j == 2) im_width = sizeofdim;
  68. if (j == 3) im_channel = sizeofdim;
  69. }
  70. }
  71. int CTfLiteClass::ReadInputDimenstion(int _dim)
  72. {
  73. if (_dim == 0)
  74. return im_width;
  75. if (_dim == 1)
  76. return im_height;
  77. if (_dim == 2)
  78. return im_channel;
  79. return -1;
  80. }
  81. int CTfLiteClass::GetAnzOutPut(bool silent)
  82. {
  83. TfLiteTensor* output2 = this->interpreter->output(0);
  84. int numdim = output2->dims->size;
  85. if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim);
  86. int sizeofdim;
  87. for (int j = 0; j < numdim; ++j)
  88. {
  89. sizeofdim = output2->dims->data[j];
  90. if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim);
  91. }
  92. float fo;
  93. // Process the inference results.
  94. int numeroutput = output2->dims->data[1];
  95. for (int i = 0; i < numeroutput; ++i)
  96. {
  97. fo = output2->data.f[i];
  98. if (!silent) ESP_LOGD(TAG, "Result %d: %f", i, fo);
  99. }
  100. return numeroutput;
  101. }
  102. void CTfLiteClass::Invoke()
  103. {
  104. if (interpreter != nullptr)
  105. interpreter->Invoke();
  106. }
  107. bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
  108. {
  109. std::string zw = "ClassFlowCNNGeneral::doNeuralNetwork after LoadInputResizeImage: ";
  110. unsigned int w = rs->width;
  111. unsigned int h = rs->height;
  112. unsigned char red, green, blue;
  113. // ESP_LOGD(TAG, "Image: %s size: %d x %d\n", _fn.c_str(), w, h);
  114. input_i = 0;
  115. float* input_data_ptr = (interpreter->input(0))->data.f;
  116. for (int y = 0; y < h; ++y)
  117. for (int x = 0; x < w; ++x)
  118. {
  119. red = rs->GetPixelColor(x, y, 0);
  120. green = rs->GetPixelColor(x, y, 1);
  121. blue = rs->GetPixelColor(x, y, 2);
  122. *(input_data_ptr) = (float) red;
  123. input_data_ptr++;
  124. *(input_data_ptr) = (float) green;
  125. input_data_ptr++;
  126. *(input_data_ptr) = (float) blue;
  127. input_data_ptr++;
  128. }
  129. #ifdef DEBUG_DETAIL_ON
  130. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After loading in input");
  131. #endif
  132. return true;
  133. }
  134. void CTfLiteClass::MakeAllocate()
  135. {
  136. static tflite::AllOpsResolver resolver;
  137. // ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
  138. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Make Allocate");
  139. this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
  140. // ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
  141. TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
  142. if (allocate_status != kTfLiteOk) {
  143. TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
  144. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
  145. this->GetInputDimension();
  146. return;
  147. }
  148. // ESP_LOGD(TAG, "Allocate Done");
  149. }
  150. void CTfLiteClass::GetInputTensorSize(){
  151. #ifdef DEBUG_DETAIL_ON
  152. float *zw = this->input;
  153. int test = sizeof(zw);
  154. ESP_LOGD(TAG, "Input Tensor Dimension: %d", test);
  155. #endif
  156. }
  157. long CTfLiteClass::GetFileSize(std::string filename)
  158. {
  159. struct stat stat_buf;
  160. long rc = stat(filename.c_str(), &stat_buf);
  161. return rc == 0 ? stat_buf.st_size : -1;
  162. }
  163. unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
  164. {
  165. long size;
  166. size = GetFileSize(_fn);
  167. if (size == -1)
  168. {
  169. ESP_LOGD(TAG, "File doesn't exist");
  170. return NULL;
  171. }
  172. unsigned char *result = (unsigned char*) malloc(size);
  173. int anz = 1;
  174. while (!result && (anz < 6)) // Try a maximum of 5x (= 5s)
  175. {
  176. #ifdef DEBUG_DETAIL_ON
  177. ESP_LOGD(TAG, "Speicher ist voll - Versuche es erneut: %d", anz);
  178. #endif
  179. result = (unsigned char*) malloc(size);
  180. anz++;
  181. }
  182. if(result != NULL) {
  183. FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r
  184. fread(result, 1, size, f);
  185. fclose(f);
  186. }else {
  187. ESP_LOGD(TAG, "No free memory available");
  188. }
  189. return result;
  190. }
  191. bool CTfLiteClass::LoadModel(std::string _fn){
  192. #ifdef SUPRESS_TFLITE_ERRORS
  193. this->error_reporter = new tflite::OwnMicroErrorReporter;
  194. #else
  195. this->error_reporter = new tflite::MicroErrorReporter;
  196. #endif
  197. modelload = ReadFileToCharArray(_fn.c_str());
  198. if (modelload == NULL)
  199. return false;
  200. model = tflite::GetModel(modelload);
  201. // free(rd);
  202. TFLITE_MINIMAL_CHECK(model != nullptr);
  203. return true;
  204. }
  205. CTfLiteClass::CTfLiteClass()
  206. {
  207. this->model = nullptr;
  208. this->interpreter = nullptr;
  209. this->input = nullptr;
  210. this->output = nullptr;
  211. this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024
  212. this->tensor_arena = new uint8_t[kTensorArenaSize];
  213. }
  214. CTfLiteClass::~CTfLiteClass()
  215. {
  216. delete this->tensor_arena;
  217. delete this->interpreter;
  218. delete this->error_reporter;
  219. if (modelload)
  220. free(modelload);
  221. }
  222. namespace tflite {
  223. int OwnMicroErrorReporter::Report(const char* format, va_list args) {
  224. return 0;
  225. }
  226. }