readvalue.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Copyright (c) 2020 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 <iostream>
  15. #include <vector>
  16. #include <utility>
  17. #include <limits>
  18. #include <cmath>
  19. #include <chrono> // NOLINT
  20. #include <opencv2/opencv.hpp>
  21. #include <opencv2/highgui.hpp>
  22. #include <opencv2/core/core.hpp>
  23. #include "meter/global.h"
  24. #include "meter/readvalue.h"
  25. using namespace std::chrono; // NOLINT
  26. #define SEG_IMAGE_SIZE 512
  27. #define LINE_HEIGHT 120
  28. #define LINE_WIDTH 1570
  29. #define CIRCLE_RADIUS 250
  30. const float pi = 3.1415926536f;
  31. const int circle_center[] = {256, 256};
  32. void creat_line_image(const std::vector<int64_t> &seg_image,
  33. std::vector<unsigned char> *output) {
  34. float theta;
  35. int rho;
  36. int image_x;
  37. int image_y;
  38. for (int row = 0; row < LINE_HEIGHT; row++) {
  39. for (int col = 0; col < LINE_WIDTH; col++) {
  40. theta = pi * 2 / LINE_WIDTH * (col + 1);
  41. rho = CIRCLE_RADIUS - row - 1;
  42. image_x = static_cast<int>(circle_center[0] + rho * cos(theta) + 0.5);
  43. image_y = static_cast<int>(circle_center[1] - rho * sin(theta) + 0.5);
  44. (*output)[row * LINE_WIDTH + col] =
  45. seg_image[image_x * SEG_IMAGE_SIZE + image_y];
  46. }
  47. }
  48. return;
  49. }
  50. void convert_1D_data(const std::vector<unsigned char> &line_image,
  51. std::vector<unsigned int> *scale_data,
  52. std::vector<unsigned int> *pointer_data) {
  53. for (int col = 0; col < LINE_WIDTH; col++) {
  54. (*scale_data)[col] = 0;
  55. (*pointer_data)[col] = 0;
  56. for (int row = 0; row < LINE_HEIGHT; row++) {
  57. if (line_image[row * LINE_WIDTH + col] == 1) {
  58. (*pointer_data)[col]++;
  59. } else if (line_image[row * LINE_WIDTH + col] == 2) {
  60. (*scale_data)[col]++;
  61. }
  62. }
  63. }
  64. return;
  65. }
  66. void scale_mean_filtration(const std::vector<unsigned int> &scale_data,
  67. std::vector<unsigned int> *scale_mean_data) {
  68. int sum = 0;
  69. float mean = 0;
  70. int size = scale_data.size();
  71. for (int i = 0; i < size; i++) {
  72. sum = sum + scale_data[i];
  73. }
  74. mean = static_cast<float>(sum) / static_cast<float>(size);
  75. for (int i = 0; i < size; i++) {
  76. if (static_cast<float>(scale_data[i]) >= mean) {
  77. (*scale_mean_data)[i] = scale_data[i];
  78. }
  79. }
  80. return;
  81. }
  82. void get_meter_reader(const std::vector<unsigned int> &scale,
  83. const std::vector<unsigned int> &pointer,
  84. READ_RESULT *result) {
  85. std::vector<float> scale_location;
  86. float one_scale_location = 0;
  87. bool scale_flag = 0;
  88. unsigned int one_scale_start = 0;
  89. unsigned int one_scale_end = 0;
  90. float pointer_location = 0;
  91. bool pointer_flag = 0;
  92. unsigned int one_pointer_start = 0;
  93. unsigned int one_pointer_end = 0;
  94. for (int i = 0; i < LINE_WIDTH; i++) {
  95. // scale location
  96. if (scale[i] > 0 && scale[i+1] > 0) {
  97. if (scale_flag == 0) {
  98. one_scale_start = i;
  99. scale_flag = 1;
  100. }
  101. }
  102. if (scale_flag == 1) {
  103. if (scale[i] == 0 && scale[i+1] == 0) {
  104. one_scale_end = i - 1;
  105. one_scale_location = (one_scale_start + one_scale_end) / 2.;
  106. scale_location.push_back(one_scale_location);
  107. one_scale_start = 0;
  108. one_scale_end = 0;
  109. scale_flag = 0;
  110. }
  111. }
  112. // pointer location
  113. if (pointer[i] > 0 && pointer[i+1] > 0) {
  114. if (pointer_flag == 0) {
  115. one_pointer_start = i;
  116. pointer_flag = 1;
  117. }
  118. }
  119. if (pointer_flag == 1) {
  120. if ((pointer[i] == 0) && (pointer[i+1] == 0)) {
  121. one_pointer_end = i - 1;
  122. pointer_location = (one_pointer_start + one_pointer_end) / 2.;
  123. one_pointer_start = 0;
  124. one_pointer_end = 0;
  125. pointer_flag = 0;
  126. }
  127. }
  128. }
  129. int scale_num = scale_location.size();
  130. result->scale_num = scale_num;
  131. result->scales = -1;
  132. result->ratio = -1;
  133. if (scale_num > 0) {
  134. for (int i = 0; i < scale_num - 1; i++) {
  135. if (scale_location[i] <= pointer_location &&
  136. pointer_location < scale_location[i + 1]) {
  137. result->scales = i + 1 +
  138. (pointer_location-scale_location[i]) /
  139. (scale_location[i+1]-scale_location[i] + 1e-05);
  140. }
  141. }
  142. result->ratio =
  143. (pointer_location - scale_location[0]) /
  144. (scale_location[scale_num - 1] - scale_location[0] + 1e-05);
  145. }
  146. return;
  147. }
  148. void read_process(const std::vector<std::vector<int64_t>> &seg_image,
  149. std::vector<READ_RESULT> *read_results,
  150. const int thread_num) {
  151. int read_num = seg_image.size();
  152. #pragma omp parallel for num_threads(thread_num)
  153. for (int i_read = 0; i_read < read_num; i_read++) {
  154. std::vector<unsigned char> line_result(LINE_WIDTH*LINE_HEIGHT, 0);
  155. creat_line_image(seg_image[i_read], &line_result);
  156. std::vector<unsigned int> scale_data(LINE_WIDTH);
  157. std::vector<unsigned int> pointer_data(LINE_WIDTH);
  158. convert_1D_data(line_result, &scale_data, &pointer_data);
  159. std::vector<unsigned int> scale_mean_data(LINE_WIDTH);
  160. scale_mean_filtration(scale_data, &scale_mean_data);
  161. READ_RESULT result;
  162. get_meter_reader(scale_mean_data, pointer_data, &result);
  163. (*read_results)[i_read] = std::move(result);
  164. }
  165. return;
  166. }