Files

140 lines
4.5 KiB
Python

from maix import image, app, time
# 橘黄色乒乓球的颜色阈值配置(HSV色域)
# yxl
thresholds = [
[73, 93, 7, 27, 13, 33],
[40, 65, 30, 60, 40, 70],
[39, 59, 41, 61, 48, 68],
]
# mgw
thresholds = [
[60, 85, 10, 35, 60, 90],
[40, 65, 20, 50, 60, 90],
[30, 60, 30, 60, 40, 70],
]
# 丢失目标的阈值配置
LOST_FRAME_THRESHOLD = 20 # 连续x帧没识别到才判定为真正丢失
# 全局参数初始化
kick_status = ""
# ------------------------------
# 兵乓球追踪
# ------------------------------
def select_largest_blob(blobs):
"""
筛选并选取最大的有效blob(替换原融合逻辑)
1. 筛除宽/高小于10px的小blob(过滤噪声)
2. 从剩余blob中选取面积最大的单个blob
:param blobs: 识别到的所有blob列表
:return: 最大blob的矩形参数 (x, y, width, height) 和中心点 (cx, cy);未识别到则返回None, None
"""
if not blobs:
return None, (-1,-1)
# 步骤1:过滤掉宽/高小于10px的无效blob
valid_blobs = []
for b in blobs:
x, y, w, h = b[0], b[1], b[2], b[3]
if w >= 10 and h >= 10: # 筛除边距(宽/高)小于10px的blob
valid_blobs.append(b)
# 过滤后无有效blob,返回None
if not valid_blobs:
return None, (-1,-1)
# 步骤2:选取面积(w*h)最大的blob
largest_blob = max(valid_blobs, key=lambda b: b[2] * b[3])
# 提取最大blob的矩形参数和中心点
x, y, w, h = largest_blob[0], largest_blob[1], largest_blob[2], largest_blob[3]
cx = x + w // 2
cy = y + h // 2
return (x, y, w, h), (cx, cy)
def calculate_deviation_ball(center, image_center):
"""
优化:仅计算偏移量,不直接发送指令(将指令发送逻辑移到主循环统一处理)
:return: (deviation_x, deviation_y) 或 None(无有效目标)
"""
center_x, center_y = center
if center_x == -1 and center_y == -1 :
return None # 无有效目标
# 计算x/y方向的偏移偏差(目标中心 - 图像中心)
deviation_x = center_x - image_center[0]
deviation_y = center_y - image_center[1]
# 仅当偏移超过阈值时返回有效偏移,否则返回None(避免微小抖动)
if abs(deviation_x) > 10 or abs(deviation_y) > 10 :
return (deviation_x, deviation_y)
else:
return None
def trace_ball_main(resources):
# 声明使用全局变量(两个参数都需要更新)
global kick_status
detector = resources["detector"]
cam = resources["cam"]
disp = resources["disp"]
serial_dev = resources["serial_dev"]
img_width = resources["img_width"]
img_height = resources["img_height"]
image_center = resources["image_center"]
last_valid_deviation = None # 记录最后一次有效偏移量
lost_frames = 0 # 丢失帧数计数
while not app.need_exit():
img = cam.read().flip(image.FlipDir.Y)
bcmd = ""
# 识别色块(像素阈值设为10,过滤小噪声)
blobs = img.find_blobs(thresholds, pixels_threshold=10)
# 筛选并选取最大的有效blob
largest_rect, target_center = select_largest_blob(blobs)
# 计算当前帧的偏移量
current_deviation = calculate_deviation_ball(target_center, image_center)
# -------------------------- 核心优化逻辑 --------------------------
if current_deviation is not None:
# 1. 识别到有效目标:重置丢失计数,更新最后一次有效偏移
lost_frames = 0
last_valid_deviation = current_deviation
dx, dy = current_deviation
bcmd = f"DX:{dx},DY:{dy};"
else:
# 2. 未识别到目标:累计丢失帧数
lost_frames += 1
if lost_frames < LOST_FRAME_THRESHOLD and last_valid_deviation is not None:
dx, dy = last_valid_deviation
bcmd = f"DX:{dx},DY:{dy};"
else:
# 2.2 丢失帧数达阈值:发送9999,重置最后有效偏移
bcmd = "DX:9999,DY:9999;"
last_valid_deviation = None
# 绘制识别结果
if largest_rect:
x, y, w, h = largest_rect
img.draw_rect(x, y, w, h, image.COLOR_GREEN, 2)
cx, cy = target_center
img.draw_circle(cx, cy, 3, image.COLOR_RED, -1)
serial_dev.write_str(bcmd)
print(bcmd)
disp.show(img)
time.sleep_ms(1)