ymj_data_collect/detect.py
2025-04-20 21:44:06 +08:00

449 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

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

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": ""},
{"code": "BFX1101VBPT003", "type": "300x248", "x": "778", "y": "250", "center": "0.317", "w": "300", "h": "248",
"angle": ""},
{"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()