utils.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. // Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <sys/types.h>
  15. #ifdef __linux__
  16. #include <sys/resource.h>
  17. #endif
  18. #include <cmath>
  19. #include "ultra_infer/benchmark/utils.h"
  20. #include "ultra_infer/utils/path.h"
  21. #if defined(ENABLE_BENCHMARK) && defined(ENABLE_VISION)
  22. #include "ultra_infer/vision/utils/utils.h"
  23. #endif
  24. namespace ultra_infer {
  25. namespace benchmark {
  26. #if defined(ENABLE_BENCHMARK)
  27. std::string Strip(const std::string &str, char ch) {
  28. int i = 0;
  29. while (str[i] == ch) {
  30. i++;
  31. }
  32. int j = str.size() - 1;
  33. while (str[j] == ch) {
  34. j--;
  35. }
  36. return str.substr(i, j + 1 - i);
  37. }
  38. void Split(const std::string &s, std::vector<std::string> &tokens, char delim) {
  39. tokens.clear();
  40. size_t lastPos = s.find_first_not_of(delim, 0);
  41. size_t pos = s.find(delim, lastPos);
  42. while (lastPos != std::string::npos) {
  43. tokens.emplace_back(s.substr(lastPos, pos - lastPos));
  44. lastPos = s.find_first_not_of(delim, pos);
  45. pos = s.find(delim, lastPos);
  46. }
  47. return;
  48. }
  49. ResourceUsageMonitor::ResourceUsageMonitor(int sampling_interval_ms, int gpu_id)
  50. : is_supported_(false), sampling_interval_(sampling_interval_ms),
  51. gpu_id_(gpu_id) {
  52. #ifdef __linux__
  53. is_supported_ = true;
  54. #else
  55. is_supported_ = false;
  56. #endif
  57. if (!is_supported_) {
  58. FDASSERT(false, "Currently ResourceUsageMonitor only supports Linux.")
  59. return;
  60. }
  61. }
  62. void ResourceUsageMonitor::Start() {
  63. if (!is_supported_) {
  64. return;
  65. }
  66. if (check_memory_thd_ != nullptr) {
  67. FDINFO << "Memory monitoring has already started!" << std::endl;
  68. return;
  69. }
  70. FDINFO << "Start monitoring memory!" << std::endl;
  71. stop_signal_ = false;
  72. check_memory_thd_.reset(new std::thread(([this]() {
  73. // Note we retrieve the memory usage at the very beginning of the thread.
  74. while (true) {
  75. #ifdef __linux__
  76. rusage res;
  77. if (getrusage(RUSAGE_SELF, &res) == 0) {
  78. max_cpu_mem_ =
  79. std::max(max_cpu_mem_, static_cast<float>(res.ru_maxrss / 1024.0));
  80. }
  81. #endif
  82. #if defined(WITH_GPU)
  83. std::string gpu_mem_info = GetCurrentGpuMemoryInfo(gpu_id_);
  84. // get max_gpu_mem and max_gpu_util
  85. std::vector<std::string> gpu_tokens;
  86. Split(gpu_mem_info, gpu_tokens, ',');
  87. max_gpu_mem_ = std::max(max_gpu_mem_, stof(gpu_tokens[6]));
  88. max_gpu_util_ = std::max(max_gpu_util_, stof(gpu_tokens[7]));
  89. #endif
  90. if (stop_signal_) {
  91. break;
  92. }
  93. std::this_thread::sleep_for(
  94. std::chrono::milliseconds(sampling_interval_));
  95. }
  96. })));
  97. }
  98. void ResourceUsageMonitor::Stop() {
  99. if (!is_supported_) {
  100. return;
  101. }
  102. if (check_memory_thd_ == nullptr) {
  103. FDINFO << "Memory monitoring hasn't started yet or has stopped!"
  104. << std::endl;
  105. return;
  106. }
  107. FDINFO << "Stop monitoring memory!" << std::endl;
  108. StopInternal();
  109. }
  110. void ResourceUsageMonitor::StopInternal() {
  111. stop_signal_ = true;
  112. if (check_memory_thd_ == nullptr) {
  113. return;
  114. }
  115. if (check_memory_thd_ != nullptr) {
  116. check_memory_thd_->join();
  117. }
  118. check_memory_thd_.reset(nullptr);
  119. }
  120. std::string ResourceUsageMonitor::GetCurrentGpuMemoryInfo(int device_id) {
  121. std::string result = "";
  122. #if defined(__linux__) && defined(WITH_GPU)
  123. std::string command = "nvidia-smi --id=" + std::to_string(device_id) +
  124. " --query-gpu=index,uuid,name,timestamp,memory.total,"
  125. "memory.free,memory.used,utilization.gpu,utilization."
  126. "memory --format=csv,noheader,nounits";
  127. FILE *pp = popen(command.data(), "r");
  128. if (!pp)
  129. return "";
  130. char tmp[1024];
  131. while (fgets(tmp, sizeof(tmp), pp) != NULL) {
  132. result += tmp;
  133. }
  134. pclose(pp);
  135. #else
  136. FDASSERT(false,
  137. "Currently collect gpu memory info only supports Linux in GPU.")
  138. #endif
  139. return result;
  140. }
  141. #endif // ENABLE_BENCHMARK
  142. /// Utils for precision evaluation
  143. #if defined(ENABLE_BENCHMARK)
  144. static const char KEY_VALUE_SEP = '#';
  145. static const char VALUE_SEP = ',';
  146. std::vector<std::string> ReadLines(const std::string &path) {
  147. std::ifstream fin(path);
  148. std::vector<std::string> lines;
  149. std::string line;
  150. if (fin.is_open()) {
  151. while (getline(fin, line)) {
  152. lines.push_back(line);
  153. }
  154. } else {
  155. FDERROR << "Failed to open file " << path << std::endl;
  156. std::abort();
  157. }
  158. fin.close();
  159. return lines;
  160. }
  161. std::map<std::string, std::vector<std::string>>
  162. SplitDataLine(const std::string &data_line) {
  163. std::map<std::string, std::vector<std::string>> dict;
  164. std::vector<std::string> tokens, value_tokens;
  165. Split(data_line, tokens, KEY_VALUE_SEP);
  166. std::string key = tokens[0];
  167. std::string value = tokens[1];
  168. Split(value, value_tokens, VALUE_SEP);
  169. dict[key] = value_tokens;
  170. return dict;
  171. }
  172. bool ResultManager::SaveFDTensor(const FDTensor &tensor,
  173. const std::string &path) {
  174. if (tensor.CpuData() == nullptr || tensor.Numel() <= 0) {
  175. FDERROR << "Input tensor is empty!" << std::endl;
  176. return false;
  177. }
  178. std::ofstream fs(path, std::ios::out);
  179. if (!fs.is_open()) {
  180. FDERROR << "Fail to open file:" << path << std::endl;
  181. return false;
  182. }
  183. fs.precision(20);
  184. if (tensor.Dtype() != FDDataType::FP32 &&
  185. tensor.Dtype() != FDDataType::INT32 &&
  186. tensor.Dtype() != FDDataType::INT64) {
  187. FDERROR << "Only support FP32/INT32/INT64 now, but got "
  188. << Str(tensor.dtype) << std::endl;
  189. return false;
  190. }
  191. // name
  192. fs << "name" << KEY_VALUE_SEP << tensor.name << "\n";
  193. // shape
  194. fs << "shape" << KEY_VALUE_SEP;
  195. for (int i = 0; i < tensor.shape.size(); ++i) {
  196. if (i < tensor.shape.size() - 1) {
  197. fs << tensor.shape[i] << VALUE_SEP;
  198. } else {
  199. fs << tensor.shape[i];
  200. }
  201. }
  202. fs << "\n";
  203. // dtype
  204. fs << "dtype" << KEY_VALUE_SEP << Str(tensor.dtype) << "\n";
  205. // data
  206. fs << "data" << KEY_VALUE_SEP;
  207. const void *data_ptr = tensor.CpuData();
  208. for (int i = 0; i < tensor.Numel(); ++i) {
  209. if (tensor.Dtype() == FDDataType::INT64) {
  210. if (i < tensor.Numel() - 1) {
  211. fs << (static_cast<const int64_t *>(data_ptr))[i] << VALUE_SEP;
  212. } else {
  213. fs << (static_cast<const int64_t *>(data_ptr))[i];
  214. }
  215. } else if (tensor.Dtype() == FDDataType::INT32) {
  216. if (i < tensor.Numel() - 1) {
  217. fs << (static_cast<const int32_t *>(data_ptr))[i] << VALUE_SEP;
  218. } else {
  219. fs << (static_cast<const int32_t *>(data_ptr))[i];
  220. }
  221. } else { // FP32
  222. if (i < tensor.Numel() - 1) {
  223. fs << (static_cast<const float *>(data_ptr))[i] << VALUE_SEP;
  224. } else {
  225. fs << (static_cast<const float *>(data_ptr))[i];
  226. }
  227. }
  228. }
  229. fs << "\n";
  230. fs.close();
  231. return true;
  232. }
  233. bool ResultManager::LoadFDTensor(FDTensor *tensor, const std::string &path) {
  234. if (!CheckFileExists(path)) {
  235. FDERROR << "Can't found file from " << path << std::endl;
  236. return false;
  237. }
  238. auto lines = ReadLines(path);
  239. std::map<std::string, std::vector<std::string>> data;
  240. // name
  241. data = SplitDataLine(lines[0]);
  242. tensor->name = data.begin()->first;
  243. // shape
  244. data = SplitDataLine(lines[1]);
  245. tensor->shape.clear();
  246. for (const auto &s : data.begin()->second) {
  247. tensor->shape.push_back(std::stol(s));
  248. }
  249. // dtype
  250. data = SplitDataLine(lines[2]);
  251. if (data.begin()->second.at(0) == Str(FDDataType::INT64)) {
  252. tensor->dtype = FDDataType::INT64;
  253. } else if (data.begin()->second.at(0) == Str(FDDataType::INT32)) {
  254. tensor->dtype = FDDataType::INT32;
  255. } else if (data.begin()->second.at(0) == Str(FDDataType::FP32)) {
  256. tensor->dtype = FDDataType::FP32;
  257. } else {
  258. FDERROR << "Only support FP32/INT64/INT32 now, but got "
  259. << data.begin()->second.at(0) << std::endl;
  260. return false;
  261. }
  262. // data
  263. data = SplitDataLine(lines[3]);
  264. tensor->Allocate(tensor->shape, tensor->dtype, tensor->name);
  265. if (tensor->dtype == FDDataType::INT64) {
  266. int64_t *mutable_data_ptr = static_cast<int64_t *>(tensor->MutableData());
  267. for (int i = 0; i < data.begin()->second.size(); ++i) {
  268. mutable_data_ptr[i] = std::stol(data.begin()->second[i]);
  269. }
  270. } else if (tensor->dtype == FDDataType::INT32) {
  271. int32_t *mutable_data_ptr = static_cast<int32_t *>(tensor->MutableData());
  272. for (int i = 0; i < data.begin()->second.size(); ++i) {
  273. mutable_data_ptr[i] = std::stoi(data.begin()->second[i]);
  274. }
  275. } else { // FP32
  276. float *mutable_data_ptr = static_cast<float *>(tensor->MutableData());
  277. for (int i = 0; i < data.begin()->second.size(); ++i) {
  278. mutable_data_ptr[i] = std::stof(data.begin()->second[i]);
  279. }
  280. }
  281. return true;
  282. }
  283. TensorDiff ResultManager::CalculateDiffStatis(const FDTensor &lhs,
  284. const FDTensor &rhs) {
  285. if (lhs.Numel() != rhs.Numel() || lhs.Dtype() != rhs.Dtype()) {
  286. FDASSERT(false,
  287. "The size and dtype of input FDTensor must be equal!"
  288. " But got size %d, %d, dtype %s, %s",
  289. lhs.Numel(), rhs.Numel(), Str(lhs.Dtype()).c_str(),
  290. Str(rhs.Dtype()).c_str())
  291. }
  292. FDDataType dtype = lhs.Dtype();
  293. int numel = lhs.Numel();
  294. if (dtype != FDDataType::FP32 && dtype != FDDataType::INT64 &&
  295. dtype != FDDataType::INT32) {
  296. FDASSERT(false, "Only support FP32/INT64/INT32 now, but got %s",
  297. Str(dtype).c_str())
  298. }
  299. if (dtype == FDDataType::INT64) {
  300. std::vector<int64_t> tensor_diff(numel);
  301. const int64_t *lhs_data_ptr = static_cast<const int64_t *>(lhs.CpuData());
  302. const int64_t *rhs_data_ptr = static_cast<const int64_t *>(rhs.CpuData());
  303. for (int i = 0; i < numel; ++i) {
  304. tensor_diff[i] = lhs_data_ptr[i] - rhs_data_ptr[i];
  305. }
  306. TensorDiff diff;
  307. CalculateStatisInfo<int64_t>(tensor_diff.data(), numel, &(diff.data.mean),
  308. &(diff.data.max), &(diff.data.min));
  309. return diff;
  310. } else if (dtype == FDDataType::INT32) {
  311. std::vector<int32_t> tensor_diff(numel);
  312. const int32_t *lhs_data_ptr = static_cast<const int32_t *>(lhs.CpuData());
  313. const int32_t *rhs_data_ptr = static_cast<const int32_t *>(rhs.CpuData());
  314. for (int i = 0; i < numel; ++i) {
  315. tensor_diff[i] = lhs_data_ptr[i] - rhs_data_ptr[i];
  316. }
  317. TensorDiff diff;
  318. CalculateStatisInfo<float>(tensor_diff.data(), numel, &(diff.data.mean),
  319. &(diff.data.max), &(diff.data.min));
  320. return diff;
  321. } else { // FP32
  322. std::vector<float> tensor_diff(numel);
  323. const float *lhs_data_ptr = static_cast<const float *>(lhs.CpuData());
  324. const float *rhs_data_ptr = static_cast<const float *>(rhs.CpuData());
  325. for (int i = 0; i < numel; ++i) {
  326. tensor_diff[i] = lhs_data_ptr[i] - rhs_data_ptr[i];
  327. }
  328. TensorDiff diff;
  329. CalculateStatisInfo<float>(tensor_diff.data(), numel, &(diff.data.mean),
  330. &(diff.data.max), &(diff.data.min));
  331. return diff;
  332. }
  333. }
  334. void ResultManager::SaveBenchmarkResult(const std::string &res,
  335. const std::string &path) {
  336. if (path.empty()) {
  337. FDERROR << "Benchmark data path can not be empty!" << std::endl;
  338. return;
  339. }
  340. auto openmode = std::ios::app;
  341. std::ofstream fs(path, openmode);
  342. if (!fs.is_open()) {
  343. FDERROR << "Fail to open result file: " << path << std::endl;
  344. }
  345. fs << res;
  346. fs.close();
  347. }
  348. bool ResultManager::LoadBenchmarkConfig(
  349. const std::string &path,
  350. std::unordered_map<std::string, std::string> *config_info) {
  351. if (!CheckFileExists(path)) {
  352. FDERROR << "Can't found file from " << path << std::endl;
  353. return false;
  354. }
  355. auto lines = ReadLines(path);
  356. for (auto line : lines) {
  357. std::vector<std::string> tokens;
  358. Split(line, tokens, ':');
  359. (*config_info)[tokens[0]] = Strip(tokens[1], ' ');
  360. }
  361. return true;
  362. }
  363. std::vector<std::vector<int32_t>>
  364. ResultManager::GetInputShapes(const std::string &raw_shapes) {
  365. std::vector<std::vector<int32_t>> shapes;
  366. std::vector<std::string> shape_tokens;
  367. Split(raw_shapes, shape_tokens, ':');
  368. for (auto str_shape : shape_tokens) {
  369. std::vector<int32_t> shape;
  370. std::string tmp_str = str_shape;
  371. while (!tmp_str.empty()) {
  372. int dim = atoi(tmp_str.data());
  373. shape.push_back(dim);
  374. size_t next_offset = tmp_str.find(",");
  375. if (next_offset == std::string::npos) {
  376. break;
  377. } else {
  378. tmp_str = tmp_str.substr(next_offset + 1);
  379. }
  380. }
  381. shapes.push_back(shape);
  382. }
  383. return shapes;
  384. }
  385. std::vector<std::string>
  386. ResultManager::GetInputNames(const std::string &raw_names) {
  387. std::vector<std::string> names_tokens;
  388. Split(raw_names, names_tokens, ':');
  389. return names_tokens;
  390. }
  391. std::vector<std::string> ResultManager::SplitStr(const std::string &raw_str,
  392. char delim) {
  393. std::vector<std::string> str_tokens;
  394. Split(raw_str, str_tokens, delim);
  395. return str_tokens;
  396. }
  397. std::vector<FDDataType>
  398. ResultManager::GetInputDtypes(const std::string &raw_dtypes) {
  399. std::vector<FDDataType> dtypes;
  400. std::vector<std::string> dtypes_tokens;
  401. Split(raw_dtypes, dtypes_tokens, ':');
  402. for (auto dtype : dtypes_tokens) {
  403. if (dtype == "FP32") {
  404. dtypes.push_back(FDDataType::FP32);
  405. } else if (dtype == "INT32") {
  406. dtypes.push_back(FDDataType::INT32);
  407. } else if (dtype == "INT64") {
  408. dtypes.push_back(FDDataType::INT64);
  409. } else if (dtype == "INT8") {
  410. dtypes.push_back(FDDataType::INT8);
  411. } else if (dtype == "UINT8") {
  412. dtypes.push_back(FDDataType::UINT8);
  413. } else if (dtype == "FP16") {
  414. dtypes.push_back(FDDataType::FP16);
  415. } else if (dtype == "FP64") {
  416. dtypes.push_back(FDDataType::FP64);
  417. } else {
  418. dtypes.push_back(FDDataType::FP32); // default
  419. }
  420. }
  421. return dtypes;
  422. }
  423. #if defined(ENABLE_VISION)
  424. bool ResultManager::SaveDetectionResult(const vision::DetectionResult &res,
  425. const std::string &path) {
  426. if (res.boxes.empty()) {
  427. FDERROR << "DetectionResult can not be empty!" << std::endl;
  428. return false;
  429. }
  430. std::ofstream fs(path, std::ios::out);
  431. if (!fs.is_open()) {
  432. FDERROR << "Fail to open file:" << path << std::endl;
  433. return false;
  434. }
  435. fs.precision(20);
  436. // boxes
  437. fs << "boxes" << KEY_VALUE_SEP;
  438. for (int i = 0; i < res.boxes.size(); ++i) {
  439. for (int j = 0; j < 4; ++j) {
  440. if ((i == res.boxes.size() - 1) && (j == 3)) {
  441. fs << res.boxes[i][j];
  442. } else {
  443. fs << res.boxes[i][j] << VALUE_SEP;
  444. }
  445. }
  446. }
  447. fs << "\n";
  448. // scores
  449. fs << "scores" << KEY_VALUE_SEP;
  450. for (int i = 0; i < res.scores.size(); ++i) {
  451. if (i < res.scores.size() - 1) {
  452. fs << res.scores[i] << VALUE_SEP;
  453. } else {
  454. fs << res.scores[i];
  455. }
  456. }
  457. fs << "\n";
  458. // label_ids
  459. fs << "label_ids" << KEY_VALUE_SEP;
  460. for (int i = 0; i < res.label_ids.size(); ++i) {
  461. if (i < res.label_ids.size() - 1) {
  462. fs << res.label_ids[i] << VALUE_SEP;
  463. } else {
  464. fs << res.label_ids[i];
  465. }
  466. }
  467. fs << "\n";
  468. // TODO(qiuyanjun): dump masks
  469. fs.close();
  470. return true;
  471. }
  472. bool ResultManager::SaveClassifyResult(const vision::ClassifyResult &res,
  473. const std::string &path) {
  474. if (res.label_ids.empty()) {
  475. FDERROR << "ClassifyResult can not be empty!" << std::endl;
  476. return false;
  477. }
  478. std::ofstream fs(path, std::ios::out);
  479. if (!fs.is_open()) {
  480. FDERROR << "Fail to open file:" << path << std::endl;
  481. return false;
  482. }
  483. fs.precision(20);
  484. // label_ids
  485. fs << "label_ids" << KEY_VALUE_SEP;
  486. for (int i = 0; i < res.label_ids.size(); ++i) {
  487. if (i < res.label_ids.size() - 1) {
  488. fs << res.label_ids[i] << VALUE_SEP;
  489. } else {
  490. fs << res.label_ids[i];
  491. }
  492. }
  493. fs << "\n";
  494. // scores
  495. fs << "scores" << KEY_VALUE_SEP;
  496. for (int i = 0; i < res.scores.size(); ++i) {
  497. if (i < res.scores.size() - 1) {
  498. fs << res.scores[i] << VALUE_SEP;
  499. } else {
  500. fs << res.scores[i];
  501. }
  502. }
  503. fs << "\n";
  504. fs.close();
  505. return true;
  506. }
  507. bool ResultManager::SaveSegmentationResult(
  508. const vision::SegmentationResult &res, const std::string &path) {
  509. if (res.label_map.empty()) {
  510. FDERROR << "SegmentationResult can not be empty!" << std::endl;
  511. return false;
  512. }
  513. std::ofstream fs(path, std::ios::out);
  514. if (!fs.is_open()) {
  515. FDERROR << "Fail to open file:" << path << std::endl;
  516. return false;
  517. }
  518. fs.precision(20);
  519. // label_map
  520. fs << "label_map" << KEY_VALUE_SEP;
  521. for (int i = 0; i < res.label_map.size(); ++i) {
  522. if (i < res.label_map.size() - 1) {
  523. fs << static_cast<int32_t>(res.label_map[i]) << VALUE_SEP;
  524. } else {
  525. fs << static_cast<int32_t>(res.label_map[i]);
  526. }
  527. }
  528. fs << "\n";
  529. // score_map
  530. if (res.contain_score_map) {
  531. fs << "score_map" << KEY_VALUE_SEP;
  532. for (int i = 0; i < res.score_map.size(); ++i) {
  533. if (i < res.score_map.size() - 1) {
  534. fs << res.score_map[i] << VALUE_SEP;
  535. } else {
  536. fs << res.score_map[i];
  537. }
  538. }
  539. fs << "\n";
  540. }
  541. fs.close();
  542. return true;
  543. }
  544. bool ResultManager::SaveOCRDetResult(const std::vector<std::array<int, 8>> &res,
  545. const std::string &path) {
  546. if (res.empty()) {
  547. FDERROR << "OCRDetResult can not be empty!" << std::endl;
  548. return false;
  549. }
  550. std::ofstream fs(path, std::ios::out);
  551. if (!fs.is_open()) {
  552. FDERROR << "Fail to open file:" << path << std::endl;
  553. return false;
  554. }
  555. fs.precision(20);
  556. // boxes
  557. fs << "boxes" << KEY_VALUE_SEP;
  558. for (int i = 0; i < res.size(); ++i) {
  559. for (int j = 0; j < 8; ++j) {
  560. if ((i == res.size() - 1) && (j == 7)) {
  561. fs << res[i][j];
  562. } else {
  563. fs << res[i][j] << VALUE_SEP;
  564. }
  565. }
  566. }
  567. fs << "\n";
  568. fs.close();
  569. return true;
  570. }
  571. bool ResultManager::SaveMattingResult(const vision::MattingResult &res,
  572. const std::string &path) {
  573. if (res.alpha.empty()) {
  574. FDERROR << "MattingResult can not be empty!" << std::endl;
  575. return false;
  576. }
  577. std::ofstream fs(path, std::ios::out);
  578. if (!fs.is_open()) {
  579. FDERROR << "Fail to open file:" << path << std::endl;
  580. return false;
  581. }
  582. fs.precision(20);
  583. // alpha
  584. fs << "alpha" << KEY_VALUE_SEP;
  585. for (int i = 0; i < res.alpha.size(); ++i) {
  586. if (i < res.alpha.size() - 1) {
  587. fs << res.alpha[i] << VALUE_SEP;
  588. } else {
  589. fs << res.alpha[i];
  590. }
  591. }
  592. fs << "\n";
  593. // foreground
  594. if (res.contain_foreground) {
  595. fs << "foreground" << KEY_VALUE_SEP;
  596. for (int i = 0; i < res.foreground.size(); ++i) {
  597. if (i < res.foreground.size() - 1) {
  598. fs << res.foreground[i] << VALUE_SEP;
  599. } else {
  600. fs << res.foreground[i];
  601. }
  602. }
  603. fs << "\n";
  604. }
  605. fs.close();
  606. return true;
  607. }
  608. bool ResultManager::LoadDetectionResult(vision::DetectionResult *res,
  609. const std::string &path) {
  610. if (!CheckFileExists(path)) {
  611. FDERROR << "Can't found file from " << path << std::endl;
  612. return false;
  613. }
  614. auto lines = ReadLines(path);
  615. std::map<std::string, std::vector<std::string>> data;
  616. // boxes
  617. data = SplitDataLine(lines[0]);
  618. int boxes_num = data.begin()->second.size() / 4;
  619. res->Resize(boxes_num);
  620. for (int i = 0; i < boxes_num; ++i) {
  621. res->boxes[i][0] = std::stof(data.begin()->second[i * 4 + 0]);
  622. res->boxes[i][1] = std::stof(data.begin()->second[i * 4 + 1]);
  623. res->boxes[i][2] = std::stof(data.begin()->second[i * 4 + 2]);
  624. res->boxes[i][3] = std::stof(data.begin()->second[i * 4 + 3]);
  625. }
  626. // scores
  627. data = SplitDataLine(lines[1]);
  628. for (int i = 0; i < data.begin()->second.size(); ++i) {
  629. res->scores[i] = std::stof(data.begin()->second[i]);
  630. }
  631. // label_ids
  632. data = SplitDataLine(lines[2]);
  633. for (int i = 0; i < data.begin()->second.size(); ++i) {
  634. res->label_ids[i] = std::stoi(data.begin()->second[i]);
  635. }
  636. // TODO(qiuyanjun): load masks
  637. return true;
  638. }
  639. bool ResultManager::LoadClassifyResult(vision::ClassifyResult *res,
  640. const std::string &path) {
  641. if (!CheckFileExists(path)) {
  642. FDERROR << "Can't found file from " << path << std::endl;
  643. return false;
  644. }
  645. auto lines = ReadLines(path);
  646. std::map<std::string, std::vector<std::string>> data;
  647. // label_ids
  648. data = SplitDataLine(lines[0]);
  649. res->Resize(data.begin()->second.size());
  650. for (int i = 0; i < data.begin()->second.size(); ++i) {
  651. res->label_ids[i] = std::stoi(data.begin()->second[i]);
  652. }
  653. // scores
  654. data = SplitDataLine(lines[1]);
  655. for (int i = 0; i < data.begin()->second.size(); ++i) {
  656. res->scores[i] = std::stof(data.begin()->second[i]);
  657. }
  658. return true;
  659. }
  660. bool ResultManager::LoadSegmentationResult(vision::SegmentationResult *res,
  661. const std::string &path) {
  662. if (!CheckFileExists(path)) {
  663. FDERROR << "Can't found file from " << path << std::endl;
  664. return false;
  665. }
  666. auto lines = ReadLines(path);
  667. if (lines.size() > 1) {
  668. res->contain_score_map = true;
  669. }
  670. std::map<std::string, std::vector<std::string>> data;
  671. // label_map
  672. data = SplitDataLine(lines[0]);
  673. res->Resize(data.begin()->second.size());
  674. for (int i = 0; i < data.begin()->second.size(); ++i) {
  675. res->label_map[i] = std::stoi(data.begin()->second[i]);
  676. }
  677. // score_map
  678. if (lines.size() > 1) {
  679. data = SplitDataLine(lines[1]);
  680. for (int i = 0; i < data.begin()->second.size(); ++i) {
  681. res->score_map[i] = std::stof(data.begin()->second[i]);
  682. }
  683. }
  684. return true;
  685. }
  686. bool ResultManager::LoadOCRDetResult(std::vector<std::array<int, 8>> *res,
  687. const std::string &path) {
  688. if (!CheckFileExists(path)) {
  689. FDERROR << "Can't found file from " << path << std::endl;
  690. return false;
  691. }
  692. auto lines = ReadLines(path);
  693. std::map<std::string, std::vector<std::string>> data;
  694. // boxes
  695. data = SplitDataLine(lines[0]);
  696. int boxes_num = data.begin()->second.size() / 8;
  697. res->resize(boxes_num);
  698. for (int i = 0; i < boxes_num; ++i) {
  699. for (int j = 0; j < 8; ++j) {
  700. (*res)[i][j] = std::stoi(data.begin()->second[i * 8 + j]);
  701. }
  702. }
  703. return true;
  704. }
  705. bool ResultManager::LoadMattingResult(vision::MattingResult *res,
  706. const std::string &path) {
  707. if (!CheckFileExists(path)) {
  708. FDERROR << "Can't found file from " << path << std::endl;
  709. return false;
  710. }
  711. auto lines = ReadLines(path);
  712. if (lines.size() > 1) {
  713. res->contain_foreground = true;
  714. }
  715. std::map<std::string, std::vector<std::string>> data;
  716. // alpha
  717. data = SplitDataLine(lines[0]);
  718. res->Resize(data.begin()->second.size());
  719. for (int i = 0; i < data.begin()->second.size(); ++i) {
  720. res->alpha[i] = std::stof(data.begin()->second[i]);
  721. }
  722. // foreground
  723. if (lines.size() > 1) {
  724. data = SplitDataLine(lines[1]);
  725. for (int i = 0; i < data.begin()->second.size(); ++i) {
  726. res->foreground[i] = std::stof(data.begin()->second[i]);
  727. }
  728. }
  729. return true;
  730. }
  731. DetectionDiff
  732. ResultManager::CalculateDiffStatis(const vision::DetectionResult &lhs,
  733. const vision::DetectionResult &rhs,
  734. const float &score_threshold) {
  735. vision::DetectionResult lhs_sort = lhs;
  736. vision::DetectionResult rhs_sort = rhs;
  737. // lex sort by x(w) & y(h)
  738. vision::utils::LexSortDetectionResultByXY(&lhs_sort);
  739. vision::utils::LexSortDetectionResultByXY(&rhs_sort);
  740. // get value diff & trunc it by score_threshold
  741. const int boxes_num = std::min(lhs_sort.boxes.size(), rhs_sort.boxes.size());
  742. std::vector<float> boxes_diff;
  743. std::vector<float> scores_diff;
  744. std::vector<int32_t> labels_diff;
  745. // TODO(qiuyanjun): process the diff of masks.
  746. for (int i = 0; i < boxes_num; ++i) {
  747. if (lhs_sort.scores[i] > score_threshold &&
  748. rhs_sort.scores[i] > score_threshold) {
  749. scores_diff.push_back(lhs_sort.scores[i] - rhs_sort.scores[i]);
  750. labels_diff.push_back(lhs_sort.label_ids[i] - rhs_sort.label_ids[i]);
  751. boxes_diff.push_back(lhs_sort.boxes[i][0] - rhs_sort.boxes[i][0]);
  752. boxes_diff.push_back(lhs_sort.boxes[i][1] - rhs_sort.boxes[i][1]);
  753. boxes_diff.push_back(lhs_sort.boxes[i][2] - rhs_sort.boxes[i][2]);
  754. boxes_diff.push_back(lhs_sort.boxes[i][3] - rhs_sort.boxes[i][3]);
  755. }
  756. }
  757. FDASSERT(boxes_diff.size() > 0,
  758. "Can't get any valid boxes while score_threshold is %f, "
  759. "The boxes.size of lhs is %d, the boxes.size of rhs is %d",
  760. score_threshold, lhs_sort.boxes.size(), rhs_sort.boxes.size())
  761. DetectionDiff diff;
  762. CalculateStatisInfo<float>(boxes_diff.data(), boxes_diff.size(),
  763. &(diff.boxes.mean), &(diff.boxes.max),
  764. &(diff.boxes.min));
  765. CalculateStatisInfo<float>(scores_diff.data(), scores_diff.size(),
  766. &(diff.scores.mean), &(diff.scores.max),
  767. &(diff.scores.min));
  768. CalculateStatisInfo<int32_t>(labels_diff.data(), labels_diff.size(),
  769. &(diff.labels.mean), &(diff.labels.max),
  770. &(diff.labels.min));
  771. return diff;
  772. }
  773. ClassifyDiff
  774. ResultManager::CalculateDiffStatis(const vision::ClassifyResult &lhs,
  775. const vision::ClassifyResult &rhs) {
  776. const int class_nums = std::min(lhs.label_ids.size(), rhs.label_ids.size());
  777. std::vector<float> scores_diff;
  778. std::vector<int32_t> labels_diff;
  779. for (int i = 0; i < class_nums; ++i) {
  780. scores_diff.push_back(lhs.scores[i] - rhs.scores[i]);
  781. labels_diff.push_back(lhs.label_ids[i] - rhs.label_ids[i]);
  782. }
  783. ClassifyDiff diff;
  784. CalculateStatisInfo<float>(scores_diff.data(), scores_diff.size(),
  785. &(diff.scores.mean), &(diff.scores.max),
  786. &(diff.scores.min));
  787. CalculateStatisInfo<int32_t>(labels_diff.data(), labels_diff.size(),
  788. &(diff.labels.mean), &(diff.labels.max),
  789. &(diff.labels.min));
  790. return diff;
  791. }
  792. SegmentationDiff
  793. ResultManager::CalculateDiffStatis(const vision::SegmentationResult &lhs,
  794. const vision::SegmentationResult &rhs) {
  795. const int pixel_nums = std::min(lhs.label_map.size(), rhs.label_map.size());
  796. std::vector<int32_t> labels_diff;
  797. std::vector<float> scores_diff;
  798. for (int i = 0; i < pixel_nums; ++i) {
  799. labels_diff.push_back(lhs.label_map[i] - rhs.label_map[i]);
  800. if (lhs.contain_score_map && rhs.contain_score_map) {
  801. scores_diff.push_back(lhs.score_map[i] - rhs.score_map[i]);
  802. }
  803. }
  804. SegmentationDiff diff;
  805. CalculateStatisInfo<int32_t>(labels_diff.data(), labels_diff.size(),
  806. &(diff.labels.mean), &(diff.labels.max),
  807. &(diff.labels.min));
  808. if (lhs.contain_score_map && rhs.contain_score_map) {
  809. CalculateStatisInfo<float>(scores_diff.data(), scores_diff.size(),
  810. &(diff.scores.mean), &(diff.scores.max),
  811. &(diff.scores.min));
  812. }
  813. return diff;
  814. }
  815. OCRDetDiff
  816. ResultManager::CalculateDiffStatis(const std::vector<std::array<int, 8>> &lhs,
  817. const std::vector<std::array<int, 8>> &rhs) {
  818. const int boxes_nums = std::min(lhs.size(), rhs.size());
  819. std::vector<std::array<int, 8>> lhs_sort = lhs;
  820. std::vector<std::array<int, 8>> rhs_sort = rhs;
  821. // lex sort by x(w) & y(h)
  822. vision::utils::LexSortOCRDetResultByXY(&lhs_sort);
  823. vision::utils::LexSortOCRDetResultByXY(&rhs_sort);
  824. // get value diff
  825. const int boxes_num = std::min(lhs_sort.size(), rhs_sort.size());
  826. std::vector<float> boxes_diff;
  827. for (int i = 0; i < boxes_num; ++i) {
  828. for (int j = 0; j < 8; ++j) {
  829. boxes_diff.push_back(lhs_sort[i][j] - rhs_sort[i][j]);
  830. }
  831. }
  832. OCRDetDiff diff;
  833. CalculateStatisInfo<float>(boxes_diff.data(), boxes_diff.size(),
  834. &(diff.boxes.mean), &(diff.boxes.max),
  835. &(diff.boxes.min));
  836. return diff;
  837. }
  838. MattingDiff
  839. ResultManager::CalculateDiffStatis(const vision::MattingResult &lhs,
  840. const vision::MattingResult &rhs) {
  841. const int pixel_nums = std::min(lhs.alpha.size(), rhs.alpha.size());
  842. std::vector<float> alpha_diff;
  843. std::vector<float> foreground_diff;
  844. for (int i = 0; i < pixel_nums; ++i) {
  845. alpha_diff.push_back(lhs.alpha[i] - rhs.alpha[i]);
  846. if (lhs.contain_foreground && rhs.contain_foreground) {
  847. foreground_diff.push_back(lhs.foreground[i] - rhs.foreground[i]);
  848. }
  849. }
  850. MattingDiff diff;
  851. CalculateStatisInfo<float>(alpha_diff.data(), alpha_diff.size(),
  852. &(diff.alpha.mean), &(diff.alpha.max),
  853. &(diff.alpha.min));
  854. if (lhs.contain_foreground && rhs.contain_foreground) {
  855. CalculateStatisInfo<float>(foreground_diff.data(), foreground_diff.size(),
  856. &(diff.foreground.mean), &(diff.foreground.max),
  857. &(diff.foreground.min));
  858. }
  859. return diff;
  860. }
  861. #endif // ENABLE_VISION
  862. #endif // ENABLE_BENCHMARK
  863. } // namespace benchmark
  864. } // namespace ultra_infer