diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/IYDroneScrewCtrlStatus.h b/App/DroneScrewbolt/DroneScrewCtrlApp/IYDroneScrewCtrlStatus.h index 17fcfaa8..fd7313f6 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/IYDroneScrewCtrlStatus.h +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/IYDroneScrewCtrlStatus.h @@ -17,6 +17,8 @@ struct CtrlDetectionBox int y{0}; int width{0}; int height{0}; + bool hasPhysicalHeight{false}; + float physicalHeightMm{0.0f}; }; /** diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/Presenter/Src/DroneScrewCtrlPresenter.cpp b/App/DroneScrewbolt/DroneScrewCtrlApp/Presenter/Src/DroneScrewCtrlPresenter.cpp index 16c96757..a49d678e 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/Presenter/Src/DroneScrewCtrlPresenter.cpp +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/Presenter/Src/DroneScrewCtrlPresenter.cpp @@ -758,6 +758,8 @@ CtrlDetectionFrame DroneScrewCtrlPresenter::toCtrlFrame(const WDRemoteDetectionF cb.y = b.y; cb.width = b.width; cb.height = b.height; + cb.hasPhysicalHeight = b.hasPhysicalHeight; + cb.physicalHeightMm = b.physicalHeightMm; frame.boxes.push_back(cb); } frame.distances.reserve(f.distances.size()); diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/Version.h b/App/DroneScrewbolt/DroneScrewCtrlApp/Version.h index b03ce064..be512ecc 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/Version.h +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/Version.h @@ -3,8 +3,8 @@ #define DRONESCREWCTRL_APP_NAME "无人机螺杆控制端" #define DRONESCREWCTRL_VERSION_STRING "1.0.0" -#define DRONESCREWCTRL_BUILD_STRING "3" -#define DRONESCREWCTRL_FULL_VERSION_STRING "V1.0.0_3" +#define DRONESCREWCTRL_BUILD_STRING "4" +#define DRONESCREWCTRL_FULL_VERSION_STRING "V1.0.0_4" inline const char* GetDroneScrewCtrlFullVersion() { return DRONESCREWCTRL_FULL_VERSION_STRING; } diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/mainwindow.cpp b/App/DroneScrewbolt/DroneScrewCtrlApp/mainwindow.cpp index 9f522106..36a08295 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/mainwindow.cpp +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/mainwindow.cpp @@ -355,7 +355,7 @@ void MainWindow::OnDetectionResult(const CtrlDetectionFrame& result) upsertResultItem(row++, head, static_cast(i), ResultItem::DisplayMode::Distance); } } - else if (result.boxes.empty()) + else if (result.boxes.empty() && result.distances.empty()) { const QString head = QStringLiteral("帧#%1 精准目标 0") .arg(result.frameId); @@ -371,6 +371,14 @@ void MainWindow::OnDetectionResult(const CtrlDetectionFrame& result) .arg(static_cast(result.boxes.size())); upsertResultItem(row++, head, static_cast(i), ResultItem::DisplayMode::Precision); } + for (size_t i = 0; i < result.distances.size(); ++i) + { + const QString head = QStringLiteral("帧#%1 杆间距 %2/%3") + .arg(result.frameId) + .arg(static_cast(i + 1)) + .arg(static_cast(result.distances.size())); + upsertResultItem(row++, head, static_cast(i), ResultItem::DisplayMode::PrecisionDistance); + } } trimResultItems(row); diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.cpp b/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.cpp index f524f60c..2f15ddf9 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.cpp +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.cpp @@ -37,6 +37,11 @@ QString oneDistanceText(const CtrlDetectionDistance& d) return QStringLiteral("%1m").arg(meters, 0, 'f', 3); } +QString oneDistanceMmText(const CtrlDetectionDistance& d) +{ + return QStringLiteral("%1 mm").arg(d.distanceMm, 0, 'f', 2); +} + QString distanceText(const CtrlDetectionFrame& frame, int targetIndex) { if (targetIndex >= 0 && targetIndex < static_cast(frame.distances.size())) @@ -50,6 +55,19 @@ QString distanceText(const CtrlDetectionFrame& frame, int targetIndex) : distanceParts.join(" "); } +QString distanceMmText(const CtrlDetectionFrame& frame, int targetIndex) +{ + if (targetIndex >= 0 && targetIndex < static_cast(frame.distances.size())) + return oneDistanceMmText(frame.distances[static_cast(targetIndex)]); + + QStringList distanceParts; + for (size_t i = 0; i < frame.distances.size(); ++i) + distanceParts << oneDistanceMmText(frame.distances[i]); + return distanceParts.isEmpty() + ? QStringLiteral("未测到距离") + : distanceParts.join(" "); +} + QString distanceIndexText(const CtrlDetectionFrame& frame, int targetIndex) { const int total = static_cast(frame.distances.size()); @@ -60,6 +78,22 @@ QString distanceIndexText(const CtrlDetectionFrame& frame, int targetIndex) } return QStringLiteral("-"); } + +QString precisionDistanceIndexText(const CtrlDetectionFrame& frame, int targetIndex) +{ + const int total = static_cast(frame.distances.size()); + if (targetIndex >= 0 && targetIndex < total) + { + const CtrlDetectionDistance& d = frame.distances[static_cast(targetIndex)]; + if (d.fromId >= 0 && d.toId >= 0) + return QStringLiteral("%1-%2").arg(d.fromId + 1).arg(d.toId + 1); + if (d.fromId >= 0) + return QString::number(d.fromId + 1); + if (d.toId >= 0) + return QString::number(d.toId + 1); + } + return QStringLiteral("-"); +} } ResultItem::ResultItem(QWidget* parent) @@ -110,15 +144,23 @@ void ResultItem::setResultData(int targetIndex, DisplayMode mode) { const bool precisionMode = (mode == DisplayMode::Precision); + const bool precisionDistanceMode = (mode == DisplayMode::PrecisionDistance); setResultTextStyle(ui); - setMinimumHeight(precisionMode ? 104 : 108); + setMinimumHeight((precisionMode || precisionDistanceMode) ? 104 : 108); if (ui->lb_id_t) ui->lb_id_t->setText(QStringLiteral("ID")); if (ui->lb_status_t) - ui->lb_status_t->setText(mode == DisplayMode::Distance - ? QStringLiteral("距离") - : QStringLiteral("状态")); + { + if (mode == DisplayMode::Distance) + ui->lb_status_t->setText(QStringLiteral("距离")); + else if (precisionDistanceMode) + ui->lb_status_t->setText(QStringLiteral("杆间距")); + else if (precisionMode) + ui->lb_status_t->setText(QStringLiteral("物理高度")); + else + ui->lb_status_t->setText(QStringLiteral("状态")); + } if (ui->label_id) { @@ -126,6 +168,10 @@ void ResultItem::setResultData(int targetIndex, ui->label_id->setText(QString("%1/%2") .arg(targetIndex + 1) .arg(static_cast(frame.boxes.size()))); + else if (precisionDistanceMode) + { + ui->label_id->setText(precisionDistanceIndexText(frame, targetIndex)); + } else if (mode == DisplayMode::Distance) { ui->label_id->setText(distanceIndexText(frame, targetIndex)); @@ -134,10 +180,16 @@ void ResultItem::setResultData(int targetIndex, ui->label_id->setText(QStringLiteral("0/0")); } - if (mode == DisplayMode::Distance) + if (mode == DisplayMode::Distance || precisionDistanceMode) { if (ui->label_status) - ui->label_status->setText(frame.success ? distanceText(frame, targetIndex) : failedText(frame)); + { + ui->label_status->setText(frame.success + ? (precisionDistanceMode + ? distanceMmText(frame, targetIndex) + : distanceText(frame, targetIndex)) + : failedText(frame)); + } return; } @@ -146,11 +198,19 @@ void ResultItem::setResultData(int targetIndex, if (targetIndex >= 0 && targetIndex < static_cast(frame.boxes.size())) { const CtrlDetectionBox& b = frame.boxes[static_cast(targetIndex)]; - const QString text = QStringLiteral("score=%1 w=%2 h=%3") - .arg(b.score, 0, 'f', 3) - .arg(b.width) - .arg(b.height); - ui->label_status->setText(text); + if (b.hasPhysicalHeight) + { + ui->label_status->setText(QStringLiteral("%1 mm") + .arg(b.physicalHeightMm, 0, 'f', 2)); + } + else + { + const QString text = QStringLiteral("score=%1 w=%2 h=%3") + .arg(b.score, 0, 'f', 3) + .arg(b.width) + .arg(b.height); + ui->label_status->setText(text); + } } else if (!frame.success) { diff --git a/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.h b/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.h index eda2205e..0f4b3ad8 100644 --- a/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.h +++ b/App/DroneScrewbolt/DroneScrewCtrlApp/resultitem.h @@ -14,7 +14,8 @@ public: enum class DisplayMode { Distance, - Precision + Precision, + PrecisionDistance }; explicit ResultItem(QWidget* parent = nullptr); diff --git a/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.cpp b/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.cpp index 2cd21361..cf66bc06 100644 --- a/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.cpp +++ b/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.cpp @@ -700,6 +700,18 @@ void DroneScrewAlgoStub::appendRoiBox(const StereoBoltModuleRoiC& roi, result.boxes.push_back(box); } +void DroneScrewAlgoStub::appendBoltBox(const StereoBoltModuleBoltC& bolt, + DroneScrewResult& result) const +{ + DroneScrewBox box; + if (mapRectifiedLeftRoi(bolt.left_roi, result.imageWidth, result.imageHeight, box)) + { + box.hasPhysicalHeight = true; + box.physicalHeightMm = static_cast(bolt.height_mm); + result.boxes.push_back(box); + } +} + int DroneScrewAlgoStub::Init(const DroneScrewAlgoParams& params) { std::lock_guard lk(m_mutex); @@ -899,7 +911,7 @@ int DroneScrewAlgoStub::Detect(const DroneScrewInputImage& leftImage, if (out.data.n_bolts > 0 && out.data.bolts) { for (int i = 0; i < out.data.n_bolts; ++i) - appendRoiBox(out.data.bolts[i].left_roi, result); + appendBoltBox(out.data.bolts[i], result); } if (out.data.n_adjacent_distances > 0 && out.data.adjacent_distances) { diff --git a/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.h b/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.h index f904fedf..bfd2c3f6 100644 --- a/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.h +++ b/App/DroneScrewbolt/DroneScrewServer/Algo/DroneScrewAlgoStub.h @@ -47,6 +47,8 @@ private: DroneScrewBox& box) const; void appendRoiBox(const StereoBoltModuleRoiC& roi, DroneScrewResult& result) const; + void appendBoltBox(const StereoBoltModuleBoltC& bolt, + DroneScrewResult& result) const; #endif DroneScrewAlgoParams m_params; diff --git a/App/DroneScrewbolt/DroneScrewServer/Algo/IDroneScrewAlgo.h b/App/DroneScrewbolt/DroneScrewServer/Algo/IDroneScrewAlgo.h index b16f9db0..6ffb93f8 100644 --- a/App/DroneScrewbolt/DroneScrewServer/Algo/IDroneScrewAlgo.h +++ b/App/DroneScrewbolt/DroneScrewServer/Algo/IDroneScrewAlgo.h @@ -16,6 +16,8 @@ struct DroneScrewBox int y{0}; int width{0}; int height{0}; + bool hasPhysicalHeight{false}; + float physicalHeightMm{0.0f}; }; /** diff --git a/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp b/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp index 37bef26a..3151302e 100644 --- a/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp +++ b/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp @@ -69,7 +69,6 @@ constexpr int kDetectPipelineDistance = 1; constexpr const char* kImageSaveRootDir = "/home/cat"; constexpr size_t kMaxImageSaveQueueDepth = 100; constexpr size_t kImageSaveWorkerCount = 4; -constexpr int kDistanceImageSaveStride = 3; const char* mvsSdkErrorName(int code) { @@ -253,6 +252,70 @@ void logDetectionResultFixed(const char* tag, int frameNo, const DroneScrewResul } } +QString savedImageFileName(unsigned long long index, const QString& prefix) +{ + return QStringLiteral("%1_%2Image.png").arg(index).arg(prefix); +} + +bool saveDetectionResultText(const QString& dirPath, + unsigned long long imageIndex, + const DroneScrewResult& result) +{ + const QString filePath = QDir(dirPath).filePath( + QStringLiteral("%1_result.txt").arg(imageIndex)); + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) + { + LOG_WARN("[SAVE] result save open failed: %s\n", + filePath.toStdString().c_str()); + return false; + } + + QTextStream out(&file); + out << "index:" << static_cast(imageIndex) << '\n'; + out << "leftImage:" << savedImageFileName(imageIndex, QStringLiteral("left")) << '\n'; + out << "rightImage:" << savedImageFileName(imageIndex, QStringLiteral("right")) << '\n'; + out << "frameId:" << static_cast(result.frameId) << '\n'; + out << "timestampUs:" << static_cast(result.timestampUs) << '\n'; + out << "success:" << (result.success ? 1 : 0) << '\n'; + out << "errorCode:" << result.errorCode << '\n'; + out << "message:" << QString::fromStdString(result.message) << '\n'; + + int physicalHeightCount = 0; + for (const auto& b : result.boxes) + { + if (b.hasPhysicalHeight) + ++physicalHeightCount; + } + out << "physicalHeightCount:" << physicalHeightCount << '\n'; + int physicalHeightIndex = 1; + for (const auto& b : result.boxes) + { + if (!b.hasPhysicalHeight) + continue; + out << "physicalHeight" << physicalHeightIndex << "Id:" << physicalHeightIndex << '\n'; + out << "physicalHeight" << physicalHeightIndex << "Mm:" + << QString::number(b.physicalHeightMm, 'f', 3) << '\n'; + ++physicalHeightIndex; + } + + out << "rodSpacingCount:" << static_cast(result.distances.size()) << '\n'; + for (size_t i = 0; i < result.distances.size(); ++i) + { + const auto& d = result.distances[i]; + const int index = static_cast(i + 1); + out << "rodSpacing" << index << "FromId:" << (d.fromId + 1) << '\n'; + out << "rodSpacing" << index << "ToId:" << (d.toId + 1) << '\n'; + out << "rodSpacing" << index << "Mm:" + << QString::number(d.distanceMm, 'f', 3) << '\n'; + } + out.flush(); + if (out.status() != QTextStream::Ok) + return false; + + return true; +} + double clampCameraFloatFeature(IMvsDevice* camera, const char* role, const char* featureName, @@ -1814,9 +1877,9 @@ int DroneScrewServerPresenter::stopDetectionWork() stopGpioTriggerLoop(); m_bThreadExit = true; - stopImageSaveThread(); if (m_detectThread.joinable()) m_detectThread.join(); + stopImageSaveThread(); m_bIsDetecting = false; m_detectPipelineMode = kDetectPipelinePrecision; m_activeTriggerFps = static_cast(kPrecisionFrameRate); @@ -1909,7 +1972,6 @@ int DroneScrewServerPresenter::startLiveStream() m_bLiveStreaming = true; m_bThreadExit = false; m_bIsDetecting = true; - startImageSaveThread(imageSaveModeName()); startGpioTriggerLoop(); m_detectThread = std::thread(&DroneScrewServerPresenter::detectThreadFunc, this); emit statusChanged(QStringLiteral("开始实时传图")); @@ -1935,9 +1997,9 @@ int DroneScrewServerPresenter::stopLiveStream() m_bRtspStarted = false; stopGpioTriggerLoop(); m_bThreadExit = true; - stopImageSaveThread(); if (m_detectThread.joinable()) m_detectThread.join(); + stopImageSaveThread(); m_bIsDetecting = false; m_detectPipelineMode = kDetectPipelinePrecision; m_activeTriggerFps = static_cast(kPrecisionFrameRate); @@ -2374,7 +2436,7 @@ void DroneScrewServerPresenter::startImageSaveThread(const QString& modeName) void DroneScrewServerPresenter::stopImageSaveThread() { const bool shouldJoin = !m_imageSaveThreads.empty(); - size_t droppedPending = 0; + size_t pendingJobs = 0; { std::lock_guard lk(m_imageSaveMutex); if (!shouldJoin) @@ -2384,16 +2446,14 @@ void DroneScrewServerPresenter::stopImageSaveThread() m_imageSaveThreadExit = false; return; } - droppedPending = m_imageSaveQueue.size(); - if (droppedPending > 0) - m_imageSaveQueue.clear(); + pendingJobs = m_imageSaveQueue.size(); m_imageSaveThreadExit = true; } - if (droppedPending > 0) + if (pendingJobs > 0) { - LOG_WARN("[SAVE] stop requested, drop pending save jobs=%zu\n", - droppedPending); + LOG_INFO("[SAVE] stop requested, flush pending save jobs=%zu\n", + pendingJobs); } m_imageSaveCv.notify_all(); @@ -2414,6 +2474,7 @@ void DroneScrewServerPresenter::stopImageSaveThread() void DroneScrewServerPresenter::enqueueImageSave(const MvsImageData& leftImg, const MvsImageData& rightImg, + const DroneScrewResult& result, unsigned long long index) { auto dropIfQueueFull = [this, index]() -> bool { @@ -2460,6 +2521,8 @@ void DroneScrewServerPresenter::enqueueImageSave(const MvsImageData& leftImg, ImageSaveJob job; job.index = index; + job.result = result; + job.hasResult = true; if (!copyMono8(leftImg, job.left) || !copyMono8(rightImg, job.right)) { LOG_WARN("[SAVE] skip image save: unsupported image pair index=%llu left=%ux%u pf=0x%x right=%ux%u pf=0x%x\n", @@ -2494,14 +2557,10 @@ void DroneScrewServerPresenter::imageSaveThreadFunc(int workerIndex) return m_imageSaveThreadExit.load() || !m_imageSaveQueue.empty(); }); - if (m_imageSaveThreadExit.load()) - { - m_imageSaveQueue.clear(); - break; - } - if (m_imageSaveQueue.empty()) { + if (m_imageSaveThreadExit.load()) + break; continue; } @@ -2523,7 +2582,7 @@ void DroneScrewServerPresenter::imageSaveThreadFunc(int workerIndex) static_cast(img.width), QImage::Format_Grayscale8); const QString filePath = QDir(job.dirPath).filePath( - QStringLiteral("%1_%2Image.png").arg(job.index).arg(prefix)); + savedImageFileName(job.index, prefix)); if (!q.save(filePath, "PNG")) { LOG_WARN("[SAVE] image save failed: %s\n", @@ -2532,9 +2591,9 @@ void DroneScrewServerPresenter::imageSaveThreadFunc(int workerIndex) }; saveMono8(job.left, QStringLiteral("left")); - if (m_imageSaveThreadExit.load()) - break; saveMono8(job.right, QStringLiteral("right")); + if (job.hasResult) + saveDetectionResultText(job.dirPath, job.index, job.result); } LOG_DEBUG("[SAVE] worker #%d stopped\n", workerIndex); } @@ -2908,12 +2967,6 @@ void DroneScrewServerPresenter::detectThreadFunc() haveProcessedFrame = true; lastProcessedLeftFrameId = leftImg.frameID; lastProcessedRightFrameId = rightImg.frameID; - const bool distanceSaveMode = - (m_detectPipelineMode.load() == kDetectPipelineDistance); - const bool shouldSaveFrame = - !distanceSaveMode || ((frameCnt % kDistanceImageSaveStride) == 0); - if (shouldSaveFrame) - enqueueImageSave(leftImg, rightImg, ++savedFrameCnt); // Publish the display frame before detection work. detectMode only controls raw transport. if (m_bRawPubEnabled.load()) @@ -3138,6 +3191,9 @@ void DroneScrewServerPresenter::detectThreadFunc() result.success ? 1 : 0, result.errorCode, result.boxes.size(), result.distances.size()); + if (!distanceMode) + enqueueImageSave(leftImg, rightImg, result, ++savedFrameCnt); + emit detectionResult(result); LOG_DEBUG("[DETECT] frame #%d after detectionResult emit\n", frameCnt + 1); diff --git a/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.h b/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.h index 6f4ce51e..a71fa543 100644 --- a/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.h +++ b/App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.h @@ -239,6 +239,7 @@ private: void imageSaveThreadFunc(int workerIndex); void enqueueImageSave(const MvsImageData& leftImg, const MvsImageData& rightImg, + const DroneScrewResult& result, unsigned long long index); QString imageSaveModeName() const; @@ -258,6 +259,8 @@ private: unsigned long long index{0}; ImageSaveBuffer left; ImageSaveBuffer right; + DroneScrewResult result; + bool hasResult{false}; }; // 双目相机设备 diff --git a/App/DroneScrewbolt/DroneScrewServer/DroneScrewZmqProtocol.cpp b/App/DroneScrewbolt/DroneScrewServer/DroneScrewZmqProtocol.cpp index fb4cb906..052c7639 100644 --- a/App/DroneScrewbolt/DroneScrewServer/DroneScrewZmqProtocol.cpp +++ b/App/DroneScrewbolt/DroneScrewServer/DroneScrewZmqProtocol.cpp @@ -163,6 +163,8 @@ void fillDetectionJson(const DroneScrewResult& result, QJsonObject& obj) jb["y"] = b.y; jb["w"] = b.width; jb["h"] = b.height; + if (b.hasPhysicalHeight) + jb["physicalHeightMm"] = static_cast(b.physicalHeightMm); boxes.append(jb); } obj["boxes"] = boxes; diff --git a/App/DroneScrewbolt/DroneScrewServer/Version.h b/App/DroneScrewbolt/DroneScrewServer/Version.h index ddbd32ae..15ce1d15 100644 --- a/App/DroneScrewbolt/DroneScrewServer/Version.h +++ b/App/DroneScrewbolt/DroneScrewServer/Version.h @@ -8,6 +8,6 @@ #define DRONESCREWSERVER_COMPANY_NAME "VisionTech" #define DRONESCREWSERVER_COPYRIGHT "Copyright (C) 2026" #define DRONESCREWSERVER_VERSION_STRING "1.0.0" -#define DRONESCREWSERVER_VERSION_BUILD "3" +#define DRONESCREWSERVER_VERSION_BUILD "4" #endif // DRONESCREW_VERSION_H diff --git a/Module/WDRemoteReceiver/Inc/WDRemoteDataTypes.h b/Module/WDRemoteReceiver/Inc/WDRemoteDataTypes.h index 8c3a8425..b578f8bd 100644 --- a/Module/WDRemoteReceiver/Inc/WDRemoteDataTypes.h +++ b/Module/WDRemoteReceiver/Inc/WDRemoteDataTypes.h @@ -55,6 +55,8 @@ struct WDRemoteDetectionBox int y{0}; int width{0}; int height{0}; + bool hasPhysicalHeight{false}; + float physicalHeightMm{0.0f}; }; /** diff --git a/Module/WDRemoteReceiver/Src/WDRemoteReceiver.cpp b/Module/WDRemoteReceiver/Src/WDRemoteReceiver.cpp index 6433c0ce..625e44e8 100644 --- a/Module/WDRemoteReceiver/Src/WDRemoteReceiver.cpp +++ b/Module/WDRemoteReceiver/Src/WDRemoteReceiver.cpp @@ -1297,6 +1297,8 @@ bool WDRemoteReceiver::parseDetectionJson(const std::string& jsonStr, box.y = b.get("y", 0 ).asInt(); box.width = b.get("w", 0 ).asInt(); box.height = b.get("h", 0 ).asInt(); + box.hasPhysicalHeight = b.isMember("physicalHeightMm"); + box.physicalHeightMm = static_cast(b.get("physicalHeightMm", 0.0).asDouble()); outFrame.boxes.push_back(box); } }