-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.cpp
More file actions
257 lines (227 loc) · 6.67 KB
/
script.cpp
File metadata and controls
257 lines (227 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#include "script.h"
#include "./UI/mainwindow.h"
#include "./UI/ui_mainwindow.h"
#include <QCoreApplication>
#include <QObject>
#include <QPixmap>
#include <QSize>
// json数据处理(数据库配置)
#include <QJsonDocument>
#include <QJsonObject>
using namespace std;
Script::~Script()
{
if (p_thread) {
p_thread->Stop();
delete p_thread; // 释放线程
}
delete session;
std::cout << "player close." << std::endl;
std::cout << "deleted yolo and mainwindow." << std::endl;
delete imageProcessor;
delete *database_ptr;
delete database_ptr;
}
void Script::Configurate(){
// 数据库配置
QFile configFile;
int ret = loadConfig(configFile);// 读取配置文件
if (ret < 0) {
// 配置出现问题将删除错误的配置文件
configFile.remove();
return;
}
// yolo = new Yolo(nullptr);
// facenet配置
// try {
// QString modelPath = mw->ui->le_facenetonnx->text();
// facenet = new FaceNet(modelPath);
// }
// catch(const Ort::Exception& e)
// {
// QMessageBox::critical(nullptr, "Facenet error", e.what());
// return;
// }
// 模型初始化放在主窗口里(构造函数)
if(!yolo->isLoaded || !facenet->isLoaded){
QMessageBox::critical(nullptr, "Init error", "Yolo or Facenet is nullptr.");
return;
}
std::cout << "Created yolo." << std::endl;
qRegisterMetaType<cv::Mat>("cv::Mat");
imageProcessor = new ImageProcessor(yolo, facenet, getCurrentDatabase());
imageProcessor->setCallback([this](const QPixmap& img) {
// 在主线程中更新 UI
QMetaObject::invokeMethod(this, [this, img]() {
updateUI(img);
}, Qt::QueuedConnection);
});
std::cout << "Processor set callback." << std::endl;
startProcessingTimer();
isinite = true;
}
int Script::loadConfig(QFile &configFile) {
// 获取用户目录
QString configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
QDir().mkpath(configPath);
configFile.setFileName(configPath + "/db_config.json");// 配置文件路径
qDebug() << configPath;
// 读取配置文件
if (configFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QByteArray jsonData = configFile.readAll();
configFile.close();
// 解析json数据
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
if (jsonDoc.isNull()) {
std::cerr << "Error : Failed to parse the configuration file." << std::endl;
perror("Error message");
return -1;
}
// 转换为json对象
QJsonObject jsonObj = jsonDoc.object();
// 读取数据库配置
string host = jsonObj.value("host").toString("localhost").toStdString();
unsigned int port = jsonObj.value("port").toString("3306").toUInt();
string userName = jsonObj.value("userName").toString("root").toStdString();
string password = jsonObj.value("password").toString().toStdString();
// 设置数据库连接名称 在UI中显示
mw->ui->le_storagefile->setText(jsonObj.value("connectionName").toString(""));
// 初始化数据库连接
try {
*database_ptr = new FaceDatabase(host, userName, password, "FaceDB", port);
std::cout << "Database connected." << std::endl;
}
catch (const std::runtime_error& e){
std::cerr << e.what() << std::endl;
QMessageBox::critical(nullptr, "Database error", e.what());
return -1;
}
return 0;
}
else {
std::cerr << "Error : Failed to open the configuration file." << std::endl;
perror("Error message");
return -1;
}
return 0;
}
void Script::startProcessingTimer() {
processingTimer = new QTimer(this);
connect(processingTimer, &QTimer::timeout, this, &Script::processNextFrame);
processingTimer->start(10); // 每50ms处理一帧,可以根据需要调整
}
void Script::processNextFrame() {
cv::Mat frame;
{
QMutexLocker locker(&queueMutex);
if (!frameQueue.isEmpty()) {
frame = frameQueue.dequeue();
// 主动清理队列
if (frameQueue.size() > 25) {
while (frameQueue.size() > 25) {
cv::Mat old_frame = frameQueue.dequeue();
old_frame.release();
}
}
}
}
if (!frame.empty()) {
imageProcessor->setImage(frame);
frame.release();
}
}
int Script::ensureEnter(std::string modelPath, std::string url)// 初始化检测线程
{
// 判断初始化
if (!isinite) { //若数据库连接初始化出现问题,将会直接退出函数,因此需要判断是否已经初始化
std::cout << "Script is not inited." << std::endl;
if(!yolo->loadModel(QString::fromStdString(modelPath))){
std::cerr << "Session load model failed." << std::endl;
return -1;
}
Configurate();
if(isinite){
rtsp_url = url;
std::cout << "Script is inited." << std::endl;
return 0;
}
return -1;
}
rtsp_url = url;
std::cout << "Script is inited." << std::endl;
imageProcessor->resetHSWN();
std::cout << "Reset HSWN." << std::endl;
return 0;
}
int Script::play() {
if(!isinite) return -1;
// 确认拉流链接的合法性
bool is_rtspurl = string_compare(rtsp_url, "rtsp://");
QObject::connect(yolo, &Yolo::signal_str, this,
[this] (QString str) {
mw->ui->te_onnxmessage->append(str);
});
if ( is_rtspurl || 1 ) {
// 创建拉流线程
if (p_thread) {
p_thread->Stop();
while(!p_thread->isFinished()){
std::cout << "Waitting...." << std::endl;
}
delete p_thread; // 释放线程
imageProcessor->paused = true; // 停止处理线程
}
p_thread = new PlayThread(rtsp_url);
std::cout << "PlayThread created." << std::endl;
p_thread->Start();
imageProcessor->paused = false; // 开始处理线程
// 拉流信号
QObject::connect(p_thread, &PlayThread::pixframesSignal, this,
&Script::prossPixSignal);
QObject::connect(p_thread, &PlayThread::cvframesSignal, this,
&Script::prossCVSignal);
return 0;
} else return -1;
return 0;
}
void Script::pasue()
{
if (p_thread) {
p_thread->Pause(1);
}
isPause = true;
}
void Script::resume()
{
if (p_thread) {
p_thread->Pause(0);
}
isPause = false;
}
void Script::prossPixSignal(QPixmap image){
// 按 label 大小等比例缩放图像
QSize labelSize = mw->ui->lb_camera->size();
// 设置缩放后的图像
mw->ui->lb_camera->setPixmap(image.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
void Script::prossCVSignal(cv::Mat image) {
if (isPause) {
image.release();
return; // 若处于暂停状态,则不处理图像
}
QMutexLocker locker(&queueMutex);
if (frameQueue.size() < 30) { // 限制队列大小,防止内存溢出
frameQueue.enqueue(std::move(image));
p_thread->Pause(0);
} else {
p_thread->Pause(1);
image.release();
}
}
// 更新UI显示图像
void Script::updateUI(QPixmap image) {
QPixmap scaledPixmap = image.scaled(mw->ui->lb_camera->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
mw->ui->lb_camera->setPixmap(scaledPixmap);
scaledPixmap = QPixmap();
image = QPixmap();
}