Compare commits

..

3 Commits

22 changed files with 8597 additions and 4270 deletions

4
.gitignore vendored
View File

@ -11,4 +11,6 @@ Makefile.*
*.dll *.dll
*.qm *.qm
*.onnx *.onnx
*.bmp *.bmp
opencv*
opencv

View File

@ -241,6 +241,7 @@ Makefile: cotton_double2.pro ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\win32-msvc
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\resolve_config.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\resolve_config.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exclusive_builds_post.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exclusive_builds_post.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\default_post.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\default_post.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\win32\console.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qtquickcompiler.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qtquickcompiler.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\precompile_header.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\precompile_header.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\warn_on.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\warn_on.prf \
@ -253,7 +254,6 @@ Makefile: cotton_double2.pro ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\win32-msvc
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\uic.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\uic.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qmake_use.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qmake_use.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\file_copies.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\file_copies.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\win32\windows.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\testcase_targets.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\testcase_targets.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exceptions.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exceptions.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\yacc.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\yacc.prf \
@ -263,13 +263,11 @@ Makefile: cotton_double2.pro ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\win32-msvc
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Gui.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Gui.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Network.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Network.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Core.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Core.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPoint.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\build_pass.prf \ ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\build_pass.prf \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Widgetsd.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Widgetsd.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Guid.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Guid.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Networkd.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Networkd.prl \
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Cored.prl \ ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Cored.prl
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPointd.prl
$(QMAKE) -o Makefile cotton_double2.pro -spec win32-msvc "CONFIG+=qtquickcompiler" $(QMAKE) -o Makefile cotton_double2.pro -spec win32-msvc "CONFIG+=qtquickcompiler"
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\spec_pre.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\spec_pre.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\common\windows-desktop.conf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\common\windows-desktop.conf:
@ -428,6 +426,7 @@ Makefile: cotton_double2.pro ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\win32-msvc
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\resolve_config.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\resolve_config.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exclusive_builds_post.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exclusive_builds_post.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\default_post.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\default_post.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\win32\console.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qtquickcompiler.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qtquickcompiler.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\precompile_header.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\precompile_header.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\warn_on.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\warn_on.prf:
@ -440,7 +439,6 @@ Makefile: cotton_double2.pro ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\win32-msvc
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\uic.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\uic.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qmake_use.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\qmake_use.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\file_copies.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\file_copies.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\win32\windows.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\testcase_targets.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\testcase_targets.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exceptions.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\exceptions.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\yacc.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\yacc.prf:
@ -450,13 +448,11 @@ cotton_double2.pro:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Gui.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Gui.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Network.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Network.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Core.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Core.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPoint.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\build_pass.prf: ..\..\..\..\Qt\6.7.3\msvc2022_64\mkspecs\features\build_pass.prf:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Widgetsd.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Widgetsd.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Guid.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Guid.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Networkd.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Networkd.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Cored.prl: ..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Cored.prl:
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPointd.prl:
qmake: FORCE qmake: FORCE
@$(QMAKE) -o Makefile cotton_double2.pro -spec win32-msvc "CONFIG+=qtquickcompiler" @$(QMAKE) -o Makefile cotton_double2.pro -spec win32-msvc "CONFIG+=qtquickcompiler"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -41,12 +41,9 @@ int SaveImg_Flag;
ONNXRunner runner; ONNXRunner runner;
std::map<std::string, int> params;
int dual_cam_offset_y = 0; // 双相机之间的上下偏移值 int dual_cam_offset_y = 0; // 双相机之间的上下偏移值
int widthBlocks = 20; // 输出的喷阀通道数 int widthBlocks = 20; // 输出的喷阀通道数
int heightBlocks = 512; // 输出的Mask高度 int heightBlocks = 512; // 输出的Mask高度
int sizeThreshold = 4; // 转化为喷阀的每块要求像素个数
int expansionRaidus = 1; // 获取mask后进行左右位置的扩展
int padLeft = 1; // 左侧在结果Mask上补0 int padLeft = 1; // 左侧在结果Mask上补0
int padRight = 1; // 右侧在结果Mask上补0 int padRight = 1; // 右侧在结果Mask上补0
int rowRange = 1; // 结果维持行数至少为1 int rowRange = 1; // 结果维持行数至少为1
@ -63,13 +60,18 @@ static std::vector<std::vector<uint8_t>> tail_1(0);
uint8_t temp_buf[512 * 64] = {0}; uint8_t temp_buf[512 * 64] = {0};
extern int file_delay; // 总体参数
extern int lowmac_sm; //吹气量
extern int file_encoder; extern int file_encoder;
extern int file_valve; extern int file_valve;
//下位机参数 // 颜色模块参数
extern int sizeThreshold; // 转化为喷阀的每块要求像素个数
extern int expansionRaidus; // 获取mask后进行左右位置的扩展
extern int file_delay;
// 偏振模块参数
extern int lowmac_dp; //偏振延迟时间 extern int lowmac_dp; //偏振延迟时间
extern int lowmac_sm; //吹气量
extern int lowmac_ts; //模板匹配阈值 extern int lowmac_ts; //模板匹配阈值
extern int lowmac_sg; //偏振绿色通道大小阈值 extern int lowmac_sg; //偏振绿色通道大小阈值
extern int lowmac_td; //偏振红色通道差值 extern int lowmac_td; //偏振红色通道差值
@ -221,7 +223,7 @@ MIL_INT ProcessingFunction0(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
// 使用 std::async 将 high_sat_detect 封装为异步任务 // 使用 std::async 将 high_sat_detect 封装为异步任务
auto future = std::async(std::launch::async, [&]() { auto future = std::async(std::launch::async, [&]() {
MIL_ID detection_result_id; MIL_ID detection_result_id;
high_sat_detect(MimFlipDedtination, detection_result_id, params); high_sat_detect(MimFlipDedtination, detection_result_id, params,colors);
matrox_mat = ImageUtils::mil2Mat(detection_result_id); matrox_mat = ImageUtils::mil2Mat(detection_result_id);
MbufFree(detection_result_id); MbufFree(detection_result_id);
}); });
@ -391,7 +393,7 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
// 使用 std::async 将 high_sat_detect 封装为异步任务 // 使用 std::async 将 high_sat_detect 封装为异步任务
auto future = std::async(std::launch::async, [&]() { auto future = std::async(std::launch::async, [&]() {
MIL_ID detection_result_id; MIL_ID detection_result_id;
high_sat_detect(MimResizedestination, detection_result_id, params); high_sat_detect(MimResizedestination, detection_result_id, params,colors);
matrox_mat = ImageUtils::mil2Mat(detection_result_id); matrox_mat = ImageUtils::mil2Mat(detection_result_id);
MbufFree(detection_result_id); MbufFree(detection_result_id);
}); });
@ -548,22 +550,8 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
// 将结果的左右补充上0让物体大小符合要求 // 将结果的左右补充上0让物体大小符合要求
PadColumns(mask_expaned, padLeft, padRight, 0); PadColumns(mask_expaned, padLeft, padRight, 0);
// ======= 新增:统计 mask_expaned 里的 1 的总个数,并累加到全局变量 ======= max_valves_together_limit(mask_expaned, params["max_valves_together"]);
{
long long count_ones_this_time = 0;
for(const auto & row : mask_expaned)
{
for(uint8_t val : row)
{
count_ones_this_time += (val == 1);
}
}
g_valveActionCount += count_ones_this_time;
// 如果你想调试打印,可以
// qDebug() << "This callback1 new triggered bits =" << count_ones_this_time
// << ", total=" << g_valveActionCount;
}
// ======= 新增结束 =======
//将mask扩展到合适发送的大小 //将mask扩展到合适发送的大小
std::vector<std::vector<uint8_t>> mask_Total = expandArray(mask_expaned,64); std::vector<std::vector<uint8_t>> mask_Total = expandArray(mask_expaned,64);
@ -612,245 +600,6 @@ bool DestoryCamera()
return 1; return 1;
} }
// Optimized LabProcess function
void lab_process_raw(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map<std::string, int>& params,
const std::vector<std::string>& color_vector)
{
MIL_ID MilLabImage = M_NULL, MilLChannel = M_NULL, MilAChannel = M_NULL, MilBChannel = M_NULL;
MIL_ID lab_result=M_NULL;
int denoising = params.at("lab_denoising");
// Check number of bands
MIL_INT NumBands = 0;
MbufInquire(inputImage, M_SIZE_BAND, &NumBands);
if (NumBands != 3)
{
printf("输入图像不是 3 通道图像,请提供彩色图像。\n");
return;
}
// Inquire image properties once
// MIL_ID MilSystem = MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL);
MIL_INT SizeX = MbufInquire(inputImage, M_SIZE_X, M_NULL);
MIL_INT SizeY = MbufInquire(inputImage, M_SIZE_Y, M_NULL);
// Allocate buffer for Lab image
MbufAllocColor(MilSystem, 3, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilLabImage);
// Convert image from sRGB to Lab
MimConvert(inputImage, MilLabImage, M_SRGB_TO_LAB);
// Create child buffers for L, a, b channels
MbufChildColor(MilLabImage, 0, &MilLChannel);
MbufChildColor(MilLabImage, 1, &MilAChannel);
MbufChildColor(MilLabImage, 2, &MilBChannel);
// Allocate output image as 1-bit image
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &outputImageLab);
MbufClear(outputImageLab, 0); // Initialize to 0
// Pre-allocate binary buffers as 1-bit images
MIL_ID MilBinaryL = M_NULL, MilBinaryA = M_NULL, MilBinaryB = M_NULL, MilResultLab = M_NULL;
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryL);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryA);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryB);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilResultLab);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &lab_result);
MbufClear(lab_result, M_COLOR_BLACK);
// Iterate over colors
// 遍历颜色
for (const auto& color : color_vector) {
// 构建参数键
std::string L_min_key = color + "_L_min";
std::string L_max_key = color + "_L_max";
std::string a_min_key = color + "_a_min";
std::string a_max_key = color + "_a_max";
std::string b_min_key = color + "_b_min";
std::string b_max_key = color + "_b_max";
// 获取参数值
int L_min = params.at(L_min_key);
int L_max = params.at(L_max_key);
int a_min = params.at(a_min_key);
int a_max = params.at(a_max_key);
int b_min = params.at(b_min_key);
int b_max = params.at(b_max_key);
std::vector<int> lab_min_ps = {L_min, a_min, b_min};
std::vector<int> lab_max_ps = {L_max, a_max, b_max};
std::vector<int> lab_min_cv = psLabToOpenCVLab(lab_min_ps);
std::vector<int> lab_max_cv = psLabToOpenCVLab(lab_max_ps);
L_min = lab_min_cv[0];
L_max = lab_max_cv[0];
a_min = lab_min_cv[1];
a_max = lab_max_cv[1];
b_min = lab_min_cv[2];
b_max = lab_max_cv[2];
// 对每个通道进行二值化
MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, L_min, L_max);
MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, a_min, a_max);
MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, b_min, b_max);
// 合并阈值结果
MimArith(MilBinaryL, MilBinaryA, MilResultLab, M_AND);
MimArith(MilResultLab, MilBinaryB, MilResultLab, M_AND);
// 与输出图像合并
MimArith(lab_result, MilResultLab, lab_result, M_OR);
}
MimClose(lab_result, MilResultLab, denoising, M_BINARY);
MimOpen(MilResultLab, outputImageLab, denoising, M_BINARY);
// Free binary buffers
MbufFree(MilBinaryL);
MbufFree(MilBinaryA);
MbufFree(MilBinaryB);
MbufFree(MilResultLab);
// Free resources
MbufFree(MilLChannel);
MbufFree(MilAChannel);
MbufFree(MilBChannel);
MbufFree(MilLabImage);
MbufFree(lab_result);
}
void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map<std::string, int>& params) {
const std::vector<std::string> colors = {"green", "blue", "orange", "black", "red", "purple"};
lab_process_raw(inputImage, outputImageLab, params, colors);
}
vector<int> psLabToOpenCVLab(const vector<int>& lab_ps) {
int l_ps = lab_ps[0];
int a_ps = lab_ps[1];
int b_ps = lab_ps[2];
// Conversion formulas
int l_cv = round((l_ps / 100.0) * 255.0); // Scale L from 0-100 to 0-255
int a_cv = round(((a_ps + 128.0) / 255.0) * 255.0); // Shift and scale a
int b_cv = round(((b_ps + 128.0) / 255.0) * 255.0); // Shift and scale b
return {l_cv, a_cv, b_cv};
}
vector<int> opencvLabToPsLab(const vector<int>& lab_cv) {
int l_cv = lab_cv[0];
int a_cv = lab_cv[1];
int b_cv = lab_cv[2];
// Conversion formulas
int l_ps = round((l_cv / 255.0) * 100.0); // Scale L from 0-255 to 0-100
int a_ps = round((a_cv / 255.0) * 255.0 - 128.0); // Scale and shift a
int b_ps = round((b_cv / 255.0) * 255.0 - 128.0); // Scale and shift b
return {l_ps, a_ps, b_ps};
}
void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map<std::string, int>& params)
{
MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL;
MIL_ID hsv_result = M_NULL;
MIL_ID hsv_denoising = M_NULL;
int saturationThreshold = params.at("saturation_threshold");
int denoising = params.at("saturation_denoising");
// 检查输入图像的通道数
MIL_INT NumBands = 0;
MbufInquire(inputImage, M_SIZE_BAND, &NumBands);
if (NumBands != 3)
{
printf("输入图像不是 3 通道图像,请提供彩色图像。\n");
return;
}
// 分配用于存储 HSV 图像的缓冲区
MbufAllocColor(MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL), 3,
MbufInquire(inputImage, M_SIZE_X, M_NULL),
MbufInquire(inputImage, M_SIZE_Y, M_NULL),
8 + M_UNSIGNED,
M_IMAGE + M_PROC + M_DISP,
&MilHSVImage);
// 将图像从 sRGB 转换到 HSV
MimConvert(inputImage, MilHSVImage, M_RGB_TO_HSV);
// 创建 HSV 通道的子缓冲区
MbufChildColor(MilHSVImage, 0, &MilHChannel);
MbufChildColor(MilHSVImage, 1, &MilSChannel);
MbufChildColor(MilHSVImage, 2, &MilVChannel);
// 分配输出图像缓冲区
MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL),
MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED,
M_IMAGE + M_PROC + M_DISP, &hsv_result);
MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL),
MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED,
M_IMAGE + M_PROC + M_DISP, &hsv_denoising);
MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL),
MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED,
M_IMAGE + M_PROC + M_DISP, &outputImageHSV);
// 对 S 通道进行阈值分割
MimBinarize(MilSChannel, hsv_result, M_GREATER,
saturationThreshold, M_NULL);
MimClose(hsv_result, hsv_denoising, denoising, M_BINARY);
MimOpen(hsv_denoising, outputImageHSV, denoising, M_BINARY);
// 释放资源
MbufFree(MilHChannel);
MbufFree(MilSChannel);
MbufFree(MilVChannel);
MbufFree(MilHSVImage);
MbufFree(hsv_result);
MbufFree(hsv_denoising);
}
void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map<std::string, int>& params) {
MIL_ID output_hsv=M_NULL, output_lab=M_NULL;
hsv_process(inputImage, output_hsv, params);
lab_process(inputImage, output_lab, params);
MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL),
MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED,
M_IMAGE + M_PROC, &outputImage);
// 合并 Lab 和 HSV 的结果(取“或”运算)
MimArith(output_hsv, output_lab, outputImage, M_OR);
// MIL_ID MilBlobContext = M_NULL, MilBlobResult = M_NULL, MilFiltered = M_NULL;
// MIL_INT SizeX = 0, SizeY = 0;
// MIL_INT blob_count = 0;
// MblobAlloc(MilSystem, M_DEFAULT, M_DEFAULT, &MilBlobContext);
// MblobAllocResult(MilSystem, M_DEFAULT, M_DEFAULT, &MilBlobResult);
// MblobCalculate(MilBlobContext, outputImage, M_NULL, MilBlobResult);
// MblobSelect(MilBlobResult, M_EXCLUDE, M_AREA, M_LESS, MIN_AREA, M_NULL);
// MblobGetResult(MilBlobResult, M_NUMBER, &blob_count); // 修正:只传 M_NUMBER
// // 获取 detection_result 的尺寸
// MbufInquire(outputImage, M_SIZE_X, &SizeX);
// MbufInquire(outputImage, M_SIZE_Y, &SizeY);
// // 分配一个新的二值图像来存储筛选后的结果
// MbufAlloc2d(MilSystem, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilFiltered);
// // 将 MilFiltered 初始化为 0全黑
// MbufClear(MilFiltered, 0);
// MIL_ID MilGraphicsContext;
// MgraAlloc(MilSystem, &MilGraphicsContext);
// MblobDraw(MilGraphicsContext, MilBlobResult, MilFiltered, M_DRAW_BLOBS, M_INCLUDED_BLOBS, M_DEFAULT);
// // 将筛选后的结果复制回 detection_result
// MbufCopy(MilFiltered, outputImage);
MbufFree(output_lab);
MbufFree(output_hsv);
}
void read_params_from_file(const std::string& filename, std::map<std::string, int>& params) { void read_params_from_file(const std::string& filename, std::map<std::string, int>& params) {
std::ifstream infile(filename); std::ifstream infile(filename);
@ -895,6 +644,33 @@ void read_params_from_file(const std::string& filename, std::map<std::string, in
} }
} }
void read_color(const std::string& filename, std::vector<std::string>& colors) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error: Unable to open file " << filename << std::endl;
return;
}
std::vector<std::string> new_colors;
std::string color;
while (std::getline(file, color)) {
if (!color.empty()) {
new_colors.push_back(color);
}
}
if (!new_colors.empty()) {
colors = std::move(new_colors); // Replace the existing colors
}
else {
std::cerr << "Warning: File is empty or contains no valid data." << std::endl;
}
file.close();
}
std::vector<std::vector<uint8_t>> generateMaskFromImage(const MIL_ID& inputImage, int widthBlocks, int heightBlocks, int thresholds= 10) { std::vector<std::vector<uint8_t>> generateMaskFromImage(const MIL_ID& inputImage, int widthBlocks, int heightBlocks, int thresholds= 10) {
// 读取图像 // 读取图像
// cv::Mat image = cv::imread(imagePath, cv::IMREAD_GRAYSCALE); // cv::Mat image = cv::imread(imagePath, cv::IMREAD_GRAYSCALE);
@ -990,10 +766,48 @@ std::vector<std::vector<uint8_t>> generateMaskFromMatImage(const cv::Mat& image,
return mask; return mask;
} }
void max_valves_together_limit(std::vector<std::vector<uint8_t>> &mask_expaned, const int row_threshold)
{
// 初始化当前回调的1的计数
long long count_ones_this_time = 0;
// 遍历每一行
for(auto & row : mask_expaned)
{
// 计算当前行中1的数量
long long row_count = 0;
for(uint8_t val : row)
{
row_count += (val == 1);
}
// 检查是否超过阈值
if(row_count > row_threshold)
{
// 如果超过阈值将整行置为0
std::fill(row.begin(), row.end(), 0);
g_camera_error.store(true); // 原子赋值为 true
}
else
{
count_ones_this_time += row_count;
g_camera_error.store(false); // 原子赋值为 true
}
}
// 更新全局的1的计数
g_valveActionCount += count_ones_this_time;
// 如果需要调试打印,可以取消注释以下代码
// qDebug() << "This callback1 new triggered bits =" << count_ones_this_time
// << ", total=" << g_valveActionCount;
}
bool iniColor() bool iniColor()
{ {
read_params_from_file((getConfigDirectory()+"/color_range_config.txt").toStdString(), params); // read_params_from_file((getConfigDirectory()+"/color_range_config.txt").toStdString(), params);
// loadConfig(getConfigDirectory()+"/color_range_config.txt");
// read_color((getConfigDirectory()+"/colors.txt").toStdString(), colors);
return 1; return 1;
} }
@ -1048,14 +862,15 @@ bool iniLowMac()
cout << "Error: Lower machine is not available or writable." << endl; cout << "Error: Lower machine is not available or writable." << endl;
return 0 ; return 0 ;
} }
return setLowMacParam();
}
bool setLowMacParam(){
// 计算 Y = 100000000 / X // 计算 Y = 100000000 / X
int divide_camera = (file_encoder != 0) ? 100000000 / file_encoder : 0; // 防止除以零的情况 int divide_camera = (file_encoder != 0) ? 100000000 / file_encoder : 0; // 防止除以零的情况
int divide_valve = (file_valve != 0) ? 100000000 / file_valve : 0; // 防止除以零的情况 int divide_valve = (file_valve != 0) ? 100000000 / file_valve : 0; // 防止除以零的情况
// 将参数转换为长度为8的字符串前面补0 // 将参数转换为长度为8的字符串前面补0
QString delay_time = QString("%1").arg(file_delay, 8, 10, QChar('0')); QString delay_time = QString("%1").arg(file_delay, 8, 10, QChar('0'));
QString divide_parameter = QString("%1").arg(divide_camera, 8, 10, QChar('0')); QString divide_parameter = QString("%1").arg(divide_camera, 8, 10, QChar('0'));
@ -1083,6 +898,7 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)delay_buf, len_delay + 8); lower_machine->write((const char*)delay_buf, len_delay + 8);
qDebug() << "彩色相机延迟时间:" << delay_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for delay parameter." << endl; cout << "Error: Unable to write to lower machine for delay parameter." << endl;
} }
@ -1102,6 +918,7 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)divide_buf, len_divide + 8); lower_machine->write((const char*)divide_buf, len_divide + 8);
qDebug() << "彩色相机分频系数:" << divide_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for encoder parameter." << endl; cout << "Error: Unable to write to lower machine for encoder parameter." << endl;
} }
@ -1119,24 +936,14 @@ bool iniLowMac()
valve_divide_buf[len_sv + 6] = 0xFF; valve_divide_buf[len_sv + 6] = 0xFF;
valve_divide_buf[len_sv + 7] = 0xBB; valve_divide_buf[len_sv + 7] = 0xBB;
qDebug()<<"相机参数"<<divide_byte.data();
qDebug()<<"阀门参数"<<sv_byte.data();
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)valve_divide_buf, len_sv + 8); lower_machine->write((const char*)valve_divide_buf, len_sv + 8);
qDebug() << "阀门分频系数:" << sv_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for valve parameter." << endl; cout << "Error: Unable to write to lower machine for valve parameter." << endl;
} }
delete[] valve_divide_buf; delete[] valve_divide_buf;
// //下位机参数
// int lowmac_dp = 400; //偏振延迟时间
// int lowmac_sm = 5; //吹气量
// int lowmac_ts = 15; //模板匹配阈值
// int lowmac_sg = 80; //偏振绿色通道大小阈值
// int lowmac_td = 10; //偏振红色通道差值
//新增下位机协议
// 将参数转换为长度为8的字符串前面补0 // 将参数转换为长度为8的字符串前面补0
QString dp = QString("%1").arg(lowmac_dp, 8, 10, QChar('0')); QString dp = QString("%1").arg(lowmac_dp, 8, 10, QChar('0'));
QString sm = QString("%1").arg(lowmac_sm, 8, 10, QChar('0')); QString sm = QString("%1").arg(lowmac_sm, 8, 10, QChar('0'));
@ -1156,6 +963,7 @@ bool iniLowMac()
QByteArray sg_byte = sg.toLatin1(); QByteArray sg_byte = sg.toLatin1();
QByteArray td_byte = td.toLatin1(); QByteArray td_byte = td.toLatin1();
//偏振延迟时间
uint8_t* dp_buf = new uint8_t[len_dp + 8]; uint8_t* dp_buf = new uint8_t[len_dp + 8];
dp_buf[0] = 0xAA; dp_buf[0] = 0xAA;
dp_buf[1] = 0x00; dp_buf[1] = 0x00;
@ -1169,11 +977,13 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)dp_buf, len_dp + 8); lower_machine->write((const char*)dp_buf, len_dp + 8);
qDebug() << "偏振延迟时间: " << dp_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for dp parameter." << endl; cout << "Error: Unable to write to lower machine for dp parameter." << endl;
} }
delete[] dp_buf; delete[] dp_buf;
// 吹气量
uint8_t* sm_buf = new uint8_t[len_sm + 8]; uint8_t* sm_buf = new uint8_t[len_sm + 8];
sm_buf[0] = 0xAA; sm_buf[0] = 0xAA;
sm_buf[1] = 0x00; sm_buf[1] = 0x00;
@ -1187,11 +997,13 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)sm_buf, len_sm + 8); lower_machine->write((const char*)sm_buf, len_sm + 8);
qDebug() << "吹气量: " << sm_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for sm parameter." << endl; cout << "Error: Unable to write to lower machine for sm parameter." << endl;
} }
delete[] sm_buf; delete[] sm_buf;
// 模板匹配阈值
uint8_t* ts_buf = new uint8_t[len_ts + 8]; uint8_t* ts_buf = new uint8_t[len_ts + 8];
ts_buf[0] = 0xAA; ts_buf[0] = 0xAA;
ts_buf[1] = 0x00; ts_buf[1] = 0x00;
@ -1205,11 +1017,13 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)ts_buf, len_ts + 8); lower_machine->write((const char*)ts_buf, len_ts + 8);
qDebug() << "模板匹配阈值: " << ts_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for ts parameter." << endl; cout << "Error: Unable to write to lower machine for ts parameter." << endl;
} }
delete[] ts_buf; delete[] ts_buf;
// 偏振绿色通道大小阈值
uint8_t* sg_buf = new uint8_t[len_sg + 8]; uint8_t* sg_buf = new uint8_t[len_sg + 8];
sg_buf[0] = 0xAA; sg_buf[0] = 0xAA;
sg_buf[1] = 0x00; sg_buf[1] = 0x00;
@ -1223,11 +1037,13 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)sg_buf, len_sg + 8); lower_machine->write((const char*)sg_buf, len_sg + 8);
qDebug() << "偏振绿色通道大小阈值: " << sg_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for sg parameter." << endl; cout << "Error: Unable to write to lower machine for sg parameter." << endl;
} }
delete[] sg_buf; delete[] sg_buf;
// 偏振红色通道差值
uint8_t* td_buf = new uint8_t[len_td + 8]; uint8_t* td_buf = new uint8_t[len_td + 8];
td_buf[0] = 0xAA; td_buf[0] = 0xAA;
td_buf[1] = 0x00; td_buf[1] = 0x00;
@ -1241,12 +1057,13 @@ bool iniLowMac()
if (lower_machine->isWritable()) { if (lower_machine->isWritable()) {
lower_machine->write((const char*)td_buf, len_td + 8); lower_machine->write((const char*)td_buf, len_td + 8);
qDebug() << "偏振红色通道差值: " << td_byte.data();
} else { } else {
cout << "Error: Unable to write to lower machine for td parameter." << endl; cout << "Error: Unable to write to lower machine for td parameter." << endl;
} }
delete[] td_buf; delete[] td_buf;
return 1; return true;
} }
bool DestoryLowMac() bool DestoryLowMac()
@ -1365,7 +1182,7 @@ void Start_camera()
if (lower_machine != nullptr && lower_machine->isWritable()) if (lower_machine != nullptr && lower_machine->isWritable())
{ {
lower_machine->write((const char*)start_command, 9); lower_machine->write((const char*)start_command, 9);
qDebug()<<"发送相机参数成功"; qDebug()<<"发送相机启动成功";
} }
else else
{ {

View File

@ -23,6 +23,7 @@
#include <QTcpServer> #include <QTcpServer>
#include "globals.h" #include "globals.h"
#include "img_utils.h" #include "img_utils.h"
#include "color_range.h"
extern MIL_ID MilApplication; extern MIL_ID MilApplication;
extern MIL_ID MilSystem; extern MIL_ID MilSystem;
@ -68,6 +69,8 @@ bool iniOnnx();
void Start_camera(); void Start_camera();
bool setLowMacParam();
bool DestoryCamera(); bool DestoryCamera();
bool DestoryLowMac(); bool DestoryLowMac();
@ -79,26 +82,17 @@ MIL_INT MFTYPE ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void* HookDa
//图像处理 //图像处理
std::vector<int> psLabToOpenCVLab(const std::vector<int>& lab_ps);
std::vector<int> opencvLabToPsLab(const std::vector<int>& lab_cv);
std::unordered_map<std::string, int> loadConfig(const std::string& filename); std::unordered_map<std::string, int> loadConfig(const std::string& filename);
void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map<std::string, int>& params);
void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map<std::string, int>& params);
void lab_process_raw(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map<std::string, int>& params,const std::vector<std::string>& color_vector);
void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map<std::string, int>& params);
#define MIN_AREA 30
extern std::map<std::string, int> params; extern std::map<std::string, int> params;
void read_params_from_file(const std::string& filename, std::map<std::string, int>& params) ; void read_params_from_file(const std::string& filename, std::map<std::string, int>& params) ;
void read_color(const std::string& filename, std::vector<std::string>& colors);
pair<vector<vector<uint8_t>>, vector<vector<uint8_t>>> applyRowRangeDelay( pair<vector<vector<uint8_t>>, vector<vector<uint8_t>>> applyRowRangeDelay(
const vector<vector<uint8_t>>& mask, const vector<vector<uint8_t>>& mask,
const vector<vector<uint8_t>>& tail, const vector<vector<uint8_t>>& tail,
@ -128,4 +122,6 @@ extern bool volatile is_running;
bool get_valve_data(std::vector<std::vector<uint8_t>> mask ); bool get_valve_data(std::vector<std::vector<uint8_t>> mask );
void max_valves_together_limit(std::vector<std::vector<uint8_t>> &mask_expaned, const int row_threshold);
#endif // CAMERA_H #endif // CAMERA_H

View File

@ -15,12 +15,12 @@ blue_b_min = -48
blue_b_max = -8 blue_b_max = -8
# Orange color parameters # Orange color parameters
orange_L_min = 60 orange_L_min = 63
orange_L_max = 60 orange_L_max = 78
orange_a_min = 6 orange_a_min = 7
orange_a_max = 6 orange_a_max = 14
orange_b_min = 20 orange_b_min = 23
orange_b_max = 46 orange_b_max = 47
# Black color parameters # Black color parameters
black_L_min = 0 black_L_min = 0
@ -46,6 +46,14 @@ purple_a_max = 20
purple_b_min = -45 purple_b_min = -45
purple_b_max = 1 purple_b_max = 1
# yellow color parameters
yellow_L_min = 45
yellow_L_max = 56
yellow_a_min = -4
yellow_a_max = 7
yellow_b_min = 20
yellow_b_max = 21
# Other parameters # Other parameters
lab_denoising = 1 lab_denoising = 1
saturation_threshold = 165 saturation_threshold = 165

7
config/colors.txt Normal file
View File

@ -0,0 +1,7 @@
green
blue
orange
black
red
purple
yellow

View File

@ -3,6 +3,7 @@ QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17 CONFIG += c++17
CONFIG += console
# You can make your code fail to compile if it uses deprecated APIs. # You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line. # In order to do so, uncomment the following line.
@ -10,6 +11,8 @@ CONFIG += c++17
SOURCES += \ SOURCES += \
camera.cpp \ camera.cpp \
color_range.cpp \
countdowndialog.cpp \
detectionworker.cpp \ detectionworker.cpp \
globals.cpp \ globals.cpp \
img_utils.cpp \ img_utils.cpp \
@ -20,6 +23,8 @@ SOURCES += \
HEADERS += \ HEADERS += \
camera.h \ camera.h \
color_range.h \
countdowndialog.h \
detectionworker.h \ detectionworker.h \
globals.h \ globals.h \
img_utils.h \ img_utils.h \
@ -44,7 +49,9 @@ LIBS += -L$${PWD}/LIB -lmilblob
LIBS += \ LIBS += \
$${PWD}/opencv410-vs22/x64/vc17/lib/*.lib # $${PWD}/opencv410-vs22/x64/vc17/lib/*.lib
$${PWD}/opencv/build/x64/vc16/lib/*.lib
INCLUDEPATH += \ INCLUDEPATH += \
$${PWD}/opencv410-vs22/include # $${PWD}/opencv410-vs22/include
$${PWD}/opencv/build/include

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 15.0.0, 2024-12-29T01:01:20. --> <!-- Written by QtCreator 15.0.0, 2025-01-04T20:22:11. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

View File

@ -1,4 +1,3 @@
# Green color parameters
green_L_min = 16 green_L_min = 16
green_L_max = 56 green_L_max = 56
green_a_min = -33 green_a_min = -33
@ -6,7 +5,6 @@ green_a_max = -11
green_b_min = -7 green_b_min = -7
green_b_max = 24 green_b_max = 24
# Blue color parameters
blue_L_min = 20 blue_L_min = 20
blue_L_max = 43 blue_L_max = 43
blue_a_min = -13 blue_a_min = -13
@ -14,15 +12,13 @@ blue_a_max = 22
blue_b_min = -48 blue_b_min = -48
blue_b_max = -8 blue_b_max = -8
# Orange color parameters orange_L_min = 63
orange_L_min = 60 orange_L_max = 78
orange_L_max = 60 orange_a_min = 7
orange_a_min = 6 orange_a_max = 14
orange_a_max = 6 orange_b_min = 23
orange_b_min = 20 orange_b_max = 47
orange_b_max = 46
# Black color parameters
black_L_min = 0 black_L_min = 0
black_L_max = 8 black_L_max = 8
black_a_min = -4 black_a_min = -4
@ -30,7 +26,6 @@ black_a_max = 2
black_b_min = -3 black_b_min = -3
black_b_max = 4 black_b_max = 4
# Red color parameters
red_L_min = 23 red_L_min = 23
red_L_max = 48 red_L_max = 48
red_a_min = 12 red_a_min = 12
@ -38,7 +33,6 @@ red_a_max = 55
red_b_min = -80 red_b_min = -80
red_b_max = 37 red_b_max = 37
# Purple color parameters
purple_L_min = 38 purple_L_min = 38
purple_L_max = 54 purple_L_max = 54
purple_a_min = 10 purple_a_min = 10
@ -46,7 +40,20 @@ purple_a_max = 20
purple_b_min = -45 purple_b_min = -45
purple_b_max = 1 purple_b_max = 1
# Other parameters yellow_L_min = 45
yellow_L_max = 56
yellow_a_min = -4
yellow_a_max = 7
yellow_b_min = 20
yellow_b_max = 21
expansionRaidus = 1
file_delay = 1180
lab_denoising = 1 lab_denoising = 1
saturation_threshold = 165 lowmac_dp = 350
lowmac_sg = 70
lowmac_td = 7
lowmac_ts = 10
saturation_denoising = 1 saturation_denoising = 1
saturation_threshold = 165
sizeThreshold = 4

2
dist/license.txt vendored
View File

@ -61,7 +61,7 @@
1. **Software Provided “As Is”** 1. **Software Provided “As Is”**
The Software and any related services are provided on an “as is” basis. The Licensor makes no express or implied warranties regarding the performance, quality, compatibility, or suitability of the Software. The Software and any related services are provided on an “as is” basis. The Licensor makes no express or implied warranties regarding the performance, quality, compatibility, or suitability of the Software.
2. **Assumption of Risk** 2. **Assumption of Risk**
The User understands and agrees that any risks or losses arising from the use of or inability to use the Software are borne by the User. The Licensor shall not be liable for any direct or indirect losses arising therefrom. The User understands and agrees that any risks or losses arising from the use of or inability to use the Software are borne by the User. The Licensor shall not be liable for any direct or indirect losses arising therefrom. And the Licensor shall agree that NC is NC.
--- ---

13
dist/nvcc.profile vendored Normal file
View File

@ -0,0 +1,13 @@
TOP = $(_HERE_)/..
NVVMIR_LIBRARY_DIR = $(TOP)/$(_NVVM_BRANCH_)/libdevice
PATH += $(TOP)/$(_NVVM_BRANCH_)/bin;$(_HERE_);$(TOP)/lib;
INCLUDES += "-I$(TOP)/include" $(_SPACE_)
LIBRARIES =+ $(_SPACE_) "/LIBPATH:$(TOP)/lib/$(_WIN_PLATFORM_)"
CUDAFE_FLAGS +=
PTXAS_FLAGS +=

View File

@ -3,6 +3,7 @@
// camera.cpp 顶部或 globals.cpp 中 // camera.cpp 顶部或 globals.cpp 中
long long g_valveActionCount = 0; long long g_valveActionCount = 0;
std::atomic<bool> g_camera_error(false);
// 初始化图片显示互斥锁和MIL_ID // 初始化图片显示互斥锁和MIL_ID
QMutex gDispPicMutex0; QMutex gDispPicMutex0;
@ -17,6 +18,9 @@ MIL_ID gMask0 = 0;
QMutex gMaskMutex1; QMutex gMaskMutex1;
MIL_ID gMask1 = 0; MIL_ID gMask1 = 0;
//艳丽检测参数
std::map<std::string, int> params;
std::vector<std::string> colors;
// 初始化 CameraData 实例 // 初始化 CameraData 实例
DetectionResult g_detection_result[2]; DetectionResult g_detection_result[2];
@ -40,6 +44,9 @@ std::atomic<bool>* g_recognitionRunning[2] = { nullptr, nullptr };
bool g_dl_enable[2] = { true, true }; bool g_dl_enable[2] = { true, true };
bool g_traditional_enable[2] = { true, true }; bool g_traditional_enable[2] = { true, true };
int sizeThreshold = 4; // 转化为喷阀的每块要求像素个数
int expansionRaidus = 1; // 获取mask后进行左右位置的扩展
// 初始化全局ONNXRunner实例数组 // 初始化全局ONNXRunner实例数组
ONNXRunner* g_runner_array[2] = { nullptr, nullptr }; ONNXRunner* g_runner_array[2] = { nullptr, nullptr };
@ -173,3 +180,6 @@ struct GlobalsInitializer {
} }
} globalsInitializerInstance; // 全局实例,确保在程序结束时清理 } globalsInitializerInstance; // 全局实例,确保在程序结束时清理

View File

@ -16,7 +16,9 @@
#include <atomic> #include <atomic>
#include "onnxrunner.h" #include "onnxrunner.h"
// 计数喷阀次数
extern long long g_valveActionCount; extern long long g_valveActionCount;
extern std::atomic<bool> g_camera_error;
// 图片显示0 // 图片显示0
extern QMutex gDispPicMutex0; extern QMutex gDispPicMutex0;
@ -39,6 +41,9 @@ extern QSemaphore detection_ready;
extern bool g_dl_enable[2]; extern bool g_dl_enable[2];
extern bool g_traditional_enable[2]; extern bool g_traditional_enable[2];
extern int sizeThreshold; // 转化为喷阀的每块要求像素个数
extern int expansionRaidus;
// 获取保存目录和配置目录函数 // 获取保存目录和配置目录函数
QString getSaveDirectory(); QString getSaveDirectory();
QString getConfigDirectory(); QString getConfigDirectory();
@ -143,4 +148,11 @@ extern std::atomic<bool>* g_recognitionRunning[2];
// 定义全局ONNXRunner实例数组 // 定义全局ONNXRunner实例数组
extern ONNXRunner* g_runner_array[2]; extern ONNXRunner* g_runner_array[2];
extern std::map<std::string, int> params;
extern std::vector<std::string> colors;
#define MIN_AREA 30
#endif // GLOBALS_H #endif // GLOBALS_H

View File

@ -282,3 +282,5 @@ void VectorToImg(const std::vector<std::vector<uint8_t> > &array, const std::str
// 将图像保存为文件传入的image_path指定保存路径和文件名 // 将图像保存为文件传入的image_path指定保存路径和文件名
imwrite(image_path, image); imwrite(image_path, image);
} }

View File

@ -68,8 +68,8 @@ cv::dnn::Net ONNXRunner::loadModel(const std::string& modelPath) {
} else { } else {
qDebug() << "成功加载ONNX模型:" << QString::fromStdString(modelPath); qDebug() << "成功加载ONNX模型:" << QString::fromStdString(modelPath);
} }
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // Use CUDA backend // net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // Use CUDA backend
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // Run on GPU // net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // Run on GPU
return net; return net;
} }

View File

@ -1,4 +1,3 @@
# Green color parameters
green_L_min = 16 green_L_min = 16
green_L_max = 56 green_L_max = 56
green_a_min = -33 green_a_min = -33
@ -6,7 +5,6 @@ green_a_max = -11
green_b_min = -7 green_b_min = -7
green_b_max = 24 green_b_max = 24
# Blue color parameters
blue_L_min = 20 blue_L_min = 20
blue_L_max = 43 blue_L_max = 43
blue_a_min = -13 blue_a_min = -13
@ -14,15 +12,13 @@ blue_a_max = 22
blue_b_min = -48 blue_b_min = -48
blue_b_max = -8 blue_b_max = -8
# Orange color parameters orange_L_min = 63
orange_L_min = 60 orange_L_max = 78
orange_L_max = 60 orange_a_min = 7
orange_a_min = 6 orange_a_max = 14
orange_a_max = 6 orange_b_min = 23
orange_b_min = 20 orange_b_max = 47
orange_b_max = 46
# Black color parameters
black_L_min = 0 black_L_min = 0
black_L_max = 8 black_L_max = 8
black_a_min = -4 black_a_min = -4
@ -30,7 +26,6 @@ black_a_max = 2
black_b_min = -3 black_b_min = -3
black_b_max = 4 black_b_max = 4
# Red color parameters
red_L_min = 23 red_L_min = 23
red_L_max = 48 red_L_max = 48
red_a_min = 12 red_a_min = 12
@ -38,7 +33,6 @@ red_a_max = 55
red_b_min = -80 red_b_min = -80
red_b_max = 37 red_b_max = 37
# Purple color parameters
purple_L_min = 38 purple_L_min = 38
purple_L_max = 54 purple_L_max = 54
purple_a_min = 10 purple_a_min = 10
@ -46,7 +40,23 @@ purple_a_max = 20
purple_b_min = -45 purple_b_min = -45
purple_b_max = 1 purple_b_max = 1
# Other parameters yellow_L_min = 45
yellow_L_max = 56
yellow_a_min = -4
yellow_a_max = 7
yellow_b_min = 20
yellow_b_max = 21
expansionRaidus = 1
file_delay = 1180
lab_denoising = 1 lab_denoising = 1
saturation_threshold = 165 lowmac_dp = 350
lowmac_sg = 70
lowmac_sm = 1200
lowmac_td = 7
lowmac_ts = 10
machine_num = 0
max_valves_together = 20
saturation_denoising = 1 saturation_denoising = 1
saturation_threshold = 165
sizeThreshold = 4

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,14 @@
#include <QTabBar> #include <QTabBar>
#include <img_utils.h> #include <img_utils.h>
#include <detectionworker.h> #include <detectionworker.h>
#include <Qstring>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <algorithm>
#include <cctype>
#include <warning.h>
#include <QMessageBox>
using namespace std; using namespace std;
@ -30,6 +38,7 @@ int lowmac_sm = 1200; //吹气量 valve/12 = 吹气时间ms
int lowmac_ts = 10; //模板匹配阈值 int lowmac_ts = 10; //模板匹配阈值
int lowmac_sg = 65; //偏振绿色通道大小阈值 int lowmac_sg = 65; //偏振绿色通道大小阈值
int lowmac_td = 7; //偏振红色通道差值 int lowmac_td = 7; //偏振红色通道差值
Widget::Widget(QWidget *parent) Widget::Widget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::Widget) , ui(new Ui::Widget)
@ -54,10 +63,13 @@ Widget::Widget(QWidget *parent)
ui->camera_1_img->setScaledContents(false); ui->camera_1_img->setScaledContents(false);
iniOnnx(); iniOnnx();
iniColor(); // iniColor();
loadConfig(getConfigDirectory()+"/color_range_config.txt"); // 读取配置文件
iniLowMac(); iniLowMac();
iniCamera(); iniCamera();
update_machine_num();
update_colorlist(); // 更新色彩列表
update_polar(); // 更新偏振相机界面
// 初始化存储工作者和线程 // 初始化存储工作者和线程
storageWorker = new StorageWorker(); storageWorker = new StorageWorker();
storageWorker->moveToThread(&storageThread); storageWorker->moveToThread(&storageThread);
@ -71,9 +83,41 @@ Widget::Widget(QWidget *parent)
// 启动显示定时器,每秒检查一次 // 启动显示定时器,每秒检查一次
QTimer* timer = new QTimer(this); QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Widget::refreshImage); connect(timer, &QTimer::timeout, this, &Widget::refreshImage);
timer->start(40); // 每50毫秒秒刷新一次界面 timer->start(40); // 每40毫秒秒刷新一次界面
ui->tabWidget->setCurrentIndex(1); ui->tabWidget->setCurrentIndex(1);
// on_btn_start_clicked();
// 显示启动倒计时
showStartupCountdown();
}
void Widget::showStartupCountdown()
{
CountdownDialog* countdown = new CountdownDialog(10, this);
countdown->setAttribute(Qt::WA_DeleteOnClose); // 对话框关闭后自动删除
// 连接倒计时完成信号
connect(countdown, &CountdownDialog::countdownFinished, this, &Widget::onCountdownFinished);
// 连接对话框的关闭事件,以处理用户提前关闭
connect(countdown, &QDialog::rejected, this, &Widget::onCountdownCancelled);
countdown->show(); // 非模态显示,允许用户在倒计时期间与主窗口交互
}
void Widget::onCountdownCancelled()
{
qDebug() << "用户取消了启动倒计时。";
// 根据需求处理取消后的操作,例如不启动识别任务
// 可以选择什么都不做,或者提供提示
}
void Widget::onCountdownFinished()
{
qDebug() << "启动倒计时结束,继续执行开机操作。";
on_btn_start_clicked();
} }
Widget::~Widget() Widget::~Widget()
@ -106,6 +150,17 @@ void Widget::refreshImage()
this->ui->tra_enable_0->setEnabled(!this->isCamRunning); this->ui->tra_enable_0->setEnabled(!this->isCamRunning);
this->ui->tra_enable_1->setEnabled(!this->isCamRunning); this->ui->tra_enable_1->setEnabled(!this->isCamRunning);
this->ui->btn_quit->setEnabled(!this->isCamRunning); this->ui->btn_quit->setEnabled(!this->isCamRunning);
// refresh settings buttons
this->ui->btn_setColor->setEnabled(!this->isCamRunning);
this->ui->btn_reset_color->setEnabled(!this->isCamRunning);
this->ui->btn_del_color->setEnabled(!this->isCamRunning);
this->ui->btn_add_color->setEnabled(!this->isCamRunning);
this->ui->btn_reset_polar->setEnabled(!this->isCamRunning);
this->ui->btn_save_polar->setEnabled(!this->isCamRunning);
this->ui->btn_set_lower->setEnabled(!this->isCamRunning);
// //
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTime();
ui->label_currentDateTime->setText(now.toString("yyyy-MM-dd hh:mm:ss")); ui->label_currentDateTime->setText(now.toString("yyyy-MM-dd hh:mm:ss"));
@ -149,7 +204,11 @@ void Widget::refreshImage()
} }
else else
{ {
info = "运行"; if(g_camera_error.load()){
info = "图像问题!!!";
} else {
info = "运行";
}
}; };
}else { }else {
info = "停止"; info = "停止";
@ -329,6 +388,8 @@ void Widget::on_btn_stop_clicked()
void Widget::on_btn_start_clicked() void Widget::on_btn_start_clicked()
{ {
// 设置相机参数
setLowMacParam();
g_dl_enable[0] = !this->ui->dl_enable_0->isChecked(); g_dl_enable[0] = !this->ui->dl_enable_0->isChecked();
g_dl_enable[1] = !this->ui->dl_enable_0->isChecked(); g_dl_enable[1] = !this->ui->dl_enable_0->isChecked();
g_traditional_enable[0] = !this->ui->tra_enable_0->isChecked(); g_traditional_enable[0] = !this->ui->tra_enable_0->isChecked();
@ -350,17 +411,12 @@ void Widget::on_btn_start_clicked()
HANDLE hThread = static_cast<HANDLE>(g_recognitionThread[i]->native_handle()); HANDLE hThread = static_cast<HANDLE>(g_recognitionThread[i]->native_handle());
// 设置线程优先级为最高 // 设置线程优先级为最高
if(SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST)) if(!SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST))
{
std::cout << "DL Thread " << i << " set highest thread priority。" << std::endl;
}
else
{ {
std::cerr << "SET thread " << i << " failed, error code" << GetLastError() << std::endl; std::cerr << "SET thread " << i << " failed, error code" << GetLastError() << std::endl;
} }
} }
Start_camera(); Start_camera();
} }
@ -413,11 +469,23 @@ void Widget::on_btn_quit_clicked()
void Widget::on_btn_set_lower_clicked() void Widget::on_btn_set_lower_clicked()
{ {
// 硬编码参数值 // 硬编码参数值
file_delay = ui->spinbox_delaytime->text().toInt(); // 延迟时间(毫秒) lowmac_sm = ui->spinbox_maintime->value();
params["lowmac_sm"]=lowmac_sm;
params["machine_num"] = ui->spinbox_machine_code->value();
params["max_valves_together"] = ui->spinbox_max_valves_together->value();
saveConfig(getConfigDirectory()+"/color_range_config.txt", params, colors);
// 两个过去的参量不支持读取配置文件
file_encoder = ui->spinbox_encoder->text().toInt(); // 编码器值++ file_encoder = ui->spinbox_encoder->text().toInt(); // 编码器值++
file_valve = ui->spinbox_valve->text().toInt(); // 阀门通道 file_valve = ui->spinbox_valve->text().toInt(); // 阀门通道
} }
void Widget::update_machine_num()
{
ui->lab_machine_num->setText(QString("%1号机").arg(params["machine_num"]));
ui->spinbox_machine_code->setValue(params["machine_num"]);
ui->spinbox_maintime->setValue(params["lowmac_sm"]);
}
void Widget::on_btn_set_valve_clicked() void Widget::on_btn_set_valve_clicked()
{ {
@ -439,7 +507,7 @@ void Widget::on_btn_live_clicked()
void Widget::on_btn_tab3_backtab2_2_clicked() void Widget::on_btn_tab3_backtab2_2_clicked()
{ {
ui->tabWidget->setCurrentIndex(3); ui->tabWidget->setCurrentIndex(5);
} }
@ -448,3 +516,530 @@ void Widget::on_btn_settings_clicked()
ui->tabWidget->setCurrentIndex(2); ui->tabWidget->setCurrentIndex(2);
} }
bool Widget::saveConfig(const QString &filePath, const std::map<std::string, int>& params_to_set, const std::vector<std::string>& color_vector_to_set)
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
qWarning() << "无法打开配置文件进行写入:" << filePath;
return false;
}
QTextStream out(&file);
// Qt 6 默认使用 UTF-8 编码,无需设置编码
// 保存每种颜色的参数
for (const auto &color : color_vector_to_set)
{
std::string color_lower = color;
// 将颜色名称首字母小写以匹配键名
if (!color_lower.empty())
{
color_lower[0] = static_cast<char>(std::tolower(color_lower[0]));
}
try {
// 使用 at() 方法访问元素
out << QString::fromStdString(color_lower) << "_L_min = " << QString::number(params_to_set.at(color_lower + "_L_min")) << "\n";
out << QString::fromStdString(color_lower) << "_L_max = " << QString::number(params_to_set.at(color_lower + "_L_max")) << "\n";
out << QString::fromStdString(color_lower) << "_a_min = " << QString::number(params_to_set.at(color_lower + "_a_min")) << "\n";
out << QString::fromStdString(color_lower) << "_a_max = " << QString::number(params_to_set.at(color_lower + "_a_max")) << "\n";
out << QString::fromStdString(color_lower) << "_b_min = " << QString::number(params_to_set.at(color_lower + "_b_min")) << "\n";
out << QString::fromStdString(color_lower) << "_b_max = " << QString::number(params_to_set.at(color_lower + "_b_max")) << "\n\n";
}
catch (const std::out_of_range& e) {
qWarning() << "缺少参数:" << QString::fromStdString(color_lower + "_L_min") << "等在颜色" << QString::fromStdString(color_lower);
// 根据需要,您可以决定如何处理缺少的参数,例如设置默认值或跳过
continue;
}
}
// 保存其他参数(不涉及颜色参数)
for (const auto &param : params_to_set)
{
std::string key = param.first;
// 如果不是颜色参数,则保存
if (key.find("_L_min") == std::string::npos &&
key.find("_L_max") == std::string::npos &&
key.find("_a_min") == std::string::npos &&
key.find("_a_max") == std::string::npos &&
key.find("_b_min") == std::string::npos &&
key.find("_b_max") == std::string::npos)
{
out << QString::fromStdString(key) << " = " << QString::number(param.second) << "\n";
}
}
file.close();
qDebug() << "配置已成功保存到" << filePath;
return true;
}
bool Widget::loadConfig(const QString &filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qWarning() << "无法打开配置文件进行读取:" << filePath;
return false;
}
QTextStream in(&file);
// Qt 6 默认使用 UTF-8 编码,无需设置编码
// 清空当前配置
colors.clear();
params.clear();
while (!in.atEnd())
{
QString line = in.readLine().trimmed();
// 跳过空行和注释行
if (line.isEmpty() || line.startsWith("#"))
continue;
// 处理键值对
QStringList keyValue = line.split("=");
if (keyValue.size() != 2)
continue; // 无效行
QString key = keyValue[0].trimmed();
QString valueStr = keyValue[1].trimmed();
bool ok;
int value = valueStr.toInt(&ok);
if (!ok)
{
qWarning() << "无效的数值:" << valueStr << "在行:" << line;
continue;
}
std::string key_std = key.toStdString();
params[key_std] = value;
// 检查是否为颜色参数(格式为 color_property例如 green_L_min
size_t underscorePos = key_std.find('_');
if (underscorePos != std::string::npos)
{
std::string colorName = key_std.substr(0, underscorePos);
size_t second_underscore = key_std.find('_', underscorePos + 1);
if (second_underscore != std::string::npos)
{
// 提取第二个部分,例如 "L"、"a"、"b"
std::string param_type = key_std.substr(underscorePos + 1, second_underscore - underscorePos - 1);
// 过滤不需要的参数类型
if ((param_type != "L") && (param_type != "a") && (param_type != "b"))
continue;
// 避免重复添加颜色
if (std::find(colors.begin(), colors.end(), colorName) == colors.end())
{
colors.push_back(colorName);
}
}
}
}
file.close();
lowmac_dp = params["lowmac_dp"]; //偏振延迟时间
lowmac_ts = params["lowmac_ts"]; //模板匹配阈值
lowmac_sg = params["lowmac_sg"]; //偏振绿色通道大小阈值
lowmac_td = params["lowmac_td"]; //偏振红色通道差值
file_delay = params["file_delay"]; // 延迟时间
expansionRaidus = params["expansionRaidus"]; // 扩展半径
sizeThreshold = params["sizeThreshold"]; // 大小过滤
qDebug() << "配置已成功从" << filePath << "加载";
// qDebug()<<colors;
return true;
}
void Widget::initDefaultConfig()
{
// 定义默认颜色和参数
colors = {"green", "blue", "orange", "black", "red", "purple", "yellow"};
params = {
// Green
{"green_L_min", 16}, {"green_L_max", 56},
{"green_a_min", -33}, {"green_a_max", -11},
{"green_b_min", -7}, {"green_b_max", 24},
// Blue
{"blue_L_min", 20}, {"blue_L_max", 43},
{"blue_a_min", -13}, {"blue_a_max", 22},
{"blue_b_min", -48}, {"blue_b_max", -8},
// Orange
{"orange_L_min", 63}, {"orange_L_max", 78},
{"orange_a_min", 7}, {"orange_a_max", 14},
{"orange_b_min", 23}, {"orange_b_max", 47},
// Black
{"black_L_min", 0}, {"black_L_max", 8},
{"black_a_min", -4}, {"black_a_max", 2},
{"black_b_min", -3}, {"black_b_max", 4},
// Red
{"red_L_min", 23}, {"red_L_max", 48},
{"red_a_min", 12}, {"red_a_max", 55},
{"red_b_min", -80}, {"red_b_max", 37},
// Purple
{"purple_L_min", 38}, {"purple_L_max", 54},
{"purple_a_min", 10}, {"purple_a_max", 20},
{"purple_b_min", -45}, {"purple_b_max", 1},
// Yellow
{"yellow_L_min", 45}, {"yellow_L_max", 56},
{"yellow_a_min", -4}, {"yellow_a_max", 7},
{"yellow_b_min", 20}, {"yellow_b_max", 21},
// Other parameters
{"lab_denoising", 1},
{"saturation_threshold", 165},
{"saturation_denoising", 1},
{"lowmac_sg",lowmac_sg},
{"lowmac_td",lowmac_td},
{"lowmac_ts",lowmac_ts},
{"lowmac_dp",lowmac_dp},
{"lowmac_sm", lowmac_sm},
{"machine_num", params["machine_num"]},
{"max_valves_together", params["max_valves_together"]},
{"sizeThreshold",4},
{"file_delay",1180},
{"expansionRaidus",1}
};
}
void Widget::on_btn_setColor_clicked()
{
std::string current_color=ui->comboBox_colorlist->currentText().toLocal8Bit().constData();
if (!(std::find(colors.begin(), colors.end(), current_color) != colors.end()))
return;
// 设置当前色彩
params[current_color+"_L_min"]=ui->spinBox_L_min->value();
params[current_color+"_L_max"]=ui->spinBox_L_max->value();
params[current_color+"_a_min"]=ui->spinBox_A_min->value();
params[current_color+"_a_max"]=ui->spinBox_A_max->value();
params[current_color+"_b_min"]=ui->spinBox_B_min->value();
params[current_color+"_b_max"]=ui->spinBox_B_max->value();
// 准备写入本地
params["file_delay"]=ui->spinbox_delaytime->value();
params["saturation_threshold"]=ui->spb_saturation->value(); // 这个参数会通过params直接被调用无需赋值给其他全局变量
params["sizeThreshold"]=ui->spinbox_msize_color->value();
params["expansionRaidus"]=ui->spb_expandsize->value();
// 写入内存进行使用
file_delay = params["file_delay"];
sizeThreshold = params["sizeThreshold"];
expansionRaidus = params["expansionRaidus"];
// 存入本地
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
}
void Widget::update_colorlist()
{
ui->comboBox_colorlist->clear();
for(auto color :colors)
{
ui->comboBox_colorlist->addItem(QString::fromStdString(color));
}
}
void Widget::on_comboBox_colorlist_currentIndexChanged(int index)
{
std::string current_color=ui->comboBox_colorlist->currentText().toLocal8Bit().constData();
if (!(std::find(colors.begin(), colors.end(), current_color) != colors.end()))
return;
int l_min = params[current_color+"_L_min"];
int l_max = params[current_color+"_L_max"];
int a_min = params[current_color+"_a_min"];
int a_max = params[current_color+"_a_max"];
int b_min = params[current_color+"_b_min"];
int b_max = params[current_color+"_b_max"];
ui->spinBox_L_max->setValue(l_max);
ui->spinBox_L_min->setValue(l_min);
ui->spinBox_A_max->setValue(a_max);
ui->spinBox_A_min->setValue(a_min);
ui->spinBox_B_max->setValue(b_max);
ui->spinBox_B_min->setValue(b_min);
}
void Widget::on_btn_add_color_clicked()
{
std::string current_color=ui->lineEdit_color->text().toLocal8Bit().constData();
// 空不添加
if(current_color== "")
{
QMessageBox::warning(this, "什么颜色?", "这名字起的不雅");
return;
}
// 必须跟之前所有颜色都不一致
if (!(std::find(colors.begin(), colors.end(), current_color) != colors.end()))
{
colors.push_back(current_color);
}
else
{
QMessageBox::warning(this, "已有名字", "这名字跟别的色撞了");
return;
}
// 存盘刷界面
params[current_color+"_L_min"]=ui->spinBox_L_min->value();
params[current_color+"_L_max"]=ui->spinBox_L_max->value();
params[current_color+"_a_min"]=ui->spinBox_A_min->value();
params[current_color+"_a_max"]=ui->spinBox_A_max->value();
params[current_color+"_b_min"]=ui->spinBox_B_min->value();
params[current_color+"_b_max"]=ui->spinBox_B_max->value();
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
update_colorlist();
ui->lineEdit_color->clear();
}
void Widget::on_btn_del_color_clicked()
{
// 获取当前选中的颜色文本
QString currentColorQStr = ui->comboBox_colorlist->currentText();
if (currentColorQStr.isEmpty())
{
QMessageBox::warning(this, "删除颜色", "当前没有选中的颜色。");
return;
}
std::string currentColor = currentColorQStr.toStdString();
std::string color_lower = currentColor;
if (!color_lower.empty())
{
color_lower[0] = static_cast<char>(std::tolower(color_lower[0]));
}
// 确认删除
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "删除颜色",
QString("确定要删除颜色 '%1' 吗?").arg(currentColorQStr),
QMessageBox::Yes | QMessageBox::No);
if (reply != QMessageBox::Yes)
return;
// 查找颜色在 colors 向量中的位置
auto it = std::find(colors.begin(), colors.end(), currentColor);
if (it != colors.end())
{
// 计算索引
size_t index = std::distance(colors.begin(), it);
// 从 colors 向量中删除
colors.erase(it);
// 从 params 映射中删除相关参数
params.erase(color_lower + "_L_min");
params.erase(color_lower + "_L_max");
params.erase(color_lower + "_a_min");
params.erase(color_lower + "_a_max");
params.erase(color_lower + "_b_min");
params.erase(color_lower + "_b_max");
// 更新配置文件
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
// 更新 UI
update_colorlist();
// 如果还有颜色,选择被删除颜色后的第一个颜色
if (!colors.empty())
{
if (index >= colors.size())
index = colors.size() - 1;
ui->comboBox_colorlist->setCurrentIndex(static_cast<int>(index));
}
else
{
// 如果没有颜色,重置所有 spinBox
ui->spinBox_L_min->setValue(0);
ui->spinBox_L_max->setValue(0);
ui->spinBox_A_min->setValue(0);
ui->spinBox_A_max->setValue(0);
ui->spinBox_B_min->setValue(0);
ui->spinBox_B_max->setValue(0);
}
QMessageBox::information(this, "删除颜色", QString("颜色 '%1' 已成功删除。").arg(currentColorQStr));
}
else
{
QMessageBox::warning(this, "删除颜色", "未找到选中的颜色。");
}
}
void Widget::on_btn_reset_color_clicked()
{
// 新增全部还原槽
// 确认重置
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "全部还原", "确定要将配置还原为默认设置吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply != QMessageBox::Yes)
return;
// 初始化默认配置
initDefaultConfig();
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
// 更新 UI
update_colorlist();
// 选择第一个颜色(如果有)
if (!colors.empty())
{
ui->comboBox_colorlist->setCurrentIndex(0);
}
else
{
// 如果没有颜色,重置所有 spinBox
ui->spinBox_L_min->setValue(0);
ui->spinBox_L_max->setValue(0);
ui->spinBox_A_min->setValue(0);
ui->spinBox_A_max->setValue(0);
ui->spinBox_B_min->setValue(0);
ui->spinBox_B_max->setValue(0);
}
QMessageBox::information(this, "全部还原", "配置已成功还原为默认设置。");
}
void Widget::on_btn_tab_color_clicked()
{
ui->tabWidget->setCurrentIndex(3);
}
void Widget::on_btn_tab3_backtab2_3_clicked()
{
ui->tabWidget->setCurrentIndex(5);
}
void Widget::on_btn_tab3_backtab2_5_clicked()
{
ui->tabWidget->setCurrentIndex(1);
}
void Widget::on_btn_tab_color_2_clicked()
{
ui->tabWidget->setCurrentIndex(3);
}
void Widget::on_btn_tab3_backtab2_6_clicked()
{
ui->tabWidget->setCurrentIndex(4);
}
void Widget::on_btn_tab3_backtab2_7_clicked()
{
ui->tabWidget->setCurrentIndex(5);
}
void Widget::on_btn_tab3_backtab2_8_clicked()
{
ui->tabWidget->setCurrentIndex(1);
}
void Widget::on_btn_tab_color_3_clicked()
{
ui->tabWidget->setCurrentIndex(3);
}
void Widget::on_btn_tab3_backtab2_9_clicked()
{
ui->tabWidget->setCurrentIndex(4);
}
void Widget::on_btn_tab3_backtab2_4_clicked()
{
ui->tabWidget->setCurrentIndex(4);
}
void Widget::on_btn_save_polar_clicked()
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确定保存", "确定要将偏振配置保存吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply != QMessageBox::Yes)
return;
params["lowmac_td"]=ui->spb_diff->value();
params["lowmac_sg"]=ui->spb_green->value();
params["lowmac_dp"]=ui->spb_delay_polar->value();
params["lowmac_ts"]=ui->spb_msize_polar->value();
lowmac_dp = params["lowmac_dp"]; //偏振延迟时间
lowmac_ts = params["lowmac_ts"]; //模板匹配阈值
lowmac_sg = params["lowmac_sg"]; //偏振绿色通道大小阈值
lowmac_td = params["lowmac_td"]; //偏振红色通道差值
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
}
void Widget::on_btn_reset_polar_clicked()
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确定重置", "确定要将偏振部分配置重置吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply != QMessageBox::Yes)
return;
params["lowmac_td"]= 7;
params["lowmac_sg"]= 65;
params["lowmac_dp"]= 350;
params["lowmac_ts"]= 10;
lowmac_dp = params["lowmac_dp"]; //偏振延迟时间
lowmac_ts = params["lowmac_ts"]; //模板匹配阈值
lowmac_sg = params["lowmac_sg"]; //偏振绿色通道大小阈值
lowmac_td = params["lowmac_td"]; //偏振红色通道差值
saveConfig(getConfigDirectory()+"/color_range_config.txt",params,colors);
update_polar();
}
void Widget::update_polar()
{
ui->spb_green->setValue(lowmac_sg);
ui->spb_diff->setValue(lowmac_td);
ui->spb_delay_polar->setValue(lowmac_dp);
ui->spb_msize_polar->setValue(lowmac_ts);
}
void Widget::on_tabWidget_currentChanged(int index)
{
update_machine_num();
update_colorlist(); // 更新色彩列表
update_polar(); // 更新偏振相机界面
}

View File

@ -8,6 +8,7 @@
#include <QPushButton> #include <QPushButton>
#include "globals.h" #include "globals.h"
#include "storageworker.h" #include "storageworker.h"
#include "countdowndialog.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { namespace Ui {
@ -28,6 +29,10 @@ public slots:
private slots: private slots:
void onCountdownFinished();
void onCountdownCancelled();
void refreshSingleImage(int camera_id, bool overlay_traditional_result = false, bool overlay_dl_result = false, bool mirror = false); void refreshSingleImage(int camera_id, bool overlay_traditional_result = false, bool overlay_dl_result = false, bool mirror = false);
void on_pushButton_2_clicked(); void on_pushButton_2_clicked();
@ -54,6 +59,54 @@ private slots:
void on_btn_settings_clicked(); void on_btn_settings_clicked();
void on_btn_setColor_clicked();
void update_colorlist();
void on_comboBox_colorlist_currentIndexChanged(int index);
bool loadConfig(const QString &filePath);
bool saveConfig(const QString &filePath, const std::map<std::string, int>& params_to_set,const std::vector<std::string>& color_vector_to_set);
void initDefaultConfig();
void on_btn_add_color_clicked();
void on_btn_del_color_clicked();
void on_btn_reset_color_clicked();
void on_btn_tab_color_clicked();
void on_btn_tab3_backtab2_3_clicked();
void on_btn_tab3_backtab2_5_clicked();
void on_btn_tab_color_2_clicked();
void on_btn_tab3_backtab2_6_clicked();
void on_btn_tab3_backtab2_7_clicked();
void on_btn_tab3_backtab2_8_clicked();
void on_btn_tab_color_3_clicked();
void on_btn_tab3_backtab2_9_clicked();
void on_btn_tab3_backtab2_4_clicked();
void on_btn_save_polar_clicked();
void on_btn_reset_polar_clicked();
void update_polar();
void update_machine_num();
void on_tabWidget_currentChanged(int index);
private: private:
Ui::Widget *ui; Ui::Widget *ui;
@ -64,5 +117,7 @@ private:
QThread storageThread; // 存储线程 QThread storageThread; // 存储线程
StorageWorker* storageWorker; // 存储工作者 StorageWorker* storageWorker; // 存储工作者
void showStartupCountdown();
}; };
#endif // WIDGET_H #endif // WIDGET_H

4314
widget.ui

File diff suppressed because it is too large Load Diff