我的屏幕画面为什么只显示黑色的背景
import gc
import os
import time
import heapq
import aicube
import image
import nncase_runtime as nn
import ujson
import ulab.numpy as np
from libs.PipeLine import ScopedTiming
from libs.Utils import *
from media.display import *
from media.media import *
from media.sensor import *
display_mode = "lcd"
if display_mode == "lcd":
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
else:
DISPLAY_WIDTH = ALIGN_UP(1920, 16)
DISPLAY_HEIGHT = 1080
OUT_RGB888P_WIDTH = ALIGN_UP(640, 16)
OUT_RGB888P_HEIGH = 360
root_path = "/sdcard/mp_deployment_source/"
config_path = root_path + "deploy_config.json"
deploy_conf = {}
debug_mode = 1
# 定义9x9地图
grid_size = 9
# 柱子位置 (行, 列)
pillar_positions = [
(2, 2), (2, 4), (2, 6),
(4, 2), (4, 4), (4, 6),
(6, 2), (6, 4), (6, 6)
]
# 固定位置分配顺序 (从左到右排序后对应位置)
fixed_positions = [
(6, 2), (4, 2), (2, 2), # 左列 (从下到上)
(6, 4), (4, 4), (2, 4), # 中列 (从下到上)
(2, 6), (4, 6), (6, 6) # 右列 (从上到下)
]
# 多帧确认参数
MIN_CONFIRMATION_FRAMES = 15
PILLAR_CONFIRMATION_THRESHOLD = 0.85 # 提高确认阈值
max_history_length = MIN_CONFIRMATION_FRAMES + 10
def initialize_grid():
"""初始化9x9网格,柱子位置设为2,其他为0"""
grid = [[0] * grid_size for _ in range(grid_size)]
for pos in pillar_positions:
row, col = pos
grid[row][col] = 2
# 设置边界为-1
for i in range(grid_size):
for j in range(grid_size):
if i == 0 or i == grid_size-1 or j == 0 or j == grid_size-1:
grid[i][j] = -1
# 设置特定点为0(覆盖边界和柱子设置)
grid[8][5] = 0 # (8,5)
grid[0][3] = 0 # (0,3)
return grid
def map_pixel_to_grid(x, y):
"""改进的像素坐标到网格坐标映射 - 使用整个图像区域"""
# 使用整个图像区域 (0%到100%)
grid_top = 0
grid_bottom = OUT_RGB888P_HEIGH
grid_left = 0
grid_right = OUT_RGB888P_WIDTH
# 确保点在图像范围内
if not (grid_left <= x <= grid_right and grid_top <= y <= grid_bottom):
return None
# 计算在网格坐标系中的位置
grid_x = (x - grid_left) / (grid_right - grid_left) * grid_size
grid_y = (y - grid_top) / (grid_bottom - grid_top) * grid_size
# 四舍五入到最近的整数索引
col = round(grid_x)
row = round(grid_y)
# 确保索引在有效范围内
col = max(0, min(col, grid_size - 1))
row = max(0, min(row, grid_size - 1))
return int(row), int(col) # 返回(行, 列)
def two_side_pad_param(input_size, output_size):
ratio_w = output_size[0] / input_size[0] # 宽度缩放比例
ratio_h = output_size[1] / input_size[1] # 高度缩放比例
ratio = min(ratio_w, ratio_h) # 取较小的缩放比例
new_w = int(ratio * input_size[0]) # 新宽度
new_h = int(ratio * input_size[1]) # 新高度
dw = (output_size[0] - new_w) / 2 # 宽度差
dh = (output_size[1] - new_h) / 2 # 高度差
top = int(round(dh - 0.1))
bottom = int(round(dh + 0.1))
left = int(round(dw - 0.1))
right = int(round(dw - 0.1))
return top, bottom, left, right, ratio
def read_deploy_config(config_path):
# 打开JSON文件以进行读取deploy_config
with open(config_path, "r") as json_file:
try:
# 从文件中加载JSON数据
config = ujson.load(json_file)
except ValueError as e:
print("JSON 解析错误:", e)
return config
def mark_blocked_paths(grid):
# 标记位于两个1之间的0为不可行走(-2)
for i in range(1, 8):
for j in range(1, 8):
if grid[i][j] != 0:
continue
# 检查左右是否都是1
if grid[i][j-1] == 1 and grid[i][j+1] == 1:
grid[i][j] = -2
# 检查上下是否都是1
elif grid[i-1][j] == 1 and grid[i+1][j] == 1:
grid[i][j] = -2
def heuristic(a, b):
"""曼哈顿距离启发式函数"""
return abs(a[0] - b[0]) + abs(a[1] - b[1])
def find_shortest_path(grid):
"""使用A*算法寻找最短路径"""
start = (8, 5)
end = (0, 3)
# 使用优先队列
open_set = []
heapq.heappush(open_set, (0, start))
came_from = {}
g_score = {start: 0}
f_score = {start: heuristic(start, end)}
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右、下、左、上
while open_set:
_, current = heapq.heappop(open_set)
if current == end:
# 回溯标记路径
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
path.reverse()
# 标记路径
for pos in path:
grid[pos[0]][pos[1]] = 3
return True
for dx, dy in directions:
neighbor = (current[0] + dx, current[1] + dy)
# 检查边界
if not (0 <= neighbor[0] < grid_size and 0 <= neighbor[1] < grid_size):
continue
# 检查是否可通行
if grid[neighbor[0]][neighbor[1]] != 0:
continue
# 计算新的g分数
tentative_g = g_score[current] + 1
# 如果新路径更好
if neighbor not in g_score or tentative_g < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score[neighbor] = tentative_g + heuristic(neighbor, end)
heapq.heappush(open_set, (f_score[neighbor], neighbor))
return False # 没有找到路径
def assign_fixed_positions(pillars):
"""为检测到的柱子分配固定位置,按x坐标从左到右排序"""
if len(pillars) != 9:
print(f"Error: Expected 9 pillars, got {len(pillars)}. Using default positions.")
# 返回默认位置 (中心位置)
return [(4, 4)] * 9
# 按x坐标排序(从左到右)
sorted_pillars = sorted(pillars, key=lambda p: p[0])
# 分配固定位置
grid_positions = []
for i, pillar in enumerate(sorted_pillars):
if i < len(fixed_positions):
grid_positions.append(fixed_positions[i])
else:
grid_positions.append((4, 4)) # 默认位置
return grid_positions
def detection():
print("det_infer start")
# 增加内存池
gc.collect()
nn.shrink_memory_pool()
try:
# 尝试增加内存池大小
nn.set_memory_pool_size(1024*1024*10) # 10MB内存池
except:
print("Warning: Failed to increase memory pool")
# 使用json读取内容初始化部署变量
try:
deploy_conf = read_deploy_config(config_path)
except Exception as e:
print(f"Error reading config: {e}")
return -1
kmodel_name = deploy_conf["kmodel_path"]
labels = deploy_conf["categories"]
confidence_threshold = deploy_conf["confidence_threshold"]
nms_threshold = deploy_conf["nms_threshold"]
img_size = deploy_conf["img_size"]
num_classes = deploy_conf["num_classes"]
color_four = get_colors(num_classes)
nms_option = deploy_conf["nms_option"]
model_type = deploy_conf["model_type"]
if model_type == "AnchorBaseDet":
anchors = deploy_conf["anchors"][0] + deploy_conf["anchors"][1] + deploy_conf["anchors"][2]
kmodel_frame_size = img_size
frame_size = [OUT_RGB888P_WIDTH, OUT_RGB888P_HEIGH]
strides = [8, 16, 32]
# 计算padding值
top, bottom, left, right, ratio = two_side_pad_param(frame_size, kmodel_frame_size)
# 初始化kpu
kpu = nn.kpu()
try:
kpu.load_kmodel(root_path + kmodel_name)
except Exception as e:
print(f"Failed to load model: {e}")
return -1
# 初始化ai2d
ai2d = nn.ai2d()
ai2d.set_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
ai2d.set_pad_param(True, [0, 0, 0, 0, top, bottom, left, right], 0, [114, 114, 114])
ai2d.set_resize_param(True, nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
ai2d_builder = ai2d.build(
[1, 3, OUT_RGB888P_HEIGH, OUT_RGB888P_WIDTH], [1, 3, kmodel_frame_size[1], kmodel_frame_size[0]]
)
# 初始化并配置sensor
sensor = Sensor()
sensor.reset()
# 设置镜像
sensor.set_hmirror(False)
# 设置翻转
sensor.set_vflip(False)
# 通道0直接给到显示VO,格式为YUV420
sensor.set_framesize(width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT)
sensor.set_pixformat(PIXEL_FORMAT_YUV_SEMIPLANAR_420)
# 通道2给到AI做算法处理,格式为RGB888
sensor.set_framesize(width=OUT_RGB888P_WIDTH, height=OUT_RGB888P_HEIGH, chn=CAM_CHN_ID_2)
sensor.set_pixformat(PIXEL_FORMAT_RGB_888_PLANAR, chn=CAM_CHN_ID_2)
# 获取绑定信息
sensor_bind_info = sensor.bind_info(chn=CAM_CHN_ID_0)
print("Sensor bind info:", sensor_bind_info)
# 初始化显示
if display_mode == "lcd":
# 设置为ST7701显示,默认800x480
Display.init(Display.ST7701, to_ide=True)
else:
# 设置为LT9611显示,默认1920x1080
Display.init(Display.LT9611, to_ide=True)
# 简化显示绑定 - 使用默认值
# 创建OSD图像
osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888)
# media初始化
MediaManager.init()
# 启动sensor
sensor.run()
rgb888p_img = None
ai2d_input_tensor = None
data = np.ones((1, 3, kmodel_frame_size[1], kmodel_frame_size[0]), dtype=np.uint8)
ai2d_output_tensor = nn.from_numpy(data)
# 多帧确认系统初始化 - 使用列表代替deque
position_history = [] # 使用列表存储历史帧
confirmed_pillars = set()
frame_count = 0
while True:
try:
with ScopedTiming("total", debug_mode > 0):
rgb888p_img = sensor.snapshot(chn=CAM_CHN_ID_2)
if rgb888p_img.format() == image.RGBP888:
ai2d_input = rgb888p_img.to_numpy_ref()
ai2d_input_tensor = nn.from_numpy(ai2d_input)
# 使用ai2d进行预处理
ai2d_builder.run(ai2d_input_tensor, ai2d_output_tensor)
# 设置模型输入
kpu.set_input_tensor(0, ai2d_output_tensor)
# 模型推理
kpu.run()
# 获取模型输出
results = []
for i in range(kpu.outputs_size()):
out_data = kpu.get_output_tensor(i)
result = out_data.to_numpy()
result = result.reshape((result.shape[0] * result.shape[1] * result.shape[2] * result.shape[3]))
del out_data
results.append(result)
# 使用aicube模块封装的接口进行后处理
det_boxes = aicube.anchorbasedet_post_process(
results[0],
results[1],
results[2],
kmodel_frame_size,
frame_size,
strides,
num_classes,
confidence_threshold,
nms_threshold,
anchors,
nms_option,
)
# ====== 多帧确认系统 ======
# 初始化网格
grid = initialize_grid()
current_frame_detections = set()
# 处理所有检测到的柱子
for det_box in det_boxes:
# 确保类别索引是整数且在有效范围内
class_id = int(det_box[0])
if class_id < 0 or class_id >= len(labels):
continue # 跳过无效的类别索引
conf = det_box[1]
if conf < 0.25: # 置信度阈值
continue
# 计算边界框中心点
x1, y1, x2, y2 = det_box[2], det_box[3], det_box[4], det_box[5]
center_x = (x1 + x2) / 2
center_y = (y1 + y2) / 2
# 记录检测到的柱子(包括类别)
current_frame_detections.add((center_x, center_y, class_id, labels[class_id], conf))
# 更新位置历史记录 - 使用列表代替deque
position_history.append(current_frame_detections)
# 控制历史记录长度
if len(position_history) > max_history_length:
position_history.pop(0)
# 更新柱子确认系统
new_confirmed = set()
# 1. 保留之前已确认的柱子(除非连续多帧未检测到)
for pos in confirmed_pillars:
# 检查最近5帧中是否有该柱子
recent_detections = 0
# 获取最近5帧(如果不足5帧则取全部)
recent_frames = position_history[-5:] if len(position_history) >= 5 else position_history
for frame in recent_frames:
# 检查是否在历史帧中
for hist_pos in frame:
hist_x, hist_y, _, _, _ = hist_pos
cur_x, cur_y, _, _, _ = pos
# 使用欧氏距离检查是否为同一个柱子
distance = ((hist_x - cur_x)**2 + (hist_y - cur_y)**2)**0.5
if distance < 20: # 距离阈值
recent_detections += 1
break
# 如果最近5帧中检测到至少3次,则保留
if recent_detections >= 3:
new_confirmed.add(pos)
# 2. 检查新柱子是否达到确认阈值
for pos in current_frame_detections:
# 检查是否已确认
already_confirmed = False
for conf_pos in confirmed_pillars:
conf_x, conf_y, _, _, _ = conf_pos
cur_x, cur_y, _, _, _ = pos
distance = ((conf_x - cur_x)**2 + (conf_y - cur_y)**2)**0.5
if distance < 20:
already_confirmed = True
break
if already_confirmed:
continue
# 计算该位置在历史帧中的出现频率
detection_count = 0
for frame in position_history:
for frame_pos in frame:
frame_x, frame_y, _, _, _ = frame_pos
cur_x, cur_y, _, _, _ = pos
distance = ((frame_x - cur_x)**2 + (frame_y - cur_y)**2)**0.5
if distance < 20:
detection_count += 1
break
# 计算确认比例
MIN_HISTORY_FRAMES = max(5, min(len(position_history), MIN_CONFIRMATION_FRAMES))
if MIN_HISTORY_FRAMES > 0:
confirmation_ratio = detection_count / MIN_HISTORY_FRAMES
else:
confirmation_ratio = 0
# 如果达到确认阈值,则添加为新柱子
if confirmation_ratio >= PILLAR_CONFIRMATION_THRESHOLD:
new_confirmed.add(pos)
if debug_mode > 0:
print(f"Confirmed new pillar at ({pos[0]}, {pos[1]}) (ratio: {confirmation_ratio:.2f})")
# 更新确认的柱子集合
confirmed_pillars = new_confirmed
# 3. 确保不超过9个柱子
if len(confirmed_pillars) > 9:
print(f"Warning: Too many pillars confirmed ({len(confirmed_pillars)}), selecting the top 9 by confidence")
# 按置信度排序并取前9个
sorted_pillars = sorted(confirmed_pillars, key=lambda p: p[4], reverse=True)
confirmed_pillars = set(sorted_pillars[:9])
# ====== 显示处理 ======
osd_img.clear()
# 1. 显示已确认的柱子数量
status_text = f"Confirmed: {len(confirmed_pillars)}/9"
color = (0, 255, 0) if len(confirmed_pillars) == 9 else (255, 255, 0)
osd_img.draw_string(10, 10, status_text, scale=2, color=color)
# 显示警告信息(如果柱子数量不等于9)
if len(confirmed_pillars) != 9:
warning_text = f"WARNING: Expected 9, got {len(confirmed_pillars)}"
osd_img.draw_string(10, 40, warning_text, scale=1.5, color=(255, 0, 0))
# 2. 在图像上标记已确认的柱子位置
for pos in confirmed_pillars:
center_x, center_y, class_id, class_name, conf = pos
# 转换为显示坐标
display_x = int(center_x * DISPLAY_WIDTH / OUT_RGB888P_WIDTH)
display_y = int(center_y * DISPLAY_HEIGHT / OUT_RGB888P_HEIGH)
# 根据类别设置颜色
if class_name == "hs":
color = (0, 0, 255) # 红色表示黑色柱子
else:
color = (255, 255, 255) # 白色表示白色柱子
# 绘制圆圈标记柱子
osd_img.draw_circle(display_x, display_y, 15, color=color, thickness=3)
# 显示类别标签
osd_img.draw_string(display_x-20, display_y-30, class_name, scale=1.2, color=color)
# 显示置信度
osd_img.draw_string(display_x-30, display_y+20, f"{conf:.2f}", scale=1.0, color=color)
# 3. 绘制检测结果
if det_boxes:
for det_box in det_boxes:
# 确保类别索引是整数且在有效范围内
class_id = int(det_box[0])
if class_id < 0 or class_id >= len(labels):
continue # 跳过无效的类别索引
conf = det_box[1]
if conf < 0.25: # 置信度阈值
continue
x1, y1, x2, y2 = det_box[2], det_box[3], det_box[4], det_box[5]
x = int(x1 * DISPLAY_WIDTH // OUT_RGB888P_WIDTH)
y = int(y1 * DISPLAY_HEIGHT // OUT_RGB888P_HEIGH)
w = int((x2 - x1) * DISPLAY_WIDTH // OUT_RGB888P_WIDTH)
h = int((y2 - y1) * DISPLAY_HEIGHT // OUT_RGB888P_HEIGH)
# 获取颜色
color = color_four[class_id][1:] if class_id < len(color_four) else (255, 0, 0)
osd_img.draw_rectangle(x, y, w, h, color=color)
# 获取标签
label = labels[class_id] if class_id < len(labels) else "unknown"
text = f"{label} {conf:.2f}"
osd_img.draw_string_advanced(x, y - 40, 32, text, color=color)
# 检查是否达到九个柱子
if len(confirmed_pillars) >= 9:
print("\n九个柱子已全部确认!开始分配位置...")
# 提取柱子的中心坐标和类别
pillars = []
for pos in confirmed_pillars:
center_x, center_y, class_id, class_name, conf = pos
pillars.append((center_x, center_y, class_name))
try:
# 按x坐标从左到右排序
pillars_sorted = sorted(pillars, key=lambda p: p[0])
# 分配固定位置
grid_positions = assign_fixed_positions([(p[0], p[1]) for p in pillars_sorted])
# 确保我们正好有9个位置
if len(grid_positions) != 9:
print(f"Warning: Got {len(grid_positions)} grid positions, using fixed positions")
grid_positions = fixed_positions.copy()
# 初始化网格
grid = initialize_grid()
# 标记黑色柱子位置为1
for i, pillar in enumerate(pillars_sorted):
center_x, center_y, class_name = pillar
if class_name == "hs": # 如果是黑色柱子
row, col = grid_positions[i]
grid[row][col] = 1
if debug_mode > 0:
print(f"Black pillar at ({center_x}, {center_y}) mapped to grid ({row}, {col})")
else: # 白色柱子保持为2
row, col = grid_positions[i]
if debug_mode > 0:
print(f"White pillar at ({center_x}, {center_y}) mapped to grid ({row}, {col})")
# 标记阻塞路径并寻找最短路径
mark_blocked_paths(grid)
path_found = find_shortest_path(grid)
# 打印最终网格状态
print("\n最终网格状态:")
for row in grid:
print(" ".join(str(x) for x in row))
# 在图像上标记最终位置
for i, pillar in enumerate(pillars_sorted):
center_x, center_y, class_name = pillar
row, col = grid_positions[i]
# 计算网格位置对应的像素坐标
pixel_x = (col + 0.5) * (OUT_RGB888P_WIDTH / grid_size)
pixel_y = (row + 0.5) * (OUT_RGB888P_HEIGH / grid_size)
display_x = int(pixel_x * DISPLAY_WIDTH / OUT_RGB888P_WIDTH)
display_y = int(pixel_y * DISPLAY_HEIGHT / OUT_RGB888P_HEIGH)
# 根据类别设置颜色
if class_name == "hs":
color = (0, 0, 255) # 红色表示黑色柱子
else:
color = (255, 255, 255) # 白色表示白色柱子
# 绘制位置标记
osd_img.draw_circle(display_x, display_y, 20, color=color, thickness=3)
osd_img.draw_string(display_x-20, display_y-40, f"({row},{col})", scale=1.5, color=color)
# 显示成功消息
if path_found:
osd_img.draw_string(200, 200, "ALL PILLARS MAPPED! PATH FOUND", scale=3, color=(0, 255, 0))
else:
osd_img.draw_string(200, 200, "ALL PILLARS MAPPED! NO PATH", scale=3, color=(255, 0, 0))
except Exception as e:
print(f"Error in grid processing: {e}")
# 在屏幕上显示错误信息
osd_img.draw_string(200, 200, f"GRID ERROR: {str(e)[:30]}", scale=2, color=(255, 0, 0))
Display.show_image(osd_img, 0, 0, Display.LAYER_OSD3)
# 等待3秒后退出
time.sleep(3)
sensor.stop()
Display.deinit()
MediaManager.deinit()
gc.collect()
nn.shrink_memory_pool()
print("检测完成")
return 0
# 显示当前帧结果
Display.show_image(osd_img, 0, 0, Display.LAYER_OSD3)
frame_count += 1
# 定期垃圾回收
if frame_count % 10 == 0:
gc.collect()
# 限制帧率
time.sleep(0.05) # 约20FPS
except Exception as e:
print(f"Error in frame processing: {e}")
# 显示错误信息
osd_img.clear()
osd_img.draw_string(10, 10, "Processing Error", scale=2, color=(255,0,0))
osd_img.draw_string(10, 50, f"Frame: {frame_count}", scale=1.5, color=(255,0,0))
osd_img.draw_string(10, 80, str(e)[:50], scale=1, color=(255,0,0))
Display.show_image(osd_img, 0, 0, Display.LAYER_OSD3)
time.sleep(1)
# 尝试恢复
try:
rgb888p_img = None
gc.collect()
except:
pass
# 清理资源
del ai2d_input_tensor
del ai2d_output_tensor
sensor.stop()
Display.deinit()
MediaManager.deinit()
gc.collect()
time.sleep(1)
nn.shrink_memory_pool()
print("det_infer end")
return 0
if __name__ == "__main__":
detection()
现在我只要你稍微的修改:
现在画面是黑色,我想要显示真实的画面,帮我该,最小改动,
最新发布