这是在问答社区找到关于送药小车的一篇很好的回答
但我对这个还有几个问题
1.双线程运行机制是什么
2.为什么我在巡线线程子函数结尾加个 print(1)串行终端并没有打印出“1”,但是我在子函数开头加上却能打印出,这是巡线线程子函数执行不到下半部分吗?
3.如何通过OSD层机制或者其他方式把不同线程“图像绘制”的结果一同显示到屏幕上
关于此问题的代码和问答链接附在下边了,感谢大佬们的解答!!!
https://www.kendryte.com/answer/questions/10010000000005607/10020000000005631
from media.sensor import *
from media.display import *
from media.media import *
from libs.PlatTasks import DetectionApp
from libs.Utils import *
from machine import UART, FPIOA, Pin
import image
import time, gc, _thread, ujson
# ---------- 全局配置 ----------
sensor=None
display_size=[800,480]
redline_img_size=[640,480]
rgb888p_size = [1280, 720]
det_stop=False
redline_stop=False
det_osd_img=None
redline_osd_img=None
# ---------- 串口 & 按键 ----------
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)
fpioa.set_function(53, FPIOA.GPIO53)
KEY = Pin(53, Pin.IN, Pin.PULL_DOWN)
uart = UART(UART.UART2, baudrate=115200)
# ---------- 红线识别参数 ----------
thresholds = [(23, 57, 30, 127, -128, 127)]
ROIS1 = [(225, 0, 400, 160, 0.3), (225, 160, 400, 160, 0.35), (225, 320, 400, 160, 0.35)]
ROIS2 = [(0, 150, 250, 300), (550, 150, 250, 300)]
# ---------- 状态变量 ----------
key_flag = 0
flag = 0
turn_flag = 0
move_record = []
return_mode = False
current_index = 0
cross_detected = False
num = 1 # 模拟外部识别(1=左转, 2=右转, else 直行)
def media_init():
global sensor,osd_img,rgb888p_size,display_size,det_osd_img,yolo_osd_img
Display.init(Display.ST7701, width = display_size[0], height = display_size[1], to_ide = True, osd_num=3)
sensor = Sensor(fps=30)
sensor.reset()
sensor.set_framesize(w = display_size[0], h = display_size[1],chn=CAM_CHN_ID_0)
sensor.set_pixformat(Sensor.YUV420SP,chn=CAM_CHN_ID_0)
sensor.set_framesize(w = redline_img_size[0], h = redline_img_size[1], chn=CAM_CHN_ID_1)
sensor.set_pixformat(Sensor.RGB565,chn=CAM_CHN_ID_1)
sensor.set_framesize(w = rgb888p_size[0], h = rgb888p_size[1], chn=CAM_CHN_ID_2)
sensor.set_pixformat(Sensor.RGBP888,chn=CAM_CHN_ID_2)
sensor_bind_info = sensor.bind_info(x = 0, y = 0, chn = CAM_CHN_ID_0)
Display.bind_layer(**sensor_bind_info, layer = Display.LAYER_VIDEO1)
Display.init(Display.ST7701, osd_num=2, to_ide=True)
det_osd_img = image.Image(display_size[0], display_size[1], image.ARGB8888)
redline_osd_img = image.Image(display_size[0], display_size[1], image.ARGB8888)
MediaManager.init()
sensor.run()
def media_deinit():
global sensor
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
sensor.stop()
Display.deinit()
time.sleep_ms(50)
MediaManager.deinit()
# ---------- 红线线程 ----------
def calculate_error(blobs, rois):
global flag, turn_flag
detected_any = False
weight_sum = 0
centroid_sum = 0
for i, roi in enumerate(rois):
if blobs[i]:
detected_any = True
largest = max(blobs[i], key=lambda b: b.pixels())
centroid_sum += largest.cx() * roi[4]
weight_sum += roi[4]
flag = 1 if detected_any else 0
if weight_sum:
center_x = centroid_sum / weight_sum
dx = center_x - 400
if dx > 0:
turn_flag = 1
else:
dx = -dx
turn_flag = 2
return dx
return 0
def filter_blob(blob):
if blob.pixels() < 2000:
return False
if 140 < blob.cx() < 160 and 240 < blob.cy() < 260:
return False
if 640 < blob.cx() < 660 and 240 < blob.cy() < 260:
return False
return True
def redline_thread():
global sensor,flag, turn_flag, return_mode, move_record, key_flag, cross_detected, current_index
while True:
if redline_stop:
break
img = sensor.snapshot(chn=CAM_CHN_ID_1)
# ROI 红色检测
mid_blobs = [img.find_blobs(thresholds, roi=roi[:4], merge=True) for roi in ROIS1]
delta_pos_x = int(calculate_error(mid_blobs, ROIS1))
# 按键切换
if KEY.value() == 1:
if flag == 0:
return_mode = True
current_index = len(move_record) - 1
print("切换到回程模式")
else:
return_mode = False
move_record.clear()
print("切换到正常模式")
key_flag = 1 - key_flag
time.sleep_ms(300)
if not key_flag:
time.sleep_ms(50)
continue
# 左右色块检测
left = img.find_blobs(thresholds, roi=ROIS2[0], merge=True)
right = img.find_blobs(thresholds, roi=ROIS2[1], merge=True)
left = [b for b in left if filter_blob(b)]
right = [b for b in right if filter_blob(b)]
is_cross = bool(left and right)
# 自动回程切换
if flag == 0 and not return_mode:
return_mode = True
current_index = len(move_record)-1
print("自动切换到回程模式")
move_prepare = 1 if num == 1 else (3 if num == 2 else 2)
if is_cross and not cross_detected:
print("检测到十字边沿,记录动作")
if not return_mode:
move_record.append(move_prepare)
print("记录动作:", move_record)
else:
if current_index >= 0:
print(f"回程:准备执行动作 {move_record[current_index]}")
if is_cross:
if not return_mode:
if move_prepare == 1:
delta_pos_x = 400
turn_flag = 2
elif move_prepare == 3:
delta_pos_x = 400
turn_flag = 1
else:
delta_pos_x = 0
turn_flag = 0
else:
if current_index >= 0:
m = move_record[current_index]
if m == 1:
delta_pos_x = 410
turn_flag = 1
elif m == 3:
delta_pos_x = 400
turn_flag = 2
else:
delta_pos_x = 0
turn_flag = 0
cross_detected = is_cross
uart.write(f"S:{num},{delta_pos_x},{flag},{turn_flag}\n".encode())
time.sleep_ms(25)
.............................略.....................................