Compare commits
3 Commits
eeee1a2252
...
1ba0432ad2
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ba0432ad2 | |||
| 9394384cd8 | |||
| 5daf7b6bf2 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,3 +12,5 @@ Makefile.*
|
||||
*.qm
|
||||
*.onnx
|
||||
*.bmp
|
||||
opencv*
|
||||
opencv
|
||||
|
||||
10
Makefile
10
Makefile
@ -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\exclusive_builds_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\precompile_header.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\qmake_use.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\exceptions.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\Qt6Network.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\lib\Qt6Widgetsd.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\Qt6Cored.prl \
|
||||
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPointd.prl
|
||||
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6Cored.prl
|
||||
$(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\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\exclusive_builds_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\precompile_header.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\qmake_use.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\exceptions.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\Qt6Network.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\lib\Qt6Widgetsd.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\Qt6Cored.prl:
|
||||
..\..\..\..\Qt\6.7.3\msvc2022_64\lib\Qt6EntryPointd.prl:
|
||||
qmake: FORCE
|
||||
@$(QMAKE) -o Makefile cotton_double2.pro -spec win32-msvc "CONFIG+=qtquickcompiler"
|
||||
|
||||
|
||||
3111
Makefile.Debug
3111
Makefile.Debug
File diff suppressed because one or more lines are too long
3111
Makefile.Release
3111
Makefile.Release
File diff suppressed because one or more lines are too long
375
camera.cpp
375
camera.cpp
@ -41,12 +41,9 @@ int SaveImg_Flag;
|
||||
ONNXRunner runner;
|
||||
|
||||
|
||||
std::map<std::string, int> params;
|
||||
int dual_cam_offset_y = 0; // 双相机之间的上下偏移值
|
||||
int widthBlocks = 20; // 输出的喷阀通道数
|
||||
int heightBlocks = 512; // 输出的Mask高度
|
||||
int sizeThreshold = 4; // 转化为喷阀的每块要求像素个数
|
||||
int expansionRaidus = 1; // 获取mask后进行左右位置的扩展
|
||||
int padLeft = 1; // 左侧在结果Mask上补0
|
||||
int padRight = 1; // 右侧在结果Mask上补0
|
||||
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};
|
||||
|
||||
extern int file_delay;
|
||||
// 总体参数
|
||||
extern int lowmac_sm; //吹气量
|
||||
extern int file_encoder;
|
||||
extern int file_valve;
|
||||
|
||||
//下位机参数
|
||||
// 颜色模块参数
|
||||
extern int sizeThreshold; // 转化为喷阀的每块要求像素个数
|
||||
extern int expansionRaidus; // 获取mask后进行左右位置的扩展
|
||||
extern int file_delay;
|
||||
|
||||
// 偏振模块参数
|
||||
extern int lowmac_dp; //偏振延迟时间
|
||||
extern int lowmac_sm; //吹气量
|
||||
extern int lowmac_ts; //模板匹配阈值
|
||||
extern int lowmac_sg; //偏振绿色通道大小阈值
|
||||
extern int lowmac_td; //偏振红色通道差值
|
||||
@ -221,7 +223,7 @@ MIL_INT ProcessingFunction0(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
|
||||
// 使用 std::async 将 high_sat_detect 封装为异步任务
|
||||
auto future = std::async(std::launch::async, [&]() {
|
||||
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);
|
||||
MbufFree(detection_result_id);
|
||||
});
|
||||
@ -391,7 +393,7 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
|
||||
// 使用 std::async 将 high_sat_detect 封装为异步任务
|
||||
auto future = std::async(std::launch::async, [&]() {
|
||||
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);
|
||||
MbufFree(detection_result_id);
|
||||
});
|
||||
@ -548,22 +550,8 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
|
||||
// 将结果的左右补充上0,让物体大小符合要求
|
||||
PadColumns(mask_expaned, padLeft, padRight, 0);
|
||||
|
||||
// ======= 新增:统计 mask_expaned 里的 1 的总个数,并累加到全局变量 =======
|
||||
{
|
||||
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;
|
||||
}
|
||||
// ======= 新增结束 =======
|
||||
max_valves_together_limit(mask_expaned, params["max_valves_together"]);
|
||||
|
||||
//将mask扩展到合适发送的大小
|
||||
std::vector<std::vector<uint8_t>> mask_Total = expandArray(mask_expaned,64);
|
||||
|
||||
@ -612,245 +600,6 @@ bool DestoryCamera()
|
||||
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) {
|
||||
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) {
|
||||
// 读取图像
|
||||
// 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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1048,14 +862,15 @@ bool iniLowMac()
|
||||
cout << "Error: Lower machine is not available or writable." << endl;
|
||||
return 0 ;
|
||||
}
|
||||
return setLowMacParam();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool setLowMacParam(){
|
||||
// 计算 Y = 100000000 / X
|
||||
int divide_camera = (file_encoder != 0) ? 100000000 / file_encoder : 0; // 防止除以零的情况
|
||||
int divide_valve = (file_valve != 0) ? 100000000 / file_valve : 0; // 防止除以零的情况
|
||||
|
||||
|
||||
// 将参数转换为长度为8的字符串,前面补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'));
|
||||
@ -1083,6 +898,7 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)delay_buf, len_delay + 8);
|
||||
qDebug() << "彩色相机延迟时间:" << delay_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for delay parameter." << endl;
|
||||
}
|
||||
@ -1102,6 +918,7 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)divide_buf, len_divide + 8);
|
||||
qDebug() << "彩色相机分频系数:" << divide_byte.data();
|
||||
} else {
|
||||
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 + 7] = 0xBB;
|
||||
|
||||
qDebug()<<"相机参数"<<divide_byte.data();
|
||||
qDebug()<<"阀门参数"<<sv_byte.data();
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)valve_divide_buf, len_sv + 8);
|
||||
qDebug() << "阀门分频系数:" << sv_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for valve parameter." << endl;
|
||||
}
|
||||
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
|
||||
QString dp = QString("%1").arg(lowmac_dp, 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 td_byte = td.toLatin1();
|
||||
|
||||
//偏振延迟时间
|
||||
uint8_t* dp_buf = new uint8_t[len_dp + 8];
|
||||
dp_buf[0] = 0xAA;
|
||||
dp_buf[1] = 0x00;
|
||||
@ -1169,11 +977,13 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)dp_buf, len_dp + 8);
|
||||
qDebug() << "偏振延迟时间: " << dp_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for dp parameter." << endl;
|
||||
}
|
||||
delete[] dp_buf;
|
||||
|
||||
// 吹气量
|
||||
uint8_t* sm_buf = new uint8_t[len_sm + 8];
|
||||
sm_buf[0] = 0xAA;
|
||||
sm_buf[1] = 0x00;
|
||||
@ -1187,11 +997,13 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)sm_buf, len_sm + 8);
|
||||
qDebug() << "吹气量: " << sm_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for sm parameter." << endl;
|
||||
}
|
||||
delete[] sm_buf;
|
||||
|
||||
// 模板匹配阈值
|
||||
uint8_t* ts_buf = new uint8_t[len_ts + 8];
|
||||
ts_buf[0] = 0xAA;
|
||||
ts_buf[1] = 0x00;
|
||||
@ -1205,11 +1017,13 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)ts_buf, len_ts + 8);
|
||||
qDebug() << "模板匹配阈值: " << ts_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for ts parameter." << endl;
|
||||
}
|
||||
delete[] ts_buf;
|
||||
|
||||
// 偏振绿色通道大小阈值
|
||||
uint8_t* sg_buf = new uint8_t[len_sg + 8];
|
||||
sg_buf[0] = 0xAA;
|
||||
sg_buf[1] = 0x00;
|
||||
@ -1223,11 +1037,13 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)sg_buf, len_sg + 8);
|
||||
qDebug() << "偏振绿色通道大小阈值: " << sg_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for sg parameter." << endl;
|
||||
}
|
||||
delete[] sg_buf;
|
||||
|
||||
// 偏振红色通道差值
|
||||
uint8_t* td_buf = new uint8_t[len_td + 8];
|
||||
td_buf[0] = 0xAA;
|
||||
td_buf[1] = 0x00;
|
||||
@ -1241,12 +1057,13 @@ bool iniLowMac()
|
||||
|
||||
if (lower_machine->isWritable()) {
|
||||
lower_machine->write((const char*)td_buf, len_td + 8);
|
||||
qDebug() << "偏振红色通道差值: " << td_byte.data();
|
||||
} else {
|
||||
cout << "Error: Unable to write to lower machine for td parameter." << endl;
|
||||
}
|
||||
delete[] td_buf;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DestoryLowMac()
|
||||
@ -1365,7 +1182,7 @@ void Start_camera()
|
||||
if (lower_machine != nullptr && lower_machine->isWritable())
|
||||
{
|
||||
lower_machine->write((const char*)start_command, 9);
|
||||
qDebug()<<"发送相机参数成功";
|
||||
qDebug()<<"发送相机启动成功";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
18
camera.h
18
camera.h
@ -23,6 +23,7 @@
|
||||
#include <QTcpServer>
|
||||
#include "globals.h"
|
||||
#include "img_utils.h"
|
||||
#include "color_range.h"
|
||||
|
||||
extern MIL_ID MilApplication;
|
||||
extern MIL_ID MilSystem;
|
||||
@ -68,6 +69,8 @@ bool iniOnnx();
|
||||
|
||||
void Start_camera();
|
||||
|
||||
bool setLowMacParam();
|
||||
|
||||
bool DestoryCamera();
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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(
|
||||
const vector<vector<uint8_t>>& mask,
|
||||
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 );
|
||||
|
||||
void max_valves_together_limit(std::vector<std::vector<uint8_t>> &mask_expaned, const int row_threshold);
|
||||
|
||||
#endif // CAMERA_H
|
||||
|
||||
@ -15,12 +15,12 @@ blue_b_min = -48
|
||||
blue_b_max = -8
|
||||
|
||||
# Orange color parameters
|
||||
orange_L_min = 60
|
||||
orange_L_max = 60
|
||||
orange_a_min = 6
|
||||
orange_a_max = 6
|
||||
orange_b_min = 20
|
||||
orange_b_max = 46
|
||||
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 color parameters
|
||||
black_L_min = 0
|
||||
@ -46,6 +46,14 @@ purple_a_max = 20
|
||||
purple_b_min = -45
|
||||
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
|
||||
lab_denoising = 1
|
||||
saturation_threshold = 165
|
||||
|
||||
7
config/colors.txt
Normal file
7
config/colors.txt
Normal file
@ -0,0 +1,7 @@
|
||||
green
|
||||
blue
|
||||
orange
|
||||
black
|
||||
red
|
||||
purple
|
||||
yellow
|
||||
@ -3,6 +3,7 @@ QT += core gui network
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++17
|
||||
CONFIG += console
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
@ -10,6 +11,8 @@ CONFIG += c++17
|
||||
|
||||
SOURCES += \
|
||||
camera.cpp \
|
||||
color_range.cpp \
|
||||
countdowndialog.cpp \
|
||||
detectionworker.cpp \
|
||||
globals.cpp \
|
||||
img_utils.cpp \
|
||||
@ -20,6 +23,8 @@ SOURCES += \
|
||||
|
||||
HEADERS += \
|
||||
camera.h \
|
||||
color_range.h \
|
||||
countdowndialog.h \
|
||||
detectionworker.h \
|
||||
globals.h \
|
||||
img_utils.h \
|
||||
@ -44,7 +49,9 @@ LIBS += -L$${PWD}/LIB -lmilblob
|
||||
|
||||
|
||||
LIBS += \
|
||||
$${PWD}/opencv410-vs22/x64/vc17/lib/*.lib
|
||||
# $${PWD}/opencv410-vs22/x64/vc17/lib/*.lib
|
||||
$${PWD}/opencv/build/x64/vc16/lib/*.lib
|
||||
|
||||
INCLUDEPATH += \
|
||||
$${PWD}/opencv410-vs22/include
|
||||
# $${PWD}/opencv410-vs22/include
|
||||
$${PWD}/opencv/build/include
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!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>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
35
dist/config/color_range_config.txt
vendored
35
dist/config/color_range_config.txt
vendored
@ -1,4 +1,3 @@
|
||||
# Green color parameters
|
||||
green_L_min = 16
|
||||
green_L_max = 56
|
||||
green_a_min = -33
|
||||
@ -6,7 +5,6 @@ green_a_max = -11
|
||||
green_b_min = -7
|
||||
green_b_max = 24
|
||||
|
||||
# Blue color parameters
|
||||
blue_L_min = 20
|
||||
blue_L_max = 43
|
||||
blue_a_min = -13
|
||||
@ -14,15 +12,13 @@ blue_a_max = 22
|
||||
blue_b_min = -48
|
||||
blue_b_max = -8
|
||||
|
||||
# Orange color parameters
|
||||
orange_L_min = 60
|
||||
orange_L_max = 60
|
||||
orange_a_min = 6
|
||||
orange_a_max = 6
|
||||
orange_b_min = 20
|
||||
orange_b_max = 46
|
||||
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 color parameters
|
||||
black_L_min = 0
|
||||
black_L_max = 8
|
||||
black_a_min = -4
|
||||
@ -30,7 +26,6 @@ black_a_max = 2
|
||||
black_b_min = -3
|
||||
black_b_max = 4
|
||||
|
||||
# Red color parameters
|
||||
red_L_min = 23
|
||||
red_L_max = 48
|
||||
red_a_min = 12
|
||||
@ -38,7 +33,6 @@ red_a_max = 55
|
||||
red_b_min = -80
|
||||
red_b_max = 37
|
||||
|
||||
# Purple color parameters
|
||||
purple_L_min = 38
|
||||
purple_L_max = 54
|
||||
purple_a_min = 10
|
||||
@ -46,7 +40,20 @@ purple_a_max = 20
|
||||
purple_b_min = -45
|
||||
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
|
||||
saturation_threshold = 165
|
||||
lowmac_dp = 350
|
||||
lowmac_sg = 70
|
||||
lowmac_td = 7
|
||||
lowmac_ts = 10
|
||||
saturation_denoising = 1
|
||||
saturation_threshold = 165
|
||||
sizeThreshold = 4
|
||||
|
||||
2
dist/license.txt
vendored
2
dist/license.txt
vendored
@ -61,7 +61,7 @@
|
||||
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.
|
||||
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
13
dist/nvcc.profile
vendored
Normal 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 +=
|
||||
10
globals.cpp
10
globals.cpp
@ -3,6 +3,7 @@
|
||||
|
||||
// camera.cpp 顶部或 globals.cpp 中
|
||||
long long g_valveActionCount = 0;
|
||||
std::atomic<bool> g_camera_error(false);
|
||||
|
||||
// 初始化图片显示互斥锁和MIL_ID
|
||||
QMutex gDispPicMutex0;
|
||||
@ -17,6 +18,9 @@ MIL_ID gMask0 = 0;
|
||||
|
||||
QMutex gMaskMutex1;
|
||||
MIL_ID gMask1 = 0;
|
||||
//艳丽检测参数
|
||||
std::map<std::string, int> params;
|
||||
std::vector<std::string> colors;
|
||||
|
||||
// 初始化 CameraData 实例
|
||||
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_traditional_enable[2] = { true, true };
|
||||
|
||||
int sizeThreshold = 4; // 转化为喷阀的每块要求像素个数
|
||||
int expansionRaidus = 1; // 获取mask后进行左右位置的扩展
|
||||
|
||||
// 初始化全局ONNXRunner实例数组
|
||||
ONNXRunner* g_runner_array[2] = { nullptr, nullptr };
|
||||
|
||||
@ -173,3 +180,6 @@ struct GlobalsInitializer {
|
||||
}
|
||||
} globalsInitializerInstance; // 全局实例,确保在程序结束时清理
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
12
globals.h
12
globals.h
@ -16,7 +16,9 @@
|
||||
#include <atomic>
|
||||
#include "onnxrunner.h"
|
||||
|
||||
// 计数喷阀次数
|
||||
extern long long g_valveActionCount;
|
||||
extern std::atomic<bool> g_camera_error;
|
||||
|
||||
// 图片显示0
|
||||
extern QMutex gDispPicMutex0;
|
||||
@ -39,6 +41,9 @@ extern QSemaphore detection_ready;
|
||||
extern bool g_dl_enable[2];
|
||||
extern bool g_traditional_enable[2];
|
||||
|
||||
extern int sizeThreshold; // 转化为喷阀的每块要求像素个数
|
||||
extern int expansionRaidus;
|
||||
|
||||
// 获取保存目录和配置目录函数
|
||||
QString getSaveDirectory();
|
||||
QString getConfigDirectory();
|
||||
@ -143,4 +148,11 @@ extern std::atomic<bool>* g_recognitionRunning[2];
|
||||
// 定义全局ONNXRunner实例数组
|
||||
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
|
||||
|
||||
@ -282,3 +282,5 @@ void VectorToImg(const std::vector<std::vector<uint8_t> > &array, const std::str
|
||||
// 将图像保存为文件,传入的image_path指定保存路径和文件名
|
||||
imwrite(image_path, image);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ cv::dnn::Net ONNXRunner::loadModel(const std::string& modelPath) {
|
||||
} else {
|
||||
qDebug() << "成功加载ONNX模型:" << QString::fromStdString(modelPath);
|
||||
}
|
||||
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // Use CUDA backend
|
||||
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // Run on GPU
|
||||
// net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // Use CUDA backend
|
||||
// net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // Run on GPU
|
||||
return net;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# Green color parameters
|
||||
green_L_min = 16
|
||||
green_L_max = 56
|
||||
green_a_min = -33
|
||||
@ -6,7 +5,6 @@ green_a_max = -11
|
||||
green_b_min = -7
|
||||
green_b_max = 24
|
||||
|
||||
# Blue color parameters
|
||||
blue_L_min = 20
|
||||
blue_L_max = 43
|
||||
blue_a_min = -13
|
||||
@ -14,15 +12,13 @@ blue_a_max = 22
|
||||
blue_b_min = -48
|
||||
blue_b_max = -8
|
||||
|
||||
# Orange color parameters
|
||||
orange_L_min = 60
|
||||
orange_L_max = 60
|
||||
orange_a_min = 6
|
||||
orange_a_max = 6
|
||||
orange_b_min = 20
|
||||
orange_b_max = 46
|
||||
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 color parameters
|
||||
black_L_min = 0
|
||||
black_L_max = 8
|
||||
black_a_min = -4
|
||||
@ -30,7 +26,6 @@ black_a_max = 2
|
||||
black_b_min = -3
|
||||
black_b_max = 4
|
||||
|
||||
# Red color parameters
|
||||
red_L_min = 23
|
||||
red_L_max = 48
|
||||
red_a_min = 12
|
||||
@ -38,7 +33,6 @@ red_a_max = 55
|
||||
red_b_min = -80
|
||||
red_b_max = 37
|
||||
|
||||
# Purple color parameters
|
||||
purple_L_min = 38
|
||||
purple_L_max = 54
|
||||
purple_a_min = 10
|
||||
@ -46,7 +40,23 @@ purple_a_max = 20
|
||||
purple_b_min = -45
|
||||
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
|
||||
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_threshold = 165
|
||||
sizeThreshold = 4
|
||||
|
||||
1094
ui_widget.h
1094
ui_widget.h
File diff suppressed because it is too large
Load Diff
617
widget.cpp
617
widget.cpp
@ -15,6 +15,14 @@
|
||||
#include <QTabBar>
|
||||
#include <img_utils.h>
|
||||
#include <detectionworker.h>
|
||||
#include <Qstring>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <warning.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -30,6 +38,7 @@ int lowmac_sm = 1200; //吹气量 valve/12 = 吹气时间ms
|
||||
int lowmac_ts = 10; //模板匹配阈值
|
||||
int lowmac_sg = 65; //偏振绿色通道大小阈值
|
||||
int lowmac_td = 7; //偏振红色通道差值
|
||||
|
||||
Widget::Widget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::Widget)
|
||||
@ -54,10 +63,13 @@ Widget::Widget(QWidget *parent)
|
||||
ui->camera_1_img->setScaledContents(false);
|
||||
|
||||
iniOnnx();
|
||||
iniColor();
|
||||
// iniColor();
|
||||
loadConfig(getConfigDirectory()+"/color_range_config.txt"); // 读取配置文件
|
||||
iniLowMac();
|
||||
iniCamera();
|
||||
|
||||
update_machine_num();
|
||||
update_colorlist(); // 更新色彩列表
|
||||
update_polar(); // 更新偏振相机界面
|
||||
// 初始化存储工作者和线程
|
||||
storageWorker = new StorageWorker();
|
||||
storageWorker->moveToThread(&storageThread);
|
||||
@ -71,9 +83,41 @@ Widget::Widget(QWidget *parent)
|
||||
// 启动显示定时器,每秒检查一次
|
||||
QTimer* timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, &Widget::refreshImage);
|
||||
timer->start(40); // 每50毫秒秒刷新一次界面
|
||||
timer->start(40); // 每40毫秒秒刷新一次界面
|
||||
|
||||
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()
|
||||
@ -106,6 +150,17 @@ void Widget::refreshImage()
|
||||
this->ui->tra_enable_0->setEnabled(!this->isCamRunning);
|
||||
this->ui->tra_enable_1->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();
|
||||
ui->label_currentDateTime->setText(now.toString("yyyy-MM-dd hh:mm:ss"));
|
||||
@ -149,7 +204,11 @@ void Widget::refreshImage()
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g_camera_error.load()){
|
||||
info = "图像问题!!!";
|
||||
} else {
|
||||
info = "运行";
|
||||
}
|
||||
};
|
||||
}else {
|
||||
info = "停止";
|
||||
@ -329,6 +388,8 @@ void Widget::on_btn_stop_clicked()
|
||||
|
||||
void Widget::on_btn_start_clicked()
|
||||
{
|
||||
// 设置相机参数
|
||||
setLowMacParam();
|
||||
g_dl_enable[0] = !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();
|
||||
@ -350,17 +411,12 @@ void Widget::on_btn_start_clicked()
|
||||
HANDLE hThread = static_cast<HANDLE>(g_recognitionThread[i]->native_handle());
|
||||
|
||||
// 设置线程优先级为最高
|
||||
if(SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST))
|
||||
{
|
||||
std::cout << "DL Thread " << i << " set highest thread priority。" << std::endl;
|
||||
}
|
||||
else
|
||||
if(!SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST))
|
||||
{
|
||||
std::cerr << "SET thread " << i << " failed, error code:" << GetLastError() << std::endl;
|
||||
}
|
||||
}
|
||||
Start_camera();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -413,11 +469,23 @@ void Widget::on_btn_quit_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_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()
|
||||
{
|
||||
@ -439,7 +507,7 @@ void Widget::on_btn_live_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);
|
||||
}
|
||||
|
||||
|
||||
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 ¶m : 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(); // 更新偏振相机界面
|
||||
}
|
||||
|
||||
|
||||
55
widget.h
55
widget.h
@ -8,6 +8,7 @@
|
||||
#include <QPushButton>
|
||||
#include "globals.h"
|
||||
#include "storageworker.h"
|
||||
#include "countdowndialog.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
@ -28,6 +29,10 @@ public 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 on_pushButton_2_clicked();
|
||||
@ -54,6 +59,54 @@ private slots:
|
||||
|
||||
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:
|
||||
Ui::Widget *ui;
|
||||
|
||||
@ -64,5 +117,7 @@ private:
|
||||
QThread storageThread; // 存储线程
|
||||
StorageWorker* storageWorker; // 存储工作者
|
||||
|
||||
void showStartupCountdown();
|
||||
|
||||
};
|
||||
#endif // WIDGET_H
|
||||
|
||||
Loading…
Reference in New Issue
Block a user