From 725c869fe6f527da84dbfbfa3bb250a48d3bd0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LAPTOP-S9HJSOEB=5C=E6=98=8A=E5=A4=A9?= Date: Thu, 21 Aug 2025 11:04:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=82=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Point.py | 413 ++++++++++-------- SimpleView_SaveImage.py | 370 ++++++++++++---- __pycache__/Point.cpython-311.pyc | Bin 11217 -> 14463 bytes .../SimpleView_SaveImage.cpython-311.pyc | Bin 8807 -> 7907 bytes __pycache__/config.cpython-311.pyc | Bin 4708 -> 6246 bytes __pycache__/image.cpython-311.pyc | Bin 10097 -> 10007 bytes config.py | 4 +- config/camera/00DA6823936.json | 11 +- config/camera/00DA6823953.json | 10 + config/cut/00DA6823936.json | 24 + config/cut/00DA6823936_47.json | 24 + config/cut/00DA6823936_A.json | 24 - config/cut/00DA6823936_B.json | 24 - config/cut/00DA6823953.json | 24 + config/cut/00DA6823953_47.json | 24 + config/template/45.json | 8 +- config/template/46.json | 8 + config/template/47.json | 8 + config/接口说明 | 190 ++++++++ config/配置文件说明.txt | 27 +- image.py | 223 ++++++---- logConfig.py | 64 +++ logs/app.log | 374 ++++++++++++++++ logs/app.log.2025-08-13 | 31 ++ logs/app.log.2025-08-14 | 129 ++++++ main.py | 315 +++++++++++-- thread_pool.py | 74 ++++ 27 files changed, 1973 insertions(+), 430 deletions(-) create mode 100644 config/camera/00DA6823953.json create mode 100644 config/cut/00DA6823936.json create mode 100644 config/cut/00DA6823936_47.json delete mode 100644 config/cut/00DA6823936_A.json delete mode 100644 config/cut/00DA6823936_B.json create mode 100644 config/cut/00DA6823953.json create mode 100644 config/cut/00DA6823953_47.json create mode 100644 config/template/46.json create mode 100644 config/template/47.json create mode 100644 config/接口说明 create mode 100644 logConfig.py create mode 100644 logs/app.log create mode 100644 logs/app.log.2025-08-13 create mode 100644 logs/app.log.2025-08-14 create mode 100644 thread_pool.py diff --git a/Point.py b/Point.py index 158d60b..54fcbea 100644 --- a/Point.py +++ b/Point.py @@ -1,129 +1,130 @@ +from datetime import time + import numpy as np from PIL import Image import math import config -from cat import clip_and_rotate_point_cloud, merge_point_clouds -from image import detect_large_holes - +import asyncio -def tiff_depth_to_point_clouds(tiff_paths, sn, dedup=True): - """ - 将多个 TIFF 深度图转换为点云,并拼接在一起后生成 PCD 文件 - :param tiff_paths: list of str, TIFF 深度图路径列表 - :param sn: str, 设备序列号,用于查找配置参数 - :param dedup: bool, 是否根据 (x, y) 去重,默认开启 - :return: list of [x, y, z], 合并后的点云数据 - """ - merged_points = [] - - # Step 1: 遍历每个 TIFF 文件,生成对应的点云 - for tiff_path in tiff_paths: - points = tiff_depth_to_point_cloud(tiff_path+".tiff", sn, dedup) - merged_points.extend([points]) - - # Step 2: 可选:使用 merge_point_clouds 对点云进行 x 轴拼接(若需要) - # 注意:如果每个点云已经带有偏移,则不需要再次拼接 - has_voids = True - if hasattr(config, 'CUT_CONFIG_MAP') and isinstance(config.CUT_CONFIG_MAP, dict) and (sn in config.CUT_CONFIG_MAP): - merged_points, xrange = merge_point_clouds(merged_points, config.CUT_CONFIG_MAP[sn],sn) - - real_holes = detect_large_holes(merged_points, sn, xrange) - if real_holes.__len__()==0: - has_voids=False - # Step 3: 写入最终的 PCD 文件 - output_pcd_path = config.save_path("pcd", f"{sn}_merged.pcd") - write_pcd(output_pcd_path, merged_points) - # print(f"Merged and saved to {output_pcd_path}") - return has_voids - - -def tiff_depth_to_point_cloud(tiff_path,sn, dedup=True): - """ - 将 TIFF 深度图转换为点云,基于给定的视场角计算相机内参 - - :param tiff_path: str, TIFF 深度图路径 - :param hfov_degrees: float or None, 水平视场角(单位:度) - :param vfov_degrees: float or None, 垂直视场角(单位:度) - :param output_ply_path: str or None, 输出 Pcd 文件路径(可选) - :param dedup: bool, 是否根据 (x, y) 去重,默认开启 - :return: list of [x, y, z] 点云数据 - """ - hfov_degrees = config.CAMERA_CONFIG_MAP[sn].get("x_angle") - max_z = config.CAMERA_CONFIG_MAP[sn].get("max_z") - vfov_degrees = config.CAMERA_CONFIG_MAP[sn].get("y_angle") - # plane_scaling_ratio = config.CAMERA_CONFIG_MAP[sn].get("plane_scaling_ratio") - # 加载 TIFF 图像 - depth_image = Image.open(tiff_path) - depth_array = np.array(depth_image, dtype=np.float32) - - height, width = depth_array.shape - - # 根据提供的 FOV 计算 fx/fy - if hfov_degrees is not None: - hfov_rad = math.radians(hfov_degrees) - fx = width / (2 * math.tan(hfov_rad / 2)) - fy = fx * height / width # 保持像素方形比例 - else: - vfov_rad = math.radians(vfov_degrees) - fy = height / (2 * math.tan(vfov_rad / 2)) - fx = fy * width / height # 保持像素方形比例 +import numpy as np +from scipy.spatial.transform import Rotation as R - cx = width / 2 - cy = height / 2 +from logConfig import get_logger - print(f"Calculated intrinsics: fx={fx:.2f}, fy={fy:.2f}, cx={cx:.2f}, cy={cy:.2f}") +# 使用示例 +logger = get_logger() - points = [] - seen_xy = set() # 用于记录已添加的 (x, y) +def apply_rotation(matrix, angle_degrees, axis='x'): + """ + 对输入的 3x3 旋转矩阵 应用额外的旋转 - # 获取裁剪配置 - clip_config = config.CUT_CONFIG_MAP.get(sn) - if clip_config: - min_pt = np.array(clip_config.get("min_pt", [-np.inf] * 3)) - max_pt = np.array(clip_config.get("max_pt", [np.inf] * 3)) - rotation = np.array(clip_config.get("rotation", [1,0,0,0,1,0,0,0,1])).reshape(3, 3) - else: - min_pt = max_pt = rotation = None - - for v in range(height): - for u in range(width): - z = depth_array[v, u] # mm -> m - if z <= 0 or z > max_z: - continue - - x = (u - cx) * z / fx - y = (v - cy) * z / fy - - # 构造点并旋转(保留浮点精度) - point = np.array([x, y, z]) - if clip_config: - rotated_point = (rotation @ point.T).T - if not np.all(rotated_point >= min_pt) or not np.all(rotated_point <= max_pt): - continue - x_final, y_final, z_final = rotated_point - else: - x_final, y_final, z_final = point - - # 到这里才进行去重判断 - if dedup: - x_int = int(round(x_final)) - y_int = int(round(y_final)) - z_int = int(round(z_final)) - if (x_int, y_int) in seen_xy: - continue - seen_xy.add((x_int, y_int)) - # 保留浮点精度写入结果 - points.append([x_int, y_int, z_int]) - - - # 可选输出PLY文件用于可视化 - if config.CAMERA_CONFIG_MAP[sn].get("save_pcd"): - output_ply_path = config.save_path("pcd",sn+".pcd") - write_pcd(output_ply_path, points) + 参数: + matrix (np.ndarray): 原始的 3x3 旋转矩阵 + angle_degrees (float): 旋转角度 (单位: 度) + axis (str): 旋转轴,支持 'x', 'y', 'z' - return points + 返回: + np.ndarray: 新的 3x3 旋转矩阵 + """ + # 创建绕指定轴旋转的旋转对象 + rot = R.from_euler(axis, angle_degrees, degrees=True) + + # 将当前旋转转换为矩阵 + rotation_matrix = rot.as_matrix() + + # 合并旋转:新旋转 × 原始矩阵 + combined_rotation = np.dot(rotation_matrix, matrix) + + return combined_rotation + +# +# def tiff_depth_to_point_cloud(tiff_path,sn, dedup=True): +# """ +# 将 TIFF 深度图转换为点云,基于给定的视场角计算相机内参 +# +# :param tiff_path: str, TIFF 深度图路径 +# :param hfov_degrees: float or None, 水平视场角(单位:度) +# :param vfov_degrees: float or None, 垂直视场角(单位:度) +# :param output_ply_path: str or None, 输出 Pcd 文件路径(可选) +# :param dedup: bool, 是否根据 (x, y) 去重,默认开启 +# :return: list of [x, y, z] 点云数据 +# """ +# hfov_degrees = config.CAMERA_CONFIG_MAP[sn].get("x_angle") +# max_z = config.CAMERA_CONFIG_MAP[sn].get("max_z") +# vfov_degrees = config.CAMERA_CONFIG_MAP[sn].get("y_angle") +# # plane_scaling_ratio = config.CAMERA_CONFIG_MAP[sn].get("plane_scaling_ratio") +# # 加载 TIFF 图像 +# depth_image = Image.open(tiff_path) +# depth_array = np.array(depth_image, dtype=np.float32) +# +# height, width = depth_array.shape +# +# # 根据提供的 FOV 计算 fx/fy +# if hfov_degrees is not None: +# hfov_rad = math.radians(hfov_degrees) +# fx = width / (2 * math.tan(hfov_rad / 2)) +# fy = fx * height / width # 保持像素方形比例 +# else: +# vfov_rad = math.radians(vfov_degrees) +# fy = height / (2 * math.tan(vfov_rad / 2)) +# fx = fy * width / height # 保持像素方形比例 +# +# cx = width / 2 +# cy = height / 2 +# +# print(f"Calculated intrinsics: fx={fx:.2f}, fy={fy:.2f}, cx={cx:.2f}, cy={cy:.2f}") +# +# points = [] +# seen_xy = set() # 用于记录已添加的 (x, y) +# +# # 获取裁剪配置 +# clip_config = config.CUT_CONFIG_MAP.get(sn) +# if clip_config: +# min_pt = np.array(clip_config.get("min_pt", [-np.inf] * 3)) +# max_pt = np.array(clip_config.get("max_pt", [np.inf] * 3)) +# rotation = np.array(clip_config.get("rotation", [1,0,0,0,1,0,0,0,1])).reshape(3, 3) +# else: +# min_pt = max_pt = rotation = None +# +# for v in range(height): +# for u in range(width): +# z = depth_array[v, u] # mm -> m +# if z <= 0 or z > max_z: +# continue +# +# x = (u - cx) * z / fx +# y = (v - cy) * z / fy +# +# # 构造点并旋转(保留浮点精度) +# point = np.array([x, y, z]) +# if clip_config: +# rotated_point = (rotation @ point.T).T +# if not np.all(rotated_point >= min_pt) or not np.all(rotated_point <= max_pt): +# continue +# x_final, y_final, z_final = rotated_point +# else: +# x_final, y_final, z_final = point +# +# # 到这里才进行去重判断 +# if dedup: +# x_int = int(round(x_final)) +# y_int = int(round(y_final)) +# z_int = int(round(z_final)) +# if (x_int, y_int) in seen_xy: +# continue +# seen_xy.add((x_int, y_int)) +# # 保留浮点精度写入结果 +# points.append([x_int, y_int, z_int]) +# +# +# # 可选输出PLY文件用于可视化 +# if config.CAMERA_CONFIG_MAP[sn].get("save_pcd"): +# output_ply_path = config.save_path("pcd",sn+".pcd") +# write_pcd(output_ply_path, points) +# +# return points # 新增点云数据转换函数 @@ -141,67 +142,139 @@ def convert_sdk_points(sValue, width, height): mask = np.all(np.isfinite(points), axis=1) return points[mask] +# def process_point_cloud_fast(points, sn, type): +# points = np.array(points, dtype=np.float32) +# # 获取目标高度和容差(来自模板配置) +# template_config = config.TEMPLATE_CONFIG_MAP.get(type, {}) +# target_z = template_config.get("height", 0) # 假设 height 是期望的中心高度 +# tolerance = template_config.get("tolerance", 50) # 默认容差为 50 +# +# # 计算上下限 +# z_min = target_z - tolerance +# z_max = target_z + tolerance # 不超过 200 +# # Z 值过滤 +# valid_mask = ((points[:, 2] > 0) +# & (points[:, 2] <= config.CAMERA_CONFIG_MAP[sn].get("max_z", np.inf)) +# ) +# +# points = points[valid_mask] +# +# if clip_config := config.CUT_CONFIG_MAP.get(sn): +# rotation = np.array(clip_config["rotation"], dtype=np.float32).reshape(3, 3) +# min_pt = np.array(clip_config["min_pt"], dtype=np.float32) +# max_pt = np.array(clip_config["max_pt"], dtype=np.float32) +# floorHeight = clip_config.get("floorHeight", 0) +# +# # 批量旋转 +# rotated = (rotation @ points.T).T +# +# # 裁剪范围过滤 +# bounds_mask = np.all((rotated >= min_pt) & (rotated <= max_pt), axis=1) +# rotated = rotated[bounds_mask] +# x_trimmed = np.round(rotated[:, 0], 3) +# y_trimmed = np.round(rotated[:, 1], 3) +# z_trimmed = np.round(floorHeight - rotated[:, 2], 3) +# else: +# x_trimmed = np.round(points[:, 0], 3) +# y_trimmed = np.round(points[:, 1], 3) +# z_trimmed = np.round(points[:, 2], 3) +# +# # 合并为一个数组 +# trimmed_points = np.column_stack((x_trimmed, y_trimmed, z_trimmed)) +# # 应用 z 值过滤 +# final_mask = ( +# (trimmed_points[:, 2] >= z_min) & +# (trimmed_points[:, 2] <= z_max) +# ) +# filtered_points = trimmed_points[final_mask] +# +# # 去重 +# keys = np.column_stack((filtered_points[:, 0], filtered_points[:, 1])) +# _, unique_indices = np.unique(keys, axis=0, return_index=True) +# +# # 返回 list of [x, y, z] +# return filtered_points[unique_indices].tolist() +def process_point_cloud_fast(points, sn, type): + points = np.array(points, dtype=np.float32) + if not len(points): + return [] + + # 获取配置 + template_config = config.TEMPLATE_CONFIG_MAP.get(type, {}) + target_z = template_config.get("height", 0) + tolerance = template_config.get("tolerance", 25) + z_min = target_z - tolerance + z_max = target_z + tolerance + + # 初始 Z 过滤 + valid_mask = (points[:, 2] > 0) & (points[:, 2] <= config.CAMERA_CONFIG_MAP[sn].get("max_z", np.inf)) + points = points[valid_mask] -def process_point_cloud(points, sn, dedup=True): - """ - 对原始点云应用旋转、裁剪和去重 + # 获取裁剪配置 + clip_config = config.CUT_CONFIG_MAP.get(sn + "_" + type, None) or config.CUT_CONFIG_MAP.get(sn) - :param points: np.ndarray(shape=(N,3)), 原始点云数据 - :param sn: str, 设备序列号(用于加载配置) - :param dedup: bool, 是否启用去重 - :return: list of [x, y, z], 处理后的点云列表 - """ - # 加载配置参数 - clip_config = config.CUT_CONFIG_MAP.get(sn) if clip_config: - min_pt = np.array(clip_config.get("min_pt", [-np.inf] * 3)) - max_pt = np.array(clip_config.get("max_pt", [np.inf] * 3)) - rotation = np.array(clip_config.get("rotation", [1, 0, 0, 0, 1, 0, 0, 0, 1])).reshape(3, 3) + rotation = np.array(clip_config["rotation"], dtype=np.float32).reshape(3, 3) + min_pt = np.array(clip_config["min_pt"], dtype=np.float32) + max_pt = np.array(clip_config["max_pt"], dtype=np.float32) + floorHeight = clip_config.get("floorHeight", 0) + + # 批量旋转 + rotated = (rotation @ points.T).T + + # 裁剪范围过滤 + bounds_mask = np.all((rotated >= min_pt) & (rotated <= max_pt), axis=1) + rotated = rotated[bounds_mask] + + # 计算坐标并应用 floorHeight + x_trimmed = rotated[:, 0] + y_trimmed = rotated[:, 1] + z_trimmed = floorHeight - rotated[:, 2] else: - min_pt = max_pt = rotation = None - - processed_points = [] - seen_xy = set() - - for point in points: - x, y, z = point + x_trimmed = points[:, 0] + y_trimmed = points[:, 1] + z_trimmed = points[:, 2] - # 无效点过滤(Z ≤ 0 或超出最大距离) - if z <= 0 or z > config.CAMERA_CONFIG_MAP[sn].get("max_z", np.inf): - continue + # 合并为一个数组 + trimmed_points = np.column_stack(( + np.round(x_trimmed, 3), + np.round(y_trimmed, 3), + np.round(z_trimmed, 3) + )) - # 应用旋转矩阵 - if clip_config: - rotated = rotation @ point - if not np.all(rotated >= min_pt) or not np.all(rotated <= max_pt): - continue - x_final, y_final, z_final = rotated - else: - x_final, y_final, z_final = x, y, z + # 应用 z 值过滤 + final_mask = (trimmed_points[:, 2] >= z_min) & (trimmed_points[:, 2] <= z_max) + filtered_points = trimmed_points[final_mask] - # 去重逻辑(保留浮点精度) - if dedup: - # 使用浮点哈希避免离散化损失 - key = (round(x_final, 3), round(y_final, 3)) - if key in seen_xy: - continue - seen_xy.add(key) + # 去重 + keys = filtered_points[:, :2] # 只取 x,y + _, unique_indices = np.unique(keys, axis=0, return_index=True) - processed_points.append([x_final, y_final, z_final]) + # 返回 list of [x, y, z] + return filtered_points[unique_indices].tolist() - return processed_points - -def sValue_to_pcd(sValue,stPointCloudImage,sn): +def sValue_to_pcd(sValue,stPointCloudImage,sn,type): # 数据格式转换 points = convert_sdk_points(sValue, stPointCloudImage.nWidth, stPointCloudImage.nHeight) # 应用旋转、裁剪、去重(假设设备序列号已知) - processed_points = process_point_cloud(points, sn, dedup=True) + processed_points = process_point_cloud_fast(points, sn,type) output_ply_path = config.save_path("pcd", sn + ".pcd") # 保存结果 - write_pcd(output_ply_path, processed_points) + # Point.py 修改部分 + from thread_pool import submit_task + + if config.CAMERA_CONFIG_MAP[sn].get("save_pcd"): + output_ply_path = config.save_path("pcd", sn + ".pcd") + # 使用线程池异步执行点云文件写入 + submit_task(write_pcd, output_ply_path, processed_points) + if config.CAMERA_CONFIG_MAP[sn].get("save_not_cut", True): + output_ply_path = config.save_path("pcd", sn + "_original.pcd") + submit_task(write_pcd, output_ply_path, points) + + return output_ply_path,processed_points def write_pcd(filename, points): @@ -214,23 +287,21 @@ def write_pcd(filename, points): with open(filename, 'w') as f: # 写入 PCD 文件头 f.write("# .PCD v0.7 - Point Cloud Data file format\n") - f.write(f"VERSION 0.7\n") + f.write("VERSION 0.7\n") f.write("FIELDS x y z\n") - f.write("SIZE 4 4 4\n") # float 类型的大小是 4 字节 - f.write("TYPE F F F\n") # 每个字段的数据类型 - f.write(f"COUNT 1 1 1\n") # 每个字段的数量 - f.write(f"WIDTH {len(points)}\n") # 点数量 - f.write("HEIGHT 1\n") # 单行表示无结构点云 - f.write("VIEWPOINT 0 0 0 1 0 0 0\n") # 默认视角参数 - f.write(f"POINTS {len(points)}\n") # 总点数 - f.write("DATA ascii\n") # 数据部分以 ASCII 形式存储 + f.write("SIZE 4 4 4\n") + f.write("TYPE F F F\n") + f.write("COUNT 1 1 1\n") + f.write(f"WIDTH {len(points)}\n") + f.write(f"HEIGHT 1\n") + f.write("VIEWPOINT 0 0 0 1 0 0 0\n") + f.write(f"POINTS {len(points)}\n") + f.write("DATA ascii\n") + # 写入点数据 for point in points: f.write(f"{point[0]} {point[1]} {point[2]}\n") - print(f"Saved point cloud to {filename}") - + logger.info(f"Saved point cloud to {filename}") -if __name__ == '__main__': - tiff_depth_to_point_cloud("D:/git/test/hik3d-python/image/2025-06-26/depth/191330147_-Depth.tiff", "00DA6823936") diff --git a/SimpleView_SaveImage.py b/SimpleView_SaveImage.py index 936f1b1..fb5ee15 100644 --- a/SimpleView_SaveImage.py +++ b/SimpleView_SaveImage.py @@ -5,6 +5,7 @@ import ctypes import time import os import struct +from thread_pool import submit_task from ctypes import * from datetime import datetime import Point as point @@ -17,17 +18,47 @@ from Mv3dRgbdImport.Mv3dRgbdDefine import DeviceType_Ethernet, DeviceType_USB, D import config as configMap # 全局变量 SN_MAP = {} # {sn: camera_instance} +import time +import random +from ctypes import * +from logConfig import get_logger -def initialize_devices(): - nDeviceNum = ctypes.c_uint(0) +# 使用示例 +logger = get_logger() + +def reconnect_device(sn, max_retries=5, base_delay=1.0, max_delay=10.0): + """ + 重新连接指定序列号的设备 + + Args: + sn (str): 设备序列号 + max_retries (int): 最大重试次数 + base_delay (float): 初始延迟时间(秒) + max_delay (float): 最大延迟时间(秒) + + Returns: + bool: 重连是否成功 + """ + camera = SN_MAP.get(sn) + + + # 如果设备已存在,先尝试关闭 + try: + camera.MV3D_RGBD_CloseDevice() + except: + pass # 忽略关闭时可能的错误 + + # 获取设备信息(需要重新枚举设备) + nDeviceNum = c_uint(0) ret = Mv3dRgbd.MV3D_RGBD_GetDeviceNumber( DeviceType_Ethernet | DeviceType_USB | DeviceType_Ethernet_Vir | DeviceType_USB_Vir, byref(nDeviceNum) ) + if ret != MV3D_RGBD_OK or nDeviceNum.value == 0: - print("Failed to get device number or no devices found.") - return + logger.error("Failed to get device number or no devices found.") + return False stDeviceList = MV3D_RGBD_DEVICE_INFO_LIST() Mv3dRgbd.MV3D_RGBD_GetDeviceList( @@ -35,115 +66,280 @@ def initialize_devices(): pointer(stDeviceList.DeviceInfo[0]), 20, byref(nDeviceNum) ) + # 查找对应序列号的设备 + target_device_info = None for i in range(nDeviceNum.value): - serial_number = ''.join(chr(c) for c in stDeviceList.DeviceInfo[i].chSerialNumber).rstrip('\x00') - print(f"Found device [{i}]: Serial Number: {serial_number}") + device_sn = ''.join(chr(c) for c in stDeviceList.DeviceInfo[i].chSerialNumber).rstrip('\x00') + if device_sn == sn: + target_device_info = stDeviceList.DeviceInfo[i] + break - camera = Mv3dRgbd() + if not target_device_info: + logger.error(f"Device with SN: {sn} not found during reconnection attempt") + return False - # 打开设备 - ret = camera.MV3D_RGBD_OpenDevice(pointer(stDeviceList.DeviceInfo[i])) - if ret != MV3D_RGBD_OK: - print(f"Failed to open device with SN: {serial_number}. Error code: {ret:#x}") - continue + # 尝试重连 + for attempt in range(max_retries): + try: + # 创建新的相机实例 + new_camera = Mv3dRgbd() - # 存入全局 map - SN_MAP[serial_number] = camera - print(f"Successfully added device {serial_number} to SN_MAP") + # 尝试打开设备 + ret = new_camera.MV3D_RGBD_OpenDevice(pointer(target_device_info)) + if ret == MV3D_RGBD_OK: + # 更新全局映射 + SN_MAP[sn] = new_camera + logger.info(f"Successfully reconnected to device {sn}") + return True + else: + logger.info(f"Failed to reconnect to device {sn}. Error code: {ret:#x}") -def pic(sn): + except Exception as e: + logger.info(f"Exception during reconnection attempt {attempt + 1}: {e}") + + # 如果不是最后一次尝试,等待后重试 + if attempt < max_retries - 1: + # 指数退避延迟 + delay = min(base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay) + logger.info(f"Retrying reconnection in {delay:.2f} seconds...") + time.sleep(delay) + + logger.info(f"Failed to reconnect to device {sn} after {max_retries} attempts") + return False + + +def retry_initialize_devices(max_retries=3, base_delay=2.0): + """ + 重试初始化设备 + + Args: + max_retries (int): 最大重试次数 + base_delay (float): 初始延迟时间(秒) + + Returns: + bool: 初始化是否成功 + """ + for attempt in range(max_retries): + try: + # 清空现有设备映射 + SN_MAP.clear() + + nDeviceNum = c_uint(0) + ret = Mv3dRgbd.MV3D_RGBD_GetDeviceNumber( + DeviceType_Ethernet | DeviceType_USB | DeviceType_Ethernet_Vir | DeviceType_USB_Vir, + byref(nDeviceNum) + ) + + if ret != MV3D_RGBD_OK or nDeviceNum.value == 0: + logger.info("Failed to get device number or no devices found.") + if attempt < max_retries - 1: + delay = base_delay * (2 ** attempt) + logger.info(f"Retrying device initialization in {delay} seconds...") + time.sleep(delay) + continue + + stDeviceList = MV3D_RGBD_DEVICE_INFO_LIST() + Mv3dRgbd.MV3D_RGBD_GetDeviceList( + DeviceType_Ethernet | DeviceType_USB | DeviceType_Ethernet_Vir | DeviceType_USB_Vir, + pointer(stDeviceList.DeviceInfo[0]), 20, byref(nDeviceNum) + ) + + success_count = 0 + for i in range(nDeviceNum.value): + serial_number = ''.join(chr(c) for c in stDeviceList.DeviceInfo[i].chSerialNumber).rstrip('\x00') + logger.info(f"Found device [{i}]: Serial Number: {serial_number}") + + camera = Mv3dRgbd() + + # 打开设备 + ret = camera.MV3D_RGBD_OpenDevice(pointer(stDeviceList.DeviceInfo[i])) + if ret != MV3D_RGBD_OK: + logger.info(f"Failed to open device with SN: {serial_number}. Error code: {ret:#x}") + continue + + # 存入全局 map + SN_MAP[serial_number] = camera + logger.info(f"Successfully added device {serial_number} to SN_MAP") + success_count += 1 + + if success_count > 0: + logger.info(f"Successfully initialized {success_count} devices") + return True + else: + logger.info("No devices were successfully initialized") + + except Exception as e: + logger.info(f"Exception during device initialization attempt {attempt + 1}: {e}") + + if attempt < max_retries - 1: + delay = base_delay * (2 ** attempt) + logger.info(f"Retrying device initialization in {delay} seconds...") + time.sleep(delay) + + logger.info(f"Failed to initialize devices after {max_retries} attempts") + return False + + +def enhanced_pic(sn, type): + """ + 增强版的图片采集函数,包含重连机制和点云数据重试机制 + """ camera = SN_MAP.get(sn) if not camera: - print(f"No camera found for SN: {sn}") - return + logger.info(f"No camera found for SN: {sn}, attempting reconnection...") + if not reconnect_device(sn): + logger.info(f"Failed to reconnect to device {sn}") + return None + camera = SN_MAP.get(sn) config = configMap.CAMERA_CONFIG_MAP.get(sn) if not config: - print(f"No config found for SN: {sn}") - return + logger.info(f"No config found for SN: {sn}") + return None - time_on = config.get("time_on", 0) # 延时开始(毫秒) - print(f"Delaying start by {time_on}ms...") - time.sleep(time_on / 1000.0) # 转成秒 + time_on = config.get("time_on", 0) + logger.info(f"Delaying start by {time_on}ms...") + time.sleep(time_on / 1000.0) saved_files = { - "depth": [], - "color": [], - "pcd": [] + "sn": sn, + "depth": "", + "color": "", + "pcd": "", + "point": [] } - # 开始取流 + # 尝试开始取流,如果失败则尝试重连 ret = camera.MV3D_RGBD_Start() if ret != MV3D_RGBD_OK: - print(f"Failed to start grabbing. Error code: {ret:#x}") - return + logger.info(f"Failed to start grabbing. Error code: {ret:#x}") + logger.info("Attempting reconnection...") + if reconnect_device(sn): + camera = SN_MAP.get(sn) + ret = camera.MV3D_RGBD_Start() + if ret != MV3D_RGBD_OK: + logger.info(f"Failed to start grabbing after reconnection. Error code: {ret:#x}") + return saved_files + else: + logger.info("Reconnection failed") + return saved_files try: - stFrameData = MV3D_RGBD_FRAME_DATA() - - # 获取单帧数据 - ret = camera.MV3D_RGBD_FetchFrame(pointer(stFrameData), 5000) - if ret == MV3D_RGBD_OK: - - for i in range(stFrameData.nImageCount): - image_info = stFrameData.stImageData[i] - - # 保存深度图 - if image_info.enImageType == ImageType_Depth: - file_name = configMap.save_path("depth", "-Depth") - ret_save = camera.MV3D_RGBD_SaveImage(pointer(image_info), FileType_TIFF, file_name) - print("Saved depth image." if ret_save == MV3D_RGBD_OK else "Failed to save depth image.") - if ret_save == MV3D_RGBD_OK: - saved_files["depth"].append(file_name) - - # 点云转换与保存 - stPointCloudImage = MV3D_RGBD_IMAGE_DATA() - ret = camera.MV3D_RGBD_MapDepthToPointCloud(pointer(stFrameData.stImageData[i]), pointer(stPointCloudImage)) - if MV3D_RGBD_OK != ret: - print("_MapDepthToPointCloud() Run failed...") - else: - print( - "_MapDepthToPointCloud() Run Succeed: framenum (%d) height(%d) width(%d) len (%d)!" % ( - stPointCloudImage.nFrameNum, - stPointCloudImage.nHeight, stPointCloudImage.nWidth, stPointCloudImage.nDataLen)) - strMode = string_at(stPointCloudImage.pData, stPointCloudImage.nDataLen) - sValue = struct.unpack('f' * int(stPointCloudImage.nHeight * stPointCloudImage.nWidth * 3), - strMode) - pcd_file = point.sValue_to_pcd(sValue, stPointCloudImage, sn) - if pcd_file: - saved_files["pcd"].append(pcd_file) - - # 保存彩色图 - elif image_info.enImageType in ( - ImageType_RGB8_Planar, ImageType_YUV420SP_NV12, - ImageType_YUV420SP_NV21, ImageType_YUV422 - ): - file_name = configMap.save_path("color", "-_Color") - ret_save = camera.MV3D_RGBD_SaveImage(pointer(image_info), FileType_BMP, file_name) - print("Saved color image." if ret_save == MV3D_RGBD_OK else "Failed to save color image.") - if ret_save == MV3D_RGBD_OK: - saved_files["color"].append(file_name) + # 最多重试10次获取有效的点云数据 + max_retries = 10 + retry_count = 0 + point_cloud_success = False - else: - print("Failed to fetch frame.") + # 用于存储最后一次成功的彩色图数据 + last_color_image_info = None + last_color_file_name = None + + while retry_count < max_retries and not point_cloud_success: + stFrameData = MV3D_RGBD_FRAME_DATA() + + # 获取单帧数据 + ret = camera.MV3D_RGBD_FetchFrame(pointer(stFrameData), 5000) + if ret == MV3D_RGBD_OK: + has_depth_data = False + current_color_image_info = None + current_color_file_name = None + + flag = True + for i in range(stFrameData.nImageCount): + image_info = stFrameData.stImageData[i] + + # 保存深度图 + if image_info.enImageType == ImageType_Depth: + has_depth_data = True + stPointCloudImage = MV3D_RGBD_IMAGE_DATA() + ret = camera.MV3D_RGBD_MapDepthToPointCloud(pointer(stFrameData.stImageData[i]), + pointer(stPointCloudImage)) + if MV3D_RGBD_OK != ret: + logger.info(f"_MapDepthToPointCloud() Run failed... Retry: {retry_count + 1}/{max_retries}") + else: + logger.info( + "_MapDepthToPointCloud() Run Succeed: framenum (%d) height(%d) width(%d) len (%d)!" % ( + stPointCloudImage.nFrameNum, + stPointCloudImage.nHeight, stPointCloudImage.nWidth, stPointCloudImage.nDataLen)) + strMode = string_at(stPointCloudImage.pData, stPointCloudImage.nDataLen) + sValue = struct.unpack('f' * int(stPointCloudImage.nHeight * stPointCloudImage.nWidth * 3), + strMode) + pcd_file, processed_points = point.sValue_to_pcd(sValue, stPointCloudImage, sn, type) + if pcd_file and len(processed_points) > 0: + saved_files["pcd"] = pcd_file + saved_files["point"] = processed_points + point_cloud_success = True # 成功获取点云数据 + flag = False + + # 记录彩色图信息,但不立即保存 + elif image_info.enImageType in ( + ImageType_RGB8_Planar, ImageType_YUV420SP_NV12, + ImageType_YUV420SP_NV21, ImageType_YUV422 + ): + file_name = configMap.save_path("color", sn+"_Color") + if config.get("save_image"): + submit_task(camera.MV3D_RGBD_SaveImage,pointer(image_info), FileType_BMP, file_name) + saved_files["color"] = file_name + ".bmp" + logger.info(f"Color image saved successfully: {saved_files['color']}") + + if flag:break + # 如果没有深度数据或点云处理失败,增加重试次数 + if not has_depth_data: + logger.info(f"No depth data found in frame. Retry: {retry_count + 1}/{max_retries}") + retry_count += 1 + time.sleep(0.1) # 短暂等待后重试 + elif not point_cloud_success: + retry_count += 1 + time.sleep(0.1) # 短暂等待后重试 + + else: + logger.info(f"Failed to fetch frame. Error code: {ret:#x}. Retry: {retry_count + 1}/{max_retries}") + retry_count += 1 + time.sleep(0.1) # 短暂等待后重试 + + except Exception as e: + logger.error(f"Error during frame capture for device {sn}: {e}") finally: camera.MV3D_RGBD_Stop() - print("Single capture completed.") - - # 输出结果路径 - print("Saved files:") - for key, paths in saved_files.items(): - if paths: - print(f" {key.upper()}:") - for path in paths: - print(f" - {path}") + # logger.info(f"Single capture completed. Results: {saved_files}") return saved_files -initialize_devices() +def initialize_devices(): + nDeviceNum = ctypes.c_uint(0) + ret = Mv3dRgbd.MV3D_RGBD_GetDeviceNumber( + DeviceType_Ethernet | DeviceType_USB | DeviceType_Ethernet_Vir | DeviceType_USB_Vir, + byref(nDeviceNum) + ) + if ret != MV3D_RGBD_OK or nDeviceNum.value == 0: + logger.info("Failed to get device number or no devices found.") + return -if __name__ == '__main__': - pic("00DA6823936") \ No newline at end of file + stDeviceList = MV3D_RGBD_DEVICE_INFO_LIST() + Mv3dRgbd.MV3D_RGBD_GetDeviceList( + DeviceType_Ethernet | DeviceType_USB | DeviceType_Ethernet_Vir | DeviceType_USB_Vir, + pointer(stDeviceList.DeviceInfo[0]), 20, byref(nDeviceNum) + ) + + for i in range(nDeviceNum.value): + serial_number = ''.join(chr(c) for c in stDeviceList.DeviceInfo[i].chSerialNumber).rstrip('\x00') + logger.info(f"Found device [{i}]: Serial Number: {serial_number}") + + camera = Mv3dRgbd() + + # 打开设备 + ret = camera.MV3D_RGBD_OpenDevice(pointer(stDeviceList.DeviceInfo[i])) + if ret != MV3D_RGBD_OK: + logger.info(f"Failed to open device with SN: {serial_number}. Error code: {ret:#x}") + continue + + # 存入全局 map + SN_MAP[serial_number] = camera + logger.info(f"Successfully added device {serial_number} to SN_MAP") + + + +initialize_devices() diff --git a/__pycache__/Point.cpython-311.pyc b/__pycache__/Point.cpython-311.pyc index 42d59a1c50034fc3538df99c716f5d979463365f..02a82fb8c46ad37781b4e87e612043dde4d87864 100644 GIT binary patch delta 6462 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 delta 3286 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 diff --git a/__pycache__/SimpleView_SaveImage.cpython-311.pyc b/__pycache__/SimpleView_SaveImage.cpython-311.pyc index a43789ea532994173160e5a5f8b119ea4b093fe9..9a5d3731e84c297f745b8046cdebdc85eda10f74 100644 GIT binary patch delta 2496 zcmbVOeP|nH7=JIxCD&XoN%L{}YI)p#=dLy66SYXZ;Y6E(`&>t%{q{5TE??i zREpLJkZj?pQ#$oVVDNl1U$;zP1|BPo06a0OjWB&JP8>A{e|i+pOlXg+awvS&^^zX$v$PX>xMcCbH!TjgK_pk7!55yC3>N@zggs1{Fu=5nbxDAy z)ZY}~>)t09NJ+P3f=w1D{MuzREEpvtL`)NDmW(_N|6~G$6MnDvktR$tYqYnV*8Qg1 z4e*v_to6#@dev1#`UZ(5+R!&;q|s5Rz7om7{y zRcFLd6#=liFd+z{Y0aCeuVS9zt?Q(j@kSigdF={6akz5pQX+0%qe$ju9QiA1^tHA? zKNw+&-ndgi$J^2bZ?BCK0sfIoNoKy@I**r@NS^7zS23)G+=7+5t08Ah?6A$=xbysP59;Nek|o8i>;%8klJY!&y$@g?9IodA+o~Ro z8>rsl=X~(G-IHU)MAZjCDp~ zt7MUYL@XO{lJHn*&*5TRur1gnn_!k~II^r7S;>x(M@4z!Jgljzy#T=Nj%eqk;S3OF zA5uhFgY`RZaO^`%8KKH z7&>t-G*8ZEJ32b1v}p9d(=Yfj3X>&WHeDk5WJWw$A}8i%=7f?yGr^b0%-nQZgul2u zNueJzVU+Er$PRIOa&mqXe4A~6ud+#-fO7?e0oCkLNx!n)#(6`>iP;R4JU)|e6ib*% z!X=N3Xoa78its(}E2PGUjlQ<+CF`N5y9UROjO-m88x`j=;d()>tdc=Imq`lUDl|^a zr6;GSgg*6#&W@i+@^Hy_qNzk-m1C3BGs%)YBg{=Cv)Lp+rispG)l&yj{s!|52HWw- zI$?+Zb@+?Fv%zXF);ra1t1sFe724=DRsc3HAFMdwaG*CAC)>+xL}8-C7zeF$|Q`es3XVM^gnBJN~>_hD6#%UdTB)QM(-IxxL0ZGLv4MsYg5r5y5-+p@bCW0bc06w#^mGU zXlUOFrGEnTPuxt-$g?jg$s9`N?f?+jqr0ow{6N{$vXm`&BC;n^_6Fs~A;mk4yu-5A zZ+nBqh7A0(A&?V^(>MaUAhvqFPay6B)mAinj{+@GIogY&1M<+*XlP7nK8~7?FPh3t ztrvrrv!9O2i32EcM1E=#JvFN&X64LjC2?BWCZKJC5)+EC?RWG<^Uk{fn?>X8cml;o zZW!gmUiLnEGd5iI#%^xiQz7+R99S#6VzAz($V!@yDWMS*8u{leN%HfP3O9wgseJA~ zrioQzyI0fnN97Qq*3Z2o1YjJpBcfQ^k)>U>v}37twp&!NKm`?wLlh@dT$y5IYgnNo zh>FNszhBXVI!JQv)>`-d``^*5Y+$nt{wTg|Ibe942H(<~9^V4@a6Tg;sAm>D#y#SA z76U;&!b{{~^&k)i;5*z0?s3&UqMEpBcBy6t?hQR+K8vCHH!6GYS|)Uf2=o(A5`?D$ MHrTWdMw)y70+#Af-v9sr delta 3139 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 delta 1964 zcmZWqO>7%g5Z<+S*Z`dTWK?z=@gNI0ROP)9>x&xZiP7BXNuQa|4*W9N`GBa|&;dF2!Y!?yR7Q zJnCG!l=Ubco9A_};w2Fxt?-JEM2QbZKZ%h5i~$l{;gle0BB7NOuY^b#rePuj%32+% zn{%OC+V0}CFsWbTIqo5R4k`7dL1`e3N+W1xtzK);8rR%l0iQ$Qp1)*&@#d!}n)>R; z2ZDGIIDgp?f0kbI0s9nvth*`lJFw1MKEtH*DRZ7`@h}atOz@S4Fxue$miSIuqZ*aj z<6xRku+C7P?_r;W+Qf69JzOq_{^0rE@;&*GQ0l`){RrqH?x!Qj2N6aQwl}4NI2}Wf z5rz@Q0pdX`Fq6q8>4KU~8guk0$Slc`&;(kYKsbqF57lmD@;QT^LeXiC3vu);vS$!p zW3NY|9X)6mA)2YBOm#+2rsmYzstcgHQeKIOaD4Vbbp7~Y5X5=s7y&woE2aGGtf84S zh7&*4lDeAC>zYAZKtT5(IL?qe%gk6e#O7YCQ@jF#68kPzg3wGf6FI(G110?UWO6xP& z|NA{Y1)^ebs&iQEN>x2Y)>@GerVr6)(K*|AE67tz#X=n zbaYTVa5CH&mf*5{CTAM-HrU)Rx9_{p^D*{qN1LmKW1Zdzd*2)M7G1NhCAZ13x0|AF z-cf{!8zbeAqdEtw8WCX^zsnLf63m(rj5jfHZ7S|sz3OJi_ea>L&2#9EqTlUOZuaI5|%IVn0700EN)_?ZCZmi@UYejxK%H>iiR3$ zS~!xQb+k2?%%&Yt(M!CKd~4w3;r4l#eCEy-xuUoDf}ZD0%%UwS`ih>S_}|iA@)!M= zpq8dADVxcu1(V|Dc7a*acsBViiZDOpZhN43BHE0g06dMLinj|1id%=76+ZdKWj5W_ zEn$D4ge`XMJ^4bVVsTJRGK!fT56~zKmdnV|Rut~|K+n`p=u7N*SFD6-O)mo&0f6m% zs%2EeRw?R9dPCc)rH{by8(i@>z%uuj#MQ;Ba`)=Rs@(fUb5$PN7_7>}8(JlNbotfa zZp8x4$b#z*;TzIoOs#LCCtBzi;gx_N8-TA=d6P4h^li)-(IKd7aNR)cP zkL6XN!$3gQ#i_}c6VnT+bdqMLY5pd33L|kQGk0V%VV7cJXkci#Z(yWvXgC3-kQf{r z8XOoO8y{B(1}2Y>j13(bKQf|bHMkJz2LmgxOP)CmT^wEpbC6;>Q4d!FiHpW@atHt( z=e#{k#UqxOo6i;&oR&#IYSm|xWw jFQ3{JVih6w@vYBhRu4Q8daFWjrS^N~ `message` 表示是否检测到空洞: +> - `true`:有空洞 +> - `false`:无空洞 + +#### 📤 错误响应 + +- 缺少参数: + ```json + { + "message": "", + "status": "ERROR", + "error": "Missing required parameter: 'sn'" + } + ``` + + +- 模板不存在: + ```json + { + "message": "", + "status": "ERROR", + "error": "Missing required parameter: 'type'" + } + ``` + + +- 其他异常: + ```json + { + "message": "", + "status": "ERROR", + "error": "Failed to get TIFF paths: [错误信息]" + } + ``` + + +--- + +## ⚠️ 全局异常处理 + +所有未捕获的异常都会被全局异常处理器捕获,并返回如下格式: + +```json +{ + "message": "", + "status": "ERROR", + "error": "[错误信息]" +} +``` + + +--- diff --git a/config/配置文件说明.txt b/config/配置文件说明.txt index caf4797..e7ae3cd 100644 --- a/config/配置文件说明.txt +++ b/config/配置文件说明.txt @@ -2,13 +2,26 @@ camera文档 { "sn": "00DA6823936",#sn "direction": "1",#方向 - "x_angle": 55,#相机的水平视场角(相机自身的) - "y_angle": 84,#相机的垂直视场角 "save_pcd": true,#是否保存pcd - "resolution": 8,#像素大小(可以调整来区别 + "resolution": 8,#像素大小(可以调整生成的图片,根据生成图片识别空洞 "max_z": 2000,#最大深度(裁剪之前的 - "reverse_order": false,#是否pcd组成的图片是否翻转 "time_on": 300,#开始时间 - "time_off": 3500,#结束时间 - "time_hop": 500#时间间隔 -} \ No newline at end of file + "save_not_cut": true #基础的没有裁剪的pcd是否保存 +} + +cut 裁剪文档 +名称:sn_template +当template没有的时候读取sn.json + +template 模版文档 +{ + "type": "45", #模版名称 + "width":"299",#模版横 暂无作用 + "length":"355",#模版宽 暂无作用 + "height": 314 ,#最高高度,从裁剪文档里的floorHeight为0 + "min_area": 20 ,#空洞的最小面积 + "tolerance": 30 #冗余,将判断在最高的位置附近,单位毫米 +} + + +先进行最低的位置,写入floorHeight和旋转参数 \ No newline at end of file diff --git a/image.py b/image.py index e4122cc..b06eb81 100644 --- a/image.py +++ b/image.py @@ -1,12 +1,50 @@ import numpy as np import cv2 -import matplotlib.pyplot as plt +import threading +from thread_pool import submit_task from scipy.ndimage import label import config - +from logConfig import get_logger + +# 使用示例 +logger = get_logger() +# +# def point_cloud_to_2d_image(points, resolution=1.0, x_range=(17, 275), y_range=(-129, -1227)): +# """ +# 将点云转换为 2D 图像(X-Y 平面),每个像素值表示对应位置的 Z 值平均值 +# """ +# if not isinstance(points, np.ndarray): +# points = np.array(points) +# +# if len(points) == 0: +# raise ValueError("点云为空") +# +# x_min, x_max = x_range +# y_min, y_max = y_range +# +# width = int((x_max - x_min) / resolution) + 1 +# height = int((y_max - y_min) / resolution) + 1 +# +# image = np.zeros((height, width), dtype=np.float32) +# count_map = np.zeros((height, width), dtype=np.int32) +# +# for x, y, z in points: +# xi = int((x - x_min) / resolution) +# yi = int((y - y_min) / resolution) +# +# if 0 <= xi < width and 0 <= yi < height: +# image[yi, xi] += z +# count_map[yi, xi] += 1 +# +# # 防止除零错误 +# count_map[count_map == 0] = 1 +# image /= count_map +# +# return image, (x_min, y_min) +# 优化 point_cloud_to_2d_image 函数 def point_cloud_to_2d_image(points, resolution=1.0, x_range=(17, 275), y_range=(-129, -1227)): """ 将点云转换为 2D 图像(X-Y 平面),每个像素值表示对应位置的 Z 值平均值 @@ -23,16 +61,32 @@ def point_cloud_to_2d_image(points, resolution=1.0, x_range=(17, 275), y_range=( width = int((x_max - x_min) / resolution) + 1 height = int((y_max - y_min) / resolution) + 1 + # 使用向量化操作替代循环 + x_coords = points[:, 0] + y_coords = points[:, 1] + z_coords = points[:, 2] + + # 计算像素坐标 + xi = ((x_coords - x_min) / resolution).astype(int) + yi = ((y_coords - y_min) / resolution).astype(int) + + # 筛选有效坐标 + valid_mask = (xi >= 0) & (xi < width) & (yi >= 0) & (yi < height) + xi = xi[valid_mask] + yi = yi[valid_mask] + z_coords = z_coords[valid_mask] + + # 使用直方图统计替代循环累加 image = np.zeros((height, width), dtype=np.float32) count_map = np.zeros((height, width), dtype=np.int32) - for x, y, z in points: - xi = int((x - x_min) / resolution) - yi = int((y - y_min) / resolution) + # 使用 bincount 进行快速统计 + indices = yi * width + xi + z_sums = np.bincount(indices, weights=z_coords, minlength=height * width) + counts = np.bincount(indices, minlength=height * width) - if 0 <= xi < width and 0 <= yi < height: - image[yi, xi] += z - count_map[yi, xi] += 1 + image.flat[:] = z_sums + count_map.flat[:] = counts # 防止除零错误 count_map[count_map == 0] = 1 @@ -41,50 +95,30 @@ def point_cloud_to_2d_image(points, resolution=1.0, x_range=(17, 275), y_range=( return image, (x_min, y_min) -def detect_holes_by_density(density_map, density_threshold_ratio=0.5, min_area=100): - """ - 基于点云密度图识别空洞区域 +def stitch(imagePath1, imagePath2): + # 读取两张图像 + image1 = cv2.imread(imagePath1) + image2 = cv2.imread(imagePath2) - :param density_map: 2D numpy array, 每个像素表示该位置点云密度 - :param density_threshold_ratio: 密度低于均值的 ratio 倍时视为空洞候选 - :param min_area: 最小空洞面积(像素数) - :return: list of ((cx, cy), area),空洞中心和面积(图像坐标) - """ - # 计算邻域平均密度(3x3窗口) - avg_density = np.zeros_like(density_map) - for i in range(density_map.shape[0]): - for j in range(density_map.shape[1]): - # 取 3x3 邻域 - neighbors = density_map[ - max(0, i - 1):min(i + 2, density_map.shape[0]), - max(0, j - 1):min(j + 2, density_map.shape[1]) - ] - avg_density[i, j] = np.mean(neighbors) - - # 构建空洞候选区:密度低于邻域平均值的 50% - binary_map = (density_map < avg_density * density_threshold_ratio).astype(np.uint8) - - # 连通域分析 - structure = np.array([[1, 1, 1], - [1, 1, 1], - [1, 1, 1]]) - labeled_map, num_features = label(binary_map, structure=structure) + # 创建 Stitcher 对象 + stitcher = cv2.Stitcher_create() - holes = [] - for label_id in range(1, num_features + 1): - coords = np.where(labeled_map == label_id) - hole_pixel_count = len(coords[0]) + # 拼接图像 + (status, stitched) = stitcher.stitch((image1, image2)) - if hole_pixel_count >= min_area: - cx = np.mean(coords[1]) # x 坐标(列) - cy = np.mean(coords[0]) # y 坐标(行) - area = hole_pixel_count - holes.append(((cx, cy), area)) + # 检查拼接结果 + if status == cv2.Stitcher_OK: + cv2.imwrite('stitched_output.jpg', stitched) + print("图像拼接成功!") + else: + print(f"图像拼接失败,错误代码: {status}") +if __name__ == '__main__': + stitch('D:/git/test/hik3d-python/image/2025-07-01/color/105601193_-_Color.bmp' + , 'D:/git/test/hik3d-python/image/2025-07-01/color/164646720_-_Color.bmp') - return holes -def detect_black_regions(binary_mask, min_area=10): +def detect_black_regions(binary_mask, min_area=10,box_area=10): """ 检测图像中的黑色连通区域(值为 0 的区域) @@ -111,19 +145,18 @@ def detect_black_regions(binary_mask, min_area=10): labeled_map, num_features = label(binary, structure=structure) regions = [] + count = 0 for label_id in range(1, num_features + 1): coords = np.where(labeled_map == label_id) area = len(coords[0]) - if area >= min_area: cx = np.mean(coords[1]) # x 坐标(列) cy = np.mean(coords[0]) # y 坐标(行) - + logger.info(f"区域: {label_id} 中心: {cx, cy} 面积: {area}") regions.append(((cx, cy),area)) - - - return regions + count += ( area/box_area) + return regions,count def convert_image_holes_to_real(holes, offset, resolution): real_holes = [] x_min, y_min = offset @@ -138,23 +171,39 @@ def visualize_holes_on_image(image, holes, output_path=None): """ 在图像上画出检测到的空洞中心和轮廓 """ - # 彩色化灰度图用于可视化 - color_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) - - for (cx, cy), _ in holes: - # 绘制圆形标注空洞中心 - cv2.circle(color_image, (int(cx), int(cy)), radius=5, color=(0, 0, 255), thickness=-1) - - # 显示图像 - # plt.figure(figsize=(10, 8)) - plt.imshow(cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB)) - # plt.title("Detected Holes") - plt.axis("off") - output_path = config.save_path("image", "_holes.png") - if output_path: - plt.savefig(output_path, bbox_inches='tight', dpi=200) - print(f"Saved visualization to {output_path}") - # plt.show() + try: + # 确保图像数据有效 + if image is None or len(image) == 0: + print("Warning: Empty image data for visualization") + return + + # 彩色化灰度图用于可视化 + if len(image.shape) == 2: # 灰度图 + color_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) + else: + color_image = image.copy() + + # 绘制空洞标记 + if holes: + for (cx, cy), _ in holes: + # 确保坐标有效 + if 0 <= int(cx) < color_image.shape[1] and 0 <= int(cy) < color_image.shape[0]: + cv2.circle(color_image, (int(cx), int(cy)), radius=5, color=(0, 0, 255), thickness=-1) + + # 生成输出路径 + if output_path is None: + output_path = config.save_path("image", "_holes.png") + + # 保存图像 + success = cv2.imwrite(output_path, color_image) + if success: + print(f"Saved visualization to {output_path}") + else: + print(f"Failed to save visualization to {output_path}") + + except Exception as e: + print(f"Error in visualize_holes_on_image: {e}") + def read_pcd_points(pcd_path): """ @@ -183,30 +232,44 @@ def read_pcd_points(pcd_path): continue return points -def detect_large_holes(points,sn, x_max): + +def detect_large_holes(points, sn, type): + # 获取裁剪配置 + cat_map = config.CUT_CONFIG_MAP.get(sn + "_" + type, None) or config.CUT_CONFIG_MAP.get(sn) + template_map = config.TEMPLATE_CONFIG_MAP[type] + camera_map = config.CAMERA_CONFIG_MAP[sn] # 2. 生成 2D 图像 - x_range = (config.CUT_CONFIG_MAP[sn]["min_pt"][0],x_max) # 手动指定 X 范围 - y_range = (config.CUT_CONFIG_MAP[sn]["min_pt"][1], config.CUT_CONFIG_MAP[sn]["max_pt"][1]) # 注意:这里要保证 y_min < y_max,否则反转一下 + x_range = (cat_map["min_pt"][0], cat_map["max_pt"][0]) + y_range = (cat_map["min_pt"][1], cat_map["max_pt"][1]) resolution = config.CAMERA_CONFIG_MAP[sn].get("resolution") image, offset = point_cloud_to_2d_image(points, resolution=resolution, x_range=x_range, y_range=y_range) # 3. 图像归一化用于可视化 normalized_image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) + min_area = min(template_map["min_area"], (template_map["width"] * template_map["height"]) /(2*camera_map["resolution"]*camera_map["resolution"])) # 4. 检测空洞 - holes = detect_black_regions(normalized_image, min_area=20) + holes, count = detect_black_regions(normalized_image, min_area, (template_map["width"] * template_map["height"]) / 2) + + if config.CAMERA_CONFIG_MAP[sn].get("save_image"): + # 创建数据副本确保异步执行时数据完整性 + image_copy = normalized_image.copy() + holes_copy = list(holes) # 创建holes的副本 - # 5. 可视化空洞 - visualize_holes_on_image(normalized_image, holes) + # 预先生成输出路径 + output_path = config.save_path("image", f"_{sn}_holes.png") + + # 使用线程池异步执行可视化操作 + submit_task(visualize_holes_on_image, image_copy, holes_copy, output_path) # 6. 输出真实世界坐标 real_holes = convert_image_holes_to_real(holes, offset, resolution) - return real_holes + return real_holes, count -if __name__ == '__main__': - points = read_pcd_points("D:/PycharmProjects/Hik3D/image/2025-06-25/pcd/182109899_00DA6823936_merged.pcd") - sn = "00DA6823936" - x_max = 326 - detect_large_holes(points,sn, x_max) +# if __name__ == '__main__': +# points = read_pcd_points("D:/PycharmProjects/Hik3D/image/2025-06-25/pcd/182109899_00DA6823936_merged.pcd") +# sn = "00DA6823936" +# x_max = 326 +# detect_large_holes(points,sn, x_max) \ No newline at end of file diff --git a/logConfig.py b/logConfig.py new file mode 100644 index 0000000..45e4df0 --- /dev/null +++ b/logConfig.py @@ -0,0 +1,64 @@ +import logging +from logging.handlers import TimedRotatingFileHandler +import asyncio +import time +import os + + +# 确保 logs 目录存在 +def ensure_logs_directory(): + logs_dir = "logs" + if not os.path.exists(logs_dir): + os.makedirs(logs_dir) + return logs_dir + + +# 配置日志 +def setup_logger(name, log_file, level=logging.INFO): + # 确保 logs 目录存在 + ensure_logs_directory() + + # 构建完整的日志文件路径 + logs_dir = "logs" + full_log_path = os.path.join(logs_dir, log_file) + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + # 创建按时间轮转的文件处理器 + handler = TimedRotatingFileHandler( + full_log_path, # 使用完整路径 + when="midnight", # 每天午夜轮转 + interval=1, # 间隔1天 + backupCount=30 # 保留30天的日志 + ) + handler.setFormatter(formatter) + + logger = logging.getLogger(name) + logger.setLevel(level) + # 避免重复添加 handler + if not logger.handlers: + logger.addHandler(handler) + + return logger + + +# 创建全局logger实例 +logger = setup_logger('hik3d', 'app.log') +def get_logger(): + """ + 获取全局logger实例 + """ + return logger +# 异步写入日志的包装函数 +async def async_log(logger, level, message): + # 在线程池中执行日志写入,避免阻塞事件循环 + loop = asyncio.get_event_loop() + await loop.run_in_executor(None, getattr(logger, level), message) + + +# # 使用示例 +# logger = setup_logger('my_app', 'app.log') + + +# 运行 +# asyncio.run(main()) diff --git a/logs/app.log b/logs/app.log new file mode 100644 index 0000000..2e1a4a3 --- /dev/null +++ b/logs/app.log @@ -0,0 +1,374 @@ +2025-08-15 14:58:42,508 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 14:58:43,733 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 14:58:43,733 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 14:58:44,957 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 14:58:45,411 - hik3d - INFO - ... +2025-08-15 14:58:45,412 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 15:36:29,232 - hik3d - INFO - Failed to get device number or no devices found. +2025-08-15 15:36:29,679 - hik3d - INFO - ... +2025-08-15 15:36:29,680 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 15:37:16,115 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 15:37:17,490 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 15:37:17,490 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 15:37:18,713 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 15:37:19,071 - hik3d - INFO - ... +2025-08-15 15:37:19,072 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 15:37:32,450 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:37:32,453 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:37:32,454 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:32,454 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:37:32,455 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:32,754 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:32,991 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:34,600 - hik3d - INFO - 豸 00DA6823953 ɣʱ 2.146 룬ֿն: False +2025-08-15 15:37:35,121 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.668 룬ֿն: False +2025-08-15 15:37:35,198 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.747 룬: False +2025-08-15 15:37:36,739 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153733795_00DA6823953.pcd +2025-08-15 15:37:39,054 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153734206_00DA6823936.pcd +2025-08-15 15:37:41,353 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153734217_00DA6823936_original.pcd +2025-08-15 15:37:41,502 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153733799_00DA6823953_original.pcd +2025-08-15 15:37:49,321 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:37:49,322 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:37:49,322 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:49,322 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:37:49,322 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:49,540 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:49,703 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:50,722 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.401 룬ֿն: False +2025-08-15 15:37:51,015 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.692 룬ֿն: False +2025-08-15 15:37:51,023 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.702 룬: False +2025-08-15 15:37:52,630 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153750100_00DA6823953.pcd +2025-08-15 15:37:54,952 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153750465_00DA6823936.pcd +2025-08-15 15:37:55,908 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:37:55,913 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:37:55,927 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:55,928 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:37:55,937 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:56,225 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:56,430 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:37:58,020 - hik3d - INFO - 豸 00DA6823953 ɣʱ 2.093 룬ֿն: False +2025-08-15 15:37:58,468 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.555 룬ֿն: False +2025-08-15 15:37:58,482 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.571 룬: False +2025-08-15 15:37:59,779 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:37:59,790 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:37:59,794 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:37:59,799 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:37:59,810 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:38:00,140 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:38:00,354 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:38:00,621 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153757193_00DA6823953.pcd +2025-08-15 15:38:02,657 - hik3d - INFO - 豸 00DA6823953 ɣʱ 2.858 룬ֿն: True +2025-08-15 15:38:02,670 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 15:38:02,686 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.896 룬ֿն: False +2025-08-15 15:38:02,695 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.91 룬: True +2025-08-15 15:38:03,478 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153750469_00DA6823936_original.pcd +2025-08-15 15:38:04,460 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153750102_00DA6823953_original.pcd +2025-08-15 15:38:06,804 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153801589_00DA6823953.pcd +2025-08-15 15:38:07,354 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153757607_00DA6823936.pcd +2025-08-15 15:38:11,996 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153757201_00DA6823953_original.pcd +2025-08-15 15:38:12,311 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153801613_00DA6823936.pcd +2025-08-15 15:38:13,728 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153757647_00DA6823936_original.pcd +2025-08-15 15:38:15,130 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153801599_00DA6823953_original.pcd +2025-08-15 15:38:15,862 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153801622_00DA6823936_original.pcd +2025-08-15 15:39:37,573 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:39:37,574 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:39:37,574 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:39:37,575 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:39:37,575 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:39:37,812 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:39:37,996 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:39:39,036 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.461 룬ֿն: True +2025-08-15 15:39:39,039 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 15:39:39,232 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.658 룬ֿն: False +2025-08-15 15:39:39,234 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.662 룬: True +2025-08-15 15:39:40,263 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153938358_00DA6823953.pcd +2025-08-15 15:39:42,346 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153938671_00DA6823936.pcd +2025-08-15 15:39:46,206 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153938676_00DA6823936_original.pcd +2025-08-15 15:39:46,463 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\153938359_00DA6823953_original.pcd +2025-08-15 15:42:02,249 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 15:42:03,473 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 15:42:03,474 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 15:42:04,712 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 15:42:05,112 - hik3d - INFO - ... +2025-08-15 15:42:05,112 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 15:42:06,533 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:42:06,534 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:42:06,535 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:42:06,535 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:42:06,536 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:42:06,771 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:42:06,922 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:42:08,164 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.629 룬ֿն: False +2025-08-15 15:42:08,582 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.048 룬ֿն: False +2025-08-15 15:42:08,669 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.135 룬: False +2025-08-15 15:42:10,387 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154207390_00DA6823953.pcd +2025-08-15 15:42:11,069 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 15:42:11,072 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 15:42:11,077 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:42:11,077 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 15:42:11,086 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 15:42:11,340 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:42:11,560 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 15:42:13,340 - hik3d - INFO - 豸 00DA6823953 ɣʱ 2.263 룬ֿն: False +2025-08-15 15:42:13,597 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.525 룬ֿն: False +2025-08-15 15:42:13,616 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.547 룬: False +2025-08-15 15:42:14,486 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154207737_00DA6823936.pcd +2025-08-15 15:42:15,688 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154212842_00DA6823953.pcd +2025-08-15 15:42:20,353 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154212845_00DA6823936.pcd +2025-08-15 15:42:21,444 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154207750_00DA6823936_original.pcd +2025-08-15 15:42:21,700 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154207485_00DA6823953_original.pcd +2025-08-15 15:42:25,242 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154212848_00DA6823953_original.pcd +2025-08-15 15:42:25,928 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\154212853_00DA6823936_original.pcd +2025-08-15 17:46:24,253 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 17:46:25,489 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 17:46:25,489 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 17:46:26,713 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 17:46:27,162 - hik3d - INFO - ... +2025-08-15 17:46:27,163 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 17:50:05,524 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 17:50:06,758 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 17:50:06,758 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 17:50:07,990 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 17:50:08,348 - hik3d - INFO - ... +2025-08-15 17:50:08,349 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 17:50:33,128 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 17:50:33,129 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 17:50:33,129 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 17:50:37,567 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (90) height(720) width(1280) len (11059200)! +2025-08-15 17:50:40,334 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175038509_00DA6823936.pcd +2025-08-15 17:50:41,451 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175038513_00DA6823936_original.pcd +2025-08-15 17:50:42,486 - hik3d - INFO - Point cloud data acquired but no color image found in frames +2025-08-15 17:50:42,578 - hik3d - INFO - 豸 00DA6823936 ɣʱ 9.449 룬ֿն: False +2025-08-15 17:50:42,579 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 17:50:42,579 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 17:50:42,861 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 17:50:43,284 - hik3d - INFO - Point cloud data acquired but no color image found in frames +2025-08-15 17:50:43,403 - hik3d - INFO - : 2 : (np.float64(3.015873015873016), np.float64(18.261904761904763)) : 126 +2025-08-15 17:50:43,436 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.857 룬ֿն: True +2025-08-15 17:50:43,439 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 17:50:43,440 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 10.311 룬: True +2025-08-15 17:50:44,119 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175043283_00DA6823953.pcd +2025-08-15 17:50:45,877 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175043283_00DA6823953_original.pcd +2025-08-15 17:52:55,797 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 17:52:57,003 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 17:52:57,004 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 17:52:58,218 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 17:52:58,595 - hik3d - INFO - ... +2025-08-15 17:52:58,595 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 17:53:48,204 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 17:53:48,205 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 17:53:48,205 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 17:53:48,467 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 17:53:50,800 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175349071_00DA6823936.pcd +2025-08-15 17:53:52,037 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175349073_00DA6823936_original.pcd +2025-08-15 17:55:39,217 - hik3d - ERROR - Error during frame capture for device 00DA6823936: _type_ must have storage info +2025-08-15 17:55:39,420 - hik3d - INFO - 豸 00DA6823936 ɣʱ 111.215 룬ֿն: False +2025-08-15 17:55:39,421 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 17:55:39,421 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 17:55:39,681 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 17:55:41,181 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175540199_00DA6823953.pcd +2025-08-15 17:55:43,090 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\175540200_00DA6823953_original.pcd +2025-08-15 17:57:37,611 - hik3d - ERROR - Error during frame capture for device 00DA6823953: _type_ must have storage info +2025-08-15 17:57:37,683 - hik3d - INFO - 豸 00DA6823953 ɣʱ 118.262 룬ֿն: False +2025-08-15 17:57:37,683 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 229.479 룬: False +2025-08-15 18:00:03,885 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 18:00:05,105 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 18:00:05,105 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 18:00:06,337 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 18:00:06,699 - hik3d - INFO - ... +2025-08-15 18:00:06,699 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 18:03:31,258 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:03:31,258 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:03:31,258 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:03:31,515 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:03:33,852 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180332128_00DA6823936.pcd +2025-08-15 18:03:36,009 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180332130_00DA6823936_original.pcd +2025-08-15 18:04:15,069 - hik3d - ERROR - Error during frame capture for device 00DA6823936: 'NoneType' object has no attribute 'encode' +2025-08-15 18:04:15,199 - hik3d - INFO - 豸 00DA6823936 ɣʱ 43.94 룬ֿն: False +2025-08-15 18:04:15,200 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:04:15,200 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:04:15,445 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:04:15,844 - hik3d - ERROR - Error during frame capture for device 00DA6823953: 'NoneType' object has no attribute 'encode' +2025-08-15 18:04:15,982 - hik3d - INFO - : 2 : (np.float64(3.015748031496063), np.float64(17.755905511811022)) : 127 +2025-08-15 18:04:16,016 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.817 룬ֿն: True +2025-08-15 18:04:16,018 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 18:04:16,021 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 44.763 룬: True +2025-08-15 18:04:16,688 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180415840_00DA6823953.pcd +2025-08-15 18:04:18,438 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180415841_00DA6823953_original.pcd +2025-08-15 18:04:19,070 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:04:19,070 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:04:19,070 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:04:19,284 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:04:19,748 - hik3d - ERROR - Error during frame capture for device 00DA6823936: 'NoneType' object has no attribute 'encode' +2025-08-15 18:04:20,001 - hik3d - INFO - 豸 00DA6823936 ɣʱ 0.931 룬ֿն: False +2025-08-15 18:04:20,004 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:04:20,006 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:04:20,404 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:04:20,888 - hik3d - ERROR - Error during frame capture for device 00DA6823953: 'NoneType' object has no attribute 'encode' +2025-08-15 18:04:21,096 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.092 룬ֿն: False +2025-08-15 18:04:21,102 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.032 룬: False +2025-08-15 18:04:22,477 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180420876_00DA6823953.pcd +2025-08-15 18:04:22,775 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180419746_00DA6823936.pcd +2025-08-15 18:04:26,212 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180419747_00DA6823936_original.pcd +2025-08-15 18:04:27,027 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\180420879_00DA6823953_original.pcd +2025-08-15 18:10:39,234 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 18:10:40,467 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 18:10:40,468 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 18:10:41,697 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 18:10:42,091 - hik3d - INFO - ... +2025-08-15 18:10:42,091 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 18:10:44,554 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:10:44,554 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:10:44,555 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:10:44,831 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:10:45,486 - hik3d - ERROR - Error during frame capture for device 00DA6823936: unsupported operand type(s) for +: 'NoneType' and 'str' +2025-08-15 18:10:45,762 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.208 룬ֿն: False +2025-08-15 18:10:45,764 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:10:45,766 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:10:46,024 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:10:46,428 - hik3d - ERROR - Error during frame capture for device 00DA6823953: unsupported operand type(s) for +: 'NoneType' and 'str' +2025-08-15 18:10:46,650 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.886 룬ֿն: False +2025-08-15 18:10:46,651 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.097 룬: False +2025-08-15 18:10:48,189 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181046397_00DA6823953.pcd +2025-08-15 18:10:48,746 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181045458_00DA6823936.pcd +2025-08-15 18:10:50,855 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181045461_00DA6823936_original.pcd +2025-08-15 18:10:51,277 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181046399_00DA6823953_original.pcd +2025-08-15 18:16:38,887 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 18:16:40,103 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 18:16:40,103 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 18:16:41,320 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 18:16:41,661 - hik3d - INFO - ... +2025-08-15 18:16:41,661 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 18:16:45,462 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:16:45,463 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:16:45,463 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:16:45,701 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:16:46,339 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181646336_00DA6823936_Color.bmp +2025-08-15 18:16:46,627 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.163 룬ֿն: False +2025-08-15 18:16:46,629 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:16:46,631 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:16:46,903 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:16:47,323 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181647323_00DA6823953_Color.bmp +2025-08-15 18:16:47,482 - hik3d - INFO - : 1 : (np.float64(3.1548387096774193), np.float64(16.929032258064517)) : 155 +2025-08-15 18:16:47,547 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.918 룬ֿն: True +2025-08-15 18:16:47,551 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 18:16:47,555 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.092 룬: True +2025-08-15 18:16:48,974 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181647310_00DA6823953.pcd +2025-08-15 18:16:49,964 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181646329_00DA6823936.pcd +2025-08-15 18:16:54,723 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181646331_00DA6823936_original.pcd +2025-08-15 18:16:54,887 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181647312_00DA6823953_original.pcd +2025-08-15 18:18:58,924 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-15 18:19:00,158 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-15 18:19:00,158 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-15 18:19:01,382 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-15 18:19:01,782 - hik3d - INFO - ... +2025-08-15 18:19:01,782 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-15 18:19:23,167 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:19:23,168 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:19:23,168 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:23,433 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:24,043 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181924040_00DA6823936_Color.bmp +2025-08-15 18:19:24,313 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.145 룬ֿն: False +2025-08-15 18:19:24,314 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:19:24,318 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:24,592 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:25,026 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181925024_00DA6823953_Color.bmp +2025-08-15 18:19:25,237 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.923 룬ֿն: False +2025-08-15 18:19:25,241 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.073 룬: False +2025-08-15 18:19:26,553 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:19:26,559 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:19:26,566 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:26,987 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:27,267 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181925011_00DA6823953.pcd +2025-08-15 18:19:28,068 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181928068_00DA6823936_Color.bmp +2025-08-15 18:19:28,673 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.114 룬ֿն: False +2025-08-15 18:19:28,674 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:19:28,679 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:28,939 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181924033_00DA6823936.pcd +2025-08-15 18:19:28,971 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:29,794 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181929794_00DA6823953_Color.bmp +2025-08-15 18:19:30,064 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.39 룬ֿն: False +2025-08-15 18:19:30,069 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 3.51 룬: False +2025-08-15 18:19:31,271 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:19:31,276 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:19:31,276 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:31,542 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:32,607 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181932607_00DA6823936_Color.bmp +2025-08-15 18:19:33,200 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.924 룬ֿն: False +2025-08-15 18:19:33,205 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:19:33,210 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:33,482 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:34,339 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181934339_00DA6823953_Color.bmp +2025-08-15 18:19:34,610 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.404 룬ֿն: False +2025-08-15 18:19:34,613 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 3.338 룬: False +2025-08-15 18:19:35,691 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181928053_00DA6823936.pcd +2025-08-15 18:19:36,188 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:19:36,197 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:19:36,206 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:36,503 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:37,495 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181937495_00DA6823936_Color.bmp +2025-08-15 18:19:38,204 - hik3d - INFO - 豸 00DA6823936 ɣʱ 2.007 룬ֿն: False +2025-08-15 18:19:38,213 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:19:38,219 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:19:38,702 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:19:39,359 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\181939359_00DA6823953_Color.bmp +2025-08-15 18:19:39,387 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181924035_00DA6823936_original.pcd +2025-08-15 18:19:39,577 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181929774_00DA6823953.pcd +2025-08-15 18:19:39,684 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.472 룬ֿն: False +2025-08-15 18:19:39,694 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 3.497 룬: False +2025-08-15 18:19:41,579 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181925016_00DA6823953_original.pcd +2025-08-15 18:19:45,468 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181928060_00DA6823936_original.pcd +2025-08-15 18:19:45,525 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181932590_00DA6823936.pcd +2025-08-15 18:19:47,666 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181934323_00DA6823953.pcd +2025-08-15 18:19:50,543 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181929785_00DA6823953_original.pcd +2025-08-15 18:19:50,887 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181937478_00DA6823936.pcd +2025-08-15 18:19:51,124 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181932598_00DA6823936_original.pcd +2025-08-15 18:19:52,495 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181939341_00DA6823953.pcd +2025-08-15 18:19:53,789 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181934331_00DA6823953_original.pcd +2025-08-15 18:19:55,718 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181937487_00DA6823936_original.pcd +2025-08-15 18:19:55,969 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\181939350_00DA6823953_original.pcd +2025-08-15 18:20:28,544 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:20:28,544 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:20:28,544 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:20:28,763 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:20:29,247 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\182029247_00DA6823936_Color.bmp +2025-08-15 18:20:29,515 - hik3d - INFO - 豸 00DA6823936 ɣʱ 0.971 룬ֿն: False +2025-08-15 18:20:29,519 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:20:29,521 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:20:29,756 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:20:30,185 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\182030185_00DA6823953_Color.bmp +2025-08-15 18:20:30,393 - hik3d - INFO - 豸 00DA6823953 ɣʱ 0.874 룬ֿն: False +2025-08-15 18:20:30,397 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.852 룬: False +2025-08-15 18:20:31,892 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182030178_00DA6823953.pcd +2025-08-15 18:20:32,965 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182029244_00DA6823936.pcd +2025-08-15 18:20:37,227 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:20:37,229 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:20:37,231 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:20:37,494 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:20:37,787 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182029245_00DA6823936_original.pcd +2025-08-15 18:20:38,279 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\182038279_00DA6823936_Color.bmp +2025-08-15 18:20:38,473 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182030181_00DA6823953_original.pcd +2025-08-15 18:20:38,666 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.437 룬ֿն: False +2025-08-15 18:20:38,666 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-15 18:20:38,667 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:20:39,120 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:20:39,788 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\182039788_00DA6823953_Color.bmp +2025-08-15 18:20:40,061 - hik3d - INFO - : 1 : (np.float64(6.953488372093023), np.float64(5.005813953488372)) : 172 +2025-08-15 18:20:40,124 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.458 룬ֿն: True +2025-08-15 18:20:40,130 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-15 18:20:40,139 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.91 룬: True +2025-08-15 18:20:42,058 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182039776_00DA6823953.pcd +2025-08-15 18:20:43,158 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182038265_00DA6823936.pcd +2025-08-15 18:20:47,244 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182038269_00DA6823936_original.pcd +2025-08-15 18:20:47,958 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182039781_00DA6823953_original.pcd +2025-08-15 18:20:54,497 - hik3d - INFO - յȫ豸ͼƬ +2025-08-15 18:20:54,498 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-15 18:20:54,498 - hik3d - INFO - Delaying start by 0ms... +2025-08-15 18:20:54,745 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-15 18:20:55,503 - hik3d - INFO - Color image saved successfully: .\image\2025-08-15\color\182055502_00DA6823936_Color.bmp +2025-08-15 18:20:55,764 - hik3d - INFO - : 4 : (np.float64(130.0084985835694), np.float64(10.51841359773371)) : 353 +2025-08-15 18:20:55,852 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.354 룬ֿն: True +2025-08-15 18:20:55,852 - hik3d - INFO - 豸 00DA6823936 ֿնֹͣ +2025-08-15 18:20:55,860 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.361 룬: True +2025-08-15 18:20:58,111 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182055494_00DA6823936.pcd +2025-08-15 18:21:00,396 - hik3d - INFO - Saved point cloud to .\image\2025-08-15\pcd\182055498_00DA6823936_original.pcd diff --git a/logs/app.log.2025-08-13 b/logs/app.log.2025-08-13 new file mode 100644 index 0000000..158447e --- /dev/null +++ b/logs/app.log.2025-08-13 @@ -0,0 +1,31 @@ +2025-08-13 16:12:20,821 - my_app - INFO - ??????????... +2025-08-13 16:12:20,822 - my_app - INFO - ????????????????????: http://0.0.0.0:5000 +2025-08-13 16:15:30,880 - my_app - INFO - ??????????????????? +2025-08-13 16:15:30,880 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:15:32,037 - my_app - INFO - ?? 00DA6823953 ????????????????: True +2025-08-13 16:16:18,432 - my_app - INFO - ??????????????????? +2025-08-13 16:16:18,432 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:18:41,293 - my_app - INFO - ?? 00DA6823953 ????????????????: True +2025-08-13 16:19:50,738 - my_app - INFO - ??????????????????? +2025-08-13 16:19:50,738 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:22:36,790 - my_app - INFO - ?? 00DA6823953 ????????????????: True +2025-08-13 16:22:43,332 - my_app - INFO - ??????????????????? +2025-08-13 16:22:43,333 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:32:29,290 - my_app - INFO - ?? 00DA6823953 ????????????????: True +2025-08-13 16:34:45,693 - my_app - INFO - ??????????... +2025-08-13 16:34:45,693 - my_app - INFO - ????????????????????: http://0.0.0.0:5000 +2025-08-13 16:34:48,018 - my_app - INFO - ??????????????????? +2025-08-13 16:34:48,019 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:37:21,400 - my_app - INFO - ??????????... +2025-08-13 16:37:21,400 - my_app - INFO - ????????????????????: http://0.0.0.0:5000 +2025-08-13 16:37:25,853 - my_app - INFO - ??????????????????? +2025-08-13 16:37:25,853 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:39:18,660 - my_app - INFO - ??????????... +2025-08-13 16:39:18,660 - my_app - INFO - ????????????????????: http://0.0.0.0:5000 +2025-08-13 16:39:20,967 - my_app - INFO - ??????????????????? +2025-08-13 16:39:20,967 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:42:12,161 - my_app - INFO - ??????????... +2025-08-13 16:42:12,161 - my_app - INFO - ????????????????????: http://0.0.0.0:5000 +2025-08-13 16:42:12,686 - my_app - INFO - ??????????????????? +2025-08-13 16:42:12,686 - my_app - INFO - ????????? 00DA6823953 ???? 46 ???????? +2025-08-13 16:43:58,412 - my_app - INFO - ?? 00DA6823953 ????????????????: True diff --git a/logs/app.log.2025-08-14 b/logs/app.log.2025-08-14 new file mode 100644 index 0000000..2cb4831 --- /dev/null +++ b/logs/app.log.2025-08-14 @@ -0,0 +1,129 @@ +2025-08-14 10:53:41,032 - my_app - INFO - յȫ豸ͼƬ +2025-08-14 10:53:41,063 - my_app - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 10:53:42,203 - my_app - ERROR - δ쳣: 'NoneType' object has no attribute 'get' +2025-08-14 10:53:58,406 - my_app - ERROR - δ쳣: 405 Method Not Allowed: The method is not allowed for the requested URL. +2025-08-14 10:54:02,996 - my_app - INFO - յȫ豸ͼƬ +2025-08-14 10:54:02,997 - my_app - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 10:54:04,023 - my_app - ERROR - δ쳣: 'NoneType' object has no attribute 'get' +2025-08-14 11:08:48,337 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-14 11:08:49,581 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-14 11:08:49,582 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-14 11:08:50,815 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-14 11:08:51,290 - hik3d - INFO - ... +2025-08-14 11:08:51,290 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-14 11:09:14,203 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-14 11:09:15,432 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-14 11:09:15,432 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-14 11:09:16,673 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-14 11:09:17,005 - hik3d - INFO - ... +2025-08-14 11:09:17,005 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-14 11:09:30,806 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-14 11:09:32,021 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-14 11:09:32,021 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-14 11:09:33,242 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-14 11:09:33,563 - hik3d - INFO - ... +2025-08-14 11:09:33,563 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-14 11:11:28,300 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:11:28,303 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:11:28,304 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:11:28,304 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:11:28,304 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:11:28,604 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:11:28,955 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:11:29,844 - hik3d - INFO - Single capture completed. +2025-08-14 11:11:29,890 - hik3d - INFO - Single capture completed. +2025-08-14 11:11:32,596 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111129675_00DA6823953.pcd +2025-08-14 11:11:32,999 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111129813_00DA6823936.pcd +2025-08-14 11:11:37,728 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111129826_00DA6823936_original.pcd +2025-08-14 11:11:37,912 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111129679_00DA6823953_original.pcd +2025-08-14 11:11:41,891 - hik3d - INFO - 豸 00DA6823936 ɣʱ 13.588 룬ֿն: False +2025-08-14 11:11:41,891 - hik3d - INFO - 豸 00DA6823953 ɣʱ 13.587 룬ֿն: False +2025-08-14 11:11:41,901 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 13.601 룬: False +2025-08-14 11:11:48,424 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:11:48,425 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:11:48,425 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:11:48,425 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:11:48,425 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:11:48,680 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:11:48,738 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:11:49,370 - hik3d - INFO - Single capture completed. +2025-08-14 11:11:49,373 - hik3d - INFO - Single capture completed. +2025-08-14 11:11:49,679 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.254 룬ֿն: False +2025-08-14 11:11:49,684 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.259 룬ֿն: False +2025-08-14 11:11:49,693 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.269 룬: False +2025-08-14 11:11:51,210 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111149339_00DA6823953.pcd +2025-08-14 11:11:51,587 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111149339_00DA6823936.pcd +2025-08-14 11:11:57,141 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111149341_00DA6823936_original.pcd +2025-08-14 11:11:57,405 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111149340_00DA6823953_original.pcd +2025-08-14 11:12:13,342 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:12:13,343 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:12:13,343 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:12:13,344 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:12:13,344 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:12:13,565 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:12:13,702 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:12:14,209 - hik3d - INFO - Single capture completed. +2025-08-14 11:12:14,244 - hik3d - INFO - Single capture completed. +2025-08-14 11:12:14,491 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.148 룬ֿն: False +2025-08-14 11:12:14,687 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.343 룬ֿն: True +2025-08-14 11:12:14,691 - hik3d - INFO - 豸 00DA6823953 ֿնֹͣ +2025-08-14 11:12:14,698 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.355 룬: True +2025-08-14 11:12:15,847 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111214178_00DA6823953.pcd +2025-08-14 11:12:16,160 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111214178_00DA6823936.pcd +2025-08-14 11:12:21,519 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111214180_00DA6823936_original.pcd +2025-08-14 11:12:21,798 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111214182_00DA6823953_original.pcd +2025-08-14 11:13:01,133 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:13:01,134 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:13:01,135 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:13:01,135 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:13:01,135 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:13:01,356 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:13:01,508 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:13:02,036 - hik3d - INFO - Single capture completed. +2025-08-14 11:13:02,143 - hik3d - INFO - Single capture completed. +2025-08-14 11:13:02,325 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.19 룬ֿն: False +2025-08-14 11:13:02,376 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.242 룬ֿն: False +2025-08-14 11:13:02,390 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.257 룬: False +2025-08-14 11:13:03,712 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111301877_00DA6823953.pcd +2025-08-14 11:13:04,157 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111302097_00DA6823936.pcd +2025-08-14 11:13:09,521 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111302102_00DA6823936_original.pcd +2025-08-14 11:13:09,693 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\111301877_00DA6823953_original.pcd +2025-08-14 11:21:14,864 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:21:14,865 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:21:14,865 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:21:14,865 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:21:14,866 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:21:15,111 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:21:15,278 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:21:15,884 - hik3d - INFO - Single capture completed. +2025-08-14 11:21:16,011 - hik3d - INFO - Single capture completed. +2025-08-14 11:21:16,345 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.48 룬ֿն: False +2025-08-14 11:21:16,358 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.493 룬ֿն: False +2025-08-14 11:21:16,370 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 1.506 룬: False +2025-08-14 11:21:17,908 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112115786_00DA6823953.pcd +2025-08-14 11:21:18,291 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112115958_00DA6823936.pcd +2025-08-14 11:21:24,472 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112115965_00DA6823936_original.pcd +2025-08-14 11:21:24,647 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112115786_00DA6823953_original.pcd +2025-08-14 11:25:19,160 - hik3d - INFO - Found device [0]: Serial Number: 00DA6823936 +2025-08-14 11:25:20,425 - hik3d - INFO - Successfully added device 00DA6823936 to SN_MAP +2025-08-14 11:25:20,425 - hik3d - INFO - Found device [1]: Serial Number: 00DA6823953 +2025-08-14 11:25:21,666 - hik3d - INFO - Successfully added device 00DA6823953 to SN_MAP +2025-08-14 11:25:22,165 - hik3d - INFO - ... +2025-08-14 11:25:22,165 - hik3d - INFO - ɹַ: http://0.0.0.0:5000 +2025-08-14 11:25:43,026 - hik3d - INFO - յȫ豸ͼƬ +2025-08-14 11:25:43,028 - hik3d - INFO - ʼ豸 00DA6823936 ͼƬ +2025-08-14 11:25:43,028 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:25:43,029 - hik3d - INFO - ʼ豸 00DA6823953 ͼƬ +2025-08-14 11:25:43,029 - hik3d - INFO - Delaying start by 0ms... +2025-08-14 11:25:43,265 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:25:43,531 - hik3d - INFO - _MapDepthToPointCloud() Run Succeed: framenum (1) height(720) width(1280) len (11059200)! +2025-08-14 11:25:44,154 - hik3d - INFO - Single capture completed. +2025-08-14 11:25:44,277 - hik3d - INFO - Single capture completed. +2025-08-14 11:25:44,474 - hik3d - INFO - 豸 00DA6823953 ɣʱ 1.445 룬ֿն: False +2025-08-14 11:25:44,991 - hik3d - INFO - 豸 00DA6823936 ɣʱ 1.963 룬ֿն: True +2025-08-14 11:25:44,995 - hik3d - INFO - 豸 00DA6823936 ֿնֹͣ +2025-08-14 11:25:45,035 - hik3d - INFO - ȫ豸ͼƬɣܺʱ 2.009 룬: True +2025-08-14 11:25:45,852 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112543933_00DA6823953.pcd +2025-08-14 11:25:47,209 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112544229_00DA6823936.pcd +2025-08-14 11:25:49,519 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112544234_00DA6823936_original.pcd +2025-08-14 11:25:49,681 - hik3d - INFO - Saved point cloud to .\image\2025-08-14\pcd\112544008_00DA6823953_original.pcd diff --git a/main.py b/main.py index 1af8476..a57375b 100644 --- a/main.py +++ b/main.py @@ -1,52 +1,316 @@ # 这是一个示例 Python 脚本。 - +import json +import os # 按 Shift+F10 执行或将其替换为您的代码。 # 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。 import SimpleView_SaveImage as simple import config -from Point import tiff_depth_to_point_clouds +import image +import time # 在文件顶部导入 time 模块 from flask import Flask, jsonify, request +from logConfig import get_logger + app = Flask(__name__) +import concurrent.futures +from functools import partial +# 使用示例 +logger = get_logger() # 示例接口:GET 请求 @app.route("/config/update") def home(): + logger.info("配置更新请求") config.load_configs() - return "Hello, this service config update!" - -# 示例接口:返回 JSON 数据 -@app.route("/api/data") -def get_data(): - data = {"message": "This is some data", "status": "OK"} - return jsonify(data) - -# 示例接口:接收参数 -# 示例接口:接收参数 -@app.route("/api/compute/") -def compute(direction): - try: - sn = config.DIRECTION_CAMERA[direction] - except KeyError: - return jsonify({"message": "", "status": "ERROR", "error": f"Direction '{direction}' not found in DIRECTION_CAMERA"}), 400 + logger.info("配置更新完成") + return {"message": "Hello, this service config update!", "status": "OK"} + + +@app.route("/api/addTemplate", methods=["POST"]) +def save_template(): + logger.info("接收到添加模板请求") + data = request.get_json() + + # 验证必要字段 + if not data: + logger.error("添加模板失败:未提供数据") + return jsonify({"status": "ERROR", "message": "No data provided"}), 400 + template_type = data.get("type") + if not template_type: + logger.error("添加模板失败:缺少'type'字段") + return jsonify({"status": "ERROR", "message": "Missing 'type' field"}), 400 + CONFIG_DIR = "./config/template" + # 构造文件路径 + filename = f"{template_type}.json" + file_path = os.path.join(CONFIG_DIR, filename) + + # 写入文件 try: - tiff_paths = simple.pic(sn) + with open(file_path, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=4) + config.load_configs() + logger.info(f"模板 '{template_type}' 保存成功") + return jsonify({"status": "OK", "message": f"Template '{template_type}' saved successfully."}), 200 except Exception as e: - return jsonify({"message": "", "status": "ERROR", "error": f"Failed to get TIFF paths: {str(e)}"}), 500 + logger.error(f"保存模板失败: {str(e)}") + return jsonify({"status": "ERROR", "message": f"Failed to save template: {str(e)}"}), 500 + + +@app.route("/api/initDevice", methods=['POST']) +def initDevice(): + logger.info("设备初始化请求") + simple.initialize_devices() + logger.info("设备初始化完成") + +# +# @app.route("/api/picComputeAll", methods=['POST']) +# def picComputeAll(): +# logger.info("接收到全设备图片计算请求") +# start_time_total = time.time() +# +# # 输入参数 +# # sn:设备编号 +# # type:类型 +# +# # 获取 JSON 数据 +# data = request.get_json() +# type = data['type'] +# template = config.TEMPLATE_CONFIG_MAP.get(type) +# if not template: +# logger.error("缺少模板配置: 'type'") +# return jsonify({ +# "message": "", +# "status": "ERROR", +# "error": "Missing required parameter: 'type'" +# }), 400 +# all_sn_list = list(config.CAMERA_CONFIG_MAP.keys()) +# +# # 遍历每个 sn 并判断是否都有 hole +# all_have_holes = False +# color_list = [] # 新增:用于保存所有 sn 的 color +# +# count_assemble = 0 +# for sn in all_sn_list: +# start_time = time.time() # 开始计时 +# logger.info(f"开始处理设备 {sn} 的图片计算") +# pic_info = simple.enhanced_pic(sn, type) +# points = pic_info.get("point") +# if points is None: +# logger.warning(f"设备 {sn} 未返回点云数据") +# all_have_holes = True +# break +# +# # 提取 color 并加入列表 +# color = pic_info.get("color") +# if color is not None: +# color_list.append(color) +# +# try: +# real_holes, count = image.detect_large_holes(points, sn, type) +# # count_assemble += count +# +# if len(real_holes) != 0: +# all_have_holes = True +# # 计算耗时 +# elapsed_time = round(time.time() - start_time, 3) +# # 输出日志 +# logger.info(f"[INFO] picComputeAll executed in {elapsed_time} seconds {sn}") +# break # 判断到空洞就直接退出 +# except Exception as e: +# all_have_holes = True +# logger.error(f"Failed to process request: {str(e)} sn:{sn}") +# +# # 计算总耗时 +# total_elapsed_time = round(time.time() - start_time_total, 3) +# logger.info(f"全设备图片计算完成,总耗时 {total_elapsed_time} 秒,结果: {all_have_holes}") +# +# # 返回结果中包含 color 列表 +# return jsonify({ +# "message": all_have_holes, +# "lack": all_have_holes, +# "type": type, +# "count": count_assemble, +# "colors": color_list, # 添加 color 列表 +# "status": "OK" +# }) +# +@app.route("/api/picComputeAll", methods=['POST']) +def picComputeAll(): + logger.info("接收到全设备图片计算请求") + start_time_total = time.time() + + # 获取 JSON 数据 + data = request.get_json() + type = data['type'] + template = config.TEMPLATE_CONFIG_MAP.get(type) + if not template: + logger.error("缺少模板配置: 'type'") + return jsonify({ + "message": "", + "status": "ERROR", + "error": "Missing required parameter: 'type'" + }), 400 + all_sn_list = list(config.CAMERA_CONFIG_MAP.keys()) + + # 同步处理每个设备 + all_have_holes = False + color_list = [] + count_assemble = 0 + + # 逐个同步处理设备 + for sn in all_sn_list: + try: + start_time = time.time() + logger.info(f"开始处理设备 {sn} 的图片计算") + + # 同步采集图片信息 + pic_info = simple.enhanced_pic(sn, type) + points = pic_info.get("point") + + if points is None: + logger.warning(f"设备 {sn} 未返回点云数据") + all_have_holes = True + break + + # 提取 color 并加入列表 + if pic_info.get("color") is not None: + color_list.append(pic_info["color"]) + + # 检测空洞 + real_holes, count = image.detect_large_holes(points, sn, type) + + elapsed_time = round(time.time() - start_time, 3) + logger.info(f"设备 {sn} 处理完成,耗时 {elapsed_time} 秒,发现空洞: {len(real_holes) != 0}") + + # 检查是否发现空洞 + if len(real_holes) != 0: + all_have_holes = True + count_assemble += count + logger.info(f"设备 {sn} 发现空洞,停止其他任务") + break # 发现空洞就直接退出 + + except Exception as e: + logger.error(f"处理设备 {sn} 时发生异常: {str(e)}") + all_have_holes = True + break + + # 计算总耗时 + total_elapsed_time = round(time.time() - start_time_total, 3) + logger.info(f"全设备图片计算完成,总耗时 {total_elapsed_time} 秒,结果: {all_have_holes}") + + # 返回结果中包含 color 列表 + return jsonify({ + "message": all_have_holes, + "lack": all_have_holes, + "type": type, + "count": count_assemble, + "colors": color_list, + "status": "OK" + }) + + + +@app.route("/api/picBitCloudy", methods=['POST']) +def picBitCloudy(): + logger.info("接收到picBitCloudy请求") + + # 输入参数 + # sn:设备编号 + # type:类型 + + # 获取 JSON 数据 + data = request.get_json() + direction = data.get('direction') + type = data.get('type') + all_sn_list = list(config.CAMERA_CONFIG_MAP.keys()) + + # 遍历每个 sn 并判断是否都有 hole + all_have_holes = False + color_list = [] # 新增:用于保存所有 sn 的 color + + count_assemble = 0 + for sn in all_sn_list: + if direction and config.CAMERA_CONFIG_MAP[sn].get("direction") != direction: + logger.debug(f"设备 {sn} 方向不匹配,跳过") + continue + + start_time = time.time() # 开始计时 + logger.info(f"开始处理设备 {sn} 的图片计算") + pic_info = simple.enhanced_pic(sn, type) + points = pic_info.get("point") + if points is None or len(points) < 300: + logger.warning(f"设备 {sn} 点云数据不足") + all_have_holes = True + break + + # 提取 color 并加入列表 + color = pic_info.get("color") + if color is not None: + color_list.append(color) + + logger.info(f"picBitCloudy处理完成,结果: {all_have_holes}") + # 返回结果中包含 color 列表 + return jsonify({ + "message": all_have_holes, + "lack": all_have_holes, + "colors": color_list, # 添加 color 列表 + "status": "OK" + }) + +@app.route("/api/picCompute", methods=['POST']) +def picCompute(): + logger.info("接收到单设备图片计算请求") + + # 输入参数 + # sn:设备编号 + # type:类型 try: - rest = tiff_depth_to_point_clouds(tiff_paths, sn, dedup=True) + # 获取 JSON 数据 + data = request.get_json() + if not data or 'sn' not in data: + logger.error("缺少必需参数: 'sn'") + return jsonify({ + "message": "", + "status": "ERROR", + "error": "Missing required parameter: 'sn'" + }), 400 + + sn = data['sn'] + type = data['type'] + logger.info(f"开始处理设备 {sn} 类型 {type} 的图片计算") + + template = config.TEMPLATE_CONFIG_MAP.get(type) + if not template: + logger.error(f"缺少模板配置: {type}") + return jsonify({ + "message": "", + "status": "ERROR", + "error": "Missing required parameter: 'type'" + }), 400 + + pic_info = simple.enhanced_pic(sn, type) + real_holes, count = image.detect_large_holes(pic_info["point"], sn, type) + + result = len(real_holes) != 0 + logger.info(f"设备 {sn} 图片计算完成,检测到空洞: {result}") + + return jsonify({"message": result, + "lack": result, "status": "OK"}) + except Exception as e: - return jsonify({"message": "", "status": "ERROR", "error": f"Point cloud processing failed: {str(e)}"}), 500 + logger.error(f"图片计算失败: {str(e)}") + return jsonify({"message": "", "status": "ERROR", "error": f"Failed to get TIFF paths: {str(e)}"}), 500 + + return jsonify({"message": True, "lack": True, "status": "OK"}) - print(rest) - return jsonify({"message": rest, "status": "OK"}) @app.errorhandler(Exception) def handle_exception(e): # 处理所有未被捕获的异常 + logger.error(f"未捕获的异常: {str(e)}") return jsonify({ "message": "", "status": "ERROR", @@ -57,6 +321,7 @@ def handle_exception(e): if __name__ == "__main__": from waitress import serve + logger.info("服务启动中...") print("Serving on http://0.0.0.0:5000") + logger.info("服务启动成功,监听地址: http://0.0.0.0:5000") serve(app, host='0.0.0.0', port=5000) - diff --git a/thread_pool.py b/thread_pool.py new file mode 100644 index 0000000..0ed0e4e --- /dev/null +++ b/thread_pool.py @@ -0,0 +1,74 @@ +# thread_pool.py +import concurrent.futures +import threading +from typing import Callable, Any + + +class ThreadPoolManager: + _instance = None + _lock = threading.Lock() + + def __new__(cls): + if cls._instance is None: + with cls._lock: + if cls._instance is None: + cls._instance = super(ThreadPoolManager, cls).__new__(cls) + cls._instance._initialized = False + return cls._instance + + def __init__(self): + if not self._initialized: + # 创建线程池,最大4个线程 + self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=4) + self._initialized = True + + def submit(self, fn: Callable, *args, **kwargs) -> concurrent.futures.Future: + """ + 提交任务到线程池执行 + + :param fn: 要执行的函数 + :param args: 函数的位置参数 + :param kwargs: 函数的关键字参数 + :return: Future对象 + """ + if kwargs: + # 如果有关键字参数,需要包装函数 + def wrapper(): + return fn(*args, **kwargs) + + return self.executor.submit(wrapper) + else: + return self.executor.submit(fn, *args) + + def shutdown(self, wait=True): + """ + 关闭线程池 + + :param wait: 是否等待所有任务完成 + """ + self.executor.shutdown(wait=wait) + + +# 创建全局线程池管理器实例 +_thread_pool_manager = ThreadPoolManager() + + +def get_thread_pool() -> ThreadPoolManager: + """ + 获取线程池管理器实例 + + :return: ThreadPoolManager实例 + """ + return _thread_pool_manager + + +def submit_task(fn: Callable, *args, **kwargs) -> concurrent.futures.Future: + """ + 提交任务到线程池执行的便捷函数 + + :param fn: 要执行的函数 + :param args: 函数的位置参数 + :param kwargs: 函数的关键字参数 + :return: Future对象 + """ + return _thread_pool_manager.submit(fn, *args, **kwargs)