import ctypes import os import shutil import sys import threading import time from ctypes import * import logging from logging import makeLogRecord import imgProcess from clog import logger import cv2 import numpy as np from imgProcess import detectionResProcessing from util import change_config_ini image_framework_sdk = None data_callback = None SYS_OK = 0 bStop = False # 全局 msg 缓存 g_msg_cache = [] # 全局 frame 缓存 g_frame_cache = [] # 运行模式 RUNNING_MODE_NONE = -1 # 停止状态 RUNNING_MODE_LOCATION = 0 # 广角相机运行模式 RUNNING_MODE_DETECTION = 1 # 高清检测运行模式 g_running_mode = RUNNING_MODE_NONE # 默认是广角相机运行模式 TO_CLIENT_NOTIFY_BASE = 1000 # emit的结构体 MSG_ONLY_RECORD = -1 MSG_LOCATION_RECORD = 0 MSG_DETECTION_RECORD = 1 # bim_data = [ # {"code": "BFX1101VBPT001", "type": "248x248", "x": "325", "y": "250", "center": "1.269", "w": "248", "h": "248", # "angle": "0°"}, # {"code": "BFX1101VBPT002", "type": "150x149", "x": "717", "y": "250", "center": "0.849", "w": "150", "h": "149", # "angle": "0°"}, # {"code": "BFX1101VBPT003", "type": "300x248", "x": "778", "y": "250", "center": "0.317", "w": "300", "h": "248", # "angle": "0°"}, # {"code": "BFX1101VBPT004", "type": "248x248", "x": "1668", "y": "250", "center": "0.296", "w": "248", "h": "248", # "angle": "90°"}, # {"code": "BFX1101VBPT005", "type": "248x248", "x": "2454", "y": "250", "center": "1.307", "w": "248", "h": "248", # "angle": "0°"}] bim_data = [ {"code": "BFX1101VBPT002", "type": "150x149", "x": "717", "y": "250", "center": "0.960", "w": "150", "h": "149", "angle": "0°"}, {"code": "BFX1101VBPT003", "type": "300x248", "x": "778", "y": "250", "center": "0.317", "w": "300", "h": "248", "angle": "0°"}, {"code": "BFX1101VBPT004", "type": "248x248", "x": "1668", "y": "250", "center": "0.296", "w": "248", "h": "248", "angle": "90°"}] MAX_OBJ = 32 class OjectInfo(ctypes.Structure): _fields_ = [ ("id", ctypes.c_int), ("name", ctypes.c_char * 256), ("centerX", ctypes.c_float), ("centerY", ctypes.c_float), ("w", ctypes.c_float), ("h", ctypes.c_float) ] class OjectsInfo(ctypes.Structure): _fields_ = [ ("count", ctypes.c_int), ("objs", OjectInfo * MAX_OBJ) ] # 获取消息 def _get_msg_info(code) -> str: global MSG_LIST for msg in MSG_LIST: for key, value in msg.items(): if code == key: return value.encode("utf-8") return "未知错误".encode("utf-8") class Msg: def __init__(self, msg_type, record, im2D): self.msg_type = msg_type # 0:刷新广角图片, 1:刷新高清, -1:不刷新图片,纯消息 self.record = record self.im2D = im2D class _SubRoiData_(Structure): _fields_ = [ ('mPparentId', c_long), ('mId', c_long), ('mInfo', c_char * 256), ('isGood', c_bool), ('vpOffset', c_float * 2), ('mRoiPoints', c_float * 8), # 4 * 2 ('mInnerConners', c_float * 8), # 4 * 2 ('mInnerConners3D', c_float * 12), # 4 * 3 ('edges', c_float * 4), ('center', c_float * 2), ('cloud_size', c_int), ('mVc2D', POINTER(c_float)), ('mVc3D', POINTER(c_float)), ('H', c_float * 9), # 新增部分 ('mInnerLineCenter', c_float * 8), # 4 * 2 ('mInnerLineCenter3D', c_float * 12), # 4 * 3 ('mInnerCenter', c_float * 2), # 1 * 2 ('mInnerCenter3D', c_float * 3), # 1 * 3 ('mEdgesLen', c_float * 4), # 4 # 新增字段之后需同步在_copy_record函数中进行添加 ] SubRoiData = _SubRoiData_ class _CallbackInfo_(Structure): _fields_ = [ ('code', c_int), ('errorInfo', c_char * 256), ('bGetData', c_bool), ('mId', c_long), ('mInfo', c_char * 256), ('mImPath', c_char * 256), ('mIm2D3DPtr', c_char * 256), ('roi_size', c_int), ('subRois', SubRoiData * 16), ] CallbackInfo = _CallbackInfo_ # 回调函数类型定义 CallbackType = CFUNCTYPE(None, POINTER(CallbackInfo)) def _copy_record(record): new_record = CallbackInfo() new_record.code = record.code new_record.errorInfo = record.errorInfo new_record.bGetData = record.bGetData new_record.roi_size = record.roi_size for i in range(record.roi_size): if i > 15: # 超过16个ROI,返回 break subRois = record.subRois[i] newSubRois = new_record.subRois[i] newSubRois.isGood = subRois.isGood newSubRois.mInfo = subRois.mInfo for j in range(8): newSubRois.mRoiPoints[j] = subRois.mRoiPoints[j] newSubRois.mInnerConners[j] = subRois.mInnerConners[j] newSubRois.mInnerLineCenter[j] = subRois.mInnerLineCenter[j] for j in range(12): newSubRois.mInnerConners3D[j] = subRois.mInnerConners3D[j] newSubRois.mInnerLineCenter3D[j] = subRois.mInnerLineCenter3D[j] for j in range(4): newSubRois.mEdgesLen[j] = subRois.mEdgesLen[j] for j in range(2): newSubRois.mInnerCenter[j] = subRois.mInnerCenter[j] for j in range(3): newSubRois.mInnerCenter3D[j] = subRois.mInnerCenter3D[j] return new_record # def init_callback(): # global data_callback, bStop # # def _callback(data): # print("_callback回调执行") # global g_msg_cache, g_frame_cache, g_running_mode, bStop # record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) # frame = None # ret = SYS_OK # msg = None # # # 获取数据 # data_type = CallbackInfo # 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)) # # 当定位模式下,接收到【定位完成】消息 # if g_running_mode == RUNNING_MODE_LOCATION and record.code == (6 + TO_CLIENT_NOTIFY_BASE): # if len(g_frame_cache) == 0: # print("当前没有广角数据") # return # frame = g_frame_cache.pop() # 从图像缓存中去除图像 # g_frame_cache = [] # 清空缓存,避免无限增长 # msg = Msg(MSG_LOCATION_RECORD, _copy_record(record), frame) # # 当检测模式下,接收到【拍照完成】消息 # elif record.code == (8 + TO_CLIENT_NOTIFY_BASE): # bStop = True # time.sleep(1) # elif record.code == (12 + TO_CLIENT_NOTIFY_BASE): # msg = Msg(MSG_DETECTION_RECORD, _copy_record(record), None) # detectionResProcessing(msg,data_img_path,data_detect_res_save_path) # bStop = True # time.sleep(1) # # # frame = np.zeros((7000, 9344, 3), np.uint8) # # # # frame.zeros(9344, 7000, cv2.CV_8UC3) # # # # src_frame_ptr = c_char_p(frame.data.tobytes()) # # # mv = memoryview(frame.data) # # # buffer_pointer = cast(mv.obj.ctypes.data, c_void_p) # # # ret = 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) # # # emit msg # # return # # msg = Msg(MSG_DETECTION_RECORD, _copy_record(record), frame) # # elif g_running_mode == RUNNING_MODE_LOCATION: # # msg = Msg(MSG_LOCATION_RECORD, _copy_record(record), None) # # elif g_running_mode == RUNNING_MODE_DETECTION: # # msg = Msg(MSG_DETECTION_RECORD, _copy_record(record), None) # # else: # # print("未知回调") # # return # # data_callback = CallbackType(_callback) def init_callback(): global data_callback def _callback(data): print("_callback回调执行") global g_msg_cache, g_frame_cache, g_running_mode record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) frame = None ret = SYS_OK msg = None # 获取数据 data_type = CallbackInfo data_ptr = cast(data, POINTER(data_type)) ckinfoCache = data_ptr.contents record = _copy_record(ckinfoCache) print(f"g_running_mode===={g_running_mode}") print(f"record===={record.code}") # print("callback ============ > " + str(record.code) + " mode " + str(g_running_mode)) # print(str(g_running_mode) + " : " + str(record.code) + " : " + bytes.decode(record.errorInfo)) # 当定位模式下,接收到【定位完成】消息 if g_running_mode == RUNNING_MODE_LOCATION and record.code == (6 + TO_CLIENT_NOTIFY_BASE): if len(g_frame_cache) == 0: # self.logger.error("当前没有广角数据") return frame = g_frame_cache.pop() # 从图像缓存中去除图像 g_frame_cache = [] # 清空缓存,避免无限增长 msg = Msg(MSG_LOCATION_RECORD, _copy_record(record), frame, None) # 当检测模式下,接收到【拍照完成】消息 elif (g_running_mode == RUNNING_MODE_DETECTION and record.code == (2 + TO_CLIENT_NOTIFY_BASE)) or \ (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) print("1") # frame.zeros(9344, 7000, cv2.CV_8UC3) # src_frame_ptr = c_char_p(frame.data.tobytes()) mv = memoryview(frame.data) buffer_pointer = cast(mv.obj.ctypes.data, c_void_p) print("12") # ret = self.image_framework_sdk.LibapiGetHQImage( # buffer_pointer, frame.shape[1], frame.shape[0], 3, c_char_p(b"PythonProcessing")) print("13") 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) print("14") g_msg_cache.append(msg) # emit msg return msg = Msg(MSG_DETECTION_RECORD, _copy_record(record), frame) elif g_running_mode == RUNNING_MODE_LOCATION: # msg = Msg(MSG_LOCATION_RECORD, _copy_record(record), None, None) print("") elif g_running_mode == RUNNING_MODE_DETECTION: # msg = Msg(MSG_DETECTION_RECORD, _copy_record(record), None, None) print("") else: print("未知回调") return print("15") g_msg_cache.append(msg) # self.logger.info("image framework callback done.") data_callback = CallbackType(_callback) def init_image_framework_sdk(): global image_framework_sdk try: # 加载C++库 current_file_dir = os.path.dirname(os.path.abspath(__file__)) image_framework_sdk = CDLL(os.path.join(current_file_dir, f'./image_framework.dll')) print(f"[image_framework_sdk] ====== [{image_framework_sdk}]") print("Load Image framework sdk success") except Exception as e: print(f"Load Image framework sdk failed: {str(e)}") def adjust(): global image_framework_sdk record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) # 创建一个 OjectsInfo 实例 info = OjectsInfo() for idx, bim in enumerate(bim_data): print(bim["center"]) info.objs[idx].id = idx info.objs[idx].name = bim["code"].encode("utf-8") info.objs[idx].centerX = float(bim["x"]) / 1000 info.objs[idx].centerY = float(bim["center"]) info.objs[idx].w = float(bim["w"]) / 1000 info.objs[idx].h = float(bim["h"]) / 1000 ret = image_framework_sdk.LibapiStartDetectionV2(ctypes.byref(info)) if ret != SYS_OK: print(f"image_framework_sdk.LibapiStartDetection():执行失败 :{ret}") return record def check(): print("check====================") global image_framework_sdk record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) ret = image_framework_sdk.LibapiContinuetDetection("{}") print("返回值:", ret) if ret != SYS_OK: print("image_framework_sdk.LibapiContinuetDetection:执行失败") return record def start(): global g_running_mode global bStop g_running_mode = RUNNING_MODE_DETECTION # 开始检测 logger.debug("开始adjust") adjust() # while not bStop: # logger.debug("adjust等待回调") # time.sleep(1) time.sleep(5) logger.debug("开始check") check() bStop = False while not bStop: logger.debug("check等待回调") time.sleep(1) def _main_processing_thread(): global g_msg_cache, g_running_mode record = CallbackInfo(code=SYS_OK, errorInfo=b"", bGetData=False) times = 0 while True: if len(g_msg_cache) <= 0: times += 1 time.sleep(0.01) # if times % 200 == 0: # print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") continue msg = g_msg_cache.pop() # g_msg_cache = [] # print("===============> start" + str(msg.record.code)) if msg is None: continue msg = imgProcess.process(msg) # print("===============> end" + str(msg.record.code)) # self.logger.info("msg ==> ui") # self.signals.on_image_detect_result.emit(msg) if __name__ == '__main__': process_thread = threading.Thread(target=_main_processing_thread) process_thread.daemon = True process_thread.start() # 加载驱动 init_image_framework_sdk() if image_framework_sdk is None: raise RuntimeError("Image framework SDK未正确加载!") # 设置回调函数 init_callback() ret = image_framework_sdk.LibapiInit(1, "", data_callback) if ret != 0: raise RuntimeError(f"设置回调函数始设置失败, 错误码: {ret}") dataPath = "./result2" # 数据路径 data_img_path = None # 检测的图片路径 data_detect_res_save_path = None # 检测结果的保存路径 # 遍历目录 for root, dirs, files in os.walk(dataPath): for dir in dirs: logger.debug(f"开始处理子目录:{dir}") data_detect_res_save_path = os.path.join(root, dir) # 目录下的所有文件路径 for file in os.listdir(os.path.join(root, dir)): file_path = os.path.join(root, dir, file) # 将反斜杠替换为正斜杠 file_path = file_path.replace('\\', '/') logger.debug(f"文件路径:{file_path}") # 如果是jpg图片 if file.endswith("output.jpg"): # 将文件路径修改到ini配置中 data_img_path = file_path change_config_ini("sys", "fake_image_fpath", file_path) if file.endswith(".ply"): # 将文件路径修改到ini配置中 change_config_ini("sys", "fake_lidar_fpath", file_path) if file.endswith(".txt"): # txt roi坐标复制到更目录,曹总懒得修改c代码,只能从根目录读取。 shutil.copy(file_path, os.path.join("./", file)) logger.info(f"roi坐标文件已复制到更目录") time.sleep(1) # ... # 开始检测 bStop = False logger.debug("开始检测") start() exit()