diff --git a/src.zip b/src.zip index 46774e3..09f88f4 100644 Binary files a/src.zip and b/src.zip differ diff --git a/src/core/back/summaryData.h b/src/core/back/summaryData.h index 3a16888..1a32039 100644 --- a/src/core/back/summaryData.h +++ b/src/core/back/summaryData.h @@ -1,44 +1,57 @@ +#pragma once #include +#include #include -#include -#include -#include +#include +#include template -class summaryData{ +class summaryData { public: - summaryData(){ + summaryData() {} + + summaryDataTemplate* get(const std::string& sn) { + QMutexLocker locker(&_mutex); + + cleanOldest(100); + + auto it = map.find(sn); + if (it != map.end()) { + return &(it->second.first); + } + + order.push_back(sn); + auto list_it = std::prev(order.end()); + map.emplace(sn, std::make_pair(summaryDataTemplate(), list_it)); + + return &(map.find(sn)->second.first); + } + + bool remove(const std::string& sn) { + QMutexLocker locker(&_mutex); + + auto it = map.find(sn); + if (it != map.end()) { + order.erase(it->second.second); + map.erase(it); + return true; + } + return false; + } - } - void cleanAbove(int num){ - std::lock_guardlocker(_mutex); - for (auto it = map.end(); map.size() > num ; it--){ - map.erase(it); - } - - } - - summaryDataTemplate* get(std::string sn){ - cleanAbove(100); - std::lock_guardlocker(_mutex); - auto it = map.find(sn); - if (it != map.end()) { - return &it->second; - } - map.insert(std::make_pair(sn, summaryDataTemplate())); - return &map.find(sn)->second; - } - bool remove(std::string sn) { - std::lock_guardlocker(_mutex); - auto it = map.find(sn); - if (it != map.end()) { - map.erase(it); - return true; - } - return false; - } private: - std::unordered_map map; - std::mutex _mutex; + void cleanOldest(int num) { + while (map.size() > num) { + const std::string& oldest_sn = order.front(); + auto it = map.find(oldest_sn); + if (it != map.end()) { + map.erase(it); + } + order.pop_front(); + } + } + + std::unordered_map::iterator>> map; + std::list order; + QMutex _mutex; }; -#pragma once \ No newline at end of file diff --git a/src/launcher/GUI/front/pages/summary_data_page.h b/src/launcher/GUI/front/pages/summary_data_page.h index 6b953a0..2268e9e 100644 --- a/src/launcher/GUI/front/pages/summary_data_page.h +++ b/src/launcher/GUI/front/pages/summary_data_page.h @@ -43,14 +43,14 @@ public: // 主蓝色曲线 m_plot->addGraph(); - m_plot->graph(0)->setPen(QPen(Qt::blue, 2)); + m_plot->graph(0)->setPen(QPen(QColor(0,191,255), 3)); m_plot->graph(0)->setScatterStyle(QCPScatterStyle::ssNone); // 新增红色点图层 m_plot->addGraph(); m_plot->graph(1)->setLineStyle(QCPGraph::lsNone); m_plot->graph(1)->setScatterStyle( - QCPScatterStyle(QCPScatterStyle::ssDisc, QPen(Qt::red), QBrush(Qt::red), 6) + QCPScatterStyle(QCPScatterStyle::ssDisc, QPen(Qt::red), QBrush(Qt::red), 5) ); m_plot->xAxis->setBasePen(QPen(Qt::white, 2)); // 坐标轴线 m_plot->yAxis->setBasePen(QPen(Qt::white, 2)); @@ -67,7 +67,30 @@ public: m_plot->xAxis->setLabelColor(Qt::white); // "时间" / "数值" 文字 m_plot->yAxis->setLabelColor(Qt::white); - m_plot->yAxis->setRange(m_limitLow - 1, m_limitHigh + 1); + m_plot->yAxis->setRange(m_limitLow - 2, m_limitHigh + 2); + + // 鼠标追踪用的 tracer + m_tracer = new QCPItemTracer(m_plot); + m_tracer->setGraph(m_plot->graph(0)); // 让它追踪你的蓝色曲线 + m_tracer->setStyle(QCPItemTracer::tsCircle); + m_tracer->setPen(QPen(Qt::yellow)); + m_tracer->setBrush(Qt::yellow); + m_tracer->setSize(7); + m_tracer->setVisible(false); // 默认隐藏 + + // 文本提示 + m_tracerText = new QCPItemText(m_plot); + m_tracerText->setColor(Qt::white); // 文字颜色 + m_tracerText->setFont(QFont("微软雅黑", 10, QFont::Bold)); + m_tracerText->position->setType(QCPItemPosition::ptPlotCoords); + m_tracerText->setBrush(QBrush(QColor(0, 0, 0, 150))); // 半透明背景 + m_tracerText->setPadding(QMargins(5, 2, 5, 2)); // 留点内边距 + m_tracerText->setVisible(false); + + // 绑定鼠标移动事件 + connect(m_plot, &QCustomPlot::mouseMove, this, &WaveFormWidget::onMouseMoveInPlot); + + addLimitLines(m_limitHigh, m_limitLow); } @@ -81,12 +104,12 @@ public: m_yOverLimit.append(value); auto* textItem = new QCPItemText(m_plot); - textItem->setPositionAlignment(Qt::AlignLeft | Qt::AlignVCenter); + textItem->setPositionAlignment(Qt::AlignLeft | Qt::AlignBottom); textItem->position->setType(QCPItemPosition::ptPlotCoords); textItem->position->setCoords(m_timeCounter, value); textItem->setText(QString::number(value, 'f', 2)); textItem->setColor(Qt::yellow); - textItem->setFont(QFont("微软雅黑", 8, QFont::Bold)); + textItem->setFont(QFont("微软雅黑", 8,QFont::Bold)); m_textItems.append(textItem); } @@ -122,6 +145,13 @@ protected: menu.exec(event->globalPos()); } + void leaveEvent(QEvent* event) override { + if (m_tracer) m_tracer->setVisible(false); + if (m_tracerText) m_tracerText->setVisible(false); + m_plot->replot(); + QWidget::leaveEvent(event); + } + private slots: void editJsonParameters() { JsonEditorDialog* dlg = new JsonEditorDialog(m_json, this); @@ -132,6 +162,36 @@ private slots: }); dlg->show(); } + void onMouseMoveInPlot(QMouseEvent* event) { + double x = m_plot->xAxis->pixelToCoord(event->pos().x()); + if (!m_xData.isEmpty()) { + double y = findNearestYValue(x); + + m_tracer->setGraphKey(x); + m_tracer->updatePosition(); + m_tracer->setVisible(true); + + m_tracerText->setText(QString("%1\n值:%2") + .arg(static_cast(std::round(x))) + .arg(y, 0, 'f', 2)); + m_tracerText->setVisible(true); + m_tracerText->setTextAlignment(Qt::AlignLeft); + + // 判断左右边显示气泡 + int mouseX = event->pos().x(); + int mouseY = event->pos().y(); + int plotWidth = m_plot->width(); + int plotHeight = m_plot->height(); + + Qt::Alignment hAlign = (mouseX < plotWidth / 2) ? Qt::AlignLeft : Qt::AlignRight; + Qt::Alignment vAlign = (mouseY < plotHeight / 2) ? Qt::AlignTop : Qt::AlignBottom; + + m_tracerText->setPositionAlignment(hAlign | vAlign); + + m_tracerText->position->setCoords(x, y); + m_plot->replot(); + } + } private: void applyJsonParams() { @@ -152,15 +212,45 @@ private: m_plot->replot(); } + + // 简单线性插值(或者最近点) + double interpolateYValue(double x) { + for (int i = 1; i < m_xData.size(); ++i) { + if (m_xData[i] >= x) { + double x0 = m_xData[i - 1], y0 = m_yData[i - 1]; + double x1 = m_xData[i], y1 = m_yData[i]; + if (x1 == x0) return y0; + return y0 + (y1 - y0) * (x - x0) / (x1 - x0); + } + } + return m_yData.last(); // 超出范围 + } + double findNearestYValue(double x) { + if (m_xData.isEmpty()) + return 0; + + int nearestIndex = 0; + double minDist = std::abs(m_xData[0] - x); + + for (int i = 1; i < m_xData.size(); ++i) { + double dist = std::abs(m_xData[i] - x); + if (dist < minDist) { + minDist = dist; + nearestIndex = i; + } + } + + return m_yData[nearestIndex]; + } void addLimitLines(double high, double low) { auto* line1 = new QCPItemStraightLine(m_plot); - line1->setPen(QPen(Qt::green, 1, Qt::DashLine)); + line1->setPen(QPen(Qt::green, 1, Qt::SolidLine)); line1->point1->setCoords(0, high); line1->point2->setCoords(1, high); auto* line2 = new QCPItemStraightLine(m_plot); - line2->setPen(QPen(Qt::green, 1, Qt::DashLine)); + line2->setPen(QPen(Qt::green, 1, Qt::SolidLine)); line2->point1->setCoords(0, low); line2->point2->setCoords(1, low); } @@ -175,6 +265,9 @@ private: int m_maxPoints = 50; double m_timeCounter = 0; double m_limitHigh = -1, m_limitLow = 2; + QCPItemTracer* m_tracer = nullptr; + QCPItemText* m_tracerText = nullptr; + }; diff --git a/src/mission/952_15_H_25D/952_15_H_25D.h b/src/mission/952_15_H_25D/952_15_H_25D.h index 0593949..aa5c6fd 100644 --- a/src/mission/952_15_H_25D/952_15_H_25D.h +++ b/src/mission/952_15_H_25D/952_15_H_25D.h @@ -96,8 +96,15 @@ static bool _952_15_H_Algo(std::shared_ptr data, handleAIModels* _hand qCritical() << "图片数量不满足要求:" << data->oriImgs.size(); return false; } + if (data->oriImgs[0].rows == 100) { + cv::Mat Paint; + data->oriImgs[0].copyTo(Paint); + cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2); + return true; + } cv::Mat Paint; + QMutex paintMutex; clock_t start, finish; start = clock(); @@ -109,7 +116,7 @@ static bool _952_15_H_Algo(std::shared_ptr data, handleAIModels* _hand cv::cvtColor(src2, Paint, cv::COLOR_GRAY2BGR); else src2.copyTo(Paint); - QMutex paintMutex; + std::future future = std::async(std::launch::async, _952_15_H_25D_ALGO_HuaShangAI, data, data->oriImgs[2], _handleAIModels, std::ref(Paint), std::ref(paintMutex)); HTuple out_Distance, out_ResultRows, out_ResultCols, out_Flag, out_LinePonit; { diff --git a/src/mission/952_15_Q_2D3D/952_15_Q_2D3D.h b/src/mission/952_15_Q_2D3D/952_15_Q_2D3D.h index 7c3ce45..ca46ba9 100644 --- a/src/mission/952_15_Q_2D3D/952_15_Q_2D3D.h +++ b/src/mission/952_15_Q_2D3D/952_15_Q_2D3D.h @@ -49,7 +49,6 @@ static bool _952_15_Q_2D_P_ALGO_HuaShangAI(cv::Mat& img, handleAIModels* _handle if (clsIsNg == true) { color = cv::Scalar(0, 0, 255); isNg = true; - cv::approxPolyDP(contours[i], contours[i], 3, true); // 多边形拟合 QMutexLocker locker(&paintMutex); cv::drawContours(Paint, contours, i, color, 2); } @@ -83,7 +82,6 @@ static bool _952_15_Q_2D_P_ALGO_ZangWuAI(cv::Mat& img, handleAIModels* _handleAi if (clsIsNg == true) { color = cv::Scalar(0, 0, 255); isNg = true; - cv::approxPolyDP(contours[i], contours[i], 3, true); // 多边形拟合 QMutexLocker locker(&paintMutex); cv::drawContours(Paint, contours, i, color, 2); } @@ -400,9 +398,16 @@ public: //8040 1 Summary1 void sumRequest1(QByteArray& byteArray){ _serviceManager->_triggerManager->writeShort({ "D8040_0" ,"D9402_1","D9404_1"}); - int snPos = _3D_snPos; + int snPos = summary_triggerPos; std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, snPos, false, false, -1); _952_15_Q_2D3D_1_summaryData* dataPtr = _summaryData.get(sn); + _serviceManager->_triggerManager->writeShort({ + "D6020_1", "D6021_1", "D6022_1", "D6023_1", "D6024_1", + "D6025_1", "D6026_1", "D6027_1", "D6028_1", "D6029_1", + "D6030_1", "D6031_1", "D6032_1", "D6033_1", "D6034_1", + "D6035_1", "D6036_1", "D6037_1", "D6038_1", "D6039_1" + }); + _serviceManager->_triggerManager->sendFinsMsg("write_float_D8046_"+ dataPtr->_2D_P_Result);//右上留白 _serviceManager->_triggerManager->sendFinsMsg("write_float_D8047_" + dataPtr->_2D_N_Result);//右下留白 _serviceManager->_triggerManager->sendFinsMsg("write_float_D8048_" + dataPtr->_3D_1_Result);//右对其度 @@ -410,7 +415,6 @@ public: std::cout << "通道1 SN:" << sn << " 发送结果" << std::endl;//:\n左留白->" << dataPtr->leftLiuBai.toStdString() << "\n右留白->" << dataPtr->rightLiuBai.toStdString() << "\n对其度->" << dataPtr->duiqidu.toStdString()< data, handleAiModelManager* _handleAiModelManager){ cv::Mat testImg; if(data->oriImgs[0].channels() == 1)