双向相机开启+界面mask合并展示
This commit is contained in:
parent
d12a893506
commit
e8451357d7
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ build
|
|||||||
release
|
release
|
||||||
debug
|
debug
|
||||||
.qtc_clangd
|
.qtc_clangd
|
||||||
|
.idea
|
||||||
|
|||||||
175
camera.cpp
175
camera.cpp
@ -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");
|
||||||
@ -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);
|
||||||
|
|||||||
5
camera.h
5
camera.h
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
16
globals.cpp
16
globals.cpp
@ -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;
|
||||||
|
|||||||
12
globals.h
12
globals.h
@ -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
|
||||||
|
|||||||
150
img_utils.cpp
150
img_utils.cpp
@ -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 };
|
||||||
|
}
|
||||||
|
|||||||
18
img_utils.h
18
img_utils.h
@ -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
|
||||||
|
|||||||
37
widget.cpp
37
widget.cpp
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user