修改结果显示和存储结果
This commit is contained in:
parent
d3e6b4d0f3
commit
4004807396
@ -17,6 +17,8 @@ struct CtrlDetectionBox
|
|||||||
int y{0};
|
int y{0};
|
||||||
int width{0};
|
int width{0};
|
||||||
int height{0};
|
int height{0};
|
||||||
|
bool hasPhysicalHeight{false};
|
||||||
|
float physicalHeightMm{0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -758,6 +758,8 @@ CtrlDetectionFrame DroneScrewCtrlPresenter::toCtrlFrame(const WDRemoteDetectionF
|
|||||||
cb.y = b.y;
|
cb.y = b.y;
|
||||||
cb.width = b.width;
|
cb.width = b.width;
|
||||||
cb.height = b.height;
|
cb.height = b.height;
|
||||||
|
cb.hasPhysicalHeight = b.hasPhysicalHeight;
|
||||||
|
cb.physicalHeightMm = b.physicalHeightMm;
|
||||||
frame.boxes.push_back(cb);
|
frame.boxes.push_back(cb);
|
||||||
}
|
}
|
||||||
frame.distances.reserve(f.distances.size());
|
frame.distances.reserve(f.distances.size());
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
#define DRONESCREWCTRL_APP_NAME "无人机螺杆控制端"
|
#define DRONESCREWCTRL_APP_NAME "无人机螺杆控制端"
|
||||||
#define DRONESCREWCTRL_VERSION_STRING "1.0.0"
|
#define DRONESCREWCTRL_VERSION_STRING "1.0.0"
|
||||||
#define DRONESCREWCTRL_BUILD_STRING "3"
|
#define DRONESCREWCTRL_BUILD_STRING "4"
|
||||||
#define DRONESCREWCTRL_FULL_VERSION_STRING "V1.0.0_3"
|
#define DRONESCREWCTRL_FULL_VERSION_STRING "V1.0.0_4"
|
||||||
|
|
||||||
inline const char* GetDroneScrewCtrlFullVersion() { return DRONESCREWCTRL_FULL_VERSION_STRING; }
|
inline const char* GetDroneScrewCtrlFullVersion() { return DRONESCREWCTRL_FULL_VERSION_STRING; }
|
||||||
|
|
||||||
|
|||||||
@ -355,7 +355,7 @@ void MainWindow::OnDetectionResult(const CtrlDetectionFrame& result)
|
|||||||
upsertResultItem(row++, head, static_cast<int>(i), ResultItem::DisplayMode::Distance);
|
upsertResultItem(row++, head, static_cast<int>(i), ResultItem::DisplayMode::Distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (result.boxes.empty())
|
else if (result.boxes.empty() && result.distances.empty())
|
||||||
{
|
{
|
||||||
const QString head = QStringLiteral("帧#%1 精准目标 0")
|
const QString head = QStringLiteral("帧#%1 精准目标 0")
|
||||||
.arg(result.frameId);
|
.arg(result.frameId);
|
||||||
@ -371,6 +371,14 @@ void MainWindow::OnDetectionResult(const CtrlDetectionFrame& result)
|
|||||||
.arg(static_cast<int>(result.boxes.size()));
|
.arg(static_cast<int>(result.boxes.size()));
|
||||||
upsertResultItem(row++, head, static_cast<int>(i), ResultItem::DisplayMode::Precision);
|
upsertResultItem(row++, head, static_cast<int>(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<int>(i + 1))
|
||||||
|
.arg(static_cast<int>(result.distances.size()));
|
||||||
|
upsertResultItem(row++, head, static_cast<int>(i), ResultItem::DisplayMode::PrecisionDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trimResultItems(row);
|
trimResultItems(row);
|
||||||
|
|||||||
@ -37,6 +37,11 @@ QString oneDistanceText(const CtrlDetectionDistance& d)
|
|||||||
return QStringLiteral("%1m").arg(meters, 0, 'f', 3);
|
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)
|
QString distanceText(const CtrlDetectionFrame& frame, int targetIndex)
|
||||||
{
|
{
|
||||||
if (targetIndex >= 0 && targetIndex < static_cast<int>(frame.distances.size()))
|
if (targetIndex >= 0 && targetIndex < static_cast<int>(frame.distances.size()))
|
||||||
@ -50,6 +55,19 @@ QString distanceText(const CtrlDetectionFrame& frame, int targetIndex)
|
|||||||
: distanceParts.join(" ");
|
: distanceParts.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString distanceMmText(const CtrlDetectionFrame& frame, int targetIndex)
|
||||||
|
{
|
||||||
|
if (targetIndex >= 0 && targetIndex < static_cast<int>(frame.distances.size()))
|
||||||
|
return oneDistanceMmText(frame.distances[static_cast<size_t>(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)
|
QString distanceIndexText(const CtrlDetectionFrame& frame, int targetIndex)
|
||||||
{
|
{
|
||||||
const int total = static_cast<int>(frame.distances.size());
|
const int total = static_cast<int>(frame.distances.size());
|
||||||
@ -60,6 +78,22 @@ QString distanceIndexText(const CtrlDetectionFrame& frame, int targetIndex)
|
|||||||
}
|
}
|
||||||
return QStringLiteral("-");
|
return QStringLiteral("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString precisionDistanceIndexText(const CtrlDetectionFrame& frame, int targetIndex)
|
||||||
|
{
|
||||||
|
const int total = static_cast<int>(frame.distances.size());
|
||||||
|
if (targetIndex >= 0 && targetIndex < total)
|
||||||
|
{
|
||||||
|
const CtrlDetectionDistance& d = frame.distances[static_cast<size_t>(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)
|
ResultItem::ResultItem(QWidget* parent)
|
||||||
@ -110,15 +144,23 @@ void ResultItem::setResultData(int targetIndex,
|
|||||||
DisplayMode mode)
|
DisplayMode mode)
|
||||||
{
|
{
|
||||||
const bool precisionMode = (mode == DisplayMode::Precision);
|
const bool precisionMode = (mode == DisplayMode::Precision);
|
||||||
|
const bool precisionDistanceMode = (mode == DisplayMode::PrecisionDistance);
|
||||||
setResultTextStyle(ui);
|
setResultTextStyle(ui);
|
||||||
setMinimumHeight(precisionMode ? 104 : 108);
|
setMinimumHeight((precisionMode || precisionDistanceMode) ? 104 : 108);
|
||||||
|
|
||||||
if (ui->lb_id_t)
|
if (ui->lb_id_t)
|
||||||
ui->lb_id_t->setText(QStringLiteral("ID"));
|
ui->lb_id_t->setText(QStringLiteral("ID"));
|
||||||
if (ui->lb_status_t)
|
if (ui->lb_status_t)
|
||||||
ui->lb_status_t->setText(mode == DisplayMode::Distance
|
{
|
||||||
? QStringLiteral("距离")
|
if (mode == DisplayMode::Distance)
|
||||||
: QStringLiteral("状态"));
|
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)
|
if (ui->label_id)
|
||||||
{
|
{
|
||||||
@ -126,6 +168,10 @@ void ResultItem::setResultData(int targetIndex,
|
|||||||
ui->label_id->setText(QString("%1/%2")
|
ui->label_id->setText(QString("%1/%2")
|
||||||
.arg(targetIndex + 1)
|
.arg(targetIndex + 1)
|
||||||
.arg(static_cast<int>(frame.boxes.size())));
|
.arg(static_cast<int>(frame.boxes.size())));
|
||||||
|
else if (precisionDistanceMode)
|
||||||
|
{
|
||||||
|
ui->label_id->setText(precisionDistanceIndexText(frame, targetIndex));
|
||||||
|
}
|
||||||
else if (mode == DisplayMode::Distance)
|
else if (mode == DisplayMode::Distance)
|
||||||
{
|
{
|
||||||
ui->label_id->setText(distanceIndexText(frame, targetIndex));
|
ui->label_id->setText(distanceIndexText(frame, targetIndex));
|
||||||
@ -134,10 +180,16 @@ void ResultItem::setResultData(int targetIndex,
|
|||||||
ui->label_id->setText(QStringLiteral("0/0"));
|
ui->label_id->setText(QStringLiteral("0/0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DisplayMode::Distance)
|
if (mode == DisplayMode::Distance || precisionDistanceMode)
|
||||||
{
|
{
|
||||||
if (ui->label_status)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,11 +198,19 @@ void ResultItem::setResultData(int targetIndex,
|
|||||||
if (targetIndex >= 0 && targetIndex < static_cast<int>(frame.boxes.size()))
|
if (targetIndex >= 0 && targetIndex < static_cast<int>(frame.boxes.size()))
|
||||||
{
|
{
|
||||||
const CtrlDetectionBox& b = frame.boxes[static_cast<size_t>(targetIndex)];
|
const CtrlDetectionBox& b = frame.boxes[static_cast<size_t>(targetIndex)];
|
||||||
const QString text = QStringLiteral("score=%1 w=%2 h=%3")
|
if (b.hasPhysicalHeight)
|
||||||
.arg(b.score, 0, 'f', 3)
|
{
|
||||||
.arg(b.width)
|
ui->label_status->setText(QStringLiteral("%1 mm")
|
||||||
.arg(b.height);
|
.arg(b.physicalHeightMm, 0, 'f', 2));
|
||||||
ui->label_status->setText(text);
|
}
|
||||||
|
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)
|
else if (!frame.success)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,7 +14,8 @@ public:
|
|||||||
enum class DisplayMode
|
enum class DisplayMode
|
||||||
{
|
{
|
||||||
Distance,
|
Distance,
|
||||||
Precision
|
Precision,
|
||||||
|
PrecisionDistance
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ResultItem(QWidget* parent = nullptr);
|
explicit ResultItem(QWidget* parent = nullptr);
|
||||||
|
|||||||
@ -700,6 +700,18 @@ void DroneScrewAlgoStub::appendRoiBox(const StereoBoltModuleRoiC& roi,
|
|||||||
result.boxes.push_back(box);
|
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<float>(bolt.height_mm);
|
||||||
|
result.boxes.push_back(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DroneScrewAlgoStub::Init(const DroneScrewAlgoParams& params)
|
int DroneScrewAlgoStub::Init(const DroneScrewAlgoParams& params)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_mutex);
|
std::lock_guard<std::mutex> lk(m_mutex);
|
||||||
@ -899,7 +911,7 @@ int DroneScrewAlgoStub::Detect(const DroneScrewInputImage& leftImage,
|
|||||||
if (out.data.n_bolts > 0 && out.data.bolts)
|
if (out.data.n_bolts > 0 && out.data.bolts)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < out.data.n_bolts; ++i)
|
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)
|
if (out.data.n_adjacent_distances > 0 && out.data.adjacent_distances)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -47,6 +47,8 @@ private:
|
|||||||
DroneScrewBox& box) const;
|
DroneScrewBox& box) const;
|
||||||
void appendRoiBox(const StereoBoltModuleRoiC& roi,
|
void appendRoiBox(const StereoBoltModuleRoiC& roi,
|
||||||
DroneScrewResult& result) const;
|
DroneScrewResult& result) const;
|
||||||
|
void appendBoltBox(const StereoBoltModuleBoltC& bolt,
|
||||||
|
DroneScrewResult& result) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DroneScrewAlgoParams m_params;
|
DroneScrewAlgoParams m_params;
|
||||||
|
|||||||
@ -16,6 +16,8 @@ struct DroneScrewBox
|
|||||||
int y{0};
|
int y{0};
|
||||||
int width{0};
|
int width{0};
|
||||||
int height{0};
|
int height{0};
|
||||||
|
bool hasPhysicalHeight{false};
|
||||||
|
float physicalHeightMm{0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -69,7 +69,6 @@ constexpr int kDetectPipelineDistance = 1;
|
|||||||
constexpr const char* kImageSaveRootDir = "/home/cat";
|
constexpr const char* kImageSaveRootDir = "/home/cat";
|
||||||
constexpr size_t kMaxImageSaveQueueDepth = 100;
|
constexpr size_t kMaxImageSaveQueueDepth = 100;
|
||||||
constexpr size_t kImageSaveWorkerCount = 4;
|
constexpr size_t kImageSaveWorkerCount = 4;
|
||||||
constexpr int kDistanceImageSaveStride = 3;
|
|
||||||
|
|
||||||
const char* mvsSdkErrorName(int code)
|
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<qulonglong>(imageIndex) << '\n';
|
||||||
|
out << "leftImage:" << savedImageFileName(imageIndex, QStringLiteral("left")) << '\n';
|
||||||
|
out << "rightImage:" << savedImageFileName(imageIndex, QStringLiteral("right")) << '\n';
|
||||||
|
out << "frameId:" << static_cast<qulonglong>(result.frameId) << '\n';
|
||||||
|
out << "timestampUs:" << static_cast<qlonglong>(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<int>(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<int>(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,
|
double clampCameraFloatFeature(IMvsDevice* camera,
|
||||||
const char* role,
|
const char* role,
|
||||||
const char* featureName,
|
const char* featureName,
|
||||||
@ -1814,9 +1877,9 @@ int DroneScrewServerPresenter::stopDetectionWork()
|
|||||||
|
|
||||||
stopGpioTriggerLoop();
|
stopGpioTriggerLoop();
|
||||||
m_bThreadExit = true;
|
m_bThreadExit = true;
|
||||||
stopImageSaveThread();
|
|
||||||
if (m_detectThread.joinable())
|
if (m_detectThread.joinable())
|
||||||
m_detectThread.join();
|
m_detectThread.join();
|
||||||
|
stopImageSaveThread();
|
||||||
m_bIsDetecting = false;
|
m_bIsDetecting = false;
|
||||||
m_detectPipelineMode = kDetectPipelinePrecision;
|
m_detectPipelineMode = kDetectPipelinePrecision;
|
||||||
m_activeTriggerFps = static_cast<int>(kPrecisionFrameRate);
|
m_activeTriggerFps = static_cast<int>(kPrecisionFrameRate);
|
||||||
@ -1909,7 +1972,6 @@ int DroneScrewServerPresenter::startLiveStream()
|
|||||||
m_bLiveStreaming = true;
|
m_bLiveStreaming = true;
|
||||||
m_bThreadExit = false;
|
m_bThreadExit = false;
|
||||||
m_bIsDetecting = true;
|
m_bIsDetecting = true;
|
||||||
startImageSaveThread(imageSaveModeName());
|
|
||||||
startGpioTriggerLoop();
|
startGpioTriggerLoop();
|
||||||
m_detectThread = std::thread(&DroneScrewServerPresenter::detectThreadFunc, this);
|
m_detectThread = std::thread(&DroneScrewServerPresenter::detectThreadFunc, this);
|
||||||
emit statusChanged(QStringLiteral("开始实时传图"));
|
emit statusChanged(QStringLiteral("开始实时传图"));
|
||||||
@ -1935,9 +1997,9 @@ int DroneScrewServerPresenter::stopLiveStream()
|
|||||||
m_bRtspStarted = false;
|
m_bRtspStarted = false;
|
||||||
stopGpioTriggerLoop();
|
stopGpioTriggerLoop();
|
||||||
m_bThreadExit = true;
|
m_bThreadExit = true;
|
||||||
stopImageSaveThread();
|
|
||||||
if (m_detectThread.joinable())
|
if (m_detectThread.joinable())
|
||||||
m_detectThread.join();
|
m_detectThread.join();
|
||||||
|
stopImageSaveThread();
|
||||||
m_bIsDetecting = false;
|
m_bIsDetecting = false;
|
||||||
m_detectPipelineMode = kDetectPipelinePrecision;
|
m_detectPipelineMode = kDetectPipelinePrecision;
|
||||||
m_activeTriggerFps = static_cast<int>(kPrecisionFrameRate);
|
m_activeTriggerFps = static_cast<int>(kPrecisionFrameRate);
|
||||||
@ -2374,7 +2436,7 @@ void DroneScrewServerPresenter::startImageSaveThread(const QString& modeName)
|
|||||||
void DroneScrewServerPresenter::stopImageSaveThread()
|
void DroneScrewServerPresenter::stopImageSaveThread()
|
||||||
{
|
{
|
||||||
const bool shouldJoin = !m_imageSaveThreads.empty();
|
const bool shouldJoin = !m_imageSaveThreads.empty();
|
||||||
size_t droppedPending = 0;
|
size_t pendingJobs = 0;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_imageSaveMutex);
|
std::lock_guard<std::mutex> lk(m_imageSaveMutex);
|
||||||
if (!shouldJoin)
|
if (!shouldJoin)
|
||||||
@ -2384,16 +2446,14 @@ void DroneScrewServerPresenter::stopImageSaveThread()
|
|||||||
m_imageSaveThreadExit = false;
|
m_imageSaveThreadExit = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
droppedPending = m_imageSaveQueue.size();
|
pendingJobs = m_imageSaveQueue.size();
|
||||||
if (droppedPending > 0)
|
|
||||||
m_imageSaveQueue.clear();
|
|
||||||
m_imageSaveThreadExit = true;
|
m_imageSaveThreadExit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (droppedPending > 0)
|
if (pendingJobs > 0)
|
||||||
{
|
{
|
||||||
LOG_WARN("[SAVE] stop requested, drop pending save jobs=%zu\n",
|
LOG_INFO("[SAVE] stop requested, flush pending save jobs=%zu\n",
|
||||||
droppedPending);
|
pendingJobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imageSaveCv.notify_all();
|
m_imageSaveCv.notify_all();
|
||||||
@ -2414,6 +2474,7 @@ void DroneScrewServerPresenter::stopImageSaveThread()
|
|||||||
|
|
||||||
void DroneScrewServerPresenter::enqueueImageSave(const MvsImageData& leftImg,
|
void DroneScrewServerPresenter::enqueueImageSave(const MvsImageData& leftImg,
|
||||||
const MvsImageData& rightImg,
|
const MvsImageData& rightImg,
|
||||||
|
const DroneScrewResult& result,
|
||||||
unsigned long long index)
|
unsigned long long index)
|
||||||
{
|
{
|
||||||
auto dropIfQueueFull = [this, index]() -> bool {
|
auto dropIfQueueFull = [this, index]() -> bool {
|
||||||
@ -2460,6 +2521,8 @@ void DroneScrewServerPresenter::enqueueImageSave(const MvsImageData& leftImg,
|
|||||||
|
|
||||||
ImageSaveJob job;
|
ImageSaveJob job;
|
||||||
job.index = index;
|
job.index = index;
|
||||||
|
job.result = result;
|
||||||
|
job.hasResult = true;
|
||||||
if (!copyMono8(leftImg, job.left) || !copyMono8(rightImg, job.right))
|
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",
|
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();
|
return m_imageSaveThreadExit.load() || !m_imageSaveQueue.empty();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (m_imageSaveThreadExit.load())
|
|
||||||
{
|
|
||||||
m_imageSaveQueue.clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_imageSaveQueue.empty())
|
if (m_imageSaveQueue.empty())
|
||||||
{
|
{
|
||||||
|
if (m_imageSaveThreadExit.load())
|
||||||
|
break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2523,7 +2582,7 @@ void DroneScrewServerPresenter::imageSaveThreadFunc(int workerIndex)
|
|||||||
static_cast<int>(img.width),
|
static_cast<int>(img.width),
|
||||||
QImage::Format_Grayscale8);
|
QImage::Format_Grayscale8);
|
||||||
const QString filePath = QDir(job.dirPath).filePath(
|
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"))
|
if (!q.save(filePath, "PNG"))
|
||||||
{
|
{
|
||||||
LOG_WARN("[SAVE] image save failed: %s\n",
|
LOG_WARN("[SAVE] image save failed: %s\n",
|
||||||
@ -2532,9 +2591,9 @@ void DroneScrewServerPresenter::imageSaveThreadFunc(int workerIndex)
|
|||||||
};
|
};
|
||||||
|
|
||||||
saveMono8(job.left, QStringLiteral("left"));
|
saveMono8(job.left, QStringLiteral("left"));
|
||||||
if (m_imageSaveThreadExit.load())
|
|
||||||
break;
|
|
||||||
saveMono8(job.right, QStringLiteral("right"));
|
saveMono8(job.right, QStringLiteral("right"));
|
||||||
|
if (job.hasResult)
|
||||||
|
saveDetectionResultText(job.dirPath, job.index, job.result);
|
||||||
}
|
}
|
||||||
LOG_DEBUG("[SAVE] worker #%d stopped\n", workerIndex);
|
LOG_DEBUG("[SAVE] worker #%d stopped\n", workerIndex);
|
||||||
}
|
}
|
||||||
@ -2908,12 +2967,6 @@ void DroneScrewServerPresenter::detectThreadFunc()
|
|||||||
haveProcessedFrame = true;
|
haveProcessedFrame = true;
|
||||||
lastProcessedLeftFrameId = leftImg.frameID;
|
lastProcessedLeftFrameId = leftImg.frameID;
|
||||||
lastProcessedRightFrameId = rightImg.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.
|
// Publish the display frame before detection work. detectMode only controls raw transport.
|
||||||
if (m_bRawPubEnabled.load())
|
if (m_bRawPubEnabled.load())
|
||||||
@ -3138,6 +3191,9 @@ void DroneScrewServerPresenter::detectThreadFunc()
|
|||||||
result.success ? 1 : 0, result.errorCode,
|
result.success ? 1 : 0, result.errorCode,
|
||||||
result.boxes.size(), result.distances.size());
|
result.boxes.size(), result.distances.size());
|
||||||
|
|
||||||
|
if (!distanceMode)
|
||||||
|
enqueueImageSave(leftImg, rightImg, result, ++savedFrameCnt);
|
||||||
|
|
||||||
emit detectionResult(result);
|
emit detectionResult(result);
|
||||||
|
|
||||||
LOG_DEBUG("[DETECT] frame #%d after detectionResult emit\n", frameCnt + 1);
|
LOG_DEBUG("[DETECT] frame #%d after detectionResult emit\n", frameCnt + 1);
|
||||||
|
|||||||
@ -239,6 +239,7 @@ private:
|
|||||||
void imageSaveThreadFunc(int workerIndex);
|
void imageSaveThreadFunc(int workerIndex);
|
||||||
void enqueueImageSave(const MvsImageData& leftImg,
|
void enqueueImageSave(const MvsImageData& leftImg,
|
||||||
const MvsImageData& rightImg,
|
const MvsImageData& rightImg,
|
||||||
|
const DroneScrewResult& result,
|
||||||
unsigned long long index);
|
unsigned long long index);
|
||||||
QString imageSaveModeName() const;
|
QString imageSaveModeName() const;
|
||||||
|
|
||||||
@ -258,6 +259,8 @@ private:
|
|||||||
unsigned long long index{0};
|
unsigned long long index{0};
|
||||||
ImageSaveBuffer left;
|
ImageSaveBuffer left;
|
||||||
ImageSaveBuffer right;
|
ImageSaveBuffer right;
|
||||||
|
DroneScrewResult result;
|
||||||
|
bool hasResult{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 双目相机设备
|
// 双目相机设备
|
||||||
|
|||||||
@ -163,6 +163,8 @@ void fillDetectionJson(const DroneScrewResult& result, QJsonObject& obj)
|
|||||||
jb["y"] = b.y;
|
jb["y"] = b.y;
|
||||||
jb["w"] = b.width;
|
jb["w"] = b.width;
|
||||||
jb["h"] = b.height;
|
jb["h"] = b.height;
|
||||||
|
if (b.hasPhysicalHeight)
|
||||||
|
jb["physicalHeightMm"] = static_cast<double>(b.physicalHeightMm);
|
||||||
boxes.append(jb);
|
boxes.append(jb);
|
||||||
}
|
}
|
||||||
obj["boxes"] = boxes;
|
obj["boxes"] = boxes;
|
||||||
|
|||||||
@ -8,6 +8,6 @@
|
|||||||
#define DRONESCREWSERVER_COMPANY_NAME "VisionTech"
|
#define DRONESCREWSERVER_COMPANY_NAME "VisionTech"
|
||||||
#define DRONESCREWSERVER_COPYRIGHT "Copyright (C) 2026"
|
#define DRONESCREWSERVER_COPYRIGHT "Copyright (C) 2026"
|
||||||
#define DRONESCREWSERVER_VERSION_STRING "1.0.0"
|
#define DRONESCREWSERVER_VERSION_STRING "1.0.0"
|
||||||
#define DRONESCREWSERVER_VERSION_BUILD "3"
|
#define DRONESCREWSERVER_VERSION_BUILD "4"
|
||||||
|
|
||||||
#endif // DRONESCREW_VERSION_H
|
#endif // DRONESCREW_VERSION_H
|
||||||
|
|||||||
@ -55,6 +55,8 @@ struct WDRemoteDetectionBox
|
|||||||
int y{0};
|
int y{0};
|
||||||
int width{0};
|
int width{0};
|
||||||
int height{0};
|
int height{0};
|
||||||
|
bool hasPhysicalHeight{false};
|
||||||
|
float physicalHeightMm{0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1297,6 +1297,8 @@ bool WDRemoteReceiver::parseDetectionJson(const std::string& jsonStr,
|
|||||||
box.y = b.get("y", 0 ).asInt();
|
box.y = b.get("y", 0 ).asInt();
|
||||||
box.width = b.get("w", 0 ).asInt();
|
box.width = b.get("w", 0 ).asInt();
|
||||||
box.height = b.get("h", 0 ).asInt();
|
box.height = b.get("h", 0 ).asInt();
|
||||||
|
box.hasPhysicalHeight = b.isMember("physicalHeightMm");
|
||||||
|
box.physicalHeightMm = static_cast<float>(b.get("physicalHeightMm", 0.0).asDouble());
|
||||||
outFrame.boxes.push_back(box);
|
outFrame.boxes.push_back(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user