#include "MeterDectect.h" #include "DoublePointerCountALGO.h" #include "AtmosphericPressureALGO.h" #include "CircularArresterCurrentALGO.h" #include "ArresterCircularZeroThreeALGO.h" #include "CircularOilSinglePointALGO.h" #include "DoubleTemperatureGuageALGO.h" #include "AmpereMeterALGO.h" #include "VoltageMeterALGO.h" using namespace std; static AtmosphericPressureALGO atmosphericPressureALGO; static CircularArresterCurrentALGO circularArresterCurrentALGO; static CircularOilSinglePointALGO circularOilSinglePointALGO; static DoubleTemperatureGuageALGO doubleTemperatureGuageALGO; static AmpereMeterALGO ampereMeterALGO; static VoltageMeterALGO voltageMeterALGO; static DoublePointerCountALGO doublePointerCountALGO; bool MeterDectect::Init(bool isCuda) { string model_path = "models/meter-sim.onnx"; try { net = cv::dnn::readNet(model_path); atmosphericPressureALGO.Init(); circularArresterCurrentALGO.Init(); circularOilSinglePointALGO.Init(isCuda); doubleTemperatureGuageALGO.Init(isCuda); ampereMeterALGO.Init(isCuda); voltageMeterALGO.Init(isCuda); doublePointerCountALGO.Init(isCuda); } catch (const std::exception& ex) { YunDaISASImageRecognitionService::ConsoleLog(ex.what()); return false; } //cuda if (isCuda) { net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16); } //cpu else { net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT); net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); } return true; return false; } IDetection::DectectResult MeterDectect::GetStateResult(cv::Mat img, cv::Rect rec) { return resultValue; } IDetection::DectectResult MeterDectect::GetDigitResult(cv::Mat img, cv::Rect rec) { //resultValue.clear(); //std::cout << "test" << std::endl; //try //{ // cv::Mat ROI = img(rec); // /*imwrite("test.png", ROI); // YunDaISASImageRecognitionService::SetImage(QString::fromStdString("test.png"));*/ // Detect(ROI); //} //catch (const std::exception& ex) //{ // YunDaISASImageRecognitionService::ConsoleLog(ex.what()); //} //if (resultValue.m_confidence < 0.1) //{ // resultValue = DectectResult(0.45, 0, ""); //} return resultValue; } vector MeterDectect::GetDigitResults(cv::Mat img, cv::Rect rec) { resultValues.clear(); try { cv::Mat ROI = img(rec); /*imwrite("test.png", ROI); YunDaISASImageRecognitionService::SetImage(QString::fromStdString("test.png"));*/ Detect(ROI); if (YunDaISASImageRecognitionService::GetIsShowDectect()) { cv::Mat drawROI; ROI.copyTo(drawROI); DrawPred(drawROI, output,className); imwrite("test.png", drawROI); YunDaISASImageRecognitionService::SetImage(QString::fromStdString("test.png")); } } catch (const std::exception& ex) { YunDaISASImageRecognitionService::ConsoleLog(ex.what()); } /*if (resultValue.m_confidence < 0.1) { resultValue = DectectResult(0.45, 0, ""); }*/ return resultValues; } bool MeterDectect::Detect(cv::Mat& SrcImg) { cv::Mat blob; int col = SrcImg.cols; int row = SrcImg.rows; int maxLen = MAX(col, row); cv::Mat netInputImg = SrcImg.clone(); if (maxLen > 1.2 * col || maxLen > 1.2 * row) { cv::Mat resizeImg = cv::Mat::zeros(maxLen, maxLen, CV_8UC3); SrcImg.copyTo(resizeImg(cv::Rect(0, 0, col, row))); netInputImg = resizeImg; } cv::dnn::blobFromImage(netInputImg, blob, 1 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(0, 0, 0), true, false); net.setInput(blob); std::vector netOutputImg; net.forward(netOutputImg, net.getUnconnectedOutLayersNames()); std::vector classIds;//结果id数组 std::vector confidences;//结果每个id对应置信度数组 std::vector boxes;//每个id矩形框 float ratio_h = (float)netInputImg.rows / netHeight; float ratio_w = (float)netInputImg.cols / netWidth; int net_width = className.size() + 5; //输出的网络宽度是类别数+5 float* pdata = (float*)netOutputImg[0].data; for (int stride = 0; stride < strideSize; stride++) { //stride int grid_x = (int)(netWidth / netStride[stride]); int grid_y = (int)(netHeight / netStride[stride]); for (int anchor = 0; anchor < 3; anchor++) { //anchors const float anchor_w = netAnchors[stride][anchor * 2]; const float anchor_h = netAnchors[stride][anchor * 2 + 1]; for (int i = 0; i < grid_y; i++) { for (int j = 0; j < grid_x; j++) { float box_score = pdata[4]; ;//获取每一行的box框中含有某个物体的概率 if (box_score >= boxThreshold) { cv::Mat scores(1, className.size(), CV_32FC1, pdata + 5); cv::Point classIdPoint; double max_class_socre; minMaxLoc(scores, 0, &max_class_socre, 0, &classIdPoint); max_class_socre = (float)max_class_socre; if (max_class_socre >= classThreshold) { //rect [x,y,w,h] float x = pdata[0]; //x float y = pdata[1]; //y float w = pdata[2]; //w float h = pdata[3]; //h int left = (x - 0.5 * w) * ratio_w; int top = (y - 0.5 * h) * ratio_h; left = left < 0 ? 0 : left; top = top < 0 ? 0 : top; int widthBox = int(w * ratio_w); int heightBox = int(h * ratio_h); widthBox = widthBox > col ? col : widthBox; heightBox = heightBox > row ? row : heightBox; if (left < 0|| left>col|| top < 0|| top>row|| widthBox > col|| heightBox > row || left+ widthBox> col|| top+ heightBox> row ) { continue; } classIds.push_back(classIdPoint.x); confidences.push_back(max_class_socre * box_score); boxes.push_back(cv::Rect(left, top, widthBox, heightBox)); } } pdata += net_width;//下一行 } } } } //执行非最大抑制以消除具有较低置信度的冗余重叠框(NMS) vector nms_result; cv::dnn::NMSBoxes(boxes, confidences, nmsScoreThreshold, nmsThreshold, nms_result); float confidenceMax = -1; int confidenceMaxId = 0; output.clear(); if (nms_result.size() > 0) { for (int i = 0; i < nms_result.size()&&i<3; i++) { int idx = nms_result[i]; Output result(classIds[idx], confidences[idx], boxes[idx]); /*int figure = 0; result.id = classIds[idx]; result.confidence = confidences[idx]; result.box = boxes[idx];*/ output.push_back(result); if (className[classIds[idx]] == "rect_arrester_current") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); auto resValue = circularArresterCurrentALGO.detect(SrcImg); tempResultValue.m_dValue = resValue; resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "atmospheric_pressure") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); //auto resState = atmosphericPressureALGO.detect(SrcImg(boxes[idx])); auto resState = atmosphericPressureALGO.detect(SrcImg); tempResultValue.m_dValue = atmosphericPressureALGO.resultValue; tempResultValue.m_sValue = "atmospheric_pressure"; resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "digital_gear") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "circular_arrester_current") //0-3mA避雷器电流 { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); ArresterCircularZeroThreeALGO* algo = new ArresterCircularZeroThreeALGO; auto resNum = algo->GetResult(SrcImg(boxes[idx]), false); tempResultValue.m_dValue = resNum; delete algo; resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "ampere_meter") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); tempResultValue.m_dValue = ampereMeterALGO.detect(SrcImg); resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "voltage_meter") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); tempResultValue.m_dValue = voltageMeterALGO.detect(SrcImg); resultValues.push_back(tempResultValue); } /*else if (className[classIds[idx]] == "double_pointer_count1") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); DoublePointerCountALGO* doublePointerCountALGO = new DoublePointerCountALGO(); int resCount = doublePointerCountALGO->GetResult(SrcImg(boxes[idx]), false); tempResultValue.m_dValue = resCount; delete doublePointerCountALGO; resultValues.push_back(tempResultValue); }*/ else if (className[classIds[idx]] == "double_pointer_count") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); tempResultValue.m_dValue = doublePointerCountALGO.detect(SrcImg); resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "transformers_oil_surface_thermometer") { auto tempResultValueMin = DectectResult(confidences[idx], 60, className[classIds[idx]] + "_Min"); auto tempResultValueMax = DectectResult(confidences[idx], 80, className[classIds[idx]] + "_Max"); auto min_max = doubleTemperatureGuageALGO.detect(SrcImg, 150);//150表示量程 tempResultValueMin.m_dValue = min_max.first; tempResultValueMax.m_dValue = min_max.second; resultValues.push_back(tempResultValueMin); resultValues.push_back(tempResultValueMax); } else if (className[classIds[idx]] == "close") { resultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); } else if (className[classIds[idx]] == "open") { resultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); } else if (className[classIds[idx]] == "round_single_point_oil_level") { auto tempResultValue = DectectResult(confidences[idx], 0, className[classIds[idx]]); tempResultValue.m_dValue = circularOilSinglePointALGO.detect(SrcImg); resultValues.push_back(tempResultValue); } else if (className[classIds[idx]] == "oil_thermometer")//油位温控 { auto tempResultValueMin = DectectResult(confidences[idx], 60, className[classIds[idx]] + "_Min"); auto tempResultValueMax = DectectResult(confidences[idx], 80, className[classIds[idx]] + "_Max"); auto min_max = doubleTemperatureGuageALGO.detect(SrcImg,120);//120表示量程 tempResultValueMin.m_dValue = min_max.first; tempResultValueMax.m_dValue = min_max.second; resultValues.push_back(tempResultValueMin); resultValues.push_back(tempResultValueMax); } YunDaISASImageRecognitionService::ConsoleLog(QString::fromStdString(className[classIds[idx]])); } } else { resultValue = DectectResult(confidenceMax, 0.01, ""); } return false; }