CTfLiteClass.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. #ifdef DEBUG_DETAIL_ON
  110. LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - Start");
  111. #endif
  112. unsigned int w = rs->width;
  113. unsigned int h = rs->height;
  114. unsigned char red, green, blue;
  115. // ESP_LOGD(TAG, "Image: %s size: %d x %d\n", _fn.c_str(), w, h);
  116. input_i = 0;
  117. float* input_data_ptr = (interpreter->input(0))->data.f;
  118. for (int y = 0; y < h; ++y)
  119. for (int x = 0; x < w; ++x)
  120. {
  121. red = rs->GetPixelColor(x, y, 0);
  122. green = rs->GetPixelColor(x, y, 1);
  123. blue = rs->GetPixelColor(x, y, 2);
  124. *(input_data_ptr) = (float) red;
  125. input_data_ptr++;
  126. *(input_data_ptr) = (float) green;
  127. input_data_ptr++;
  128. *(input_data_ptr) = (float) blue;
  129. input_data_ptr++;
  130. }
  131. #ifdef DEBUG_DETAIL_ON
  132. LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - done");
  133. #endif
  134. return true;
  135. }
  136. bool CTfLiteClass::MakeAllocate()
  137. {
  138. static tflite::AllOpsResolver resolver;
  139. #ifdef DEBUG_DETAIL_ON
  140. LogFile.WriteHeapInfo("CTLiteClass::Alloc start");
  141. #endif
  142. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::MakeAllocate");
  143. this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
  144. if (this->interpreter)
  145. {
  146. TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
  147. if (allocate_status != kTfLiteOk) {
  148. TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
  149. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
  150. this->GetInputDimension();
  151. return false;
  152. }
  153. }
  154. else
  155. {
  156. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "new tflite::MicroInterpreter failed");
  157. LogFile.WriteHeapInfo("CTfLiteClass::MakeAllocate-new tflite::MicroInterpreter failed");
  158. return false;
  159. }
  160. #ifdef DEBUG_DETAIL_ON
  161. LogFile.WriteHeapInfo("CTLiteClass::Alloc done");
  162. #endif
  163. return true;
  164. }
  165. void CTfLiteClass::GetInputTensorSize()
  166. {
  167. #ifdef DEBUG_DETAIL_ON
  168. float *zw = this->input;
  169. int test = sizeof(zw);
  170. ESP_LOGD(TAG, "Input Tensor Dimension: %d", test);
  171. #endif
  172. }
  173. long CTfLiteClass::GetFileSize(std::string filename)
  174. {
  175. struct stat stat_buf;
  176. long rc = stat(filename.c_str(), &stat_buf);
  177. return rc == 0 ? stat_buf.st_size : -1;
  178. }
  179. bool CTfLiteClass::ReadFileToModel(std::string _fn)
  180. {
  181. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::ReadFileToModel: " + _fn);
  182. long size = GetFileSize(_fn);
  183. if (size == -1)
  184. {
  185. ESP_LOGE(TAG, "CTfLiteClass::ReadFileToModel: Model file doesn't exist: %s", _fn.c_str());
  186. return false;
  187. }
  188. #ifdef DEBUG_DETAIL_ON
  189. LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start");
  190. #endif
  191. modelfile = (unsigned char*)GET_MEMORY(size);
  192. if(modelfile != NULL)
  193. {
  194. FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r
  195. fread(modelfile, 1, size, f);
  196. fclose(f);
  197. #ifdef DEBUG_DETAIL_ON
  198. LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile successful");
  199. #endif
  200. return true;
  201. }
  202. else
  203. {
  204. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CTfLiteClass::ReadFileToModel: Can't allocate enough memory: " + std::to_string(size));
  205. LogFile.WriteHeapInfo("CTfLiteClass::ReadFileToModel");
  206. return false;
  207. }
  208. }
  209. bool CTfLiteClass::LoadModel(std::string _fn)
  210. {
  211. #ifdef SUPRESS_TFLITE_ERRORS
  212. this->error_reporter = new tflite::OwnMicroErrorReporter;
  213. #else
  214. this->error_reporter = new tflite::MicroErrorReporter;
  215. #endif
  216. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::LoadModel");
  217. if (!ReadFileToModel(_fn.c_str())) {
  218. return false;
  219. }
  220. model = tflite::GetModel(modelfile);
  221. if(model == nullptr)
  222. return false;
  223. return true;
  224. }
  225. CTfLiteClass::CTfLiteClass()
  226. {
  227. this->model = nullptr;
  228. this->modelfile = NULL;
  229. this->interpreter = nullptr;
  230. this->input = nullptr;
  231. this->output = nullptr;
  232. this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024
  233. this->tensor_arena = (uint8_t*)GET_MEMORY(kTensorArenaSize);
  234. }
  235. CTfLiteClass::~CTfLiteClass()
  236. {
  237. free(modelfile);
  238. free(this->tensor_arena);
  239. delete this->interpreter;
  240. delete this->error_reporter;
  241. }
  242. namespace tflite
  243. {
  244. int OwnMicroErrorReporter::Report(const char* format, va_list args)
  245. {
  246. return 0;
  247. }
  248. }