双向相机开启+界面mask合并展示

This commit is contained in:
xyxyxy666 2024-12-21 15:37:35 +08:00
parent d12a893506
commit e8451357d7
10 changed files with 327 additions and 95 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ build
release release
debug debug
.qtc_clangd .qtc_clangd
.idea

View File

@ -1,5 +1,4 @@
#include "camera.h" #include "camera.h"
#include "globals.h"
#include <QTimer> #include <QTimer>
@ -47,6 +46,7 @@ ONNXRunner runner;
std::map<std::string, int> params; std::map<std::string, int> params;
int dual_cam_offset_y = 89; // 双相机之间的上下偏移值
int widthBlocks = 20; // 输出的喷阀通道数 int widthBlocks = 20; // 输出的喷阀通道数
int heightBlocks = 512; // 输出的Mask高度 int heightBlocks = 512; // 输出的Mask高度
int sizeThreshold = 20; // 转化为喷阀的每块要求像素个数 int sizeThreshold = 20; // 转化为喷阀的每块要求像素个数
@ -58,6 +58,9 @@ int ignoreSide = 0; // 左右两侧的忽略的喷阀通道数量
int skipLeftCols = 0; // 生成mask时跳过左侧的像素数量 int skipLeftCols = 0; // 生成mask时跳过左侧的像素数量
int skipRightCols = 0; // 生成mask时跳过右侧的像素数量 int skipRightCols = 0; // 生成mask时跳过右侧的像素数量
static std::vector<std::vector<uint8_t>> mask_0(0);
static std::vector<std::vector<uint8_t>> mask_1(0);
static std::vector<std::vector<uint8_t>> tail_0(0); static std::vector<std::vector<uint8_t>> tail_0(0);
static std::vector<std::vector<uint8_t>> tail_1(0); static std::vector<std::vector<uint8_t>> tail_1(0);
@ -167,76 +170,74 @@ MIL_INT ProcessingFunction0(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
#if(GlobalDebug) #if(GlobalDebug)
qDebug()<<"回调1"; qDebug()<<"回调1";
#endif #endif
//拷贝艳丽色检测图像 // 拷贝艳丽色检测图像
// MbufCopy(ModifiedBufferId0,MilImage_Color0); MbufCopy(ModifiedBufferId0,MilImage_Color0);
// // //拷贝onnx检测图像 MIL_UNIQUE_BUF_ID MimResizedestination = MbufAllocColor(MilSystem, 3, 2048, 512, 8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, M_UNIQUE_ID);
// // MbufCopy(ModifiedBufferId1,MilImage_Onnx1); MbufClear(MimResizedestination, M_COLOR_BLACK);
MimResize(MilImage_Color0, MimResizedestination, 0.5, 1 , M_DEFAULT);
// MIL_UNIQUE_BUF_ID MimResizedestination = MbufAllocColor(MilSystem, 3, 2048, 512, 8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, M_UNIQUE_ID); //图片镜像翻转
// MbufClear(MimResizedestination, M_COLOR_BLACK); MIL_UNIQUE_BUF_ID MimFlipDedtination = MbufClone(MimResizedestination, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_UNIQUE_ID);
// MimResize(MilImage_Color0, MimResizedestination, 0.5, 1 , M_DEFAULT); MbufClear(MimFlipDedtination, M_COLOR_BLACK);
MimFlip(MimResizedestination, MimFlipDedtination, M_FLIP_HORIZONTAL, M_DEFAULT);
// MIL_UNIQUE_BUF_ID MimFlipDedtination = MbufClone(MimResizedestination, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_UNIQUE_ID); //艳丽检测mask
// MbufClear(MimFlipDedtination, M_COLOR_BLACK); high_sat_detect(MimFlipDedtination, detection_result0, params);
// MimFlip(MimResizedestination, MimFlipDedtination, M_FLIP_HORIZONTAL, M_DEFAULT);
// #if(GlobalDebug && DebugDetectionTime) // Update the current Img MIl id
// Timer timer2; {
// #endif QMutexLocker locker(&gMaskMutex0);
// //艳丽检测mask gMask0 = detection_result0;
// high_sat_detect(MimFlipDedtination, detection_result0, params); }
// #if(GlobalDebug && DebugDetectionTime) auto [mask_tmp, newTail] = generateMaskWithTail(detection_result0, tail_0, widthBlocks, heightBlocks, sizeThreshold, rowRange, skipLeftCols, skipRightCols);
// timer2.printElapsedTime("Algorithm Spent: "); tail_0 = newTail;
// #endif mask_0 = mask_tmp;
// #if(GlobalDebug && DebugDetection)
// MbufSave(SAVE_PATH_flip,MimFlipDedtination);
// // MbufSave(SAVE_PATH_resize,MimResizedestination);
// MbufSave(SAVE_PATH_raw,MilImage_Color0);
// MbufSave(SAVE_PATH_result,detection_result0);
// #endif
// //Onnx检测mask
// // cv::Mat image = mil2mat(MilImage_Onnx1);
// // cv::Mat Img_Onnx;
// // std::vector<Detection> result = runner.predict(image);
// // Img_Onnx = runner.postProcess(result, image);
// // std::vector<std::vector<uint8_t>> mask_Onnx1 = generateMaskFromImage2(Img_Onnx, widthBlocks, heightBlocks, sizeThreshold);
// // timer1.printElapsedTime("onnx sat finished");
// auto [mask_1, newTail] = generateMaskWithTail(detection_result0, tail_1, widthBlocks, heightBlocks, sizeThreshold, rowRange, skipLeftCols, skipRightCols);
// tail_1 = newTail;
// PadColumns(mask_1,padLeft,padRight,0);
// std::vector<std::vector<uint8_t>> mask_Total = expandArray(mask_1,64);
// // save masks
// #if(GlobalDebug && DebugDetection)
// VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask" + std::to_string(FuncCount1) + ".bmp");
// VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask_ignored" + std::to_string(FuncCount1) + ".bmp");
// VectorToImg(mask_Total,"C:/Users/Pc/Desktop/img/mask_expended" + std::to_string(FuncCount1) + ".bmp");
// #endif
// bool result_Low = get_valve_data(mask_Total);
// if(!result_Low)
// {
// qWarning()<<"下位机发送失败";
// }
// #if(GlobalDebug && DebugDetectionTime) bool isReady;
// timer_detection_time.printElapsedTime("Time of Processing From Get into CallBack to Sent to Lower Mac"); vector<vector<uint8_t>> merged_mask;
// #endif vector<vector<uint8_t>> mask_tail;
{
QMutexLocker locker_self(&imgDetectionReady0Mutex);
imgDetectionReady1 = true;
QMutexLocker locker_other(&imgDetectionReady1Mutex);
isReady = imgDetectionReady0 & imgDetectionReady1;
if(isReady)
{
merged_mask = ImageUtils::mergeMasks(mask_0, mask_1, dual_cam_offset_y);
std::tie(merged_mask, mask_tail) = ImageUtils::extractROI(merged_mask, 0, 0, widthBlocks, heightBlocks);
}
}
// 没有两个都完成就不发送
if(!isReady)
return 0;
// 发送前的处理
// 将每个结果左右扩展扩展半径默认为1
auto mask_expaned = expandMaskHorizontally(merged_mask, expansionRaidus);
// 将结果的左右补充上0让物体大小符合要求
PadColumns(mask_expaned,padLeft,padRight,0);
//将mask扩展到合适的大小
std::vector<std::vector<uint8_t>> mask_Total = expandArray(mask_expaned,64);
// save masks
#if(GlobalDebug && DebugDetection)
VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask" + std::to_string(FuncCount1) + ".bmp");
VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask_ignored" + std::to_string(FuncCount1) + ".bmp");
VectorToImg(mask_Total,"C:/Users/Pc/Desktop/img/mask_expended" + std::to_string(FuncCount1) + ".bmp");
#endif
// 发送到下位机
bool result_Low = get_valve_data(mask_Total);
if(!result_Low)
{
qWarning()<<"下位机发送失败";
}
return 0; return 0;
} }
Timer timer2;
MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr) MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
{ {
// CallBackTimer1.printElapsedTime("Call Back 1 reached"); // CallBackTimer1.printElapsedTime("Call Back 1 reached");
@ -252,8 +253,8 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
// Update the current Img MIl id // Update the current Img MIl id
{ {
QMutexLocker locker(&gDispPicMutex1); QMutexLocker locker(&gDispPicMutex1);
gDispCurrentPicId1 = ModifiedBufferId1; gDispCurrentPicId1 = ModifiedBufferId1;
} }
if(SaveImg_Flag) if(SaveImg_Flag)
@ -282,9 +283,7 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
MbufClear(MimResizedestination, M_COLOR_BLACK); MbufClear(MimResizedestination, M_COLOR_BLACK);
MimResize(MilImage_Color1, MimResizedestination, 0.5, 1 , M_DEFAULT); MimResize(MilImage_Color1, MimResizedestination, 0.5, 1 , M_DEFAULT);
// MIL_UNIQUE_BUF_ID MimFlipDedtination = MbufClone(MimResizedestination, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_UNIQUE_ID);
// MbufClear(MimFlipDedtination, M_COLOR_BLACK);
// MimFlip(MimResizedestination, MimFlipDedtination, M_FLIP_HORIZONTAL, M_DEFAULT);
#if(GlobalDebug && DebugDetectionTime) #if(GlobalDebug && DebugDetectionTime)
Timer timer2; Timer timer2;
@ -302,37 +301,56 @@ MIL_INT ProcessingFunction1(MIL_INT HookType, MIL_ID HookId, void *HookDataPtr)
MbufSave(SAVE_PATH_raw,MilImage_Color0); MbufSave(SAVE_PATH_raw,MilImage_Color0);
MbufSave(SAVE_PATH_result,detection_result0); MbufSave(SAVE_PATH_result,detection_result0);
#endif #endif
// Update the current Img MIl id
{
QMutexLocker locker(&gMaskMutex1);
gMask1 = detection_result1;
}
//Onnx检测mask auto [mask_tmp, newTail] = generateMaskWithTail(detection_result1, tail_1, widthBlocks, heightBlocks, sizeThreshold, rowRange, skipLeftCols, skipRightCols);
// cv::Mat image = mil2mat(MilImage_Onnx1);
// cv::Mat Img_Onnx;
// std::vector<Detection> result = runner.predict(image);
// Img_Onnx = runner.postProcess(result, image);
// std::vector<std::vector<uint8_t>> mask_Onnx1 = generateMaskFromImage2(Img_Onnx, widthBlocks, heightBlocks, sizeThreshold);
// timer1.printElapsedTime("onnx sat finished");
auto [mask_1, newTail] = generateMaskWithTail(detection_result1, tail_1, widthBlocks, heightBlocks, sizeThreshold, rowRange, skipLeftCols, skipRightCols);
tail_1 = newTail; tail_1 = newTail;
auto mask_expaned = expandMaskHorizontally(mask_1, expansionRaidus); mask_1 = mask_tmp;
bool isReady;
vector<vector<uint8_t>> merged_mask;
vector<vector<uint8_t>> mask_tail;
{
QMutexLocker locker_self(&imgDetectionReady1Mutex);
imgDetectionReady1 = true;
QMutexLocker locker_other(&imgDetectionReady0Mutex);
isReady = imgDetectionReady0 & imgDetectionReady1;
if(isReady)
{
merged_mask = ImageUtils::mergeMasks(mask_0, mask_1, dual_cam_offset_y);
std::tie(merged_mask, mask_tail) = ImageUtils::extractROI(merged_mask, 0, 0, widthBlocks, heightBlocks);
}
}
// 没有两个都完成就不发送
if(!isReady)
return 0;
// 发送前的处理
// 将每个结果左右扩展扩展半径默认为1
auto mask_expaned = expandMaskHorizontally(merged_mask, expansionRaidus);
// 将结果的左右补充上0让物体大小符合要求
PadColumns(mask_expaned,padLeft,padRight,0); PadColumns(mask_expaned,padLeft,padRight,0);
//将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);
// save masks
// save masks
#if(GlobalDebug && DebugDetection) #if(GlobalDebug && DebugDetection)
VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask" + std::to_string(FuncCount1) + ".bmp"); VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask" + std::to_string(FuncCount1) + ".bmp");
VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask_ignored" + std::to_string(FuncCount1) + ".bmp"); VectorToImg(mask_1,"C:/Users/Pc/Desktop/img/mask_ignored" + std::to_string(FuncCount1) + ".bmp");
VectorToImg(mask_Total,"C:/Users/Pc/Desktop/img/mask_expended" + std::to_string(FuncCount1) + ".bmp"); VectorToImg(mask_Total,"C:/Users/Pc/Desktop/img/mask_expended" + std::to_string(FuncCount1) + ".bmp");
#endif #endif
// 发送到下位机
bool result_Low = get_valve_data(mask_Total); bool result_Low = get_valve_data(mask_Total);
if(!result_Low) if(!result_Low)
{ {
qWarning()<<"下位机发送失败"; qWarning()<<"下位机发送失败";
} }
#if(GlobalDebug && DebugDetectionTime) #if(GlobalDebug && DebugDetectionTime)
timer_detection_time.printElapsedTime("Time of Processing From Get into Ca" timer_detection_time.printElapsedTime("Time of Processing From Get into Ca"
"..0llBack to Sent to Lower Mac"); "..0llBack to Sent to Lower Mac");
@ -357,7 +375,6 @@ bool DestoryCamera()
MbufFree(MilGrabBufferList1[i]); MbufFree(MilGrabBufferList1[i]);
} }
MbufFree(MilImage0); MbufFree(MilImage0);
MbufFree(MilImage1); MbufFree(MilImage1);
MbufFree(MilImage_Color0); MbufFree(MilImage_Color0);

View File

@ -10,8 +10,6 @@
#include <map> #include <map>
#include <string> #include <string>
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
@ -23,6 +21,9 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QTcpServer> #include <QTcpServer>
#include "globals.h"
#include "img_utils.h"
extern MIL_ID MilApplication; extern MIL_ID MilApplication;
extern MIL_ID MilSystem; extern MIL_ID MilSystem;

View File

@ -36,5 +36,5 @@ DEPENDPATH += D:/desktop/Cotton/cotton/Include
LIBS += -LD:/desktop/Cotton/cotton/LIB -lmil LIBS += -LD:/desktop/Cotton/cotton/LIB -lmil
LIBS += -LD:/desktop/Cotton/cotton/LIB -lMilim LIBS += -LD:/desktop/Cotton/cotton/LIB -lMilim
INCLUDEPATH += F:/matrox/opencv/build/include INCLUDEPATH += D:/desktop/Cotton/opencv/Withcontrib/include
LIBS += F:/matrox/opencv/build/x64/vc16/lib/opencv*.lib LIBS += F:/matrox/opencv/build/x64/vc16/lib/opencv*.lib

View File

@ -1,10 +1,20 @@
// globals.cpp // globals.cpp
#include "globals.h" #include "globals.h"
// 图片显示0 // 图片显示
QMutex gDispPicMutex0; QMutex gDispPicMutex0;
MIL_ID gDispCurrentPicId0 = 0; MIL_ID gDispCurrentPicId0 = 0;
// 图片显示1
QMutex gDispPicMutex1; QMutex gDispPicMutex1;
MIL_ID gDispCurrentPicId1 = 0; MIL_ID gDispCurrentPicId1 = 0;
// 检测结果
QMutex gMaskMutex0;
MIL_ID gMask0 = 0;
QMutex gMaskMutex1;
MIL_ID gMask1 = 0;
// 双相机结果同步
QMutex imgDetectionReady0Mutex;
QMutex imgDetectionReady1Mutex;
bool imgDetectionReady0 = false;
bool imgDetectionReady1 = false;

View File

@ -4,6 +4,7 @@
#include <MIL.h> #include <MIL.h>
#include <QMutex> #include <QMutex>
#include <opencv2/opencv.hpp>
// 图片显示0 // 图片显示0
extern QMutex gDispPicMutex0; extern QMutex gDispPicMutex0;
@ -13,4 +14,15 @@ extern MIL_ID gDispCurrentPicId0;
extern QMutex gDispPicMutex1; extern QMutex gDispPicMutex1;
extern MIL_ID gDispCurrentPicId1; extern MIL_ID gDispCurrentPicId1;
extern QMutex gMaskMutex0;
extern MIL_ID gMask0;
extern QMutex gMaskMutex1;
extern MIL_ID gMask1;
extern QMutex imgDetectionReady0Mutex;
extern QMutex imgDetectionReady1Mutex;
extern bool imgDetectionReady0;
extern bool imgDetectionReady1;
#endif // GLOBALS_H #endif // GLOBALS_H

View File

@ -115,3 +115,153 @@ void ImageUtils::convert_to_uint8(const MIL_ID& input_img, MIL_ID& output_img) {
std::cout << "Unsupported channel number!" << std::endl; std::cout << "Unsupported channel number!" << std::endl;
} }
} }
cv::Mat overlayResultOnInput(const cv::Mat& cv_input, const cv::Mat& total_result, double alpha = 0.5, int colormap = cv::COLORMAP_JET) {
// 1. 确保 total_result 的尺寸与 cv_input 一致
cv::Mat resized_total_result;
if (total_result.size() != cv_input.size()) {
cv::resize(total_result, resized_total_result, cv_input.size(), 0, 0, cv::INTER_LINEAR);
} else {
resized_total_result = total_result;
}
// 2. 将 resized_total_result 转换为伪彩色图像
cv::Mat total_result_color;
// 确保 total_result 是单通道图像以应用色图
if (resized_total_result.channels() == 1) {
cv::applyColorMap(resized_total_result, total_result_color, colormap);
} else {
// 如果已经是多通道图像,可以选择直接使用或根据需要处理
total_result_color = resized_total_result.clone();
}
// 3. 确保 cv_input 是三通道图像(如果是灰度图像,则转换为 BGR
cv::Mat cv_input_rgb;
if (cv_input.channels() == 1) {
cv::cvtColor(cv_input, cv_input_rgb, cv::COLOR_GRAY2BGR);
} else {
cv_input_rgb = cv_input.clone(); // 保证不修改原始图像
}
// 4. 设置叠加透明度alpha: 0.0-1.0
double beta = 1.0 - alpha;
// 5. 使用加权和将 total_result_color 叠加到 cv_input_rgb 上
cv::Mat overlay;
cv::addWeighted(cv_input_rgb, alpha, total_result_color, beta, 0.0, overlay);
// 6. 返回叠加后的图像
return overlay;
}
// 合并两个二值掩码,通过按位或操作,并考虑垂直偏移 offset_y
std::vector<std::vector<uint8_t>> mergeMasks(
const std::vector<std::vector<uint8_t>>& mask1,
const std::vector<std::vector<uint8_t>>& mask2,
int offset_y = 0
) {
if (mask1.empty() || mask1[0].empty() || mask2.empty() || mask2[0].empty()) {
throw std::invalid_argument("输入的掩码不能为空");
}
// 假设两个掩码的宽度相同
size_t width = mask1[0].size();
for (const auto& row : mask1)
{
if (row.size() != width)
{
throw std::invalid_argument("mask1 的所有行必须具有相同的宽度");
}
}
for (const auto& row : mask2)
{
if (row.size() != width)
{
throw std::invalid_argument("mask2 的所有行必须具有相同的宽度,并且与 mask1 的宽度一致");
}
}
size_t height1 = mask1.size();
size_t height2 = mask2.size();
// 计算合并后的高度
int merged_top = std::min(0, offset_y);
int merged_bottom = std::max(static_cast<int>(height1), static_cast<int>(height2) + offset_y);
size_t merged_height = merged_bottom - merged_top;
// 初始化合并后的掩码为全 0
std::vector<std::vector<uint8_t>> merged_mask(merged_height, std::vector<uint8_t>(width, 0));
// 将 mask1 放入 merged_mask
for (size_t y = 0; y < height1; ++y)
{
int merged_y = y - merged_top;
for (size_t x = 0; x < width; ++x)
{
merged_mask[merged_y][x] = mask1[y][x] ? 1 : 0;
}
}
// 将 mask2 放入 merged_mask考虑 offset_y
for (size_t y = 0; y < height2; ++y)
{
int merged_y = y + offset_y - merged_top;
if (merged_y < 0 || merged_y >= static_cast<int>(merged_height))
{
// 超出合并掩码的范围,跳过
continue;
}
for (size_t x = 0; x < width; ++x)
{
merged_mask[merged_y][x] = (merged_mask[merged_y][x] || mask2[y][x]) ? 1 : 0;
}
}
return merged_mask;
}
// 提取 ROI 并返回剩余部分
std::pair<std::vector<std::vector<uint8_t>>, std::vector<std::vector<uint8_t>>>
extractROI(
const std::vector<std::vector<uint8_t>>& merged_mask,
int roi_x,
int roi_y,
int roi_width,
int roi_height
) {
if (merged_mask.empty() || merged_mask[0].empty()) {
throw std::invalid_argument("merged_mask 不能为空");
}
size_t mask_height = merged_mask.size();
size_t mask_width = merged_mask[0].size();
// 校正 ROI 的边界
int x_start = std::max(0, roi_x);
int y_start = std::max(0, roi_y);
int x_end = std::min(static_cast<int>(mask_width), roi_x + roi_width);
int y_end = std::min(static_cast<int>(mask_height), roi_y + roi_height);
// 初始化 ROI 和剩余部分的掩码
std::vector<std::vector<uint8_t>> roi_mask(roi_height, std::vector<uint8_t>(roi_width, 0));
std::vector<std::vector<uint8_t>> remaining_mask(mask_height, std::vector<uint8_t>(mask_width, 0));
for (size_t y = 0; y < mask_height; ++y) {
for (size_t x = 0; x < mask_width; ++x) {
if (x >= static_cast<size_t>(roi_x) && x < static_cast<size_t>(roi_x + roi_width) &&
y >= static_cast<size_t>(roi_y) && y < static_cast<size_t>(roi_y + roi_height)) {
// 属于 ROI
if (x >= static_cast<size_t>(x_start) && y >= static_cast<size_t>(y_start) &&
x < static_cast<size_t>(x_end) && y < static_cast<size_t>(y_end)) {
roi_mask[y - roi_y][x - roi_x] = merged_mask[y][x];
}
} else {
// 属于剩余部分
remaining_mask[y][x] = merged_mask[y][x];
}
}
}
return { roi_mask, remaining_mask };
}

View File

@ -7,6 +7,7 @@
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <Mil.h> #include <Mil.h>
#include <camera.h> #include <camera.h>
#include <utility>
extern MIL_ID MilSystem; extern MIL_ID MilSystem;
@ -22,6 +23,23 @@ public:
static cv::Mat mil2Mat(const MIL_ID mil_img); static cv::Mat mil2Mat(const MIL_ID mil_img);
static void convert_to_uint8(const MIL_ID& input_img, MIL_ID& output_img); static void convert_to_uint8(const MIL_ID& input_img, MIL_ID& output_img);
static cv::Mat overlayResultOnInput(const cv::Mat& cv_input, const cv::Mat& total_result, double alpha = 0.5, int colormap = cv::COLORMAP_JET);
static std::vector<std::vector<uint8_t>> mergeMasks(
const std::vector<std::vector<uint8_t>>& mask1,
const std::vector<std::vector<uint8_t>>& mask2,
int offset_y = 0
);
static std::pair<std::vector<std::vector<uint8_t>>, std::vector<std::vector<uint8_t>>>
extractROI(
const std::vector<std::vector<uint8_t>>& merged_mask,
int roi_x,
int roi_y,
int roi_width,
int roi_height
);
}; };
#endif // IMG_UTILS_H #endif // IMG_UTILS_H

View File

@ -51,25 +51,36 @@ void Widget::refreshImage()
refreshSingleImage(1); refreshSingleImage(1);
} }
void Widget::refreshSingleImage(int camera_id) void Widget::refreshSingleImage(int camera_id, bool overlay_result)
{ {
// 更新当前的图片0 // 更新当前的图片0
MIL_ID current_id = 0; MIL_ID current_id = 0;
if (camera_id == 0) if (camera_id == 0)
{ { // 获取当前图片
{ {
QMutexLocker locker(&gDispPicMutex0); QMutexLocker locker(&gDispPicMutex0);
current_id = gDispCurrentPicId0; current_id = gDispCurrentPicId0;
} }
if (current_id == 0) if (current_id == 0)
return; return;
// 获取 QPixmap 并设置到 QLabel cv::Mat img = ImageUtils::mil2Mat(current_id);
QPixmap pixmap0 = ImageUtils::mat2QPixmap(ImageUtils::mil2Mat(current_id)); //进行结果的转化叠加
if (overlay_result)
{
MIL_ID mask_id = 0;
{
QMutexLocker locker(&gMaskMutex0);
mask_id = gMask0;
}
cv::Mat mask = ImageUtils::mil2Mat(mask_id);
img = ImageUtils::overlayResultOnInput(img,mask,0.5);
}
//刷新显示
QPixmap pixmap0 = ImageUtils::mat2QPixmap(img);
if (!pixmap0.isNull()) if (!pixmap0.isNull())
{ {
ui->camera_0_img->setPixmap(pixmap0); ui->camera_0_img->setPixmap(pixmap0);
} }
} }
// 更新当前的图片1 // 更新当前的图片1
else if (camera_id == 1) else if (camera_id == 1)
@ -81,8 +92,20 @@ void Widget::refreshSingleImage(int camera_id)
if (current_id == 0) if (current_id == 0)
return; return;
// 获取 QPixmap 并设置到 QLabel cv::Mat img = ImageUtils::mil2Mat(current_id);
QPixmap pixmap1 = ImageUtils::mat2QPixmap(ImageUtils::mil2Mat(current_id)); //进行结果的转化叠加
if (overlay_result)
{
MIL_ID mask_id = 0;
{
QMutexLocker locker(&gMaskMutex1);
mask_id = gMask1;
}
cv::Mat mask = ImageUtils::mil2Mat(mask_id);
img = ImageUtils::overlayResultOnInput(img,mask,0.5);
}
//刷新显示
QPixmap pixmap1 = ImageUtils::mat2QPixmap(img);
if (!pixmap1.isNull()) if (!pixmap1.isNull())
{ {
ui->camera_1_img->setPixmap(pixmap1); ui->camera_1_img->setPixmap(pixmap1);

View File

@ -26,7 +26,7 @@ public slots:
private slots: private slots:
void refreshSingleImage(int camera_id); void refreshSingleImage(int camera_id, bool overlay_result = true);
void on_pushButton_clicked(); void on_pushButton_clicked();