@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"params": {
|
|
||||||
"confidence_threshold": 0.5
|
|
||||||
},
|
|
||||||
"metrics": {
|
|
||||||
"f1": 0.13793103448275862,
|
|
||||||
"precision": 0.09900990099009901,
|
|
||||||
"recall": 0.22727272727272727,
|
|
||||||
"tp": 10,
|
|
||||||
"fp": 91,
|
|
||||||
"fn": 34
|
|
||||||
},
|
|
||||||
"note": "由 auto_tune.py 自动优化生成,需手动更新到 cpp/include/thermal_types.h"
|
|
||||||
}
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
# generated from CMake
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/onnxruntime_imp_lib.dir
|
||||||
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/thermal_detector.dir
|
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/thermal_detector.dir
|
||||||
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/ALL_BUILD.dir
|
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/ALL_BUILD.dir
|
||||||
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/ZERO_CHECK.dir
|
D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/ZERO_CHECK.dir
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
# generated from CMake
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<CustomBuild Include="D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\CMakeFiles\e9bd87dd49c8a00a589935b380b13b97\onnxruntime.lib.rule">
|
||||||
|
<Filter>CMake Rules</Filter>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\CMakeFiles\56e5eca5e8f7b67eb6dc57ed2871d760\onnxruntime_imp_lib.rule">
|
||||||
|
<Filter>CMake Rules</Filter>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\CMakeLists.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\CMakeFiles\onnxruntime_imp_lib" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="CMake Rules">
|
||||||
|
<UniqueIdentifier>{531032C3-567B-392F-8E3A-E279D9FF267E}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@ -1,3 +1,4 @@
|
|||||||
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\main.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\main.obj
|
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\main.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\main.obj
|
||||||
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\thermal_preprocessor.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\thermal_preprocessor.obj
|
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\thermal_preprocessor.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\thermal_preprocessor.obj
|
||||||
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\thermal_detector.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\thermal_detector.obj
|
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\thermal_detector.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\thermal_detector.obj
|
||||||
|
D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\src\yolo_detector.cpp;D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\thermal_detector.dir\Release\yolo_detector.obj
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\MAIN.OBJ|D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\THERMAL_DETECTOR.OBJ|D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\THERMAL_PREPROCESSOR.OBJ
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\MAIN.OBJ|D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\THERMAL_DETECTOR.OBJ|D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\THERMAL_PREPROCESSOR.OBJ|D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\THERMAL_DETECTOR.DIR\RELEASE\YOLO_DETECTOR.OBJ
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\E9BD87DD49C8A00A589935B380B13B97\ONNXRUNTIME.LIB.RULE
|
||||||
|
setlocal
|
||||||
|
lib.exe /def:D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/third_party/onnxruntime/lib/onnxruntime.def /out:D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/onnxruntime.lib /machine:x64
|
||||||
|
if %errorlevel% neq 0 goto :cmEnd
|
||||||
|
:cmEnd
|
||||||
|
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
|
||||||
|
:cmErrorLevel
|
||||||
|
exit /b %1
|
||||||
|
:cmDone
|
||||||
|
if %errorlevel% neq 0 goto :VCEnd
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\56E5ECA5E8F7B67EB6DC57ED2871D760\ONNXRUNTIME_IMP_LIB.RULE
|
||||||
|
setlocal
|
||||||
|
:cmEnd
|
||||||
|
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
|
||||||
|
:cmErrorLevel
|
||||||
|
exit /b %1
|
||||||
|
:cmDone
|
||||||
|
if %errorlevel% neq 0 goto :VCEnd
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\CMAKELISTS.TXT
|
||||||
|
setlocal
|
||||||
|
D:\cmake\bin\cmake.exe -SD:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp -BD:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build --check-stamp-file D:/29578/Documents/Study/computer/S_E/软件体系结构与设计/软件开发/热成像识别/cpp/build/CMakeFiles/generate.stamp
|
||||||
|
if %errorlevel% neq 0 goto :cmEnd
|
||||||
|
:cmEnd
|
||||||
|
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
|
||||||
|
:cmErrorLevel
|
||||||
|
exit /b %1
|
||||||
|
:cmDone
|
||||||
|
if %errorlevel% neq 0 goto :VCEnd
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\E9BD87DD49C8A00A589935B380B13B97\ONNXRUNTIME.LIB.RULE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\THIRD_PARTY\ONNXRUNTIME\LIB\ONNXRUNTIME.DEF
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\56E5ECA5E8F7B67EB6DC57ED2871D760\ONNXRUNTIME_IMP_LIB.RULE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\ONNXRUNTIME.LIB
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\CMAKELISTS.TXT
|
||||||
|
C:\USERS\29578\.CONDA\ENVS\OPENCV-BUILD\LIBRARY\CMAKE\OPENCVCONFIG-VERSION.CMAKE
|
||||||
|
C:\USERS\29578\.CONDA\ENVS\OPENCV-BUILD\LIBRARY\CMAKE\OPENCVCONFIG.CMAKE
|
||||||
|
C:\USERS\29578\.CONDA\ENVS\OPENCV-BUILD\LIBRARY\CMAKE\X64\VC17\LIB\OPENCVCONFIG.CMAKE
|
||||||
|
C:\USERS\29578\.CONDA\ENVS\OPENCV-BUILD\LIBRARY\CMAKE\X64\VC17\LIB\OPENCVMODULES-RELEASE.CMAKE
|
||||||
|
C:\USERS\29578\.CONDA\ENVS\OPENCV-BUILD\LIBRARY\CMAKE\X64\VC17\LIB\OPENCVMODULES.CMAKE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\4.3.2\CMAKECXXCOMPILER.CMAKE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\4.3.2\CMAKERCCOMPILER.CMAKE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\4.3.2\CMAKESYSTEM.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKECXXINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKECOMMONLANGUAGEINCLUDE.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKEGENERICSYSTEM.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKEINITIALIZECONFIGS.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKELANGUAGEINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKERCINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKESYSTEMSPECIFICINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\CMAKESYSTEMSPECIFICINITIALIZE.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\COMPILER\CMAKECOMMONCOMPILERMACROS.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\COMPILER\MSVC-CXX.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\COMPILER\MSVC.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\FINDPACKAGEHANDLESTANDARDARGS.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\FINDPACKAGEMESSAGE.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\INTERNAL\CMAKECXXLINKERINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\INTERNAL\CMAKECOMMONLINKERINFORMATION.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\LINKER\MSVC-CXX.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\LINKER\MSVC.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\LINKER\WINDOWS-MSVC-CXX.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\LINKER\WINDOWS-MSVC.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\WINDOWS-INITIALIZE.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\WINDOWS-MSVC-CXX.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\WINDOWS-MSVC.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\WINDOWS.CMAKE
|
||||||
|
D:\CMAKE\SHARE\CMAKE-4.3\MODULES\PLATFORM\WINDOWSPATHS.CMAKE
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\E9BD87DD49C8A00A589935B380B13B97\ONNXRUNTIME.LIB.RULE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\ONNXRUNTIME.LIB
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\56E5ECA5E8F7B67EB6DC57ED2871D760\ONNXRUNTIME_IMP_LIB.RULE
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\ONNXRUNTIME_IMP_LIB
|
||||||
|
^D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\CMAKELISTS.TXT
|
||||||
|
D:\29578\DOCUMENTS\STUDY\COMPUTER\S_E\软件体系结构与设计\软件开发\热成像识别\CPP\BUILD\CMAKEFILES\GENERATE.STAMP
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.43.34808:TargetPlatformVersion=10.0.22621.0:
|
||||||
|
Release|x64|D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\|
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
<ProjectOutputs>
|
||||||
|
<ProjectOutput>
|
||||||
|
<FullPath>D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\x64\Release\ZERO_CHECK</FullPath>
|
||||||
|
</ProjectOutput>
|
||||||
|
<ProjectOutput>
|
||||||
|
<FullPath>D:\29578\Documents\Study\computer\S_E\软件体系结构与设计\软件开发\热成像识别\cpp\build\x64\Release\onnxruntime_imp_lib</FullPath>
|
||||||
|
</ProjectOutput>
|
||||||
|
</ProjectOutputs>
|
||||||
|
<ContentFiles />
|
||||||
|
<SatelliteDlls />
|
||||||
|
<NonRecipeFileRefs />
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "thermal_types.h"
|
||||||
|
#include <opencv2/core.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct YoloConfig {
|
||||||
|
std::string model_path;
|
||||||
|
int input_size = 640;
|
||||||
|
float conf_threshold = 0.25f;
|
||||||
|
float nms_threshold = 0.45f;
|
||||||
|
int max_detections = 100;
|
||||||
|
int intra_threads = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class YoloDetector {
|
||||||
|
public:
|
||||||
|
explicit YoloDetector(const YoloConfig& config);
|
||||||
|
~YoloDetector();
|
||||||
|
|
||||||
|
YoloDetector(const YoloDetector&) = delete;
|
||||||
|
YoloDetector& operator=(const YoloDetector&) = delete;
|
||||||
|
YoloDetector(YoloDetector&&) noexcept;
|
||||||
|
YoloDetector& operator=(YoloDetector&&) noexcept;
|
||||||
|
|
||||||
|
std::vector<DetectionResult> detect(const cv::Mat& image);
|
||||||
|
bool is_loaded() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> impl_;
|
||||||
|
};
|
||||||
@ -0,0 +1,255 @@
|
|||||||
|
#include "yolo_detector.h"
|
||||||
|
#include <onnxruntime_cxx_api.h>
|
||||||
|
#include <opencv2/imgproc.hpp>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct YoloDetector::Impl {
|
||||||
|
YoloConfig config;
|
||||||
|
Ort::Env env;
|
||||||
|
std::unique_ptr<Ort::Session> session;
|
||||||
|
std::unique_ptr<Ort::SessionOptions> session_options;
|
||||||
|
bool loaded = false;
|
||||||
|
int num_classes = 0;
|
||||||
|
int input_size = 640;
|
||||||
|
|
||||||
|
explicit Impl(const YoloConfig& cfg)
|
||||||
|
: config(cfg), env(ORT_LOGGING_LEVEL_WARNING, "thermal-yolo"),
|
||||||
|
input_size(cfg.input_size) {
|
||||||
|
session_options = std::make_unique<Ort::SessionOptions>();
|
||||||
|
session_options->SetIntraOpNumThreads(config.intra_threads);
|
||||||
|
session_options->SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_model(const std::string& path) {
|
||||||
|
std::ifstream check(path, std::ios::binary);
|
||||||
|
if (!check) {
|
||||||
|
std::cerr << "[YOLO] Model file not found: " << path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
check.close();
|
||||||
|
|
||||||
|
try {
|
||||||
|
#ifdef _WIN32
|
||||||
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, nullptr, 0);
|
||||||
|
std::wstring wpath;
|
||||||
|
if (wlen > 0) {
|
||||||
|
wpath.resize(static_cast<std::size_t>(wlen));
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, path.c_str(), -1, &wpath[0], wlen);
|
||||||
|
}
|
||||||
|
session = std::make_unique<Ort::Session>(env, wpath.c_str(), *session_options);
|
||||||
|
#else
|
||||||
|
session = std::make_unique<Ort::Session>(env, path.c_str(), *session_options);
|
||||||
|
#endif
|
||||||
|
} catch (const Ort::Exception& e) {
|
||||||
|
std::cerr << "[YOLO] ONNX Runtime load failed: " << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从输出形状推断类别数
|
||||||
|
auto output_count = session->GetOutputCount();
|
||||||
|
if (output_count > 0) {
|
||||||
|
auto type_info = session->GetOutputTypeInfo(0);
|
||||||
|
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
|
||||||
|
auto shape = tensor_info.GetShape();
|
||||||
|
// YOLOv8 输出: [1, 4+nc, 8400]
|
||||||
|
if (shape.size() == 3 && shape[1] > 4) {
|
||||||
|
num_classes = static_cast<int>(shape[1]) - 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = session != nullptr;
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float> preprocess(const cv::Mat& image, int& orig_w, int& orig_h) {
|
||||||
|
cv::Mat bgr;
|
||||||
|
if (image.channels() == 1)
|
||||||
|
cv::cvtColor(image, bgr, cv::COLOR_GRAY2BGR);
|
||||||
|
else
|
||||||
|
bgr = image;
|
||||||
|
|
||||||
|
orig_w = bgr.cols;
|
||||||
|
orig_h = bgr.rows;
|
||||||
|
|
||||||
|
cv::Mat resized;
|
||||||
|
cv::resize(bgr, resized, cv::Size(input_size, input_size));
|
||||||
|
|
||||||
|
cv::Mat rgb;
|
||||||
|
cv::cvtColor(resized, rgb, cv::COLOR_BGR2RGB);
|
||||||
|
|
||||||
|
cv::Mat f32;
|
||||||
|
rgb.convertTo(f32, CV_32F, 1.0 / 255.0);
|
||||||
|
|
||||||
|
std::vector<cv::Mat> channels(3);
|
||||||
|
cv::split(f32, channels);
|
||||||
|
|
||||||
|
int channel_size = input_size * input_size;
|
||||||
|
std::vector<float> input_data(3 * channel_size);
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
std::memcpy(input_data.data() + c * channel_size,
|
||||||
|
channels[c].data, channel_size * sizeof(float));
|
||||||
|
}
|
||||||
|
return input_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RawDet {
|
||||||
|
float cx, cy, w, h;
|
||||||
|
int class_id;
|
||||||
|
float score;
|
||||||
|
};
|
||||||
|
|
||||||
|
static double compute_iou(const cv::Rect& a, const cv::Rect& b) {
|
||||||
|
int ix1 = std::max(a.x, b.x);
|
||||||
|
int iy1 = std::max(a.y, b.y);
|
||||||
|
int ix2 = std::min(a.x + a.width, b.x + b.width);
|
||||||
|
int iy2 = std::min(a.y + a.height, b.y + b.height);
|
||||||
|
int inter = std::max(0, ix2 - ix1) * std::max(0, iy2 - iy1);
|
||||||
|
int area_a = a.width * a.height;
|
||||||
|
int area_b = b.width * b.height;
|
||||||
|
int union_area = area_a + area_b - inter;
|
||||||
|
return static_cast<double>(inter) / std::max(union_area, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreatType map_class(int class_id) {
|
||||||
|
if (num_classes == 80) {
|
||||||
|
return (class_id == 0) ? ThreatType::PERSON : ThreatType::PERSON;
|
||||||
|
}
|
||||||
|
if (class_id == 0) return ThreatType::PERSON;
|
||||||
|
if (class_id == 1) return ThreatType::ANOMALY_HOTSPOT;
|
||||||
|
return ThreatType::PERSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DetectionResult> postprocess(
|
||||||
|
std::vector<Ort::Value>& outputs,
|
||||||
|
int orig_w, int orig_h)
|
||||||
|
{
|
||||||
|
if (outputs.empty()) return {};
|
||||||
|
|
||||||
|
float* data = outputs[0].GetTensorMutableData<float>();
|
||||||
|
auto shape = outputs[0].GetTensorTypeAndShapeInfo().GetShape();
|
||||||
|
int nc = static_cast<int>(shape[1]) - 4;
|
||||||
|
int num_preds = static_cast<int>(shape[2]);
|
||||||
|
|
||||||
|
std::vector<RawDet> raw;
|
||||||
|
for (int i = 0; i < num_preds; i++) {
|
||||||
|
float best_score = 0;
|
||||||
|
int best_class = 0;
|
||||||
|
for (int c = 0; c < nc; c++) {
|
||||||
|
float s = data[(4 + c) * num_preds + i];
|
||||||
|
if (s > best_score) { best_score = s; best_class = c; }
|
||||||
|
}
|
||||||
|
if (best_score < config.conf_threshold) continue;
|
||||||
|
|
||||||
|
raw.push_back({
|
||||||
|
data[0 * num_preds + i],
|
||||||
|
data[1 * num_preds + i],
|
||||||
|
data[2 * num_preds + i],
|
||||||
|
data[3 * num_preds + i],
|
||||||
|
best_class, best_score
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// NMS
|
||||||
|
std::sort(raw.begin(), raw.end(),
|
||||||
|
[](const RawDet& a, const RawDet& b) { return a.score > b.score; });
|
||||||
|
|
||||||
|
float scale_x = static_cast<float>(orig_w) / input_size;
|
||||||
|
float scale_y = static_cast<float>(orig_h) / input_size;
|
||||||
|
|
||||||
|
// 转换为 cv::Rect 并做 NMS
|
||||||
|
std::vector<std::pair<RawDet, cv::Rect>> boxed;
|
||||||
|
for (const auto& d : raw) {
|
||||||
|
int x = static_cast<int>((d.cx - d.w / 2) * scale_x);
|
||||||
|
int y = static_cast<int>((d.cy - d.h / 2) * scale_y);
|
||||||
|
int w = static_cast<int>(d.w * scale_x);
|
||||||
|
int h = static_cast<int>(d.h * scale_y);
|
||||||
|
boxed.push_back({d, cv::Rect(x, y, w, h)});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> keep;
|
||||||
|
for (int i = 0; i < static_cast<int>(boxed.size()); i++) {
|
||||||
|
bool suppressed = false;
|
||||||
|
for (int j : keep) {
|
||||||
|
if (compute_iou(boxed[i].second, boxed[j].second) > config.nms_threshold) {
|
||||||
|
suppressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!suppressed) keep.push_back(i);
|
||||||
|
if (static_cast<int>(keep.size()) >= config.max_detections) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DetectionResult> results;
|
||||||
|
for (int idx : keep) {
|
||||||
|
const auto& det = boxed[idx].first;
|
||||||
|
const auto& box = boxed[idx].second;
|
||||||
|
results.push_back({
|
||||||
|
map_class(det.class_id),
|
||||||
|
static_cast<double>(det.score),
|
||||||
|
box,
|
||||||
|
cv::Point2d(box.x + box.width / 2.0, box.y + box.height / 2.0),
|
||||||
|
0, 0,
|
||||||
|
box.width * box.height,
|
||||||
|
static_cast<double>(std::max(box.width, box.height)) /
|
||||||
|
std::max(std::min(box.width, box.height), 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DetectionResult> detect(const cv::Mat& image) {
|
||||||
|
if (!loaded) return {};
|
||||||
|
|
||||||
|
int orig_w, orig_h;
|
||||||
|
auto input_data = preprocess(image, orig_w, orig_h);
|
||||||
|
|
||||||
|
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
|
||||||
|
std::vector<int64_t> input_shape = {1, 3, input_size, input_size};
|
||||||
|
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
|
||||||
|
memory_info, input_data.data(), input_data.size(),
|
||||||
|
input_shape.data(), input_shape.size());
|
||||||
|
|
||||||
|
// 动态获取 I/O 名称
|
||||||
|
auto allocator = Ort::AllocatorWithDefaultOptions();
|
||||||
|
auto input_name = session->GetInputNameAllocated(0, allocator);
|
||||||
|
auto output_name = session->GetOutputNameAllocated(0, allocator);
|
||||||
|
const char* input_names[] = {input_name.get()};
|
||||||
|
const char* output_names[] = {output_name.get()};
|
||||||
|
|
||||||
|
auto outputs = session->Run(
|
||||||
|
Ort::RunOptions{nullptr},
|
||||||
|
input_names, &input_tensor, 1,
|
||||||
|
output_names, 1);
|
||||||
|
|
||||||
|
return postprocess(outputs, orig_w, orig_h);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
YoloDetector::YoloDetector(const YoloConfig& config)
|
||||||
|
: impl_(std::make_unique<Impl>(config)) {
|
||||||
|
if (!config.model_path.empty()) {
|
||||||
|
impl_->load_model(config.model_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
YoloDetector::~YoloDetector() = default;
|
||||||
|
YoloDetector::YoloDetector(YoloDetector&&) noexcept = default;
|
||||||
|
YoloDetector& YoloDetector::operator=(YoloDetector&&) noexcept = default;
|
||||||
|
|
||||||
|
std::vector<DetectionResult> YoloDetector::detect(const cv::Mat& image) {
|
||||||
|
return impl_->detect(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool YoloDetector::is_loaded() const noexcept {
|
||||||
|
return impl_->loaded;
|
||||||
|
}
|
||||||
@ -0,0 +1,535 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace onnxruntime_float16 {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
enum class endian {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
little = 0,
|
||||||
|
big = 1,
|
||||||
|
native = little,
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
little = __ORDER_LITTLE_ENDIAN__,
|
||||||
|
big = __ORDER_BIG_ENDIAN__,
|
||||||
|
native = __BYTE_ORDER__,
|
||||||
|
#else
|
||||||
|
#error onnxruntime_float16::detail::endian is not implemented in this environment.
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
endian::native == endian::little || endian::native == endian::big,
|
||||||
|
"Only little-endian or big-endian native byte orders are supported.");
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shared implementation between public and internal classes. CRTP pattern.
|
||||||
|
/// </summary>
|
||||||
|
template <class Derived>
|
||||||
|
struct Float16Impl {
|
||||||
|
protected:
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from float to uint16_t float16 representation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
constexpr static uint16_t ToUint16Impl(float v) noexcept;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts float16 to float
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>float representation of float16 value</returns>
|
||||||
|
float ToFloatImpl() const noexcept;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance that represents absolute value.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Absolute value</returns>
|
||||||
|
uint16_t AbsImpl() const noexcept {
|
||||||
|
return static_cast<uint16_t>(val & ~kSignMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance with the sign flipped.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Flipped sign instance</returns>
|
||||||
|
uint16_t NegateImpl() const noexcept {
|
||||||
|
return IsNaN() ? val : static_cast<uint16_t>(val ^ kSignMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// uint16_t special values
|
||||||
|
static constexpr uint16_t kSignMask = 0x8000U;
|
||||||
|
static constexpr uint16_t kBiasedExponentMask = 0x7C00U;
|
||||||
|
static constexpr uint16_t kPositiveInfinityBits = 0x7C00U;
|
||||||
|
static constexpr uint16_t kNegativeInfinityBits = 0xFC00U;
|
||||||
|
static constexpr uint16_t kPositiveQNaNBits = 0x7E00U;
|
||||||
|
static constexpr uint16_t kNegativeQNaNBits = 0xFE00U;
|
||||||
|
static constexpr uint16_t kMaxValueBits = 0x7BFFU; // Largest normal number
|
||||||
|
static constexpr uint16_t kOneBits = 0x3C00U;
|
||||||
|
static constexpr uint16_t kMinusOneBits = 0xBC00U;
|
||||||
|
|
||||||
|
uint16_t val{0};
|
||||||
|
|
||||||
|
Float16Impl() = default;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the value is negative
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if negative</returns>
|
||||||
|
bool IsNegative() const noexcept {
|
||||||
|
return static_cast<int16_t>(val) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is NaN
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if NaN</returns>
|
||||||
|
bool IsNaN() const noexcept {
|
||||||
|
return AbsImpl() > kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is finite
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if finite</returns>
|
||||||
|
bool IsFinite() const noexcept {
|
||||||
|
return AbsImpl() < kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value represents positive infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if positive infinity</returns>
|
||||||
|
bool IsPositiveInfinity() const noexcept {
|
||||||
|
return val == kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value represents negative infinity
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if negative infinity</returns>
|
||||||
|
bool IsNegativeInfinity() const noexcept {
|
||||||
|
return val == kNegativeInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is either positive or negative infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if absolute value is infinity</returns>
|
||||||
|
bool IsInfinity() const noexcept {
|
||||||
|
return AbsImpl() == kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is NaN or zero. Useful for comparisons.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if NaN or zero.</returns>
|
||||||
|
bool IsNaNOrZero() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs == 0 || abs > kPositiveInfinityBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is normal (not zero, subnormal, infinite, or NaN).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if so</returns>
|
||||||
|
bool IsNormal() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs < kPositiveInfinityBits) // is finite
|
||||||
|
&& (abs != 0) // is not zero
|
||||||
|
&& ((abs & kBiasedExponentMask) != 0); // is not subnormal (has a non-zero exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is subnormal (denormal).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if so</returns>
|
||||||
|
bool IsSubnormal() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs < kPositiveInfinityBits) // is finite
|
||||||
|
&& (abs != 0) // is not zero
|
||||||
|
&& ((abs & kBiasedExponentMask) == 0); // is subnormal (has a zero exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance that represents absolute value.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Absolute value</returns>
|
||||||
|
Derived Abs() const noexcept { return Derived::FromBits(AbsImpl()); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance with the sign flipped.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Flipped sign instance</returns>
|
||||||
|
Derived Negate() const noexcept { return Derived::FromBits(NegateImpl()); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IEEE defines that positive and negative zero are equal, this gives us a quick equality check
|
||||||
|
/// for two values by or'ing the private bits together and stripping the sign. They are both zero,
|
||||||
|
/// and therefore equivalent, if the resulting value is still zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">first value</param>
|
||||||
|
/// <param name="rhs">second value</param>
|
||||||
|
/// <returns>True if both arguments represent zero</returns>
|
||||||
|
static bool AreZero(const Float16Impl& lhs, const Float16Impl& rhs) noexcept {
|
||||||
|
return static_cast<uint16_t>((lhs.val | rhs.val) & ~kSignMask) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Float16Impl& rhs) const noexcept {
|
||||||
|
if (IsNaN() || rhs.IsNaN()) {
|
||||||
|
// IEEE defines that NaN is not equal to anything, including itself.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return val == rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Float16Impl& rhs) const noexcept { return !(*this == rhs); }
|
||||||
|
|
||||||
|
bool operator<(const Float16Impl& rhs) const noexcept {
|
||||||
|
if (IsNaN() || rhs.IsNaN()) {
|
||||||
|
// IEEE defines that NaN is unordered with respect to everything, including itself.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool left_is_negative = IsNegative();
|
||||||
|
if (left_is_negative != rhs.IsNegative()) {
|
||||||
|
// When the signs of left and right differ, we know that left is less than right if it is
|
||||||
|
// the negative value. The exception to this is if both values are zero, in which case IEEE
|
||||||
|
// says they should be equal, even if the signs differ.
|
||||||
|
return left_is_negative && !AreZero(*this, rhs);
|
||||||
|
}
|
||||||
|
return (val != rhs.val) && ((val < rhs.val) ^ left_is_negative);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following Float16_t conversions are based on the code from
|
||||||
|
// Eigen library.
|
||||||
|
|
||||||
|
// The conversion routines are Copyright (c) Fabian Giesen, 2016.
|
||||||
|
// The original license follows:
|
||||||
|
//
|
||||||
|
// Copyright (c) Fabian Giesen, 2016
|
||||||
|
// All rights reserved.
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted.
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
union float32_bits {
|
||||||
|
unsigned int u;
|
||||||
|
float f;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
inline constexpr uint16_t Float16Impl<Derived>::ToUint16Impl(float v) noexcept {
|
||||||
|
detail::float32_bits f{};
|
||||||
|
f.f = v;
|
||||||
|
|
||||||
|
constexpr detail::float32_bits f32infty = {255 << 23};
|
||||||
|
constexpr detail::float32_bits f16max = {(127 + 16) << 23};
|
||||||
|
constexpr detail::float32_bits denorm_magic = {((127 - 15) + (23 - 10) + 1) << 23};
|
||||||
|
constexpr unsigned int sign_mask = 0x80000000u;
|
||||||
|
uint16_t val = static_cast<uint16_t>(0x0u);
|
||||||
|
|
||||||
|
unsigned int sign = f.u & sign_mask;
|
||||||
|
f.u ^= sign;
|
||||||
|
|
||||||
|
// NOTE all the integer compares in this function can be safely
|
||||||
|
// compiled into signed compares since all operands are below
|
||||||
|
// 0x80000000. Important if you want fast straight SSE2 code
|
||||||
|
// (since there's no unsigned PCMPGTD).
|
||||||
|
|
||||||
|
if (f.u >= f16max.u) { // result is Inf or NaN (all exponent bits set)
|
||||||
|
val = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf
|
||||||
|
} else { // (De)normalized number or zero
|
||||||
|
if (f.u < (113 << 23)) { // resulting FP16 is subnormal or zero
|
||||||
|
// use a magic value to align our 10 mantissa bits at the bottom of
|
||||||
|
// the float. as long as FP addition is round-to-nearest-even this
|
||||||
|
// just works.
|
||||||
|
f.f += denorm_magic.f;
|
||||||
|
|
||||||
|
// and one integer subtract of the bias later, we have our final float!
|
||||||
|
val = static_cast<uint16_t>(f.u - denorm_magic.u);
|
||||||
|
} else {
|
||||||
|
unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd
|
||||||
|
|
||||||
|
// update exponent, rounding bias part 1
|
||||||
|
// Equivalent to `f.u += ((unsigned int)(15 - 127) << 23) + 0xfff`, but
|
||||||
|
// without arithmetic overflow.
|
||||||
|
f.u += 0xc8000fffU;
|
||||||
|
// rounding bias part 2
|
||||||
|
f.u += mant_odd;
|
||||||
|
// take the bits!
|
||||||
|
val = static_cast<uint16_t>(f.u >> 13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val |= static_cast<uint16_t>(sign >> 16);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
inline float Float16Impl<Derived>::ToFloatImpl() const noexcept {
|
||||||
|
constexpr detail::float32_bits magic = {113 << 23};
|
||||||
|
constexpr unsigned int shifted_exp = 0x7c00 << 13; // exponent mask after shift
|
||||||
|
detail::float32_bits o{};
|
||||||
|
|
||||||
|
o.u = (val & 0x7fff) << 13; // exponent/mantissa bits
|
||||||
|
unsigned int exp = shifted_exp & o.u; // just the exponent
|
||||||
|
o.u += (127 - 15) << 23; // exponent adjust
|
||||||
|
|
||||||
|
// handle exponent special cases
|
||||||
|
if (exp == shifted_exp) { // Inf/NaN?
|
||||||
|
o.u += (128 - 16) << 23; // extra exp adjust
|
||||||
|
} else if (exp == 0) { // Zero/Denormal?
|
||||||
|
o.u += 1 << 23; // extra exp adjust
|
||||||
|
o.f -= magic.f; // re-normalize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to workaround the Internal Compiler Error on ARM64
|
||||||
|
// for bitwise | operator, including std::bitset
|
||||||
|
#if (defined _MSC_VER) && (defined _M_ARM || defined _M_ARM64 || defined _M_ARM64EC)
|
||||||
|
if (IsNegative()) {
|
||||||
|
return -o.f;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// original code:
|
||||||
|
o.u |= (val & 0x8000U) << 16U; // sign bit
|
||||||
|
#endif
|
||||||
|
return o.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shared implementation between public and internal classes. CRTP pattern.
|
||||||
|
template <class Derived>
|
||||||
|
struct BFloat16Impl {
|
||||||
|
protected:
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from float to uint16_t float16 representation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
static uint16_t ToUint16Impl(float v) noexcept;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts bfloat16 to float
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>float representation of bfloat16 value</returns>
|
||||||
|
float ToFloatImpl() const noexcept;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance that represents absolute value.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Absolute value</returns>
|
||||||
|
uint16_t AbsImpl() const noexcept {
|
||||||
|
return static_cast<uint16_t>(val & ~kSignMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance with the sign flipped.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Flipped sign instance</returns>
|
||||||
|
uint16_t NegateImpl() const noexcept {
|
||||||
|
return IsNaN() ? val : static_cast<uint16_t>(val ^ kSignMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// uint16_t special values
|
||||||
|
static constexpr uint16_t kSignMask = 0x8000U;
|
||||||
|
static constexpr uint16_t kBiasedExponentMask = 0x7F80U;
|
||||||
|
static constexpr uint16_t kPositiveInfinityBits = 0x7F80U;
|
||||||
|
static constexpr uint16_t kNegativeInfinityBits = 0xFF80U;
|
||||||
|
static constexpr uint16_t kPositiveQNaNBits = 0x7FC1U;
|
||||||
|
static constexpr uint16_t kNegativeQNaNBits = 0xFFC1U;
|
||||||
|
static constexpr uint16_t kMaxValueBits = 0x7F7FU;
|
||||||
|
static constexpr uint16_t kRoundToNearest = 0x7FFFU;
|
||||||
|
static constexpr uint16_t kOneBits = 0x3F80U;
|
||||||
|
static constexpr uint16_t kMinusOneBits = 0xBF80U;
|
||||||
|
|
||||||
|
uint16_t val{0};
|
||||||
|
|
||||||
|
BFloat16Impl() = default;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the value is negative
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if negative</returns>
|
||||||
|
bool IsNegative() const noexcept {
|
||||||
|
return static_cast<int16_t>(val) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is NaN
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if NaN</returns>
|
||||||
|
bool IsNaN() const noexcept {
|
||||||
|
return AbsImpl() > kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is finite
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if finite</returns>
|
||||||
|
bool IsFinite() const noexcept {
|
||||||
|
return AbsImpl() < kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value represents positive infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if positive infinity</returns>
|
||||||
|
bool IsPositiveInfinity() const noexcept {
|
||||||
|
return val == kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value represents negative infinity
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if negative infinity</returns>
|
||||||
|
bool IsNegativeInfinity() const noexcept {
|
||||||
|
return val == kNegativeInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is either positive or negative infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if absolute value is infinity</returns>
|
||||||
|
bool IsInfinity() const noexcept {
|
||||||
|
return AbsImpl() == kPositiveInfinityBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is NaN or zero. Useful for comparisons.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if NaN or zero.</returns>
|
||||||
|
bool IsNaNOrZero() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs == 0 || abs > kPositiveInfinityBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is normal (not zero, subnormal, infinite, or NaN).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if so</returns>
|
||||||
|
bool IsNormal() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs < kPositiveInfinityBits) // is finite
|
||||||
|
&& (abs != 0) // is not zero
|
||||||
|
&& ((abs & kBiasedExponentMask) != 0); // is not subnormal (has a non-zero exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the value is subnormal (denormal).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if so</returns>
|
||||||
|
bool IsSubnormal() const noexcept {
|
||||||
|
auto abs = AbsImpl();
|
||||||
|
return (abs < kPositiveInfinityBits) // is finite
|
||||||
|
&& (abs != 0) // is not zero
|
||||||
|
&& ((abs & kBiasedExponentMask) == 0); // is subnormal (has a zero exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance that represents absolute value.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Absolute value</returns>
|
||||||
|
Derived Abs() const noexcept { return Derived::FromBits(AbsImpl()); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance with the sign flipped.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Flipped sign instance</returns>
|
||||||
|
Derived Negate() const noexcept { return Derived::FromBits(NegateImpl()); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IEEE defines that positive and negative zero are equal, this gives us a quick equality check
|
||||||
|
/// for two values by or'ing the private bits together and stripping the sign. They are both zero,
|
||||||
|
/// and therefore equivalent, if the resulting value is still zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">first value</param>
|
||||||
|
/// <param name="rhs">second value</param>
|
||||||
|
/// <returns>True if both arguments represent zero</returns>
|
||||||
|
static bool AreZero(const BFloat16Impl& lhs, const BFloat16Impl& rhs) noexcept {
|
||||||
|
// IEEE defines that positive and negative zero are equal, this gives us a quick equality check
|
||||||
|
// for two values by or'ing the private bits together and stripping the sign. They are both zero,
|
||||||
|
// and therefore equivalent, if the resulting value is still zero.
|
||||||
|
return static_cast<uint16_t>((lhs.val | rhs.val) & ~kSignMask) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
inline uint16_t BFloat16Impl<Derived>::ToUint16Impl(float v) noexcept {
|
||||||
|
uint16_t result;
|
||||||
|
if (std::isnan(v)) {
|
||||||
|
result = kPositiveQNaNBits;
|
||||||
|
} else {
|
||||||
|
auto get_msb_half = [](float fl) {
|
||||||
|
uint16_t result;
|
||||||
|
#ifdef __cpp_if_constexpr
|
||||||
|
if constexpr (detail::endian::native == detail::endian::little) {
|
||||||
|
#else
|
||||||
|
if (detail::endian::native == detail::endian::little) {
|
||||||
|
#endif
|
||||||
|
std::memcpy(&result, reinterpret_cast<char*>(&fl) + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
} else {
|
||||||
|
std::memcpy(&result, &fl, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t upper_bits = get_msb_half(v);
|
||||||
|
union {
|
||||||
|
uint32_t U32;
|
||||||
|
float F32;
|
||||||
|
};
|
||||||
|
F32 = v;
|
||||||
|
U32 += (upper_bits & 1) + kRoundToNearest;
|
||||||
|
result = get_msb_half(F32);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Derived>
|
||||||
|
inline float BFloat16Impl<Derived>::ToFloatImpl() const noexcept {
|
||||||
|
if (IsNaN()) {
|
||||||
|
return std::numeric_limits<float>::quiet_NaN();
|
||||||
|
}
|
||||||
|
float result;
|
||||||
|
char* const first = reinterpret_cast<char*>(&result);
|
||||||
|
char* const second = first + sizeof(uint16_t);
|
||||||
|
#ifdef __cpp_if_constexpr
|
||||||
|
if constexpr (detail::endian::native == detail::endian::little) {
|
||||||
|
#else
|
||||||
|
if (detail::endian::native == detail::endian::little) {
|
||||||
|
#endif
|
||||||
|
std::memset(first, 0, sizeof(uint16_t));
|
||||||
|
std::memcpy(second, &val, sizeof(uint16_t));
|
||||||
|
} else {
|
||||||
|
std::memcpy(first, &val, sizeof(uint16_t));
|
||||||
|
std::memset(second, 0, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace onnxruntime_float16
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
;
|
||||||
|
; Definition file of onnxruntime.dll
|
||||||
|
; Automatic generated by gendef 1.1
|
||||||
|
; written by Kai Tietz 2008
|
||||||
|
; The def file has to be processed by --kill-at (-k) option of dlltool or ld
|
||||||
|
;
|
||||||
|
LIBRARY "onnxruntime.dll"
|
||||||
|
EXPORTS
|
||||||
|
OrtGetApiBase
|
||||||
|
OrtSessionOptionsAppendExecutionProvider_CPU
|
||||||
|
After Width: | Height: | Size: 445 KiB |
|
After Width: | Height: | Size: 513 KiB |
|
After Width: | Height: | Size: 513 KiB |
|
After Width: | Height: | Size: 527 KiB |
|
After Width: | Height: | Size: 347 KiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 425 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 446 KiB |
|
After Width: | Height: | Size: 487 KiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
@ -0,0 +1,553 @@
|
|||||||
|
{
|
||||||
|
"20260510170010_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
882,
|
||||||
|
283,
|
||||||
|
76,
|
||||||
|
131
|
||||||
|
],
|
||||||
|
"confidence": 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
883,
|
||||||
|
394,
|
||||||
|
22,
|
||||||
|
39
|
||||||
|
],
|
||||||
|
"confidence": 0.78
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
883,
|
||||||
|
476,
|
||||||
|
125,
|
||||||
|
58
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
819,
|
||||||
|
624,
|
||||||
|
46,
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1472,
|
||||||
|
303,
|
||||||
|
42,
|
||||||
|
90
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
182,
|
||||||
|
391,
|
||||||
|
63,
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
603,
|
||||||
|
450,
|
||||||
|
97,
|
||||||
|
49
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1400,
|
||||||
|
525,
|
||||||
|
141,
|
||||||
|
58
|
||||||
|
],
|
||||||
|
"confidence": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
294,
|
||||||
|
394,
|
||||||
|
53,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"confidence": 0.55
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"20260510170100_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1452,
|
||||||
|
376,
|
||||||
|
169,
|
||||||
|
119
|
||||||
|
],
|
||||||
|
"confidence": 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
907,
|
||||||
|
416,
|
||||||
|
51,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
699,
|
||||||
|
362,
|
||||||
|
27,
|
||||||
|
45
|
||||||
|
],
|
||||||
|
"confidence": 0.63
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
834,
|
||||||
|
445,
|
||||||
|
42,
|
||||||
|
44
|
||||||
|
],
|
||||||
|
"confidence": 0.63
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
732,
|
||||||
|
435,
|
||||||
|
63,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"confidence": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
949,
|
||||||
|
338,
|
||||||
|
43,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"confidence": 0.58
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"20260510170106_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1452,
|
||||||
|
376,
|
||||||
|
169,
|
||||||
|
119
|
||||||
|
],
|
||||||
|
"confidence": 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
907,
|
||||||
|
416,
|
||||||
|
51,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
699,
|
||||||
|
362,
|
||||||
|
27,
|
||||||
|
45
|
||||||
|
],
|
||||||
|
"confidence": 0.63
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
834,
|
||||||
|
445,
|
||||||
|
42,
|
||||||
|
44
|
||||||
|
],
|
||||||
|
"confidence": 0.63
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
732,
|
||||||
|
435,
|
||||||
|
63,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"confidence": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
949,
|
||||||
|
338,
|
||||||
|
43,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"confidence": 0.58
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"20260510170110_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
737,
|
||||||
|
490,
|
||||||
|
26,
|
||||||
|
43
|
||||||
|
],
|
||||||
|
"confidence": 0.78
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1610,
|
||||||
|
68,
|
||||||
|
28,
|
||||||
|
30
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
941,
|
||||||
|
549,
|
||||||
|
51,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
765,
|
||||||
|
564,
|
||||||
|
56,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"confidence": 0.68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
867,
|
||||||
|
576,
|
||||||
|
43,
|
||||||
|
51
|
||||||
|
],
|
||||||
|
"confidence": 0.55
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
188,
|
||||||
|
59,
|
||||||
|
41,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"confidence": 0.53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
31,
|
||||||
|
143,
|
||||||
|
36,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"confidence": 0.53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
982,
|
||||||
|
473,
|
||||||
|
44,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"confidence": 0.53
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"20260510170127_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1300,
|
||||||
|
463,
|
||||||
|
110,
|
||||||
|
115
|
||||||
|
],
|
||||||
|
"confidence": 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
386,
|
||||||
|
607,
|
||||||
|
274,
|
||||||
|
82
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
485,
|
||||||
|
779,
|
||||||
|
68,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
17,
|
||||||
|
345,
|
||||||
|
41,
|
||||||
|
47
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
532,
|
||||||
|
243,
|
||||||
|
61,
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"confidence": 0.58
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
274,
|
||||||
|
323,
|
||||||
|
30,
|
||||||
|
33
|
||||||
|
],
|
||||||
|
"confidence": 0.58
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1376,
|
||||||
|
333,
|
||||||
|
31,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"confidence": 0.58
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
979,
|
||||||
|
522,
|
||||||
|
44,
|
||||||
|
62
|
||||||
|
],
|
||||||
|
"confidence": 0.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"20260510170152_1.jpg": [],
|
||||||
|
"20260510170205_1.jpg": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
796,
|
||||||
|
330,
|
||||||
|
47,
|
||||||
|
48
|
||||||
|
],
|
||||||
|
"confidence": 0.85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
773,
|
||||||
|
603,
|
||||||
|
28,
|
||||||
|
57
|
||||||
|
],
|
||||||
|
"confidence": 0.85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
792,
|
||||||
|
139,
|
||||||
|
150,
|
||||||
|
188
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
96,
|
||||||
|
194,
|
||||||
|
40,
|
||||||
|
44
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
912,
|
||||||
|
569,
|
||||||
|
55,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
679,
|
||||||
|
753,
|
||||||
|
52,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1432,
|
||||||
|
340,
|
||||||
|
83,
|
||||||
|
52
|
||||||
|
],
|
||||||
|
"confidence": 0.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
629,
|
||||||
|
312,
|
||||||
|
67,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"confidence": 0.53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
267,
|
||||||
|
537,
|
||||||
|
42,
|
||||||
|
29
|
||||||
|
],
|
||||||
|
"confidence": 0.53
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Thermal_ColdGun_001_processed.png": [],
|
||||||
|
"微信图片_20260503224413_383_75.png": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1286,
|
||||||
|
155,
|
||||||
|
52,
|
||||||
|
53
|
||||||
|
],
|
||||||
|
"confidence": 0.85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1183,
|
||||||
|
151,
|
||||||
|
57,
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"confidence": 0.75
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
903,
|
||||||
|
99,
|
||||||
|
55,
|
||||||
|
59
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
1353,
|
||||||
|
191,
|
||||||
|
70,
|
||||||
|
45
|
||||||
|
],
|
||||||
|
"confidence": 0.6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"微信图片_20260503224418_384_75.png": [],
|
||||||
|
"微信图片_20260503224424_385_75.png": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
817,
|
||||||
|
127,
|
||||||
|
44,
|
||||||
|
47
|
||||||
|
],
|
||||||
|
"confidence": 0.85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
554,
|
||||||
|
160,
|
||||||
|
73,
|
||||||
|
62
|
||||||
|
],
|
||||||
|
"confidence": 0.65
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"微信图片_20260503224430_386_75.png": [
|
||||||
|
{
|
||||||
|
"type": "Person",
|
||||||
|
"bbox": [
|
||||||
|
509,
|
||||||
|
79,
|
||||||
|
50,
|
||||||
|
50
|
||||||
|
],
|
||||||
|
"confidence": 0.85
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
placeholder
|
|
||||||