当前位置:   article > 正文

基于PaddleDetection的疲劳驾驶检测系统_paddledetection 车辆检测 c++应用接口

paddledetection 车辆检测 c++应用接口

项目简介

每一年,中国都因交通事故而造成数万人的死亡,造成了严重的损失。而其中司机疲劳驾驶,是导致事故发生的重要原因之一。但是当司机们陷入疲劳驾驶状态时,往往司机本人对此状态并不在意,甚至会陷入睡眠状态!整治疲劳驾驶行为成为了交通运输行业的首要任务。随着信息技术的日新月异,如今,我们有机会使用信息技术,消除疲劳驾驶的隐患。利用移动端设备的摄像头,我们可以实现实时的监测司机的状态。使用PaddleDetection+PaddleLite部署及Paddle2onnx转IR的OpenVINO部署,实现了通过驾驶员的眼部、嘴部动作实时推断疲劳状态,使得驾驶员能及时的被本地语音方式提醒,避免疲劳驾驶,同时后台管理人员能接收到司机疲劳报警信息。

下载完整代码在本地运行

GitHub链接: FatigueDriving

数据预处理-调整数据集

数据来源:AIStudio公开数据集:疲劳驾驶行为数据集

公开数据集为VOC格式,并划分训练集:验证集:测试集=7:2:1

  • 数据示例:

# 解压数据集
!unzip /home/aistudio/data/data106856/fatigue.zip
  • 1
  • 2
# 调整数据集的反斜杠问题
f = open('/home/aistudio/fatigue/val_list.txt')
data = f.read()
data2 = data.replace('\\', '/')
  • 1
  • 2
  • 3
  • 4
f1 = open('/home/aistudio/fatigue/val_list.txt','w')
f1.write(data2)
  • 1
  • 2
# 解压PaddleDetection
!unzip /home/aistudio/data/data122193/PaddleDetection.zip
  • 1
  • 2
# 安装PaddleDetection依赖环境
!pip install -r PaddleDetection/requirements.txt
  • 1
  • 2

平台1:使用PaddleLite部署至树莓派—模型训练及导出(PaddleLite)

ARM下部署选用了ssd算法,转为nb模型后使用PaddleLite做部署
# 模型训练
# 修改ssdlite_mobilenet_v3_small_320_coco.yml中数据集格式为'../datasets/voc.yml', 并将'../datasets/voc.yml'里的数据路径改为当前数据集目录,以适配疲劳驾驶数据集
!python PaddleDetection/tools/train.py -c PaddleDetection/configs/ssd/ssdlite_mobilenet_v3_small_320_coco.yml --use_vdl=True --eval
  • 1
  • 2
  • 3
!python PaddleDetection/tools/infer.py -c PaddleDetection/configs/ssd/ssdlite_mobilenet_v3_small_320_coco.yml \  
                        -o weights=output/ssdlite_mobilenet_v3_small_320_coco/best_model.pdparams \
                        --infer_img= ./0.jpg #(需要检测的图片)
  • 1
  • 2
  • 3
# 导出ssd模型
python PaddleDetection/tools/export_model.py -c PaddleDetection/configs/ssd/ssdlite_mobilenet_v3_small_320_coco.yml \
                            --output_dir=./ssd_inference_model \
                            -o weights=output/ssdlite_mobilenet_v3_small_320_coco/best_models.pdparams
  • 1
  • 2
  • 3
  • 4
# 安装PaddleLite
!pip install paddlelite
  • 1
  • 2
# 转换为PaddleLite部署需要的nb模型
!paddle_lite_opt \
    --model_file=ssd_inference_model/ssdlite_mobilenet_v3_small_320_coco/model.pdmodel \
    --param_file=ssd_inference_model/ssdlite_mobilenet_v3_small_320_coco/model.pdiparams \
    --optimize_out=ssd_inference_model/ssdlite_mobilenet_v3_small_320_coco/model \
    --optimize_out_type=naive_buffer \
    --valid_targets=arm 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

PaddleLite推理部分代码

// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle_api.h"
#include <arm_neon.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <vector>
#include <limits>
#include <fstream>

//#include <wiringPi.h>

int WARMUP_COUNT = 0;
int REPEAT_COUNT = 1;
const int CPU_THREAD_NUM = 2;
const paddle::lite_api::PowerMode CPU_POWER_MODE =
    paddle::lite_api::PowerMode::LITE_POWER_HIGH;
const std::vector<int64_t> INPUT_SHAPE = {1, 3, 320, 320}; //输入形状
const std::vector<float> INPUT_MEAN = {0.5f, 0.5f, 0.5f};  //输入平均值
const std::vector<float> INPUT_STD = {0.5f, 0.5f, 0.5f};   //输入标准
const float SCORE_THRESHOLD = 0.5f;                        //分数阈值
const std::string file_number = "434343434343";            //用户编号
struct RESULT {
  std::string class_name;
  float score;
  float left;
  float top;
  float right;
  float bottom;
};
// 获取时间
inline int64_t get_current_us() {
  struct timeval time;
  gettimeofday(&time, NULL);
  return 1000000LL * (int64_t)time.tv_sec + (int64_t)time.tv_usec;
}
// 年月日时分秒
static std::string getCurrentTimeStr()
{
	time_t t = time(NULL);
	char ch[64] = {0};
	strftime(ch, sizeof(ch) - 1, "%Y%m%d%H%M", localtime(&t));     //年-月-日-时-分
	return ch;
}
// 加载标签
std::vector<std::string> load_labels(const std::string &path) {
  std::ifstream file;
  std::vector<std::string> labels;
  file.open(path);
  while (file) {
    std::string line;
    std::getline(file, line);
    labels.push_back(line);
  }
  file.clear();
  file.close();
  return labels;
}
// 预处理
void preprocess(cv::Mat &input_image, const std::vector<float> &input_mean,
                const std::vector<float> &input_std, int input_width,
                int input_height, float *input_data) {
  cv::Mat resize_image;
  cv::resize(input_image, resize_image, cv::Size(input_width, input_height), 0, 0);
  if (resize_image.channels() == 4) {
    cv::cvtColor(resize_image, resize_image, 3);
  }
  cv::Mat norm_image;
  resize_image.convertTo(norm_image, CV_32FC3, 1 / 255.f);
  // NHWC->NCHW
  int image_size = input_height * input_width;
  const float *image_data = reinterpret_cast<const float *>(norm_image.data);
  float32x4_t vmean0 = vdupq_n_f32(input_mean[0]);
  float32x4_t vmean1 = vdupq_n_f32(input_mean[1]);
  float32x4_t vmean2 = vdupq_n_f32(input_mean[2]);
  float32x4_t vscale0 = vdupq_n_f32(1.0f / input_std[0]);
  float32x4_t vscale1 = vdupq_n_f32(1.0f / input_std[1]);
  float32x4_t vscale2 = vdupq_n_f32(1.0f / input_std[2]);
  float *input_data_c0 = input_data;
  float *input_data_c1 = input_data + image_size;
  float *input_data_c2 = input_data + image_size * 2;
  int i = 0;
  for (; i < image_size - 3; i += 4) {
    float32x4x3_t vin3 = vld3q_f32(image_data);
    float32x4_t vsub0 = vsubq_f32(vin3.val[0], vmean0);
    float32x4_t vsub1 = vsubq_f32(vin3.val[1], vmean1);
    float32x4_t vsub2 = vsubq_f32(vin3.val[2], vmean2);
    float32x4_t vs0 = vmulq_f32(vsub0, vscale0);
    float32x4_t vs1 = vmulq_f32(vsub1, vscale1);
    float32x4_t vs2 = vmulq_f32(vsub2, vscale2);
    vst1q_f32(input_data_c0, vs0);
    vst1q_f32(input_data_c1, vs1);
    vst1q_f32(input_data_c2, vs2);
    image_data += 12;
    input_data_c0 += 4;
    input_data_c1 += 4;
    input_data_c2 += 4;
  }
  for (; i < image_size; i++) {
    *(input_data_c0++) = (*(image_data++) - input_mean[0]) / input_std[0];
    *(input_data_c0++) = (*(image_data++) - input_mean[1]) / input_std[1];
    *(input_data_c0++) = (*(image_data++) - input_mean[2]) / input_std[2];
  }
}
// 后处理
std::vector<RESULT> postprocess(const float *output_data, int64_t output_size,
                                const std::vector<std::string> &word_labels,
                                const float score_threshold,
                                cv::Mat &output_image, double time) {
  std::vector<RESULT> results;
  std::vector<cv::Scalar> colors = {
      cv::Scalar(237, 189, 101), cv::Scalar(0, 0, 255), cv::Scalar(102, 153, 153),
      cv::Scalar(255, 0, 0), cv::Scalar(9, 255, 0), cv::Scalar(0, 0, 0),
      cv::Scalar(51, 153, 51)};
  for (int64_t i = 0; i < output_size; i += 6) {
    if (output_data[i + 1] < score_threshold) {
      continue;
    }
    int class_id = static_cast<int>(output_data[i]);
    float score = output_data[i + 1];
    RESULT result;
    std::string class_name = "Unknown";
    if (word_labels.size() > 0 && class_id >= 0 && 
        class_id < word_labels.size()) {
      class_name = word_labels[class_id];
    }
    result.class_name = class_name;
    result.score = score;
    result.left = output_data[i + 2];
    result.top = output_data[i + 3];
    result.right = output_data[i + 4];
    result.bottom = output_data[i + 5];
    int lx = static_cast<int>(result.left * output_image.cols);
    int ly = static_cast<int>(result.top * output_image.rows);
    int w = static_cast<int>(result.right * output_image.cols) - lx;
    int h = static_cast<int>(result.bottom * output_image.rows) - ly;
    cv::Rect bounding_box = cv::Rect(lx, ly, w, h) &
        cv::Rect(0, 0, output_image.cols, output_image.rows);
    if (w > 0 && h > 0 && score <= 1) {
      cv::Scalar color = colors[results.size() % colors.size()];
      cv::rectangle(output_image, bounding_box, color);
      cv::rectangle(output_image, cv::Point2d(lx, ly), cv::Point2d(lx + w, ly - 10),
                    color, -1);
      cv::putText(output_image,
                  std::to_string(results.size()) + "." + class_name + ":" +
                      std::to_string(score),
                  cv::Point2d(lx, ly), cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(255, 255, 255));
      results.push_back(result);
    }
  }
  return results;
}
//识别处理
cv::Mat process(cv::Mat &input_image,
                std::vector<std::string> &word_labels,
                std::shared_ptr<paddle::lite_api::PaddlePredictor> &predictor) {
  // 对图像进行预处理,填充输入张量数据
  std::unique_ptr<paddle::lite_api::Tensor> input_tensor(
      std::move(predictor->GetInput(0)));
  input_tensor->Resize(INPUT_SHAPE);
  int input_width = INPUT_SHAPE[3];
  int input_height = INPUT_SHAPE[2];
  auto *input_data = input_tensor->mutable_data<float>();
  double preprocess_start_time = get_current_us();
  preprocess(input_image, INPUT_MEAN, INPUT_STD, input_width, input_height,
             input_data);
  double preprocess_end_time = get_current_us();
  double preprocess_time = (preprocess_end_time - preprocess_start_time) / 1000.0f;

  double prediction_time;
  // 运行预测
  for (int i = 0; i < WARMUP_COUNT; i++) {
    predictor->Run();
  }
  double max_time_cost = 0.0f;
  double min_time_cost = std::numeric_limits<float>::max();
  double total_time_cost = 0.0f;
  for (int i = 0; i < REPEAT_COUNT; i++) {
    auto start = get_current_us();
    predictor->Run();
    auto end = get_current_us();
    double cur_time_cost = (end - start) / 1000.0f;
    if (cur_time_cost > max_time_cost) {
      max_time_cost = cur_time_cost;
    }
    if (cur_time_cost < min_time_cost) {
      min_time_cost = cur_time_cost;
    }
    total_time_cost += cur_time_cost;
    prediction_time = total_time_cost / REPEAT_COUNT;
    printf("iter %d cost: %f ms\n", i, cur_time_cost);
  }
  printf("warmup: %d repeat: %d, average: %f ms, max: %f ms, min: %f ms\n",
         WARMUP_COUNT, REPEAT_COUNT, prediction_time,
         max_time_cost, min_time_cost);

  // 获取输出张量数据,进行后处理,输出检测对象
  std::unique_ptr<const paddle::lite_api::Tensor> output_tensor(
      std::move(predictor->GetOutput(0)));
  const float *output_data = output_tensor->mutable_data<float>();
  int64_t output_size = 1;
  for (auto dim : output_tensor->shape()) {
    output_size *= dim;
  }
  cv::Mat output_image = input_image.clone();
  double postprocess_start_time = get_current_us();
  std::vector<RESULT> results = postprocess(
      output_data, output_size, word_labels, SCORE_THRESHOLD, output_image, prediction_time);
  double postprocess_end_time = get_current_us();
  double postprocess_time = (postprocess_end_time - postprocess_start_time) / 1000.0f;
  
  // wiringPi 
  //wiringPiSetup();
  std::string warning_content_0 = "closed_eye";
  std::string warning_content_1 = "open_mouth";
  std::string time_ymdhms = getCurrentTimeStr();
  
  // 结果输出
  printf("results: %d\n", results.size());
  for (int i = 0; i < results.size(); i++) {
  // GPIO 0 高电平输出触发蜂鸣器
  // pinMode(0,OUTPUT);
	// 存储图像
    if (results[i].class_name.c_str()==warning_content_0)
    {
      std::string output_path = "./fatigueDriving/screenshots/Q" + file_number + time_ymdhms + warning_content_0 + ".jpg";
      cv::imwrite(output_path,output_image);
    }
    if (results[i].class_name.c_str()==warning_content_1){
      std::string output_path = "./fatigueDriving/screenshots/Q" + file_number + time_ymdhms + warning_content_1 + ".jpg";
      cv::imwrite(output_path,output_image);
    }

    // if (results[i].class_name.c_str()==warning_content){digitalWrite(0,HIGH);delay(20);digitalWrite(0,LOW);delay(1);cv::imwrite(output_path,output_image);delay(1);}
    // else{digitalWrite(0,LOW);delay(1);}
    printf("[%d] %s - %f %f,%f,%f,%f\n", i, results[i].class_name.c_str(),
           results[i].score, results[i].left, results[i].top, results[i].right,
           results[i].bottom);
  }
  printf("Preprocess time: %f ms\n", preprocess_time);
  printf("Prediction time: %f ms\n", prediction_time);
  printf("Postprocess time: %f ms\n\n", postprocess_time);

  return output_image;
}

int main(int argc, char **argv) {
  // 加载模型地址
  std::string model_path = argv[1];
  // 加载标签地址
  std::string label_path = argv[2];
  // 加载标签
  std::vector<std::string> word_labels = load_labels(label_path);
  // 加载模型
  paddle::lite_api::MobileConfig config;
  config.set_model_from_file(model_path);
  config.set_threads(CPU_THREAD_NUM);
  config.set_power_mode(CPU_POWER_MODE);

  std::shared_ptr<paddle::lite_api::PaddlePredictor> predictor =
      paddle::lite_api::CreatePaddlePredictor<paddle::lite_api::MobileConfig>(config);
  // 视频流预测
  cv::VideoCapture cap(-1);
  cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
  cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
  // 判断是否开启摄像头
  if (!cap.isOpened()) {
    return -1;
  }
  // 执行
  while (1) {
    cv::Mat input_image;
    cap >> input_image;
    cv::Mat output_image = process(input_image, word_labels, predictor);
    cv::imshow("Real-Time", output_image);
    if (cv::waitKey(1) == char('q')) {
      break;
    }
  }
  cap.release();
  cv::destroyAllWindows();
  return 0;
}
  • 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
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298

平台2:使用OpenVINO部署至Windows系统—模型训练及模型导出

IntelCPU下部署选用了yolov3算法,转为IR模型后使用OpenVINO做部署,可使用核显加速
# 模型训练
!python PaddleDetection/tools/train.py -c PaddleDetection/configs/yolov3/yolov3_mobilenet_v3_large_270e_voc.yml --use_vdl=True --eval
  • 1
  • 2
!python PaddleDetection/tools/infer.py -c PaddleDetection/configs/yolov3/yolov3_mobilenet_v3_large_270e_voc.yml \  
                        -o weights=output/yolov3_mobilenet_v3_large_270e_voc/best_model.pdparams \
                        --infer_img= ./0.jpg #(需要检测的图片)
  • 1
  • 2
  • 3
# 安装paddle2onnx
%cd /home/aistudio/
# !git clone https://github.com/PaddlePaddle/Paddle2ONNX.git
!unzip Paddle2ONNX-develop.zip
%cd Paddle2ONNX-develop
# !git checkout release/0.9
!python setup.py install

%cd experimental
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
!pip install onnx
  • 1
import paddle2onnx
import paddle
from openvino_ppdet import nms_mapper
# 通过上面的`nms_mapper`的import来启用插件,替换了paddle2onnx原始的nms_mapper

model_prefix = "/home/aistudio/yolov3-output/yolov3_mobilenet_v3_large_270e_voc/" # 一直写到模型文件名
model = paddle.jit.load(model_prefix)
input_shape_dict = {
    "image": [1, 3, 608, 608],
    "scale_factor": [1, 2],
    "im_shape": [1, 2]
    }
onnx_model = paddle2onnx.run_convert(model, input_shape_dict=input_shape_dict, opset_version=11)

with open("./yolov3.onnx", "wb") as f:
    f.write(onnx_model.SerializeToString())

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

到此步骤后我们可以得到XXX.onnx模型文件,再使用OpenVINOmo命令转换为IR模型文件。具体操作请参照OpenVINO使用文档

OpenVINO推理部分代码

#include "fatigueDriving.h"


fatigueDriving::fatigueDriving() {};
fatigueDriving::~fatigueDriving() {};

int fatigueDriving::Init(std::string modelPath, bool useIntelgpu)
{
	std::string xmlPath, binPath;
	// 加载模型
	std::cout << "Loading model ... " << std::endl;
	xmlPath = modelPath + "/yolov3.xml";
	binPath = modelPath + "/yolov3.bin";

	network = ie.ReadNetwork(xmlPath, binPath);
	// 载至cpu/gpu
	try {
		executableNetwork = ie.LoadNetwork(network, useIntelgpu ? "GPU" : "CPU");
		std::cout << "Loading model succeeded!" << std::endl;
	}
	catch (...) {
		return -2;
	}
	// 构建预测
	inferRequest = executableNetwork.CreateInferRequest();
	// 获取输入输出的Blob
	inputImage = inferRequest.GetBlob("image");
	inputImShape = inferRequest.GetBlob("im_shape");
	inputScaleFactor = inferRequest.GetBlob("scale_factor");
	outputInfo = inferRequest.GetBlob("translated_layer/scale_0.tmp_0");
	// 输入尺寸
	inputChannelsNumber = inputImage->getTensorDesc().getDims()[1];
	inputHeight = inputImage->getTensorDesc().getDims()[2];
	inputWidth = inputImage->getTensorDesc().getDims()[3];
	// 输出尺寸
	outputBboxesNumber = outputInfo->getTensorDesc().getDims()[0];
	outputSingleInfo = outputInfo->getTensorDesc().getDims()[1];

	return 1;
}


int fatigueDriving::Process(const cv::Mat img, std::vector<std::vector<float>> &outputs, float scoreThreshold)
{
	if (!img.data)return -1;//判断是否有数据
	std::vector<float> mean;
	mean.push_back(0.485f);
	mean.push_back(0.456f);
	mean.push_back(0.406f);
	std::vector<float> std;
	std.push_back(0.229f);
	std.push_back(0.224f);
	std.push_back(0.225f);
	cv::Mat image;
	cv::cvtColor(img, image, cv::COLOR_BGR2RGB);
	cv::resize(image, image, cv::Size(inputWidth, inputHeight));
	// HWC =》NCHW
	float* data = static_cast<float*>(inputImage->buffer());
	size_t image_size = inputHeight * inputWidth;
	for (size_t row = 0; row < inputHeight; ++row) {
		for (size_t col = 0; col < inputWidth; ++col) {
			for (size_t ch = 0; ch < inputChannelsNumber; ++ch) {
				data[image_size * ch + row * inputWidth + col] = ((image.at<cv::Vec3b>(row, col)[ch]) / 255.0f) - float(mean[ch]) / std[ch];
			}
		}
	}
    // 输入尺寸
	float* im_shape = static_cast<float*>(inputImShape->buffer());
	im_shape[0] = image.rows;
	im_shape[1] = image.cols;
	// 缩放因子
	float* scale_factor = static_cast<float*>(inputScaleFactor->buffer());
	scale_factor[0] = inputHeight / float(img.rows);
	scale_factor[1] = inputWidth / float(img.cols);
	// 预测
	clock_t time_start = clock();
	inferRequest.Infer();
	clock_t time_temp = clock();

	// 获取输出
	std::vector<float> output;
	auto output_data = outputInfo->buffer().as<InferenceEngine::PrecisionTrait<InferenceEngine::Precision::FP32>::value_type*>();
	for (int i = 0; i < outputBboxesNumber; i++) {
		for (int j = 0; j < outputSingleInfo; j++) {
			output.push_back(output_data[i * outputSingleInfo + j]);
		}
		if (output[1] > scoreThreshold) {
			outputs.push_back(output);
		}
		output.clear();
	}
	return 1;
}
  • 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

c++版OpenVINO部署转python接口

#include <pybind11/stl.h>
#include <pybind11/cast.h>
#include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>

#include "fatigueDriving.h"

namespace py = pybind11;

py::array ConvertMatToNDArray(cv::Mat& m);

PYBIND11_MODULE(pyFatigueDriving, m)
{

	m.attr("__doc__") = "paddle interface";
	m.attr("__version__") = "v0.1.0";
	m.def("ConvertNDArrayToMat", [](py::array_t<uchar>& input_data)
		{
			cv::Mat dst = ConvertNDArrayToMat(input_data);
			return dst;
		}, py::arg("input_data"));
	py::class_<cv::Mat>(m, "cvMat");
	py::class_<fatigueDriving>(m, "fatigueDriving")
		.def(py::init<>())
		.def("Init", &fatigueDriving::Init)
		.def("Process", [](fatigueDriving& vc, const cv::Mat& img, float scoreThreshold)
			{
				std::vector<std::vector<float>> outputs;
				int ret = vc.Process(img, outputs, scoreThreshold);
				return py::make_tuple(ret, outputs);
			}, py::arg("img"), py::arg("scoreThreshold"));
}
  • 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

实时检测驾驶员:违规时,信息写入数据库+语音提示

通过检测部分的存储违规图像动作,触发语音提示及信息记录功能

PC端 - main.py
import os
import _thread
import sys
import time
import threading
import cv2
import numpy as np
import pygame
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
from watchdog.events import *
from watchdog.observers import Observer
from MySQL_Connect import MySQL_Connect

# 加载openvino部署封装的dll及pyd
os.add_dll_directory(os.path.join(os.getcwd(), "./OpenVINO/dlls/"))
sys.path.append(os.path.join(os.getcwd(), "./OpenVINO/libs/"))
import pyFatigueDriving

# 播放警示音频
class Play_Audio():
    def __init__(self, audio):
        self.audio = audio

    def run(self):
        pygame.mixer.init()
        pygame.mixer.music.load(self.audio)  # './audio/warning.mp3'
        pygame.mixer.music.play()
        time.sleep(7)
        pygame.mixer.music.stop()

class MyDirEventHandler(FileSystemEventHandler):

    def __init__(self):
        FileSystemEventHandler.__init__(self)
        self.audio = './audio/warning.mp3'
        self.warning = Play_Audio(self.audio)

    def on_created(self, event):
        
        print("file created:{0}".format(event.src_path))
        a = str(event.src_path)
        self.warning.run()


# 转换为可存储到数据库的格式
def save_received_info(user_info, iolations_time, new_filename):
    user_all_info = {}
    user_all_info['编号'] = user_info[0]
    user_all_info['姓名'] = user_info[1]
    user_all_info['性别'] = user_info[2]
    user_all_info['年龄'] = user_info[3]
    user_all_info['身份证号'] = user_info[4]
    user_all_info['联系电话'] = user_info[5]
    user_all_info['省份'] = user_info[6]
    user_all_info['城市'] = user_info[7]
    user_all_info['区/县'] = user_info[8]
    user_all_info['车型'] = user_info[9]
    user_all_info['行驶证编号'] = user_info[10]
    user_all_info['车牌号'] = user_info[11]
    user_all_info['违规时间'] = iolations_time
    user_all_info['违规证据图像位置'] = new_filename
    print(user_all_info)
    return user_all_info

# 信息记录至SQL
def ToSQL(a, module_name):
    # 初始化SQL
    MySQL = MySQL_Connect()
    # 拉取用户数据
    number = module_name[1:13]
    iolations_time = module_name[13:17]+'-'+module_name[17:19] + \
        '-'+module_name[19:21]+' '+module_name[21:23]+':'+module_name[23:25]
    user_info = MySQL.MC_SELECT_User_Info(local_info=number)[0]
    # 生成数据列表
    user_list_violation_info = save_received_info(
        user_info, iolations_time, a)
    MySQL.MC_Save_Violation_Info(user_list_violation_info)

# 执行预测
def run_detection_win_py(savepath):
    file_number = "434343434343"
    cap =cv2.VideoCapture(0)
    while(True):
        nowtime = time.strftime("%Y%m%d%H%M%S")
        ret , frame =cap.read()
        ret, output = fd.Process(pyFatigueDriving.ConvertNDArrayToMat(frame), 0.1)
        for single_info in output:
            cv2.rectangle(frame, (int(single_info[2]), int(single_info[3])), (int(single_info[4]), int(single_info[5])), (0, 0, 255), 1, 4)
            label = str(int(single_info[0])) + ': ' + str(single_info[1])
            cv2.putText(frame, label, (int(single_info[2]), int(single_info[3])), cv2.FONT_HERSHEY_COMPLEX, 2, (0, 0, 255), 1, 4)
            if int(single_info[0]) == 0:
                module_name = 'Q' + file_number + nowtime + str(single_info[0]) + '.jpg'
                savefile = savepath + module_name
                cv2.imwrite(savefile, frame)
                ToSQL(savefile, module_name)
                break
            if int(single_info[0]) == 3:
                if ((single_info[5]-single_info[3])/(single_info[4]-single_info[2])>=0.9):
                    module_name = 'Q' + file_number + nowtime + str(single_info[0]) + '.jpg'
                    savefile = savepath + module_name
                    cv2.imwrite(savefile, frame)
                    ToSQL(savefile, module_name)
                    break
        cv2.imshow("real-time", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

# 监控文件的变化
def run_scan_file(file_name):
    # 创建观察者对象
    observer = Observer()
    # 创建事件处理对象
    fileHandler = MyDirEventHandler()
    # 为观察者设置观察对象与处理事件对象
    observer.schedule(
        fileHandler, file_name, True)
    observer.start()
    try:
        while True:
            time.sleep(2)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == '__main__':
    fd = pyFatigueDriving.fatigueDriving()
    modelPath = "./models/yolov3_ir"
    useIntelGPU = False
    ret = fd.Init(modelPath, useIntelGPU)
    try:
        # 识别线程
        savepath="./screenshots/"
        getDetect = threading.Thread(target=run_detection_win_py, args=(savepath, ))
        getDetect.start()
        # 警示线程
        file_name="C:/project/FatigueDriving/screenshots"
        getWarning = threading.Thread(target=run_scan_file, args=(file_name, ))
        getWarning.start()
    except Exception as e:
        print("多线程异常,异常信息:{}".format(e))
  • 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
移动端 - arm_main.py
import os
import _thread
import sys
import time
import threading
import cv2
import numpy as np
import pygame
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
from watchdog.events import *
from watchdog.observers import Observer
from MySQL_Connect import MySQL_Connect

# 执行预测-raspi端
def run_detection_raspi(sh_name):
    subprocess.run(sh_name, shell=True)


# 转换为可存储到数据库的格式
def save_received_info(user_info, iolations_time, new_filename):
    user_all_info = {}
    user_all_info['编号'] = user_info[0]
    user_all_info['姓名'] = user_info[1]
    user_all_info['性别'] = user_info[2]
    user_all_info['年龄'] = user_info[3]
    user_all_info['身份证号'] = user_info[4]
    user_all_info['联系电话'] = user_info[5]
    user_all_info['省份'] = user_info[6]
    user_all_info['城市'] = user_info[7]
    user_all_info['区/县'] = user_info[8]
    user_all_info['车型'] = user_info[9]
    user_all_info['行驶证编号'] = user_info[10]
    user_all_info['车牌号'] = user_info[11]
    user_all_info['违规时间'] = iolations_time
    user_all_info['违规证据图像位置'] = new_filename
    print(user_all_info)
    return user_all_info

# 信息记录至SQL
def ToSQL(a, module_name):
    # 初始化SQL
    MySQL = MySQL_Connect()
    # 拉取用户数据
    number = module_name[1:13]
    iolations_time = module_name[13:17]+'-'+module_name[17:19] + \
        '-'+module_name[19:21]+' '+module_name[21:23]+':'+module_name[23:25]
    user_info = MySQL.MC_SELECT_User_Info(local_info=number)[0]
    # 生成数据列表
    user_list_violation_info = save_received_info(
        user_info, iolations_time, a)

    MySQL.MC_Save_Violation_Info(user_list_violation_info)

# 播放警示音频
class Play_Audio():
    def __init__(self, audio):
        self.audio = audio

    def run(self):
        pygame.mixer.init()
        pygame.mixer.music.load(self.audio)  # './audio/warning.mp3'
        pygame.mixer.music.play()
        time.sleep(3)
        pygame.mixer.music.stop()

class MyDirEventHandler(FileSystemEventHandler):

    def __init__(self):
        FileSystemEventHandler.__init__(self)
        self.audio = './audio/warning.mp3'
        self.warning = Play_Audio(self.audio)

    def on_created(self, event):

        print("file created:{0}".format(event.src_path))
        a = str(event.src_path)
        #
        self.warning.run(self.audio)

        directory, module_name = os.path.split(a)
        module_name = os.path.splitext(module_name)[0]

        ToSQL(a, module_name)


# 监控文件的变化
def run_scan_file(file_name):
    # 创建观察者对象
    observer = Observer()
    # 创建事件处理对象
    fileHandler = MyDirEventHandler()
    # 为观察者设置观察对象与处理事件对象
    observer.schedule(
        fileHandler, file_name, True)
    observer.start()
    try:
        while True:
            time.sleep(2)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

"""
多线程
run_detection 执行预测程序
run_scan_file 监控文件的变化
"""
if __name__ == '__main__':
    try:
        # 识别线程
        command='./real_time.sh'
        getDetect = threading.Thread(target=run_detection_raspi, args=(command, ))
        getDetect.start()
        # 警示线程
        file_name="C:/project/FatigueDriving/screenshots"
        getWarning = threading.Thread(target=run_scan_file, args=(file_name, ))
        getWarning.start()
    except Exception as e:
        print("多线程异常,异常信息:{}".format(e))
  • 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

数据库接入 - MySQL_Connect.py

class MySQL_Connect():
    def __init__(self):
        self.write_jud_user_info = 1
        self.write_user_info = "insert into `user_info` values("
        self.write_jud_violation_info = 1
        self.write_violation_info = "insert into `violation_info` values("

        # 加载数据库
        try:
            self._con = sql.Connect(
                host="localhost",
                user="root",
                password="yours",
                database="yours",
                port=<yoursport>,
                charset='utf8'
                )
        except Exception as e:
            print("ERROR: " + e)
            self._con.close()
            #pass

    # 编号判断
    def MC_Number_Judge(self, number):
        if len(number) != 12:
            return False
        else:
            return True

    # 性别判断
    def MC_Sex_Judge(self, sex):
        if sex != '男' and sex != '女':
            return False
        else:
            return True

    # 身份证判断
    def MC_Id_Card_Judge(self, id):
        if len(id) != 18:
            return False
        else:
            return True

    # 电话号判断
    def MC_Phone_Judge(self, tel):
        if len(tel) != 11:
            return False
        else:
            return True

    # 行驶证编号判断
    def MC_Driver_Licenise_Number_Judge(self, num):
        if len(num) != 12:
            return False
        else:
            return True

    # 车牌号判断
    def MC_Licenise_Number_Judge(self, num):
        if len(num) != 7:
            return False
        else:
            return True


    '''----------------------- 用户信息 -----------------------'''
    # 写入用户信息
    def MC_Save_User_Info(self, list_user_info):
        self.list_user_info = list_user_info
        cursor = self._con.cursor()

        if self.MC_Number_Judge(self.list_user_info['编号']):
            self.MC_Insert_User_Info(self.list_user_info['编号'])
        self.MC_Insert_User_Info(self.list_user_info['姓名'])
        if self.MC_Sex_Judge(self.list_user_info['性别']):
            self.MC_Insert_User_Info(self.list_user_info['性别'])
        self.MC_Insert_User_Info(self.list_user_info['年龄'])
        if self.MC_Id_Card_Judge(self.list_user_info['身份证号']):
            self.MC_Insert_User_Info(self.list_user_info['身份证号'])
        if self.MC_Phone_Judge(self.list_user_info['联系电话']):
            self.MC_Insert_User_Info(self.list_user_info['联系电话'])
        self.MC_Insert_User_Info(self.list_user_info['省份'])
        self.MC_Insert_User_Info(self.list_user_info['城市'])
        self.MC_Insert_User_Info(self.list_user_info['区/县'])
        self.MC_Insert_User_Info(self.list_user_info['车型'])
        if self.MC_Driver_Licenise_Number_Judge(self.list_user_info['行驶证编号']):
            self.MC_Insert_User_Info(self.list_user_info['行驶证编号'])
        if self.MC_Licenise_Number_Judge(self.list_user_info['车牌号']):
            self.MC_Insert_User_Info(self.list_user_info['车牌号'])

        self.write_user_info += ")"
        print(self.write_user_info)
        cursor.execute(self.write_user_info)
        self._con.commit()
        cursor.close()
        self.list_user_info.clear()

    # 读取数据库信息
    def MC_Read_User_Info(self):
        try:
            # 创建游标对象
            cursor = self._con.cursor()

            sql = 'SELECT * FROM `user_info`'
            cursor.execute(sql)
            result = cursor.fetchall()
            cursor.close()
        except Exception as e:
            print("ERROR: " + e)
            self._con.rollback()
            cursor.close()

        return result

    # 数据库语言 数据插入
    def MC_Insert_User_Info(self, new):
        if self.write_jud_user_info != 1:
            self.write_user_info += ", "
        self.write_user_info += "'" + new + "'"
        self.write_jud_user_info += 1
    
    # 根据单个变量查询
    def MC_SELECT_User_Info(self, local_info):
        #self.local_info = '434343434343'
        self.local_info = local_info
        try:
            # 创建游标对象
            cursor = self._con.cursor()

            sql = "SELECT * FROM `user_info` WHERE number=%s" % self.local_info
            cursor.execute(sql)
            result = cursor.fetchall()
            cursor.close()
        except Exception as e:
            print("ERROR: " + e)
            self._con.rollback()
            cursor.close()

        return result

    '''----------------------- 违规记录 -----------------------'''
    # 写入违规记录
    def MC_Save_Violation_Info(self, list_violation_info):
        self.list_violation_info = list_violation_info
        cursor = self._con.cursor()

        if self.MC_Number_Judge(self.list_violation_info['编号']):
            self.MC_Insert_Violation_Info(self.list_violation_info['编号'])
        self.MC_Insert_Violation_Info(self.list_violation_info['姓名'])
        if self.MC_Sex_Judge(self.list_violation_info['性别']):
            self.MC_Insert_Violation_Info(self.list_violation_info['性别'])
        self.MC_Insert_Violation_Info(self.list_violation_info['年龄'])
        if self.MC_Id_Card_Judge(self.list_violation_info['身份证号']):
            self.MC_Insert_Violation_Info(self.list_violation_info['身份证号'])
        if self.MC_Phone_Judge(self.list_violation_info['联系电话']):
            self.MC_Insert_Violation_Info(self.list_violation_info['联系电话'])
        self.MC_Insert_Violation_Info(self.list_violation_info['省份'])
        self.MC_Insert_Violation_Info(self.list_violation_info['城市'])
        self.MC_Insert_Violation_Info(self.list_violation_info['区/县'])
        self.MC_Insert_Violation_Info(self.list_violation_info['车型'])
        if self.MC_Driver_Licenise_Number_Judge(self.list_violation_info['行驶证编号']):
            self.MC_Insert_Violation_Info(self.list_violation_info['行驶证编号'])
        if self.MC_Licenise_Number_Judge(self.list_violation_info['车牌号']):
            self.MC_Insert_Violation_Info(self.list_violation_info['车牌号'])
        self.MC_Insert_Violation_Info(self.list_violation_info['违规时间'])
        self.MC_Insert_Violation_Info(self.list_violation_info['违规证据图像位置'])

        self.write_violation_info += ")"
        print(self.write_violation_info)
        cursor.execute(self.write_violation_info)
        self._con.commit()
        cursor.close()
        self.list_violation_info.clear()

    # 读取数据库信息
    def MC_Read_Violation_Info(self):
        try:
            # 创建游标对象
            cursor = self._con.cursor()

            sql = 'SELECT * FROM `violation_info`'
            cursor.execute(sql)
            result = cursor.fetchall()
            cursor.close()
        except Exception as e:
            print("ERROR: " + e)
            self._con.rollback()
            cursor.close()

        return result

    # 数据库语言 信息插入
    def MC_Insert_Violation_Info(self, new):
        if self.write_jud_violation_info != 1:
            self.write_violation_info += ", "
        self.write_violation_info += "'" + new + "'"
        self.write_jud_violation_info += 1
  • 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

可视化界面(GUI)

违规信息查询主界面 - Server_MainGUI.py
# 子窗口 -- 信息录入
class Ui_Info_Entry_Child(Ui_Info_Entry):
    """docstring for Ui_Info_Entry_Child"""
    def __init__(self):
        super(Ui_Info_Entry_Child, self).__init__()
        self.setupUi(self)
# 子窗口 -- 违规信息可视化
class Ui_EvidenceIm_Child(Ui_EvidenceIm):
    """docstring for Ui_EvidenceIm_Child"""

    def __init__(self, impath, oneinfo):
        super(Ui_EvidenceIm_Child, self).__init__(impath,oneinfo)
        self.setupUi(self)
        self.impath = impath
        self.oneinfo = oneinfo
# 主窗口 -- 数据库信息可视化
class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        #self.line = 5
        self.row_num = 1
        self.MainWindow = QtWidgets.QMainWindow()
        self.Info_Entry_Windows = Ui_Info_Entry_Child()
        self.setupUi(self.MainWindow)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1455, 969)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # 省份
        self.server_label_province = QtWidgets.QLabel(self.centralwidget)
        self.server_label_province.setGeometry(QtCore.QRect(0, 10, 51, 21))
        self.server_label_province.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.server_label_province.setObjectName("server_label_province")
        self.server_province = QtWidgets.QComboBox(self.centralwidget)
        self.server_province.setGeometry(QtCore.QRect(60, 10, 111, 22))
        self.server_province.setObjectName("server_province")
        # 市/州
        self.server_label_city = QtWidgets.QLabel(self.centralwidget)
        self.server_label_city.setGeometry(QtCore.QRect(190, 10, 51, 21))
        self.server_label_city.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.server_label_city.setObjectName("server_label_city")
        self.server_city = QtWidgets.QComboBox(self.centralwidget)
        self.server_city.setGeometry(QtCore.QRect(250, 10, 111, 22))
        self.server_city.setObjectName("server_city")
        # 区县
        self.server_label_borough = QtWidgets.QLabel(self.centralwidget)
        self.server_label_borough.setGeometry(QtCore.QRect(380, 10, 51, 21))
        self.server_label_borough.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.server_label_borough.setObjectName("server_label_borough")
        self.server_borough = QtWidgets.QComboBox(self.centralwidget)
        self.server_borough.setGeometry(QtCore.QRect(440, 10, 111, 22))
        self.server_borough.setObjectName("server_borough")
        # 导入
        self.pushButton_import = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_import.setGeometry(QtCore.QRect(590, 10, 111, 23))
        self.pushButton_import.setObjectName("pushButton_import")
        # 更新
        self.pushButton_update = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_update.setGeometry(QtCore.QRect(740, 10, 111, 23))
        self.pushButton_update.setObjectName("pushButton_update")
        # 信息录入
        self.pushButton_info_entry = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_info_entry.setGeometry(QtCore.QRect(1300, 10, 111, 23))
        self.pushButton_info_entry.setObjectName("pushButton_info_entry")
        # 数据表格
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        # self.tableWidget.setSelectionBehavior(
        #     QtWidgets.QAbstractItemView.SelectRows)
        self.tableWidget.setGeometry(QtCore.QRect(10, 50, 1435, 901))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(14)
        self.tableWidget.setRowCount(self.row_num)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(8, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(9, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(10, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(11, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(12, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(13, item)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        # 初始化省份数据
        self.server_province.clear()
        self.server_province.addItem('请选择')
        for key, value in dictPorovince.items():
            self.server_province.addItem(value, QVariant(key))
        # 按扭框被点击事件信号
        self.server_province.activated.connect(self.add_city)
        self.server_city.activated.connect(self.add_borough)
        self.server_borough.activated.connect(self.just_btn_enable)
        self.pushButton_import.clicked.connect(self.import_ok)
        self.pushButton_update.clicked.connect(self.import_ok)
        self.pushButton_info_entry.clicked.connect(self.show_info_entry_windows)
        
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "疲劳驾驶监测数据终端平台"))
        self.server_label_province.setText(_translate("MainWindow", "省份"))
        self.server_label_city.setText(_translate("MainWindow", "市/州"))
        self.server_label_borough.setText(_translate("MainWindow", "区/县"))
        self.pushButton_import.setText(_translate("MainWindow", "导出"))
        self.pushButton_update.setText(_translate("MainWindow", "刷新"))
        self.pushButton_info_entry.setText(_translate("MainWindow", "信息录入"))
        item = self.tableWidget.verticalHeaderItem(0)
        item.setText(_translate("MainWindow", "1"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "编号"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "姓名"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow", "性别"))
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText(_translate("MainWindow", "年龄"))
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText(_translate("MainWindow", "身份证号"))
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText(_translate("MainWindow", "联系电话"))
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText(_translate("MainWindow", "省份"))
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText(_translate("MainWindow", "市/州"))
        item = self.tableWidget.horizontalHeaderItem(8)
        item.setText(_translate("MainWindow", "区/县"))
        item = self.tableWidget.horizontalHeaderItem(9)
        item.setText(_translate("MainWindow", "车型"))
        item = self.tableWidget.horizontalHeaderItem(10)
        item.setText(_translate("MainWindow", "行驶证编号"))
        item = self.tableWidget.horizontalHeaderItem(11)
        item.setText(_translate("MainWindow", "车牌号"))
        item = self.tableWidget.horizontalHeaderItem(12)
        item.setText(_translate("MainWindow", "违规时间"))
        item = self.tableWidget.horizontalHeaderItem(13)
        item.setText(_translate("MainWindow", "操作"))
    # 当省份按钮被选择后添加对应的城市数据
    def add_city(self, index):
        pro_code = self.server_province.itemData(index)
        city_data = dictCity.get(pro_code, dict())
        self.server_city.clear()
        self.server_city.addItem('请选择')
        self.server_borough.clear()
        self.server_borough.addItem('请选择')
        if self.server_province.currentText() != '请选择':
            for key, value in city_data.items():
                self.server_city.addItem(value, QVariant(key))
        self.pushButton_import.setDisabled(True)

    # 当城市按钮被选择后添加对应的区县数据
    def add_borough(self, index):
        city_code = self.server_city.itemData(index)
        borough_data = dicBorough.get(city_code, dict())
        self.server_borough.clear()
        self.server_borough.addItem('请选择')
        if self.server_city.currentText() != '请选择':
            for key, value in borough_data.items():
                self.server_borough.addItem(value, QVariant(key))
        self.pushButton_import.setDisabled(True)

    # 导出按钮是否可用
    def just_btn_enable(self, txt):
        if self.server_borough.currentText() != '请选择':
            self.pushButton_import.setDisabled(False)
        else:
            self.pushButton_import.setDisabled(True)

    # 根据省市县筛选信息导出
    def import_ok(self):
        if self.server_province.currentText() == '请选择':
            QtWidgets.QMessageBox.warning(self, "警告", "请选择省/市/县信息", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        else:
            self.MySQL_Read = MySQL_Connect()
            self.info_all = self.MySQL_Read.MC_Read_Violation_Info()
            # 根据省市县筛选得到的信息存放
            self.info_realdata = []
            # 提取筛选后的各数据对应图片地址
            self.info_realimpath = []
            # 按钮名称
            self.btn_realname = []
            # 遍历提取相应数据
            for i in range(len(self.info_all)):
                if self.info_all[i][6] == self.server_province.currentText() and self.info_all[i][7] == self.server_city.currentText() and self.info_all[i][8] == self.server_borough.currentText():
                    self.info_realdata.append(list(self.info_all[i]))
                    self.info_realimpath.append(str(self.info_all[i][-1]))
                    self.btn_realname.append(str('详情:'+self.info_all[i][1]+' - '+self.info_all[i][-2]))
            self.pushbutton_list()
            for m in range(len(self.info_realdata)):  # m行 n列
                for n in range(14):
                    item = QtWidgets.QTableWidgetItem(str(self.info_realdata[m][n]))
                    self.tableWidget.setItem(m, n, item)

    # 创建详情按钮
    def pushbutton_list(self):
        self.tableWidget.setRowCount(len(self.info_realdata))
        for n in range(len(self.info_realdata)):
            self.btn = QtWidgets.QPushButton()
            self.btn.setDown(True)
            self.btn.setStyleSheet('QPushButton{margin:3px}'
                                   'QPushButton{padding:1px 1px}')
            self.tableWidget.setCellWidget(n, 13, self.btn)
            #此处将字传入按钮
            self.btn.setText(self.btn_realname[n])
            #传达参数,这里sender将接收你点击的字并传入函数
            self.btn.clicked.connect(
                lambda: self.btn_clicked(self.btn_realname.index(self.sender().text())))

    # 显示子页面 -- 信息录入
    def show_info_entry_windows(self):
        self.Info_Entry_Windows.show()

    # 显示子页面 -- 证据图像
    def btn_clicked(self,n):
        #self.nn = list.index(self.line[self.n])
        self.impath = self.info_realimpath[n]
        self.oneinfo = self.btn_realname[n]
        self.EvidenceIm_Windows = Ui_EvidenceIm_Child(
            self.impath, self.oneinfo)
        self.EvidenceIm_Windows.show()

# 重写QtWidgets.QMainWindow类关闭事件
class MainWindow(QtWidgets.QMainWindow):
    def closeEvent(self, event):  # 关闭窗口触发以下事件
        reply = QtWidgets.QMessageBox.question(
            self, '本程序', '你确定要退出吗?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            event.accept()  # 接受关闭事件
        else:
            event.ignore()  # 忽略关闭事件
  • 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
信息录入界面 - Input_Info_GUI.py
class Ui_Info_Entry(QtWidgets.QMainWindow):

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(432, 532)
        Form.setFixedSize(432, 532)

        # 分隔线0
        self.line_0 = QtWidgets.QLabel(Form)
        self.line_0.setGeometry(QtCore.QRect(30, 40, 371, 16))
        self.line_0.setObjectName("line_0")
        # 分隔线1
        self.line_1 = QtWidgets.QLabel(Form)
        self.line_1.setGeometry(QtCore.QRect(30, 210, 371, 16))
        self.line_1.setObjectName("line_1")
        # 分隔线2
        self.line_2 = QtWidgets.QLabel(Form)
        self.line_2.setGeometry(QtCore.QRect(30, 340, 371, 16))
        self.line_2.setObjectName("line_2")
        # 基本信息
        self.essential_information = QtWidgets.QLabel(Form)
        self.essential_information.setGeometry(QtCore.QRect(30, 20, 61, 16))
        self.essential_information.setObjectName("essential_information")
        # 地址信息
        self.address_information = QtWidgets.QLabel(Form)
        self.address_information.setGeometry(QtCore.QRect(30, 190, 54, 12))
        self.address_information.setObjectName("address_information")
        # 车辆信息
        self.vehicle_information = QtWidgets.QLabel(Form)
        self.vehicle_information.setGeometry(QtCore.QRect(30, 320, 54, 12))
        self.vehicle_information.setObjectName("vehicle_information")

        # 省份
        self.label_province = QtWidgets.QLabel(Form)
        self.label_province.setGeometry(QtCore.QRect(40, 230, 51, 21))
        self.label_province.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_province.setObjectName("label_province")
        self.province = QtWidgets.QComboBox(Form)
        self.province.setGeometry(QtCore.QRect(90, 230, 111, 22))
        self.province.setObjectName("province")
        self.province.addItem("")
        # 市/州
        self.label_city = QtWidgets.QLabel(Form)
        self.label_city.setGeometry(QtCore.QRect(230, 230, 51, 21))
        self.label_city.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_city.setObjectName("label_city")
        self.city = QtWidgets.QComboBox(Form)
        self.city.setGeometry(QtCore.QRect(280, 230, 111, 22))
        self.city.setObjectName("city")
        self.city.addItem("")
        # 区/县
        self.label_borough = QtWidgets.QLabel(Form)
        self.label_borough.setGeometry(QtCore.QRect(40, 280, 51, 21))
        self.label_borough.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_borough.setObjectName("label_borough")
        self.borough = QtWidgets.QComboBox(Form)
        self.borough.setGeometry(QtCore.QRect(90, 280, 111, 22))
        self.borough.setObjectName("borough")
        self.borough.addItem("")

        # 编号
        self.number = QtWidgets.QLabel(Form)
        self.number.setGeometry(QtCore.QRect(40, 60, 51, 21))
        self.number.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.number.setObjectName("number")
        self.lineEdit_00 = QtWidgets.QLineEdit(Form)
        self.lineEdit_00.setGeometry(QtCore.QRect(90, 60, 111, 20))
        self.lineEdit_00.setText("")
        self.lineEdit_00.setObjectName("lineEdit_00")
        # 姓名
        self.name = QtWidgets.QLabel(Form)
        self.name.setGeometry(QtCore.QRect(230, 60, 51, 21))
        self.name.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.name.setObjectName("name")
        self.lineEdit_01 = QtWidgets.QLineEdit(Form)
        self.lineEdit_01.setGeometry(QtCore.QRect(280, 60, 111, 20))
        self.lineEdit_01.setText("")
        self.lineEdit_01.setObjectName("lineEdit_01")
        # 性别
        self.sex = QtWidgets.QLabel(Form)
        self.sex.setGeometry(QtCore.QRect(40, 110, 51, 21))
        self.sex.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.sex.setObjectName("sex")
        self.lineEdit_10 = QtWidgets.QLineEdit(Form)
        self.lineEdit_10.setGeometry(QtCore.QRect(90, 110, 111, 20))
        self.lineEdit_10.setText("")
        self.lineEdit_10.setObjectName("lineEdit_10")
        # 年龄
        self.age = QtWidgets.QLabel(Form)
        self.age.setGeometry(QtCore.QRect(230, 110, 51, 21))
        self.age.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.age.setObjectName("age")
        self.lineEdit_11 = QtWidgets.QLineEdit(Form)
        self.lineEdit_11.setGeometry(QtCore.QRect(280, 110, 111, 20))
        self.lineEdit_11.setText("")
        self.lineEdit_11.setObjectName("lineEdit_11")
        # 身份证号
        self.id_number = QtWidgets.QLabel(Form)
        self.id_number.setGeometry(QtCore.QRect(30, 150, 61, 21))
        self.id_number.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.id_number.setObjectName("id_number")
        self.lineEdit_20 = QtWidgets.QLineEdit(Form)
        self.lineEdit_20.setGeometry(QtCore.QRect(90, 150, 111, 20))
        self.lineEdit_20.setText("")
        self.lineEdit_20.setObjectName("lineEdit_20")
        # 联系电话
        self.contact_number = QtWidgets.QLabel(Form)
        self.contact_number.setGeometry(QtCore.QRect(220, 150, 61, 21))
        self.contact_number.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.contact_number.setObjectName("contact_number")
        self.lineEdit_21 = QtWidgets.QLineEdit(Form)
        self.lineEdit_21.setGeometry(QtCore.QRect(280, 150, 111, 20))
        self.lineEdit_21.setText("")
        self.lineEdit_21.setObjectName("lineEdit_21")
        # 车型
        self.model = QtWidgets.QLabel(Form)
        self.model.setGeometry(QtCore.QRect(40, 360, 51, 21))
        self.model.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.model.setObjectName("model")
        self.lineEdit_30 = QtWidgets.QLineEdit(Form)
        self.lineEdit_30.setGeometry(QtCore.QRect(90, 360, 111, 20))
        self.lineEdit_30.setText("")
        self.lineEdit_30.setObjectName("lineEdit_30")
        # 驾驶证编号
        self.driver_license_number = QtWidgets.QLabel(Form)
        self.driver_license_number.setGeometry(QtCore.QRect(200, 360, 81, 21))
        self.driver_license_number.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.driver_license_number.setObjectName("driver_license_number")
        self.lineEdit_31 = QtWidgets.QLineEdit(Form)
        self.lineEdit_31.setGeometry(QtCore.QRect(280, 360, 111, 20))
        self.lineEdit_31.setText("")
        self.lineEdit_31.setObjectName("lineEdit_31")
        # 车牌号
        self.license_number = QtWidgets.QLabel(Form)
        self.license_number.setGeometry(QtCore.QRect(40, 400, 51, 21))
        self.license_number.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.license_number.setObjectName("license_number")
        self.lineEdit_40 = QtWidgets.QLineEdit(Form)
        self.lineEdit_40.setGeometry(QtCore.QRect(90, 400, 111, 20))
        self.lineEdit_40.setText("")
        self.lineEdit_40.setObjectName("lineEdit_40")
        # 保存
        self.info_entry = QtWidgets.QPushButton(Form)
        self.info_entry.setGeometry(QtCore.QRect(90, 450, 75, 23))
        self.info_entry.setObjectName("info_entry")
        # 取消
        self.cancel = QtWidgets.QPushButton(Form)
        self.cancel.setGeometry(QtCore.QRect(260, 450, 75, 23))
        self.cancel.setObjectName("cancel")

        # 中心窗口
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

        # 初始化省份数据
        self.province.clear()
        self.province.addItem('请选择')
        for key, value in dictPorovince.items():
            self.province.addItem(value, QVariant(key))

        # 按扭框被点击事件信号
        self.province.activated.connect(self.add_city)
        self.city.activated.connect(self.add_borough)
        self.borough.activated.connect(self.just_btn_enable)
        self.info_entry.clicked.connect(self.save_sql_ok)
        self.cancel.clicked.connect(self.close)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "个人信息登记"))
        # 基本信息
        self.essential_information.setText(_translate("Form", "<html><head/><body><p>基本信息<span style=\" color:#ff0000;\">*</span></p></body></html>"))
        self.line_0.setText(_translate("Form", "--------------------------------------------------------------------"))
        self.number.setText(_translate("Form", "编号:"))
        self.name.setText(_translate("Form", "姓名:"))
        self.sex.setText(_translate("Form", "性别:"))
        self.age.setText(_translate("Form", "年龄:"))
        self.id_number.setText(_translate("Form", "身份证号:"))
        self.contact_number.setText(_translate("Form", "联系电话:"))
        # 地址信息
        self.address_information.setText(_translate("Form", "<html><head/><body><p>地址信息<span style=\" color:#ff0000;\">*</span></p></body></html>"))
        self.line_1.setText(_translate("Form", "--------------------------------------------------------------------"))
        self.label_province.setText(_translate("Form", "省份:"))
        self.province.setItemText(0, _translate("Form", "请选择"))
        self.label_city.setText(_translate("Form", "城市:"))
        self.city.setItemText(0, _translate("Form", "请选择"))
        self.label_borough.setText(_translate("Form", "区/县:"))
        self.borough.setItemText(0, _translate("Form", "请选择"))
        # 车辆信息
        self.vehicle_information.setText(_translate("Form", "<html><head/><body><p>车辆信息<span style=\" color:#ff0000;\">*</span></p></body></html>"))
        self.line_2.setText(_translate("Form", "--------------------------------------------------------------------"))
        self.model.setText(_translate("Form", "车型:"))
        self.driver_license_number.setText(_translate("Form", "行驶证编号:"))
        self.license_number.setText(_translate("Form", "车牌号:"))
        # 按钮
        self.cancel.setText(_translate("Form", "取消"))
        self.info_entry.setText(_translate("Form", "录入"))

    # 当省份按钮被选择后添加对应的城市数据
    def add_city(self, index):
        pro_code = self.province.itemData(index)
        city_data = dictCity.get(pro_code, dict())
        self.city.clear()
        self.city.addItem('请选择')
        self.borough.clear()
        self.borough.addItem('请选择')
        if self.province.currentText() != '请选择':
            for key, value in city_data.items():
                self.city.addItem(value, QVariant(key))
        self.info_entry.setDisabled(True)
    # 当城市按钮被选择后添加对应的区县数据
    def add_borough(self, index):
        city_code = self.city.itemData(index)
        borough_data = dicBorough.get(city_code, dict())
        self.borough.clear()
        self.borough.addItem('请选择')
        if self.city.currentText() != '请选择':
            for key, value in borough_data.items():
                self.borough.addItem(value, QVariant(key))
        self.info_entry.setDisabled(True)
    # 导出按钮是否可用
    def just_btn_enable(self, txt):
        if self.borough.currentText() != '请选择':
            self.info_entry.setDisabled(False)
        else:
            self.info_entry.setDisabled(True)
    # 清空信息
    def clear(self):
        self.lineEdit_00.clear()
        self.lineEdit_01.clear()
        self.lineEdit_10.clear()
        self.lineEdit_11.clear()
        self.lineEdit_20.clear()
        self.lineEdit_21.clear()
        self.province.clear()
        self.province.addItem('请选择')
        self.city.clear()
        self.city.addItem('请选择')
        self.borough.clear()
        self.borough.addItem('请选择')
        self.lineEdit_30.clear()
        self.lineEdit_31.clear()
        self.lineEdit_40.clear()
        # 初始化省按钮信息
        for key, value in dictPorovince.items():
            self.province.addItem(value, QVariant(key))
    # 点击保存后,信息确认
    def save_sql_ok(self):
        self.all_info = {}
        self.all_info['编号'] = self.lineEdit_00.text()
        self.all_info['姓名'] = self.lineEdit_01.text()
        self.all_info['性别'] = self.lineEdit_10.text()
        self.all_info['年龄'] = self.lineEdit_11.text()
        self.all_info['身份证号'] = self.lineEdit_20.text()
        self.all_info['联系电话'] = self.lineEdit_21.text()
        self.all_info['省份'] = self.province.currentText()
        self.all_info['城市'] = self.city.currentText()
        self.all_info['区/县'] = self.borough.currentText()
        self.all_info['车型'] = self.lineEdit_30.text()
        self.all_info['行驶证编号'] = self.lineEdit_31.text()
        self.all_info['车牌号'] = self.lineEdit_40.text()
        print(self.all_info)

        self.MySQL_Save = MySQL_Connect()
        self.MySQL_Save.MC_Save_User_Info(list_user_info=self.all_info)
        QMessageBox.information(self,
                                "请确认信息",
                                '''您的编号:{}
姓名:{}
性别:{}
年龄:{}
身份证号:{}
联系电话:{}
省份:{}
城市:{} 
区县:{}
车型:{}
行驶证编号:{}
车牌号:{}'''.format(self.lineEdit_00.text(),
                    self.lineEdit_01.text(),
                    self.lineEdit_10.text(),
                    self.lineEdit_11.text(),
                    self.lineEdit_20.text(),
                    self.lineEdit_21.text(),
                    self.province.currentText(),
                    self.city.currentText(),
                    self.borough.currentText(),
                    self.lineEdit_30.text(),
                    self.lineEdit_31.text(),
                    self.lineEdit_40.text()),
                                QMessageBox.Yes | QMessageBox.No)
        self.clear()
  • 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
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
违规图像查看页面 - EvidenceIm_GUI.py
class Ui_EvidenceIm(QtWidgets.QMainWindow):
    def __init__(self,impath,oneinfo):
        super(Ui_EvidenceIm, self).__init__()
        self.impath = impath
        self.oneinfo = oneinfo
    def setupUi(self, Form):
        Form.setObjectName(self.oneinfo)
        Form.resize(979, 584)
        Form.setFixedSize(979, 584)
        self.evidence_im_view = GraphicsView(Form)
        self.evidence_im_view.setGeometry(QtCore.QRect(10, 40, 960, 540))
        self.evidence_im_view.setObjectName("evidence_im_view")
        self.evidence_im_label = QtWidgets.QLabel(Form)
        self.evidence_im_label.setGeometry(QtCore.QRect(10, 10, 971, 21))
        self.evidence_im_label.setObjectName("evidence_im_label")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

        try:
            # 显示图片
            #img = cv_imread()
            img = cv2.imdecode(np.fromfile(self.impath, dtype=np.uint8), -1)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)
            x = img.shape[1]  # 获取图像宽度
            y = img.shape[0]  # 获取图像高度
            frame = QtGui.QImage(img.data, x, y, x*3, QtGui.QImage.Format_RGB888)

            pix = QtGui.QPixmap.fromImage(frame)
            self.item = QtWidgets.QGraphicsPixmapItem(pix)  # 创建像素图元
            self.scene = QtWidgets.QGraphicsScene()  # 创建场景
            self.scene.clear()
            self.scene.addItem(self.item)
            self.scene.update()
            self.evidence_im_view.setScene(self.scene)  # 将场景添加至视图
        except:
            pass

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", self.oneinfo))
        self.evidence_im_label.setText(_translate(
            "Form", "<html><head/><body><p>-------------------------------------------------- <span style=\" font-size:12pt; font-weight:600; color:#000000;\">图像证据</span> --------------------------------------------------</p></body></html>"))


# 重写GraphicsView类 可拖动、放大、缩小图像
class GraphicsView(QGraphicsView):
    # 背景区域颜色
    backgroundColor = QColor(255, 255, 255)
    def __init__(self, *args, **kwargs):
        super(GraphicsView, self).__init__(*args, **kwargs)
        self.resize(800, 600)
        # 设置背景颜色
        self.setBackgroundBrush(self.backgroundColor)
        self.setCacheMode(self.CacheBackground)
        self.setDragMode(self.ScrollHandDrag)
        self.setOptimizationFlag(self.DontSavePainterState)
        self.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing |
                            QPainter.SmoothPixmapTransform)
        if QGLFormat.hasOpenGL():
            self.setRenderHint(QPainter.HighQualityAntialiasing)
        self.setResizeAnchor(self.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self.setTransformationAnchor(self.AnchorUnderMouse)
        self.setViewportUpdateMode(self.SmartViewportUpdate)
        # 设置场景(显示在屏幕中间)
        self._scene = QGraphicsScene(-180, -90, 360, 180, self)
        self.setScene(self._scene)

    def wheelEvent(self, event):
        # 滑轮事件
        if event.modifiers() & Qt.ControlModifier:
            self.scaleView(math.pow(2.0, -event.angleDelta().y() / 240.0))
            return event.accept()
        super(GraphicsView, self).wheelEvent(event)

    def scaleView(self, scaleFactor):
        factor = self.transform().scale(
            scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width()
        if factor < 0.07 or factor > 100:
            return
elf.DontSavePainterState)
        self.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing |
                            QPainter.SmoothPixmapTransform)
        if QGLFormat.hasOpenGL():
            self.setRenderHint(QPainter.HighQualityAntialiasing)
        self.setResizeAnchor(self.AnchorUnderMouse)
        self.setRubberBandSelectionMode(Qt.IntersectsItemShape)
        self.setTransformationAnchor(self.AnchorUnderMouse)
        self.setViewportUpdateMode(self.SmartViewportUpdate)
        # 设置场景(显示在屏幕中间)
        self._scene = QGraphicsScene(-180, -90, 360, 180, self)
        self.setScene(self._scene)

    def wheelEvent(self, event):
        # 滑轮事件
        if event.modifiers() & Qt.ControlModifier:
            self.scaleView(math.pow(2.0, -event.angleDelta().y() / 240.0))
            return event.accept()
        super(GraphicsView, self).wheelEvent(event)

    def scaleView(self, scaleFactor):
        factor = self.transform().scale(
            scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width()
        if factor < 0.07 or factor > 100:
            return
        self.scale(scaleFactor, scaleFactor)
  • 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
  • 非常感谢百度飞桨举办的黑客松活动,本项目还有许多待提升的地方,我们将会持续维护及优化下去,提高系统整体的性能,欢迎大家一起来交流学习!

项目总结

本次项目目前实现了实时检测能力,对于疲劳的判定标准为闭眼及张嘴的幅度,驾驶员出现疲劳反应后触发语音提示功能并留存凭证写入数据库,并搭配了数据库信息可视化的GUI界面,并已在做耗时优化。

优化方向

由于开发时间紧张,项目比较粗糙,没有打磨精细,下面是即将优化的几个部分,也欢迎小伙伴们向我们提出建议:

  • 疲劳的精准判断逻辑 ⬜
  • 模型推理耗时问题 ✅(yolov3_mobilenet_v3_large模型推理速度已优化至 70+ ms)
  • GUI界面美化 ⬜
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/605571
推荐阅读
相关标签
  

闽ICP备14008679号