稳定版本

This commit is contained in:
2025-07-14 01:17:55 +08:00
parent 288b4a7f00
commit 8c8dac0c2d
5 changed files with 165 additions and 48 deletions
BIN
View File
Binary file not shown.
+49 -36
View File
@@ -1,44 +1,57 @@
#pragma once
#include <unordered_map>
#include <list>
#include <string>
#include <vector>
#include <triggerManager.h>
#include <mutex>
#include <QMutex>
#include <QMutexLocker>
template <typename summaryDataTemplate>
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_guard<std::mutex>locker(_mutex);
for (auto it = map.end(); map.size() > num ; it--){
map.erase(it);
}
}
summaryDataTemplate* get(std::string sn){
cleanAbove(100);
std::lock_guard<std::mutex>locker(_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_guard<std::mutex>locker(_mutex);
auto it = map.find(sn);
if (it != map.end()) {
map.erase(it);
return true;
}
return false;
}
private:
std::unordered_map<std::string, summaryDataTemplate> 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<std::string, std::pair<summaryDataTemplate, std::list<std::string>::iterator>> map;
std::list<std::string> order;
QMutex _mutex;
};
#pragma once
@@ -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<int>(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;
};
+8 -1
View File
@@ -96,8 +96,15 @@ static bool _952_15_H_Algo(std::shared_ptr <detData> 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 <detData> data, handleAIModels* _hand
cv::cvtColor(src2, Paint, cv::COLOR_GRAY2BGR);
else
src2.copyTo(Paint);
QMutex paintMutex;
std::future <bool> 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;
{
+8 -4
View File
@@ -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()<<std::endl;
_summaryData.remove(sn);
}
static bool processAlgo(std::shared_ptr <detData> data, handleAiModelManager* _handleAiModelManager){
cv::Mat testImg;
if(data->oriImgs[0].channels() == 1)