diff --git a/components/image_framework.py b/components/image_framework.py index 9f65b5a..e066d64 100644 --- a/components/image_framework.py +++ b/components/image_framework.py @@ -10,7 +10,7 @@ import time import cv2 from core.edge_component import action, EdgeComponent, service -from util import get_system_and_library_suffix,imgProcess +from util import get_system_and_library_suffix, imgProcess # 给回调函数使用 @@ -32,8 +32,10 @@ class _SubRoiData_(Structure): ('H', c_float * 9), ] + SubRoiData = _SubRoiData_ + class _CallbackInfo_(Structure): _fields_ = [ ('code', c_int), @@ -47,14 +49,16 @@ class _CallbackInfo_(Structure): ('subRois', SubRoiData * 16), ] + CallbackInfo = _CallbackInfo_ # 回调函数类型定义 CallbackType = CFUNCTYPE(None, POINTER(CallbackInfo)) # emit的结构体 -MSG_ONLY_RECORD = -1 -MSG_LOCATION_RECORD = 0 -MSG_DETECTION_RECORD = 1 +MSG_ONLY_RECORD = -1 +MSG_LOCATION_RECORD = 0 +MSG_DETECTION_RECORD = 1 + class Msg: def __init__(self, msg_type, record, im2D): @@ -63,7 +67,7 @@ class Msg: self.im2D = im2D -TO_CLIENT_NOTIFY_BASE = 1000 +TO_CLIENT_NOTIFY_BASE = 1000 SYS_BASE = 1000 CAL_2D3D_BASE = 2000 CAMERA_BASE = 4000 @@ -72,55 +76,55 @@ SYS_OK = 0 CAL_OK = 0 LIDAR_OK = 0 MSG_LIST = [ - { 1 + TO_CLIENT_NOTIFY_BASE : "开始相机拍摄" }, - { 2 + TO_CLIENT_NOTIFY_BASE : "相机拍摄已完成" }, - { 3 + TO_CLIENT_NOTIFY_BASE : "开始雷达采集数据" }, - { 4 + TO_CLIENT_NOTIFY_BASE : "雷达采集数据已完成" }, - { 5 + TO_CLIENT_NOTIFY_BASE : "开始定位检测" }, # 这个消息是相机实时定位,不用打印 - { 6 + TO_CLIENT_NOTIFY_BASE : "定位检测已完成" }, - { 7 + TO_CLIENT_NOTIFY_BASE : "开始角点2D检测" }, - { 8 + TO_CLIENT_NOTIFY_BASE : "角点2D检测已完成" }, - { 9 + TO_CLIENT_NOTIFY_BASE : "开始角点3D检测" }, - { 10 + TO_CLIENT_NOTIFY_BASE : "角点3D检测已完成" }, - { 11 + TO_CLIENT_NOTIFY_BASE : "开始计算预埋件尺寸" }, - { 12 + TO_CLIENT_NOTIFY_BASE : "预埋件尺寸计算已完成" }, + {1 + TO_CLIENT_NOTIFY_BASE: "开始相机拍摄"}, + {2 + TO_CLIENT_NOTIFY_BASE: "相机拍摄已完成"}, + {3 + TO_CLIENT_NOTIFY_BASE: "开始雷达采集数据"}, + {4 + TO_CLIENT_NOTIFY_BASE: "雷达采集数据已完成"}, + {5 + TO_CLIENT_NOTIFY_BASE: "开始定位检测"}, # 这个消息是相机实时定位,不用打印 + {6 + TO_CLIENT_NOTIFY_BASE: "定位检测已完成"}, + {7 + TO_CLIENT_NOTIFY_BASE: "开始角点2D检测"}, + {8 + TO_CLIENT_NOTIFY_BASE: "角点2D检测已完成"}, + {9 + TO_CLIENT_NOTIFY_BASE: "开始角点3D检测"}, + {10 + TO_CLIENT_NOTIFY_BASE: "角点3D检测已完成"}, + {11 + TO_CLIENT_NOTIFY_BASE: "开始计算预埋件尺寸"}, + {12 + TO_CLIENT_NOTIFY_BASE: "预埋件尺寸计算已完成"}, - { 1 - SYS_BASE : "驱动初始化错误" }, - { 2 - SYS_BASE : "NPU计算单元初始化错误" }, - { 3 - SYS_BASE : "系统错误" }, - { 4 - SYS_BASE : "相机初始化错误" }, - { 5 - SYS_BASE : "当前没有可以读取的高清相片"}, + {1 - SYS_BASE: "驱动初始化错误"}, + {2 - SYS_BASE: "NPU计算单元初始化错误"}, + {3 - SYS_BASE: "系统错误"}, + {4 - SYS_BASE: "相机初始化错误"}, + {5 - SYS_BASE: "当前没有可以读取的高清相片"}, - { 1 - CAL_2D3D_BASE : "读取图片文件错误" }, - { 2 - CAL_2D3D_BASE : "写图片文件错误" }, - { 3 - CAL_2D3D_BASE : "空指针" }, - { 4 - CAL_2D3D_BASE : "空参数" }, - { 5 - CAL_2D3D_BASE : "读取图像错误" }, - { 6 - CAL_2D3D_BASE : "NPU加载数据错误" }, - { 7 - CAL_2D3D_BASE : "NPU模型执行错误" }, - { 8 - CAL_2D3D_BASE : "NPU获取结果错误" }, - { 9 - CAL_2D3D_BASE : "NPU卸载数据错误" }, - { 10 - CAL_2D3D_BASE : "YOLO推理无可信ROI区域" }, - { 11 - CAL_2D3D_BASE : "ROI处理线程错误" }, - { 12 - CAL_2D3D_BASE : "H计算错误" }, - { 13 - CAL_2D3D_BASE : "3D角点检测错误" }, - { 14 - CAL_2D3D_BASE : "2D角点定位错误" }, - { 15 - CAL_2D3D_BASE : "3D投影计算错误" }, - { 16 - CAL_2D3D_BASE : "3D点云为空" }, - { 17 - CAL_2D3D_BASE : "未检测到2D角点" }, - { 18 - CAL_2D3D_BASE : "未检测到预埋件" }, - { 19 - CAL_2D3D_BASE : "相机捕获图像失败" }, + {1 - CAL_2D3D_BASE: "读取图片文件错误"}, + {2 - CAL_2D3D_BASE: "写图片文件错误"}, + {3 - CAL_2D3D_BASE: "空指针"}, + {4 - CAL_2D3D_BASE: "空参数"}, + {5 - CAL_2D3D_BASE: "读取图像错误"}, + {6 - CAL_2D3D_BASE: "NPU加载数据错误"}, + {7 - CAL_2D3D_BASE: "NPU模型执行错误"}, + {8 - CAL_2D3D_BASE: "NPU获取结果错误"}, + {9 - CAL_2D3D_BASE: "NPU卸载数据错误"}, + {10 - CAL_2D3D_BASE: "YOLO推理无可信ROI区域"}, + {11 - CAL_2D3D_BASE: "ROI处理线程错误"}, + {12 - CAL_2D3D_BASE: "H计算错误"}, + {13 - CAL_2D3D_BASE: "3D角点检测错误"}, + {14 - CAL_2D3D_BASE: "2D角点定位错误"}, + {15 - CAL_2D3D_BASE: "3D投影计算错误"}, + {16 - CAL_2D3D_BASE: "3D点云为空"}, + {17 - CAL_2D3D_BASE: "未检测到2D角点"}, + {18 - CAL_2D3D_BASE: "未检测到预埋件"}, + {19 - CAL_2D3D_BASE: "相机捕获图像失败"}, - { 1 - CAMERA_BASE : "相机DLL初始化失败" }, + {1 - CAMERA_BASE: "相机DLL初始化失败"}, - { 1 - LIDAR_BASE : "雷达初始化SDK失败" }, - { 2 - LIDAR_BASE : "雷达SO初始化失败" }, - { 3 - LIDAR_BASE : "雷达广播失败" }, - { 5 - LIDAR_BASE : "雷达开始采样失败" }, - { 6 - LIDAR_BASE : "雷达结束采样失败" }, + {1 - LIDAR_BASE: "雷达初始化SDK失败"}, + {2 - LIDAR_BASE: "雷达SO初始化失败"}, + {3 - LIDAR_BASE: "雷达广播失败"}, + {5 - LIDAR_BASE: "雷达开始采样失败"}, + {6 - LIDAR_BASE: "雷达结束采样失败"}, - { -10001 : "已经在检测模式中"}, - { -10002 : "定位模式不支持执行该操作"} + {-10001: "已经在检测模式中"}, + {-10002: "定位模式不支持执行该操作"} ] #################################################################################### @@ -134,16 +138,17 @@ g_msg_cache = [] g_frame_cache = [] # 运行模式 -RUNNING_MODE_NONE = -1 # 停止状态 -RUNNING_MODE_LOCATION = 0 # 广角相机运行模式 -RUNNING_MODE_DETECTION = 1 # 高清检测运行模式 -g_running_mode = RUNNING_MODE_NONE # 默认是广角相机运行模式 +RUNNING_MODE_NONE = -1 # 停止状态 +RUNNING_MODE_LOCATION = 0 # 广角相机运行模式 +RUNNING_MODE_DETECTION = 1 # 高清检测运行模式 +g_running_mode = RUNNING_MODE_NONE # 默认是广角相机运行模式 -#################################################################################### + +#################################################################################### # 内部接口定义 #################################################################################### # 获取消息 -def _get_msg_info(code) -> str: +def _get_msg_info(code) -> str: global MSG_LIST for msg in MSG_LIST: for key, value in msg.items(): @@ -151,19 +156,23 @@ def _get_msg_info(code) -> str: return value.encode("utf-8") return "未知错误".encode("utf-8") +get_msg_info = _get_msg_info + # 加工检测图像 def _update_location_image(frame): global needHandle, recordCache, ckinfoCache + def switch(choice): - if ckinfoCache.code == 1006: #TO_CLIENT_NOTIFY_DETECTION_END: 1006 + if ckinfoCache.code == 1006: # TO_CLIENT_NOTIFY_DETECTION_END: 1006 for i in range(recordCache.roi_size): subRois = recordCache.subRois[i] s = "" for j in range(8): - s += str(subRois.mRoiPoints[j])+ " " + s += str(subRois.mRoiPoints[j]) + " " else: print("default Case") + # 在回调函数中将 record 数据拷贝出来 def _copy_record(record): new_record = CallbackInfo() @@ -217,7 +226,8 @@ class ImageFramework(EdgeComponent): # 加载C++库 current_file_dir = os.path.dirname(os.path.abspath(__file__)) (arch, suffix) = get_system_and_library_suffix() - self.image_framework_sdk = CDLL(os.path.join(current_file_dir, f'../vendors/image-framework/{arch}/image_framework.{suffix}')) + self.image_framework_sdk = CDLL( + os.path.join(current_file_dir, f'../vendors/image-framework/{arch}/image_framework.{suffix}')) # 设置回调函数 self.init_callback() except Exception as e: @@ -234,7 +244,7 @@ class ImageFramework(EdgeComponent): # 获取数据 data_type = CallbackInfo - data_ptr = cast(data, POINTER(data_type)) + data_ptr = cast(data, POINTER(data_type)) ckinfoCache = data_ptr.contents record = _copy_record(ckinfoCache) print(str(g_running_mode) + " : " + str(record.code) + " : " + bytes.decode(record.errorInfo)) @@ -247,8 +257,8 @@ class ImageFramework(EdgeComponent): g_frame_cache = [] # 清空缓存,避免无限增长 msg = Msg(MSG_LOCATION_RECORD, _copy_record(record), frame) # 当检测模式下,接收到【拍照完成】消息 - elif (g_running_mode == RUNNING_MODE_DETECTION and record.code == (8 + TO_CLIENT_NOTIFY_BASE)) or\ - (g_running_mode == RUNNING_MODE_DETECTION and record.code == (12 + TO_CLIENT_NOTIFY_BASE)): + elif (g_running_mode == RUNNING_MODE_DETECTION and record.code == (8 + TO_CLIENT_NOTIFY_BASE)) or \ + (g_running_mode == RUNNING_MODE_DETECTION and record.code == (12 + TO_CLIENT_NOTIFY_BASE)): frame = np.zeros((7000, 9344, 3), np.uint8) # frame.zeros(9344, 7000, cv2.CV_8UC3) # src_frame_ptr = c_char_p(frame.data.tobytes()) @@ -257,6 +267,7 @@ class ImageFramework(EdgeComponent): ret = self.image_framework_sdk.LibapiGetHQImage( buffer_pointer, frame.shape[1], frame.shape[0], 3, c_char_p(b"PythonProcessing")) if ret != SYS_OK: + print("ret != SYS_OK:" + str(ret)) record = CallbackInfo(code=ret, errorInfo=_get_msg_info(ret), bGetData=False) msg = Msg(MSG_DETECTION_RECORD, record, None) g_msg_cache.append(msg) @@ -303,25 +314,26 @@ class ImageFramework(EdgeComponent): def start_location(self): global g_running_mode self.logger.info("start_location") - if g_running_mode != RUNNING_MODE_LOCATION: - g_running_mode = RUNNING_MODE_LOCATION # 切换为定位模式 + if g_running_mode != RUNNING_MODE_LOCATION: + g_running_mode = RUNNING_MODE_LOCATION # 切换为定位模式 @service() def stop_all(self): global g_running_mode - if g_running_mode != RUNNING_MODE_NONE: - g_running_mode = RUNNING_MODE_NONE # 切换为静默模式 + if g_running_mode != RUNNING_MODE_NONE: + g_running_mode = RUNNING_MODE_NONE # 切换为静默模式 @service() def start_adjust(self): global g_running_mode record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) - if g_running_mode != RUNNING_MODE_DETECTION: - g_running_mode = RUNNING_MODE_DETECTION # 切换为检测模式 - else: + if g_running_mode != RUNNING_MODE_DETECTION: + g_running_mode = RUNNING_MODE_DETECTION # 切换为检测模式 + else: record.code = -10001 record.errorInfo = _get_msg_info(-10001) return record + ret = self.image_framework_sdk.LibapiStartDetection() if ret != SYS_OK: record = CallbackInfo() @@ -334,9 +346,9 @@ class ImageFramework(EdgeComponent): def start_check(self): global g_running_mode record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) - if g_running_mode == RUNNING_MODE_LOCATION: # 如果在定位任务模式下,该接口不执行 + if g_running_mode == RUNNING_MODE_LOCATION: # 如果在定位任务模式下,该接口不执行 record.code = -10002 - record.errorInfo = _get_msg_info( -10002) + record.errorInfo = _get_msg_info(-10002) return MSG_DETECTION_RECORD ret = self.image_framework_sdk.LibapiContinuetDetection() if ret != SYS_OK: @@ -349,16 +361,16 @@ class ImageFramework(EdgeComponent): def stop_check(self): global g_running_mode record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) - if g_running_mode == RUNNING_MODE_LOCATION: # 如果在定位任务模式下,该接口不执行 + if g_running_mode == RUNNING_MODE_LOCATION: # 如果在定位任务模式下,该接口不执行 record.code = -10002 record.errorInfo = _get_msg_info(-10002) return record - ret = self.image_framework_sdk.LibapiStopDetection() + ret = self.image_framework_sdk.LibapStopDetection() if ret != SYS_OK: record.code = ret record.errorInfo = _get_msg_info(ret) return record - g_running_mode = RUNNING_MODE_NONE # 切换为无模式 + g_running_mode = RUNNING_MODE_LOCATION # 切换为无模式 return record # 广角相机运行定位处理线程 @@ -371,7 +383,13 @@ class ImageFramework(EdgeComponent): # 如果当前不是定位模式,不处理任何事务 if g_running_mode != RUNNING_MODE_LOCATION: time.sleep(0.5) + g_frame_cache = [] continue + + # 上一帧还未处理完毕 + if len(g_frame_cache) > 0: + continue + # 获取一帧图像 _, frame = capture.read() # 如果图像为空,等待一秒,上报消息 @@ -380,6 +398,8 @@ class ImageFramework(EdgeComponent): self.logger.error("[ERROR] 广角相机未捕获到图像") continue + print("location run") + if self.times % 3 == 0: src_frame_ptr = c_char_p(frame.data.tobytes()) ret = self.image_framework_sdk.LibapiCameraSendMsgWithImage( diff --git a/styles/global.qss b/styles/global.qss index 8caa2d2..51f77ce 100644 --- a/styles/global.qss +++ b/styles/global.qss @@ -285,3 +285,10 @@ QMessageBox QPushButton:pressed { QMessageBox QDialogButtonBox#qt_msgbox_buttonbox { /* buttonBox */ button-layout: 0; /* 设置QPushButton布局好像没啥作用 */ } + +QPlainTextEdit#logText { + border: none; + background-color: #222222; + font-size: 14px; + color: #bbbbbb; +} \ No newline at end of file diff --git a/widget/task_run.py b/widget/task_run.py index c85bf9b..ae6091b 100644 --- a/widget/task_run.py +++ b/widget/task_run.py @@ -1,10 +1,10 @@ import cv2 from PyQt5.QtCore import Qt -from PyQt5.QtGui import QPixmap, QImage +from PyQt5.QtGui import QPixmap, QImage, QTextCursor from PyQt5.QtWidgets import QDialog, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QScrollArea, QPushButton, \ - QSpacerItem, QSizePolicy, QLabel, QMessageBox + QSpacerItem, QSizePolicy, QLabel, QMessageBox, QPlainTextEdit -from components.image_framework import MSG_LOCATION_RECORD, MSG_DETECTION_RECORD +from components.image_framework import MSG_LOCATION_RECORD, MSG_DETECTION_RECORD, get_msg_info from core.context import AppContext from widget.embed_item import EmbedItem @@ -29,6 +29,7 @@ class TaskRunDialog(QDialog): self.view_widget = None self.view_label = None self.picture_label = None + self.log_text = None self.start_adjust_button = None self.start_check_button = None @@ -62,6 +63,9 @@ class TaskRunDialog(QDialog): except Exception as e: dd = 0 elif msg.msg_type == MSG_DETECTION_RECORD: + # 显示日志 + self.log_text.appendPlainText(get_msg_info(msg.record.code).decode('utf-8')) + if msg.record.code < 0: QMessageBox.warning(self, '错误信息', msg.record.errorInfo.decode('utf-8')) self.set_button_default() @@ -173,37 +177,30 @@ class TaskRunDialog(QDialog): self.picture_label = QLabel() self.picture_label.setObjectName("pictureWidget") - self.picture_label.setFixedWidth(450) + self.picture_label.setFixedWidth(930 * 450 / 700) self.picture_label.setFixedHeight(450) self.picture_label.setScaledContents(True) - # picture_pixmap = QPixmap("assets/img2.png") - # self.picture_label.setPixmap(picture_pixmap) + self.picture_label.setStyleSheet("background: #222222;") self.view_widget = QWidget() self.view_widget.setObjectName("viewWidget") + self.view_widget.setFixedWidth(1920 * 450 / 1080) self.view_widget.setFixedHeight(450) self.view_label = QLabel(self.view_widget) self.view_label.setObjectName("viewLabel") self.view_label.setFixedHeight(450) self.view_label.setScaledContents(True) - # view_pixmap = QPixmap("assets/img1.jpg") - # sc = view_pixmap.height() / 450 - # self.view_label.setFixedWidth(view_pixmap.width() / sc) - # self.view_label.setPixmap(view_pixmap) - # self.view_label.setGeometry((view_widget.width() - self.view_label.width() / 2), 0, self.view_label.width(), self.view_label.height()) + self.view_label.setStyleSheet("background: #222222;") view_check_widget = QWidget(self.view_widget) view_check_widget.setObjectName("viewCheckWidget") view_check_widget.setGeometry(self.view_label.geometry().x() + 145, 170, 240, 240) - # view_widget = QWidget() - # view_widget.setObjectName("viewWidget") - # view_widget.setFixedWidth(1000) - # view_widget.setFixedHeight(450) - # picture_widget = QWidget() - # picture_widget.setObjectName("pictureWidget") - # picture_widget.setFixedHeight(450) + self.log_text = QPlainTextEdit() + self.log_text.setObjectName("logText") + self.log_text.setFixedHeight(450) + self.log_text.setReadOnly(True) tool_widget = QWidget() tool_widget.setObjectName("toolWidget") @@ -258,6 +255,8 @@ class TaskRunDialog(QDialog): content_layout.setSpacing(0) content_layout.addWidget(self.view_widget) content_layout.addSpacing(20) + content_layout.addWidget(self.log_text) + content_layout.addSpacing(20) content_layout.addWidget(self.picture_label) content_layout.addSpacing(20) content_layout.addWidget(tool_widget) @@ -293,6 +292,9 @@ class TaskRunDialog(QDialog): self.stop_check_button.setEnabled(False) self.stop_task_button.setEnabled(False) + self.log_text.setPlainText("") + self.picture_label.setPixmap(QPixmap("")) + result = AppContext.get_edge_context().get_component('image-framework').start_adjust() if result.code < 0: self.set_button_default() @@ -316,8 +318,8 @@ class TaskRunDialog(QDialog): self.stop_task_button.setEnabled(False) result = AppContext.get_edge_context().get_component('image-framework').stop_check() if result.code < 0: - self.set_button_default() QMessageBox.warning(self, '检测停止失败', result.errorInfo) + self.set_button_default() def stop_task(self): AppContext.get_edge_context().get_component('image-framework').stop_all()