You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
9.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <string>
#include <signal.h>
#include "deal.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "JpgDecoder.h"
#include <filesystem>
#include <algorithm>
#include <sys/time.h>
namespace fs = std::filesystem;
void handler(int sig)
{
printf("Get handler sig");
string strcmd = "ps -ef | grep test_JBL_Check| awk '{print $2}' | xargs kill -9 ";
const char *cmd = strcmd.c_str();
printf("delete test_JBL_Check success");
if (-1 == system(cmd))
{
std::cout << "error" << std::endl;
}
// delete UnderCarriageCoreLogic::GetInstance();
exit(0);
}
int _sysmkdir(const std::string &dir)
{
int ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret && errno == EEXIST)
{
// printf("dir[%s] already exist.\n", dir.c_str());
}
else if (ret)
{
printf("create dir[%s] error: %d %s\n", dir.c_str(), ret, strerror(errno));
return -1;
}
else
{
printf("create dir[%s] success.\n", dir.c_str());
}
return 0;
}
std::string __getParentDir(const std::string &dir)
{
std::string pdir = dir;
if (pdir.length() < 1 || (pdir[0] != '/'))
{
return "";
}
while (pdir.length() > 1 && (pdir[pdir.length() - 1] == '/'))
pdir = pdir.substr(0, pdir.length() - 1);
pdir = pdir.substr(0, pdir.find_last_of('/'));
return pdir;
}
int _sysmkdirs(const std::string &dir)
{
int ret = 0;
if (dir.empty())
return -1;
std::string pdir;
if ((ret = _sysmkdir(dir)) == -1)
{
pdir = __getParentDir(dir);
if ((ret = _sysmkdirs(pdir)) == 0)
{
ret = _sysmkdirs(dir);
}
}
return ret;
}
int main(int argc, char *argv[])
{
deal test;
if (argc > 1 && string(argv[1]) == "-h")
{
cout << "******************************************************" << endl;
cout << "*** 1、./test_JBL_Check: 默认处理一套图 图片文件夹位于 ../data/img/t1结果位于/home/aidlux/BOE/testresult" << endl;
cout << "*** 2、./test_JBL_Check -s: 1 的基础上增加 过程存图包括edge 和字符检测的中间结果存图,图片位于 当前文件夹。" << endl;
cout << "*** 3、./test_JBL_Check -fjc filepath: 处理精测套图大图 结果位于/home/aidlux/BOE/ResultImg" << endl;
cout << "*** 4、./test_JBL_Check -feai filepath num: 批量测试边缘检测算法num 至多处理张数,结果:/home/aidlux/BOE/Edge" << endl;
cout << "*** 5、./test_JBL_Check -falign filepath num : 批量测试定位算法num 至多处理张数,结果:/home/aidlux/BOE/Align" << endl;
cout << "*** 6、./test_JBL_Check -rjson filepath: 单张复测filepath xx/xx/3A3K380001B1DK_20240408_152157_Main_0_2_L255" << endl;
cout << "*** 6、./test_JBL_Check -rjsonall filepath: 一套图复测filepath xx/xx/" << endl;
cout << "*** 7、./test_CellAOI -decode [dir]: 批量解码 .ytimage → .png 到 /home/aidlux/BOE/CELL_AOI/decode_img" << endl;
cout << "******************************************************" << endl;
return 0;
}
printf("argc = %d\n", argc);
for (int i = 0; i < argc; i++)
{
printf("argv[%d]=%s\n", i, argv[i]);
}
bool bDecodeMode = false;
std::string decodeInputDir;
if (argc > 1 && string(argv[1]) != "-h")
{
for (int i = 1; i < argc; i++)
{
if (string(argv[i]) == "-decode")
{
bDecodeMode = true;
if (i + 1 < argc && argv[i + 1][0] != '-')
{
decodeInputDir = string(argv[i + 1]);
i++;
}
}
else if (string(argv[i]) == "-rs")
{
test.runConfig.run_Type = Process_Run_SaveImg;
}
else if (string(argv[i]) == "-rd")
{
test.runConfig.run_Type = Process_Run_Detect;
}
else if (string(argv[i]) == "-rjson")
{
if (i + 1 >= argc)
{
printf("error Not Path \n");
return -1;
}
test.runConfig.run_Type = Process_Run_ReJson;
test.runConfig.filePath = string(argv[i + 1]);
}
else if (string(argv[i]) == "-f" && i + 1 < argc)
{
test.runConfig.det_Type = RUNTYPE_RUN_File;
test.runConfig.filePath = string(argv[i + 1]);
}
else if (string(argv[i]) == "-fe" && i + 1 < argc)
{
test.runConfig.det_Type = RUNTYPE_RUN_EDGE_TEST;
test.runConfig.filePath = string(argv[i + 1]);
}
else if (string(argv[i]) == "-feai" && i + 1 < argc)
{
test.runConfig.det_Type = RUNTYPE_RUN_EDGE_TEST_AI;
test.runConfig.filePath = string(argv[i + 1]);
}
else if (string(argv[i]) == "-m")
{
test.runConfig.det_Type = RUNTYPE_RUN_Merge_Img;
}
if (string(argv[i]) == "-s")
{
test.runConfig.bSaveProcessImg = true;
}
if (string(argv[i]) == "-ud")
{
test.runConfig.bdecode = false;
}
if (string(argv[i]) == "-fud" && i + 1 < argc)
{
test.runConfig.det_Type = RUNTYPE_RUN_File;
test.runConfig.filePath = string(argv[i + 1]);
test.runConfig.bdecode = false;
}
}
}
// ====== 批量解码模式 (-decode) ======
if (bDecodeMode)
{
std::string inputDir = decodeInputDir.empty()
? std::string("../data/img/t1")
: decodeInputDir;
std::string outputDir = "/home/aidlux/BOE/CELL_AOI/decode_img";
printf("\n========== 批量解码模式 ==========\n");
printf(" 输入目录: %s\n", inputDir.c_str());
printf(" 输出目录: %s\n", outputDir.c_str());
printf("===================================\n\n");
// 检查输入目录
if (!fs::exists(inputDir) || !fs::is_directory(inputDir))
{
printf("[decode] 输入目录不存在: %s\n", inputDir.c_str());
return -1;
}
// 创建输出目录
_sysmkdirs(outputDir);
// 只解码 .ytimage 原始多JPEG文件
auto isYtimageFile = [](const std::string &ext) -> bool {
std::string lower = ext;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return (lower == ".ytimage");
};
// 扫描所有 .ytimage 文件
std::vector<fs::path> imageFiles;
try
{
for (const auto &entry : fs::recursive_directory_iterator(inputDir))
{
if (entry.is_regular_file() && isYtimageFile(entry.path().extension().string()))
imageFiles.push_back(entry.path());
}
}
catch (const fs::filesystem_error &e)
{
printf("[decode] 扫描目录出错: %s\n", e.what());
return -1;
}
if (imageFiles.empty())
{
printf("[decode] 未找到 .ytimage 文件: %s\n", inputDir.c_str());
return 0;
}
printf("[decode] 找到 %zu 个 .ytimage 文件,开始批量解码...\n", imageFiles.size());
// 逐个解码并保存
int successCount = 0;
int failCount = 0;
struct timeval tvTotalStart, tvTotalEnd;
gettimeofday(&tvTotalStart, nullptr);
for (size_t i = 0; i < imageFiles.size(); ++i)
{
const auto &imgPath = imageFiles[i];
std::string inputPath = imgPath.string();
printf("[%zu/%zu] %s ... ", i + 1, imageFiles.size(), imgPath.filename().c_str());
fflush(stdout);
struct timeval tv1, tv2;
gettimeofday(&tv1, nullptr);
// ★ 调用 JpgDecoder 独立模块解码
cv::Mat decoded = decodeJpgImage(inputPath);
gettimeofday(&tv2, nullptr);
long elapsed = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000;
if (decoded.empty())
{
printf("失败 (%ld ms)\n", elapsed);
failCount++;
continue;
}
// 提取 Product ID文件路径往上两级目录
std::string productId = imgPath.parent_path().parent_path().filename().string();
// 文件名 stem去掉 .ytimage 后缀)
std::string stem = imgPath.stem().string(); // e.g. "CAA"
// 输出目录outputDir / ProductID
fs::path outSubDir = fs::path(outputDir) / productId;
_sysmkdirs(outSubDir.string());
// 保存两份M_ 前缀 + A_ 前缀
bool ok = true;
for (const auto &prefix : {"M_", "A_"})
{
fs::path outPath = outSubDir / (std::string(prefix) + stem + ".png");
if (!cv::imwrite(outPath.string(), decoded))
{
printf("保存失败: %s\n", outPath.filename().c_str());
ok = false;
}
}
if (ok)
{
printf("OK → %s/M_%s.png + A_%s.png [%dx%d] (%ld ms)\n",
productId.c_str(), stem.c_str(), stem.c_str(),
decoded.cols, decoded.rows, elapsed);
successCount++;
}
else
{
failCount++;
}
}
gettimeofday(&tvTotalEnd, nullptr);
long totalElapsed = (tvTotalEnd.tv_sec - tvTotalStart.tv_sec) * 1000 +
(tvTotalEnd.tv_usec - tvTotalStart.tv_usec) / 1000;
printf("\n========================================\n");
printf("[decode] 批量解码完成!\n");
printf(" 输入目录: %s\n", inputDir.c_str());
printf(" 输出目录: %s\n", outputDir.c_str());
printf(" 成功: %d 张\n", successCount);
printf(" 失败: %d 张\n", failCount);
printf(" 总耗时: %ld ms\n", totalElapsed);
printf("========================================\n");
return (successCount > 0) ? 0 : -1;
}
test.runConfig.print("config");
// getchar();
signal(SIGINT, handler);
test.start();
while (true)
{
usleep(10 * 1000);
}
return 0;
}