DoublePointerCountALGO.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <iostream>
  3. #include <fstream>
  4. #include <string>
  5. #include <math.h>
  6. #include <cmath>
  7. #include <opencv2/imgproc.hpp>
  8. #include <opencv2/highgui.hpp>
  9. #include <opencv2/highgui/highgui.hpp>
  10. #include "opencv2/imgproc/types_c.h"
  11. #include <onnxruntime_cxx_api.h>
  12. #include "DoublePointerCountALGO.h"
  13. #include <vector>
  14. #include <algorithm>
  15. using namespace cv;
  16. using namespace std;
  17. using namespace Ort;
  18. void DoublePointerCountALGO::Init(bool isCuda)
  19. {
  20. string model_path = "models/double_pointer_count.onnx";
  21. std::wstring widestr = std::wstring(model_path.begin(), model_path.end());
  22. sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
  23. ort_session = new Session(env, widestr.c_str(), sessionOptions);
  24. size_t numInputNodes = ort_session->GetInputCount();
  25. size_t numOutputNodes = ort_session->GetOutputCount();
  26. AllocatorWithDefaultOptions allocator;
  27. for (int i = 0; i < numInputNodes; i++)
  28. {
  29. input_names.push_back(ort_session->GetInputName(i, allocator));
  30. Ort::TypeInfo input_type_info = ort_session->GetInputTypeInfo(i);
  31. auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();
  32. auto input_dims = input_tensor_info.GetShape();
  33. input_node_dims.push_back(input_dims);
  34. }
  35. for (int i = 0; i < numOutputNodes; i++)
  36. {
  37. output_names.push_back(ort_session->GetOutputName(i, allocator));
  38. Ort::TypeInfo output_type_info = ort_session->GetOutputTypeInfo(i);
  39. auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();
  40. auto output_dims = output_tensor_info.GetShape();
  41. output_node_dims.push_back(output_dims);
  42. }
  43. this->inpHeight = input_node_dims[0][2];
  44. this->inpWidth = input_node_dims[0][3];
  45. this->outHeight = output_node_dims[0][2];
  46. this->outWidth = output_node_dims[0][3];
  47. }
  48. int DoublePointerCountALGO::detect(Mat& srcimg)
  49. {
  50. vector<float> input_image_ = { 1, 3, 512, 512 };
  51. Mat dstimg;
  52. Size resize_size(input_image_[2], input_image_[3]);
  53. resize(srcimg, dstimg, resize_size, 0, 0, cv::INTER_LINEAR);
  54. int channels = dstimg.channels();
  55. input_image_.resize((this->inpWidth * this->inpHeight * dstimg.channels()));
  56. for (int c = 0; c < channels; c++)
  57. {
  58. for (int i = 0; i < this->inpHeight; i++)
  59. {
  60. for (int j = 0; j < this->inpWidth; j++)
  61. {
  62. float pix = dstimg.ptr<uchar>(i)[j * 3 + 2 - c];
  63. input_image_[(c * this->inpHeight * this->inpWidth + i * this->inpWidth + j)] = (pix / 255.0 - mean[c]) / stds[c];
  64. }
  65. }
  66. }
  67. array<int64_t, 4> input_shape_{ 1, 3, this->inpHeight, this->inpWidth };
  68. auto allocator_info = MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
  69. Value input_tensor_ = Value::CreateTensor<float>(allocator_info, input_image_.data(), input_image_.size(), input_shape_.data(), input_shape_.size());
  70. // 开始推理
  71. vector<Value> ort_outputs = ort_session->Run(RunOptions{ nullptr }, &input_names[0], &input_tensor_, 1, output_names.data(), output_names.size());
  72. float* pred = ort_outputs[0].GetTensorMutableData<float>();
  73. Mat result(outHeight, outWidth, CV_32FC1, pred);
  74. result = 2 - result;
  75. result *= 255;
  76. result.convertTo(result, CV_8UC1);
  77. Mat binary;
  78. threshold(result, binary, 150, 255, THRESH_BINARY);//二值化阈值处理
  79. //形态学变换
  80. Mat Sobel_Y_thres;
  81. Mat element = cv::getStructuringElement(MORPH_RECT, Size(1, 1));
  82. morphologyEx(binary, Sobel_Y_thres, cv::MORPH_OPEN, element, Point(-1, -1), 2);
  83. Mat result_line_image = creat_line_image(Sobel_Y_thres, 256, 130);
  84. /*namedWindow("矩形", WINDOW_NORMAL);
  85. imshow("矩形", result_line_image);
  86. waitKey(0);*/
  87. return get_meter_reader(result_line_image);
  88. //return result;
  89. }
  90. Mat DoublePointerCountALGO::creat_line_image(const Mat& circle, int Radius, int RingStride)
  91. {
  92. Mat rectangle;
  93. float theta;
  94. int rho;
  95. rectangle = Mat::zeros(Size(Radius * pi * 2, RingStride), CV_8UC1);
  96. int nl = rectangle.rows; // number of lines
  97. int nc = rectangle.cols * rectangle.channels(); // total number of elements per line
  98. for (int j = 0; j < nl; j++) {
  99. // get the address of row j
  100. uchar* data = rectangle.ptr<uchar>(j);
  101. for (int i = 0; i < nc; i++)
  102. {
  103. theta = pi * 2.0 / LINE_WIDTH * float(i + 1);
  104. rho = (Radius - j - 1);
  105. int position_y = (float)circle_center[0] + rho * (float)std::cos(theta) + 0.5;
  106. int position_x = (float)circle_center[1] - rho * (float)std::sin(theta) + 0.5;
  107. data[i] = circle.at<uchar>(position_y, position_x);
  108. }
  109. }
  110. return rectangle;
  111. }
  112. //像素值提取及累加
  113. int DoublePointerCountALGO::get_meter_reader(const Mat& image)
  114. {
  115. Mat histogram = Mat::zeros(Size(256, 1), CV_8UC1);
  116. int rows = LINE_HEIGH; //输入图像的行数
  117. int cols = LINE_WIDTH; //输入图像的列数
  118. int sum_horsum = 0; //水平方向列相加和
  119. int long_pointer = 0;
  120. int short_pointer = 0;
  121. int METER_RANGE = 9;
  122. //按矩形计算像素值
  123. vector<int>num1;
  124. vector<int>num_cols;
  125. vector<int>num3;
  126. vector<int>num_pixel;
  127. for (int c = 0; c < cols; c++)
  128. {
  129. int versum = 0;
  130. for (int r = 0; r < rows; r++)
  131. {
  132. int index = int(image.at<uchar>(r, c));
  133. versum += index;
  134. }
  135. if (versum != 0)
  136. {
  137. sum_horsum += versum;
  138. num1.push_back(c); //列索引
  139. num3.push_back(sum_horsum); //像素累加
  140. }
  141. if (versum == 0)
  142. {
  143. //列索引
  144. int maxValue1 = 0;
  145. for (auto v : num1)
  146. {
  147. if (maxValue1 < v) maxValue1 = v;
  148. }
  149. if (maxValue1 != 0)
  150. {
  151. num_cols.push_back(maxValue1);
  152. }
  153. vector<int>().swap(num1);
  154. //像素
  155. int maxValue2 = 0;
  156. for (auto v : num3)
  157. {
  158. if (maxValue2 < v) maxValue2 = v;
  159. }
  160. if (maxValue2 != 0)
  161. {
  162. num_pixel.push_back(maxValue2);
  163. }
  164. sum_horsum = 0;
  165. vector<int>().swap(num3);
  166. }
  167. }
  168. //标记长短指针
  169. auto firstValue1 = num_pixel.front();
  170. auto lastValue1 = num_pixel.back();
  171. //长短指针取值
  172. auto firstValue2 = num_cols.front() - 30;
  173. auto lastValue2 = num_cols.back() - 30;
  174. //赋值于长短指针
  175. if (firstValue1 < lastValue1)
  176. {
  177. short_pointer = firstValue2;
  178. long_pointer = lastValue2;
  179. }else
  180. {
  181. short_pointer = lastValue2;
  182. long_pointer = firstValue2;
  183. }
  184. //计算表盘读数
  185. float rectangle_value = 1650;
  186. float short_result_ratio = (1.0 * short_pointer / rectangle_value);
  187. float long_result_ratio = (1.0 * long_pointer / rectangle_value);
  188. float short_result_value = (1.0 * short_result_ratio * METER_RANGE) - 4;
  189. if (short_result_value < 0)
  190. {
  191. short_result_value += 9;
  192. }
  193. float long_result_value = (1.0 * long_result_ratio * METER_RANGE) - 4;
  194. if (long_result_value < 0)
  195. {
  196. long_result_value += 9;
  197. }
  198. //四舍五入取整
  199. if (short_result_value > 0)
  200. {
  201. short_result_value = short_result_value - int(short_result_value) >= 0.5 ? int(short_result_value) + 1 : int(short_result_value);
  202. }else
  203. {
  204. short_result_value = -short_result_value - int(-short_result_value) >= 0.5 ? -(int(-short_result_value) + 1) : -int(-short_result_value);
  205. }
  206. if (long_result_value > 0)
  207. {
  208. long_result_value = long_result_value - int(long_result_value) >= 0.5 ? int(long_result_value) + 1 : int(long_result_value);
  209. }else
  210. {
  211. long_result_value = -long_result_value - int(-long_result_value) >= 0.5 ? -(int(-long_result_value) + 1) : -int(-long_result_value);
  212. }
  213. //cout << "short_result_ratio:" << short_result_ratio << " long_result_ratio:" << long_result_ratio << endl;
  214. cout << "short_result_value:" << short_result_value << " long_result_value:" << long_result_value << endl;
  215. int result = (short_result_value * 10) + long_result_value;
  216. cout << "读数:" << result << endl;
  217. return result;
  218. }