cotton_double/widget.cpp
2024-12-25 15:49:44 +08:00

370 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include <QTcpSocket>
#include <QPushButton>
#include <QTimer>
#include <QEventLoop>
#include <QElapsedTimer>
// #include <windows.h>
#include <QApplication>
#include <QLabel>
#include <QImage>
#include <QPixmap>
#include <QDateTime>
#include <img_utils.h>
#include <detectionworker.h>
using namespace std;
// 硬编码参数值
int file_delay = 1050; // 延迟时间(毫秒)
int file_encoder = 12000; // 编码器值++
int file_valve = 200; // 阀门通道
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
this->isCamRunning = false;
ui->setupUi(this);
ui->camera_0_img->setScaledContents(false);
ui->camera_1_img->setScaledContents(false);
iniOnnx();
iniColor();
iniLowMac();
iniCamera();
// 初始化存储工作者和线程
storageWorker = new StorageWorker();
storageWorker->moveToThread(&storageThread);
connect(&storageThread, &QThread::started, storageWorker, &StorageWorker::process);
connect(this, &Widget::destroyed, &storageThread, &QThread::quit);
connect(&storageThread, &QThread::finished, storageWorker, &QObject::deleteLater);
storageThread.start();
// 启动显示定时器,每秒检查一次
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Widget::refreshImage);
timer->start(50); // 每50毫秒秒刷新一次界面
}
Widget::~Widget()
{
// 停止存储线程
g_storageQueue.stop();
storageThread.quit();
storageThread.wait();
// 现有清理代码...
DestoryCamera();
DestoryLowMac();
delete ui;
}
void Widget::refreshImage()
{
// refresh Image 1 and image 0
refreshSingleImage(0, this->ui->mtx_0_overlay->isChecked(), this->ui->dl_0_overlay->isChecked(), this->ui->img_0_mirror->isChecked());
refreshSingleImage(1, this->ui->mtx_1_overlay->isChecked(), this->ui->dl_1_overlay->isChecked(), this->ui->img_1_mirror->isChecked());
// refresh buttons
this->ui->btn_start->setEnabled(!this->isCamRunning);
this->ui->btn_stop->setEnabled(this->isCamRunning);
this->ui->btn_take_photos->setEnabled(this->isCamRunning);
// refresh checkouts
this->ui->dl_enable_0->setEnabled(!this->isCamRunning);
this->ui->dl_enable_1->setEnabled(!this->isCamRunning);
this->ui->tra_enable_0->setEnabled(!this->isCamRunning);
this->ui->tra_enable_1->setEnabled(!this->isCamRunning);
// refresh info
QString info;
if(this->isCamRunning)
{
if(SaveImg_Flag==1)
{
info = "存图中!!";
}
else
{
info = "运行";
};
}else {
info = "停止";
};
this->ui->lab_info->setText(info);
}
void Widget::refreshSingleImage(int camera_id, bool overlay_traditional_result, bool overlay_dl_result, bool mirror)
{
// 验证摄像头ID的有效性
if (camera_id < 0 || camera_id >= 2) { // 假设只有两个摄像头
qWarning() << "Invalid Camera ID:" << camera_id;
return;
}
// 定义每个摄像头对应的 QLabel
QLabel* cameraLabels[2] = { ui->camera_0_img, ui->camera_1_img };
// 定义每个摄像头对应的变量数组
QMutex* dispPicMutexes[2] = { &gDispPicMutex0, &gDispPicMutex1 };
MIL_ID dispCurrentPicIds[2] = { gDispCurrentPicId0, gDispCurrentPicId1 };
// 获取当前摄像头的数据
QMutex* currentDispMutex = dispPicMutexes[camera_id];
MIL_ID current_id;
{
QMutexLocker locker(currentDispMutex);
current_id = dispCurrentPicIds[camera_id];
}
if (current_id == 0)
return;
// 将MIL图像转换为OpenCV Mat
cv::Mat img = ImageUtils::mil2Mat(current_id);
if (img.empty())
{
qWarning() << "Failed to convert MIL image to Mat for Camera ID:" << camera_id;
return;
}
if (current_id == 0)
return;
std::vector<std::vector<uint8_t>> dl_mask;
std::vector<std::vector<uint8_t>> traditional_mask;
{
QMutexLocker locker(&g_detection_result[camera_id].mutex);
dl_mask = g_detection_result[camera_id].dl_mask;
traditional_mask = g_detection_result[camera_id].traditional_mask;
}
// 如果需要叠加结果,处理掩码
if (overlay_dl_result && g_dl_enable[camera_id])
{
if (!dl_mask.empty() && !dl_mask[0].empty())
{
// 将二维 vector 转换为 cv::Mat
int rows = dl_mask.size();
int cols = dl_mask[0].size();
cv::Mat dl_mask_mat(rows, cols, CV_8U);
for (int i = 0; i < rows; ++i)
{
if (dl_mask[i].size() != cols) {
qWarning() << "Inconsistent mask row size for dl_mask in Camera ID:" << camera_id;
dl_mask_mat.release();
break;
}
memcpy(dl_mask_mat.ptr(i), dl_mask[i].data(), cols);
}
if (!dl_mask_mat.empty())
{
// 调整掩膜尺寸以匹配图像尺寸
if (dl_mask_mat.size() != img.size()) {
cv::resize(dl_mask_mat, dl_mask_mat, img.size(), 0, 0, cv::INTER_NEAREST);
}
// 确保掩膜为二值图像
cv::threshold(dl_mask_mat, dl_mask_mat, 128, 255, cv::THRESH_BINARY);
// 创建绿色掩膜
cv::Mat green_overlay(img.size(), img.type(), cv::Scalar(0, 255, 0));
green_overlay.setTo(cv::Scalar(0, 255, 0), dl_mask_mat);
// 叠加掩膜到图像
cv::addWeighted(green_overlay, 0.5, img, 1.0, 0, img);
}
}
}
if (overlay_traditional_result & g_traditional_enable[camera_id])
{
if (!traditional_mask.empty() && !traditional_mask[0].empty())
{
// 将二维 vector 转换为 cv::Mat
int rows = traditional_mask.size();
int cols = traditional_mask[0].size();
cv::Mat traditional_mask_mat(rows, cols, CV_8U);
for (int i = 0; i < rows; ++i)
{
if (traditional_mask[i].size() != cols) {
qWarning() << "Inconsistent mask row size for traditional_mask in Camera ID:" << camera_id;
traditional_mask_mat.release();
break;
}
memcpy(traditional_mask_mat.ptr(i), traditional_mask[i].data(), cols);
}
if (!traditional_mask_mat.empty())
{
// 调整掩膜尺寸以匹配图像尺寸
if (traditional_mask_mat.size() != img.size()) {
cv::resize(traditional_mask_mat, traditional_mask_mat, img.size(), 0, 0, cv::INTER_NEAREST);
}
// 确保掩膜为二值图像
cv::threshold(traditional_mask_mat, traditional_mask_mat, 128, 255, cv::THRESH_BINARY);
// 创建红色掩膜
cv::Mat red_overlay(img.size(), img.type(), cv::Scalar(0, 0, 255));
red_overlay.setTo(cv::Scalar(0, 0, 255), traditional_mask_mat);
// 叠加掩膜到图像
cv::addWeighted(red_overlay, 0.5, img, 1.0, 0, img);
}
}
}
// 如果需要镜像处理
if (mirror)
{
cv::flip(img, img, 1); // 水平翻转
}
// 将OpenCV Mat转换为QPixmap
QPixmap pixmap = ImageUtils::mat2QPixmap(img);
if (pixmap.isNull()) {
qWarning() << "Failed to convert Mat to QPixmap for Camera ID:" << camera_id;
return;
}
// 高质量缩放图像
QSize labelSize = cameraLabels[camera_id]->size();
QPixmap scaledPixmap = pixmap.scaled(labelSize);
// 更新UI标签
cameraLabels[camera_id]->setPixmap(scaledPixmap);
}
void Widget::on_pushButton_2_clicked()
{
SaveImg_Flag = 1;
}
void Widget::on_btn_goto_sort_clicked()
{
// 回复显示的图片
{
QMutexLocker locker(&gDispPicMutex0);
gDispCurrentPicId0 = 0;
}
ui->camera_0_img->clear();
{
QMutexLocker locker(&gDispPicMutex1);
gDispCurrentPicId1 = 0;
}
ui->camera_1_img->clear();
DestoryCamera();
DestoryLowMac();
}
void Widget::on_btn_stop_clicked()
{
this->isCamRunning = false;
// 恢复显示的图片
{
QMutexLocker locker(&gDispPicMutex0);
gDispCurrentPicId0 = 0;
}
ui->camera_0_img->clear();
{
QMutexLocker locker(&gDispPicMutex1);
gDispCurrentPicId1 = 0;
}
ui->camera_1_img->clear();
// 停止检测工作者线程
for(int i = 0; i < 2; ++i)
{
g_recognitionRunning[i]->store(false);
g_img_Queue[i]->stop(); // 停止队列以唤醒线程
}
// 等待检测工作者线程结束
for(int i = 0; i < 2; ++i)
{
if(g_recognitionThread[i] && g_recognitionThread[i]->joinable())
{
g_recognitionThread[i]->join();
delete g_recognitionThread[i];
g_recognitionThread[i] = nullptr;
}
if(g_recognitionRunning[i])
{
delete g_recognitionRunning[i];
g_recognitionRunning[i] = nullptr;
}
}
DestoryCamera();
DestoryLowMac();
}
void Widget::on_btn_start_clicked()
{
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();
g_traditional_enable[1] = !this->ui->tra_enable_1->isChecked();
this->isCamRunning = true;
// 热身两个工作者
for(int i = 0; i < 2; ++i)
{
g_runner_array[i]->warm_up();
}
// 启动检测工作者线程
for(int i = 0; i < 2; ++i)
{
g_recognitionRunning[i]->store(true);
g_recognitionThread[i] = new std::thread(detectionWorker, i);
// 获取线程的本地句柄
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
{
std::cerr << "SET thread " << i << " failed, error code" << GetLastError() << std::endl;
}
}
Start_camera();
}
void Widget::on_btn_take_photos_pressed()
{
SaveImg_Flag = true;
}
void Widget::on_btn_take_photos_released()
{
SaveImg_Flag = false;
}
void Widget::on_btn_quit_clicked()
{
qApp->quit();
}