#pragma once #if defined(EUI_HANDLE_AI_2256) #include #else #include #endif #if defined(HD_NO_NAMESPACE) #define EUI_HANDLE_AI_MODEL_NAMESPACE #else #define EUI_HANDLE_AI_MODEL_NAMESPACE handdleAI:: #endif #include #include #include #include #include #include #include #include #include #include #include #include template class handleAiModelInfo { public: using TimeCostCallback = std::function; explicit handleAiModelInfo(TimeCostCallback timeCostCallbackIn = {}) : timeCostCallback(std::move(timeCostCallbackIn)) {} ~handleAiModelInfo() = default; struct modelSlot { handleAiModelPtr* modelPtr = nullptr; int gpuId = -1; QMutex mutex; }; struct getModelPtrResult { handleAiModelPtr* modelPtr = nullptr; int gpuId = -1; std::shared_ptr slot; }; int getModelCount() { QMutexLocker locker(&vectorMutex); return static_cast(modelSlots.size()); } //获取最新的SEG模型 getModelPtrResult getModelPtr(const int& id) { auto slot = getModelSlot(id); if (!slot) { return{}; } QMutexLocker locker(&slot->mutex); return{ slot->modelPtr, slot->gpuId, slot }; } std::shared_ptr getModelSlot(const int& id) { QMutexLocker locker(&vectorMutex); if (id < 0 || id >= static_cast(modelSlots.size())) { qCritical() << QString::fromStdString(path) << "模型ID越界:" << id; return {}; } return modelSlots[id]; } int addModelPtr(handleAiModelPtr* ptr,const int& gpuId,QString modelDiscribeIn) { QMutexLocker locker(&vectorMutex); modelDiscribe = modelDiscribeIn; auto slot = std::make_shared(); slot->modelPtr = ptr; slot->gpuId = gpuId; modelSlots.push_back(std::move(slot)); return static_cast(modelSlots.size()) - 1; // 返回新添加模型的ID } void updateModelPtr(int id, handleAiModelPtr* newPtr) { replaceModelPtr(id, newPtr); } handleAiModelPtr* replaceModelPtr(int id, handleAiModelPtr* newPtr) { auto slot = getModelSlot(id); if (!slot) { return nullptr; } QMutexLocker locker(&slot->mutex); handleAiModelPtr* oldPtr = slot->modelPtr; slot->modelPtr = newPtr; return oldPtr; } QString getModelDiscribe() const { return modelDiscribe; } void submitTime(double time) { TimeCostCallback callback; QString description; QString avgTimeText; QString maxTimeText; QString minTimeText; { QMutexLocker locker(&timeMutex); totalTime += time; callCount++; maxCostTime = std::max(maxCostTime, time); minCostTime = std::min(minCostTime, time); //每十次发送一次平均耗时到界面 每千次输出一次日志并重置数据 if (callCount % 10 == 0) { const double avgTime = callCount > 0 ? totalTime / callCount : 0.0; callback = timeCostCallback; description = modelDiscribe; avgTimeText = QString::number(avgTime, 'f', 2) + "ms"; maxTimeText = QString::number(maxCostTime, 'f', 2) + "ms"; minTimeText = QString::number(minCostTime, 'f', 2) + "ms"; if (callCount == 1000) { qInfo() << QString::fromStdString(path) + "近千次平均耗时" << avgTime << "ms,最高" << maxCostTime << "ms,最低" << minCostTime << "ms"; callCount = 0; totalTime = 0; maxCostTime = 0; minCostTime = 99999.0; } } } if (callback) { callback(description, avgTimeText, maxTimeText, minTimeText); } } double avgTime() { QMutexLocker locker(&timeMutex); return callCount > 0 ? totalTime / callCount : 0.0; }// 平均耗时(毫秒) double maxTime() { QMutexLocker locker(&timeMutex); return maxCostTime; }// 最大耗时(毫秒) double minTime() { QMutexLocker locker(&timeMutex); return minCostTime; }// 最小耗时(毫秒) std::string path; int batchSize = 1; private: QString modelDiscribe;//模型描述 TimeCostCallback timeCostCallback; QMutex vectorMutex; // 保护modelSlots的互斥锁 int index = 0; std::vector> modelSlots; QMutex timeMutex; double totalTime = 0.0, maxCostTime = 0.0, minCostTime = 99999.0; int callCount = 0;// 提交耗时的次数 }; class segModelWithGuard { public: using ModelInfo = handleAiModelInfo; using ModelSlot = typename ModelInfo::modelSlot; segModelWithGuard() = default; segModelWithGuard(int idIn, std::shared_ptr segPtrIn) : segInfoPtr(std::move(segPtrIn)) { if (segInfoPtr) { modelSlot = segInfoPtr->getModelSlot(idIn); } } ~segModelWithGuard() = default; bool empty() const { return !segInfoPtr || !modelSlot; } explicit operator bool() const { return !empty(); } cv::Mat Evaluate(const cv::Mat& input) const { if (empty()) { qCritical() << QString::fromStdString(segInfoPtr ? segInfoPtr->path : std::string()) << "模型未初始化"; return cv::Mat(); } QMutexLocker locker(&modelSlot->mutex); auto segPtr = modelSlot->modelPtr; if (!segPtr) { qCritical() << QString::fromStdString(segInfoPtr->path) << "模型指针为空"; return cv::Mat(); } QElapsedTimer timer; timer.start(); cv::Mat result = segPtr->Evaluate(input); segInfoPtr->submitTime(timer.elapsed()); return result; } std::vector bunchEvaluate(const std::vector& input) const { std::vector result; if (empty()) { qCritical() << QString::fromStdString(segInfoPtr ? segInfoPtr->path : std::string()) << "模型未初始化"; return result; } result.reserve(input.size()); QMutexLocker locker(&modelSlot->mutex); auto segPtr = modelSlot->modelPtr; if (!segPtr) { qCritical() << QString::fromStdString(segInfoPtr->path) << "模型指针为空"; return result; } QElapsedTimer timer; timer.start(); for (const auto& img : input) { result.push_back(segPtr->Evaluate(img)); } segInfoPtr->submitTime(timer.elapsed()); return result; } private: std::shared_ptr segInfoPtr; std::shared_ptr modelSlot; }; class clsModelWithGuard { public: using ModelInfo = handleAiModelInfo; using ModelSlot = typename ModelInfo::modelSlot; clsModelWithGuard() = default; clsModelWithGuard(int idIn, std::shared_ptr ptrIn) : clsInfoPtr(std::move(ptrIn)) { if (clsInfoPtr) { modelSlot = clsInfoPtr->getModelSlot(idIn); } } ~clsModelWithGuard() = default; struct clsResult { int classes = -1; double prob = 0.0; }; bool empty() const { return !clsInfoPtr || !modelSlot; } explicit operator bool() const { return !empty(); } clsResult Evaluate(const cv::Mat& input) const { if (empty()) { qCritical() << QString::fromStdString(clsInfoPtr ? clsInfoPtr->path : std::string()) << "模型未初始化"; return { -1,0.0 }; } QMutexLocker locker(&modelSlot->mutex); auto clsPtr = modelSlot->modelPtr; if (!clsPtr) { qCritical() << QString::fromStdString(clsInfoPtr->path) << "模型指针为空"; return { -1,0.0 }; } QElapsedTimer timer; timer.start(); clsResult result{ clsPtr->Evaluate(input),clsPtr->getProbability() }; clsInfoPtr->submitTime(timer.elapsed()); return result; } std::vector bunchEvaluate(const std::vector& input) const { std::vector result; if (empty()) { qCritical() << QString::fromStdString(clsInfoPtr ? clsInfoPtr->path : std::string()) << "模型未初始化"; return result; } result.reserve(input.size()); QMutexLocker locker(&modelSlot->mutex); auto clsPtr = modelSlot->modelPtr; if (!clsPtr) { qCritical() << QString::fromStdString(clsInfoPtr->path) << "模型指针为空"; return result; } QElapsedTimer timer; timer.start(); for (const auto& img : input) { result.push_back({ clsPtr->Evaluate(img),clsPtr->getProbability() }); } clsInfoPtr->submitTime(timer.elapsed()); return result; } private: std::shared_ptr clsInfoPtr; std::shared_ptr modelSlot; }; class detModelWithGuard { public: using ModelInfo = handleAiModelInfo; using ModelSlot = typename ModelInfo::modelSlot; detModelWithGuard() = default; detModelWithGuard(int idIn, std::shared_ptr ptrIn) : detInfoPtr(std::move(ptrIn)) { if (detInfoPtr) { modelSlot = detInfoPtr->getModelSlot(idIn); } } ~detModelWithGuard() = default; bool empty() const { return !detInfoPtr || !modelSlot; } explicit operator bool() const { return !empty(); } // 单张推理 std::vector Evaluate(const cv::Mat& input) const { if (empty()) { qCritical() << QString::fromStdString(detInfoPtr ? detInfoPtr->path : std::string()) << "模型未初始化"; return std::vector(); } QMutexLocker locker(&modelSlot->mutex); auto detPtr = modelSlot->modelPtr; if (!detPtr) { qCritical() << QString::fromStdString(detInfoPtr->path) << "模型指针为空"; return std::vector(); } QElapsedTimer timer; timer.start(); auto result = detPtr->Evaluate(input); detInfoPtr->submitTime(timer.elapsed()); return result; } // 批量推理 std::vector>bunchEvaluate(const std::vector& input) const { std::vector> result; if (empty()) { qCritical() << QString::fromStdString(detInfoPtr ? detInfoPtr->path : std::string()) << "模型未初始化"; return result; } QMutexLocker locker(&modelSlot->mutex); result.reserve(input.size()); auto detPtr = modelSlot->modelPtr; if (!detPtr) { qCritical() << QString::fromStdString(detInfoPtr->path) << "模型指针为空"; return result; } QElapsedTimer timer; timer.start(); for (const auto& img : input) { result.push_back(detPtr->Evaluate(img)); } detInfoPtr->submitTime(timer.elapsed()); return result; } private: std::shared_ptr detInfoPtr; std::shared_ptr modelSlot; }; #undef EUI_HANDLE_AI_MODEL_NAMESPACE