From 40c4b82870c4ad746a7659465cbaf42e0f910338 Mon Sep 17 00:00:00 2001 From: liusiyang Date: Mon, 17 Aug 2026 09:19:06 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E6=B7=BB=E5=8A=A0-testAIDet=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E6=B5=8B=E8=AF=95defect.engine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/CMakeLists.txt | 1 + example/deal.cpp | 152 +++++++++++++++++++++++++++++++++++++++ example/deal.h | 2 + example/test_example.cpp | 4 ++ 4 files changed, 159 insertions(+) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index bb26c9d..3ef612c 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/AlgorithmModule/include ${PROJECT_SOURCE_DIR}/ConfigModule/include +${PROJECT_SOURCE_DIR}/AIEngineModule/include_base ) link_directories( diff --git a/example/deal.cpp b/example/deal.cpp index fe433c1..21b30ea 100644 --- a/example/deal.cpp +++ b/example/deal.cpp @@ -6,9 +6,11 @@ #include "MemMonitor.h" #include #include +#include #include "CheckUtil.hpp" #include "LoadImage.hpp" // #include "LoadImage.h" #include "JsonConfig.h" +#include "AI_Factory.h" bool check_strChannel(string strChannel){ if(strChannel == "XD" || strChannel == "XON") return false; @@ -1298,6 +1300,15 @@ int deal::DetImg() return 0; } + // AI 检测独立测试:读取 in 图 -> 模型推理 -> 保存 out 图(不做其他流程) + if (runConfig.det_Type == RUNTYPE_RUN_File_AI_DetTest) + { + m_nReadThread_type = READ_THREAD_TYPE_READIMG; + m_nSystemCheckType = CHECK_TYPE_OFFLING; + TestAIDet(); + return 0; + } + m_nReadThread_type = READ_THREAD_TYPE_READIMG; m_nSystemCheckType = CHECK_TYPE_OFFLING; @@ -1315,6 +1326,147 @@ int deal::DetImg() return 0; } +/// @brief AI 检测独立测试:遍历 /home/aidlux/BOE/FOG/AI_Detect/ 下所有 *_in.png, +/// 送入 AI_defect_NF 模型推理,将输出 *_out.png 保存到 /home/aidlux/BOE/FOG/AI_Detect_TEST/ +/// @return 0 表示成功 +int deal::TestAIDet() +{ + std::string strSrcRoot = "/home/aidlux/BOE/FOG/AI_Detect/"; + std::string strDstRoot = "/home/aidlux/BOE/FOG/AI_Detect_TEST/"; + + std::shared_ptr pAIFactory = AIFactory::GetInstance(); + std::shared_ptr pAI_Model = pAIFactory->AI_defect_NF; + if (!pAI_Model || !pAI_Model->m_bInitSuccess) + { + printf("TestAIDet: AI model (AI_defect_NF) not ready!\n"); + return 1; + } + + printf("TestAIDet: model input [c=%d w=%d h=%d] output [c=%d w=%d h=%d]\n", + pAI_Model->input_0.channel, pAI_Model->input_0.width, pAI_Model->input_0.height, + pAI_Model->output_0.channel, pAI_Model->output_0.width, pAI_Model->output_0.height); + + // 收集所有 *_in.png 文件 + std::vector inList; + try + { + if (!fs::exists(strSrcRoot)) + { + printf("TestAIDet: src dir not exist: %s\n", strSrcRoot.c_str()); + return 1; + } + for (const auto &entry : fs::recursive_directory_iterator(strSrcRoot)) + { + if (!entry.is_regular_file()) + { + continue; + } + std::string path = entry.path().string(); + std::string name = entry.path().filename().string(); + const std::string suffix = "_in.png"; + if (name.size() >= suffix.size() && + name.compare(name.size() - suffix.size(), suffix.size(), suffix) == 0) + { + inList.push_back(path); + } + } + } + catch (const std::exception &e) + { + printf("TestAIDet: traverse error %s\n", e.what()); + return 1; + } + + std::sort(inList.begin(), inList.end()); + printf("TestAIDet: total %zu in images\n", inList.size()); + + const int nModelInCh = pAI_Model->input_0.channel; + const int nModelInW = pAI_Model->input_0.width; + const int nModelInH = pAI_Model->input_0.height; + + int nOK = 0; + for (size_t i = 0; i < inList.size(); i++) + { + const std::string &inPath = inList[i]; + cv::Mat inImg = cv::imread(inPath, cv::IMREAD_UNCHANGED); + if (inImg.empty()) + { + printf("[%zu/%zu] read fail: %s\n", i + 1, inList.size(), inPath.c_str()); + continue; + } + + // 统一成模型要求的输入:单通道 8U、模型输入尺寸 + if (inImg.channels() != nModelInCh) + { + cv::Mat tmp; + if (inImg.channels() >= 3) + { + cv::cvtColor(inImg, tmp, cv::COLOR_BGR2GRAY); + } + else + { + tmp = inImg.clone(); + } + inImg = tmp; + } + if (inImg.type() != CV_8U) + { + inImg.convertTo(inImg, CV_8U); + } + if (inImg.cols != nModelInW || inImg.rows != nModelInH) + { + cv::resize(inImg, inImg, cv::Size(nModelInW, nModelInH)); + } + + cv::Mat outImg; + int re = pAI_Model->AIDet(inImg, outImg); + if (re != 0 || outImg.empty()) + { + printf("[%zu/%zu] infer fail(%d): %s\n", i + 1, inList.size(), re, inPath.c_str()); + continue; + } + + // 输出 resize 回模型输入尺寸(与 AI_Detect_QX 保存的 out 图尺寸保持一致) + if (outImg.cols != nModelInW || outImg.rows != nModelInH) + { + cv::resize(outImg, outImg, cv::Size(nModelInW, nModelInH), 0, 0, 0); + } + + // 相对路径,并保持子目录结构 + std::string rel = inPath.substr(strSrcRoot.size()); + std::string outRel = rel; + const std::string inSuffix = "_in.png"; + const std::string outSuffix = "_out.png"; + size_t pos = outRel.rfind(inSuffix); + if (pos != std::string::npos) + { + outRel.replace(pos, inSuffix.size(), outSuffix); + } + std::string outPath = strDstRoot + outRel; + + // 创建输出父目录 + fs::path outParent = fs::path(outPath).parent_path(); + if (!outParent.empty()) + { + std::error_code ec; + fs::create_directories(outParent, ec); + } + + if (cv::imwrite(outPath, outImg)) + { + nOK++; + printf("[%zu/%zu] ok: %s -> %s\n", i + 1, inList.size(), rel.c_str(), outRel.c_str()); + } + else + { + printf("[%zu/%zu] save fail: %s\n", i + 1, inList.size(), outPath.c_str()); + } + } + + printf("TestAIDet: complete, success %d / %zu\n", nOK, inList.size()); + return 0; +} + /// @brief 检查文件图片 /// @detail 后续实现具体功能 /// @return 0 表示成功 diff --git a/example/deal.h b/example/deal.h index 292e4c4..c27d844 100644 --- a/example/deal.h +++ b/example/deal.h @@ -138,6 +138,7 @@ enum RUNTYPE_ RUNTYPE_RUN_File_AI_TEST, RUNTYPE_RUN_File_Edge_Test_Save_Qx, RUNTYPE_RUN_File_Edge_Test_Save_ALL, + RUNTYPE_RUN_File_AI_DetTest, // AI 检测独立测试:读 in 图 -> 推理 -> 存 out 图 }; // 程序运行模式 enum Process_Run_Type @@ -633,6 +634,7 @@ private: int ReJson(); int ReJson_ALL(); int DetImg(); // 套图复测 + int TestAIDet(); // AI 检测独立测试:读取 in 图送入模型,保存 out 图 int ReJson_product(std::vector &jsonList, std::string strProductName); // 套图复测 int CheckFileImg(); ///< 检查文件图片(新增) int CheckProduct(const LoadProductImages &product); ///< 检查单个产品(新增) diff --git a/example/test_example.cpp b/example/test_example.cpp index e1cfad6..d104735 100644 --- a/example/test_example.cpp +++ b/example/test_example.cpp @@ -188,6 +188,10 @@ int main(int argc, char *argv[]) return 0; } } + else if (string(argv[i]) == "-testAIDet") + { + test.runConfig.det_Type = RUNTYPE_RUN_File_AI_DetTest; + } else if (string(argv[i]) == "-feqx" && i + 1 < argc) { test.runConfig.det_Type = RUNTYPE_RUN_File_Edge_Test_Save_Qx;