#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include "opencv2/imgproc/types_c.h" #include #include "DoublePointerCountALGO.h" #include #include using namespace cv; using namespace std; using namespace Ort; void DoublePointerCountALGO::Init(bool isCuda) { string model_path = "models/double_pointer_count.onnx"; std::wstring widestr = std::wstring(model_path.begin(), model_path.end()); sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC); ort_session = new Session(env, widestr.c_str(), sessionOptions); size_t numInputNodes = ort_session->GetInputCount(); size_t numOutputNodes = ort_session->GetOutputCount(); AllocatorWithDefaultOptions allocator; for (int i = 0; i < numInputNodes; i++) { input_names.push_back(ort_session->GetInputName(i, allocator)); Ort::TypeInfo input_type_info = ort_session->GetInputTypeInfo(i); auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo(); auto input_dims = input_tensor_info.GetShape(); input_node_dims.push_back(input_dims); } for (int i = 0; i < numOutputNodes; i++) { output_names.push_back(ort_session->GetOutputName(i, allocator)); Ort::TypeInfo output_type_info = ort_session->GetOutputTypeInfo(i); auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo(); auto output_dims = output_tensor_info.GetShape(); output_node_dims.push_back(output_dims); } this->inpHeight = input_node_dims[0][2]; this->inpWidth = input_node_dims[0][3]; this->outHeight = output_node_dims[0][2]; this->outWidth = output_node_dims[0][3]; } int DoublePointerCountALGO::detect(Mat& srcimg) { vector input_image_ = { 1, 3, 512, 512 }; Mat dstimg; Size resize_size(input_image_[2], input_image_[3]); resize(srcimg, dstimg, resize_size, 0, 0, cv::INTER_LINEAR); int channels = dstimg.channels(); input_image_.resize((this->inpWidth * this->inpHeight * dstimg.channels())); for (int c = 0; c < channels; c++) { for (int i = 0; i < this->inpHeight; i++) { for (int j = 0; j < this->inpWidth; j++) { float pix = dstimg.ptr(i)[j * 3 + 2 - c]; input_image_[(c * this->inpHeight * this->inpWidth + i * this->inpWidth + j)] = (pix / 255.0 - mean[c]) / stds[c]; } } } array input_shape_{ 1, 3, this->inpHeight, this->inpWidth }; auto allocator_info = MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU); Value input_tensor_ = Value::CreateTensor(allocator_info, input_image_.data(), input_image_.size(), input_shape_.data(), input_shape_.size()); // 开始推理 vector ort_outputs = ort_session->Run(RunOptions{ nullptr }, &input_names[0], &input_tensor_, 1, output_names.data(), output_names.size()); float* pred = ort_outputs[0].GetTensorMutableData(); Mat result(outHeight, outWidth, CV_32FC1, pred); result = 2 - result; result *= 255; result.convertTo(result, CV_8UC1); Mat binary; threshold(result, binary, 150, 255, THRESH_BINARY);//二值化阈值处理 //形态学变换 Mat Sobel_Y_thres; Mat element = cv::getStructuringElement(MORPH_RECT, Size(1, 1)); morphologyEx(binary, Sobel_Y_thres, cv::MORPH_OPEN, element, Point(-1, -1), 2); Mat result_line_image = creat_line_image(Sobel_Y_thres, 256, 130); /*namedWindow("矩形", WINDOW_NORMAL); imshow("矩形", result_line_image); waitKey(0);*/ return get_meter_reader(result_line_image); //return result; } Mat DoublePointerCountALGO::creat_line_image(const Mat& circle, int Radius, int RingStride) { Mat rectangle; float theta; int rho; rectangle = Mat::zeros(Size(Radius * pi * 2, RingStride), CV_8UC1); int nl = rectangle.rows; // number of lines int nc = rectangle.cols * rectangle.channels(); // total number of elements per line for (int j = 0; j < nl; j++) { // get the address of row j uchar* data = rectangle.ptr(j); for (int i = 0; i < nc; i++) { theta = pi * 2.0 / LINE_WIDTH * float(i + 1); rho = (Radius - j - 1); int position_y = (float)circle_center[0] + rho * (float)std::cos(theta) + 0.5; int position_x = (float)circle_center[1] - rho * (float)std::sin(theta) + 0.5; data[i] = circle.at(position_y, position_x); } } return rectangle; } //像素值提取及累加 int DoublePointerCountALGO::get_meter_reader(const Mat& image) { Mat histogram = Mat::zeros(Size(256, 1), CV_8UC1); int rows = LINE_HEIGH; //输入图像的行数 int cols = LINE_WIDTH; //输入图像的列数 int sum_horsum = 0; //水平方向列相加和 int long_pointer = 0; int short_pointer = 0; int METER_RANGE = 9; //按矩形计算像素值 vectornum1; vectornum_cols; vectornum3; vectornum_pixel; for (int c = 0; c < cols; c++) { int versum = 0; for (int r = 0; r < rows; r++) { int index = int(image.at(r, c)); versum += index; } if (versum != 0) { sum_horsum += versum; num1.push_back(c); //列索引 num3.push_back(sum_horsum); //像素累加 } if (versum == 0) { //列索引 int maxValue1 = 0; for (auto v : num1) { if (maxValue1 < v) maxValue1 = v; } if (maxValue1 != 0) { num_cols.push_back(maxValue1); } vector().swap(num1); //像素 int maxValue2 = 0; for (auto v : num3) { if (maxValue2 < v) maxValue2 = v; } if (maxValue2 != 0) { num_pixel.push_back(maxValue2); } sum_horsum = 0; vector().swap(num3); } } //标记长短指针 auto firstValue1 = num_pixel.front(); auto lastValue1 = num_pixel.back(); //长短指针取值 auto firstValue2 = num_cols.front() - 30; auto lastValue2 = num_cols.back() - 30; //赋值于长短指针 if (firstValue1 < lastValue1) { short_pointer = firstValue2; long_pointer = lastValue2; }else { short_pointer = lastValue2; long_pointer = firstValue2; } //计算表盘读数 float rectangle_value = 1650; float short_result_ratio = (1.0 * short_pointer / rectangle_value); float long_result_ratio = (1.0 * long_pointer / rectangle_value); float short_result_value = (1.0 * short_result_ratio * METER_RANGE) - 4; if (short_result_value < 0) { short_result_value += 9; } float long_result_value = (1.0 * long_result_ratio * METER_RANGE) - 4; if (long_result_value < 0) { long_result_value += 9; } //四舍五入取整 if (short_result_value > 0) { short_result_value = short_result_value - int(short_result_value) >= 0.5 ? int(short_result_value) + 1 : int(short_result_value); }else { short_result_value = -short_result_value - int(-short_result_value) >= 0.5 ? -(int(-short_result_value) + 1) : -int(-short_result_value); } if (long_result_value > 0) { long_result_value = long_result_value - int(long_result_value) >= 0.5 ? int(long_result_value) + 1 : int(long_result_value); }else { long_result_value = -long_result_value - int(-long_result_value) >= 0.5 ? -(int(-long_result_value) + 1) : -int(-long_result_value); } //cout << "short_result_ratio:" << short_result_ratio << " long_result_ratio:" << long_result_ratio << endl; cout << "short_result_value:" << short_result_value << " long_result_value:" << long_result_value << endl; int result = (short_result_value * 10) + long_result_value; cout << "读数:" << result << endl; return result; }