562 lines
22 KiB
Python
562 lines
22 KiB
Python
|
'''
|
|||
|
K210 视频循迹示例
|
|||
|
'''
|
|||
|
import math
|
|||
|
import sensor, image, time, lcd
|
|||
|
import binascii
|
|||
|
from Maix import GPIO
|
|||
|
from machine import Timer, PWM, UART, Timer
|
|||
|
from fpioa_manager import fm
|
|||
|
|
|||
|
# Debug模式开关,打开后方便显示调试信息
|
|||
|
is_debug = True
|
|||
|
#is_debug = False
|
|||
|
|
|||
|
QR_num = 0
|
|||
|
QR_Flag = False
|
|||
|
#--------------感光芯片配置 START -------------------
|
|||
|
DISTORTION_FACTOR = 1 # 设定畸变系数
|
|||
|
IMG_WIDTH = 240
|
|||
|
IMG_HEIGHT = 320
|
|||
|
def init_sensor():
|
|||
|
'''
|
|||
|
初始化感光芯片
|
|||
|
'''
|
|||
|
lcd.init(freq=15000000) #初始化LCD
|
|||
|
sensor.reset() #复位和初始化摄像头
|
|||
|
sensor.set_vflip(1) #将摄像头设置成后置方式(所见即所得)
|
|||
|
sensor.set_pixformat(sensor.RGB565) # 设置像素格式为彩色 RGB565
|
|||
|
#sensor.set_pixformat(sensor.GRAYSCALE) # 设置像素格式为灰色
|
|||
|
sensor.set_framesize(sensor.QVGA) # 设置帧大小为 QVGA (320x240)
|
|||
|
#sensor.set_auto_gain(0,0)
|
|||
|
sensor.set_auto_exposure(1) # 设置自动曝光
|
|||
|
sensor.set_auto_gain(0, gain_db = 8) # 设置画面增益 17 dB 影响实时画面亮度
|
|||
|
#sensor.set_auto_whitebal(0, rgb_gain_db = (0,0,0))
|
|||
|
sensor.skip_frames(time = 2000) # 等待设置生效
|
|||
|
clock = time.clock() # 创建一个时钟来追踪 FPS(每秒拍摄帧数)
|
|||
|
init_sensor()
|
|||
|
#--------------感光芯片配置 END -------------------
|
|||
|
|
|||
|
#--------------串口UART部分 START -------------------
|
|||
|
|
|||
|
#映射串口引脚
|
|||
|
fm.register(6, fm.fpioa.UART1_RX, force=True) # todo
|
|||
|
fm.register(7, fm.fpioa.UART1_TX, force=True)
|
|||
|
|
|||
|
#初始化串口
|
|||
|
uart = UART(UART.UART1, 115200, read_buf_len=4096)
|
|||
|
'''
|
|||
|
UART.UART1:选择 UART1,表示我们要使用 UART 模块的 UART1 接口。
|
|||
|
115200:设置波特率为 115200,表示每秒传输的位数为 115200。
|
|||
|
read_buf_len=4096:设置读取缓冲区的长度为 4096 字节,即可以存储的最大接收数据量为 4096 字节。'''
|
|||
|
|
|||
|
|
|||
|
def get_symbol(num):
|
|||
|
'''
|
|||
|
根据数值正负,返回数值对应的符号
|
|||
|
正数: ‘+’, 负数‘-’ 主要为了方便C语言解析待符号的数值。
|
|||
|
|
|||
|
'''
|
|||
|
print("num = ", num)
|
|||
|
if num >=0:
|
|||
|
return ord('+')
|
|||
|
else:
|
|||
|
return ord('-')
|
|||
|
|
|||
|
|
|||
|
|
|||
|
def data_format_wrapper(down_center, state_crossing, deflection_angle):
|
|||
|
'''
|
|||
|
根据通信协议封装循迹数据
|
|||
|
TODO 重新编写通信协议 与配套C解析代码
|
|||
|
|
|||
|
'''
|
|||
|
send_data = [
|
|||
|
0x55,
|
|||
|
0x02,
|
|||
|
0x91,
|
|||
|
down_center, # 底部色块中心是否在中点附近#底部色块十字路口
|
|||
|
1 if state_crossing else 0, #是否越障
|
|||
|
get_symbol(deflection_angle), # 偏航角符号 print输出是43 + 45- +向左转调整 -向右转调整
|
|||
|
abs(int(deflection_angle)), # 偏航角
|
|||
|
0xbb]
|
|||
|
global is_debug
|
|||
|
if is_debug:
|
|||
|
print("send_data = ", send_data)
|
|||
|
return bytes(send_data)
|
|||
|
|
|||
|
def UsartSend(str_data):
|
|||
|
'''
|
|||
|
串口发送函数
|
|||
|
'''
|
|||
|
uart.write(str_data)
|
|||
|
|
|||
|
|
|||
|
#--------------串口UART部分 END -------------------
|
|||
|
|
|||
|
|
|||
|
#--------------定时器部分 START -------------------
|
|||
|
|
|||
|
is_need_send_data = False # 是否需要发送数据的信号标志
|
|||
|
def uart_time_trigger(tim):
|
|||
|
'''
|
|||
|
串口发送数据的定时器,定时器的回调函数
|
|||
|
'''
|
|||
|
global is_need_send_data, QR_Flag, QR_num
|
|||
|
if QR_Flag:
|
|||
|
QR_num += 1
|
|||
|
if QR_num >= 200: # 10秒计时
|
|||
|
QR_Flag = False
|
|||
|
QR_num = 0
|
|||
|
|
|||
|
|
|||
|
is_need_send_data = True
|
|||
|
|
|||
|
'''
|
|||
|
初始化定时器, 每秒执行20次
|
|||
|
period : 周期1000/20=50
|
|||
|
callback: 回调函数
|
|||
|
'''
|
|||
|
tim1 = Timer(Timer.TIMER1, Timer.CHANNEL1, mode=Timer.MODE_PERIODIC, period=50, callback=uart_time_trigger)
|
|||
|
|
|||
|
|
|||
|
#--------------定时器部分 END -------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#--------------舵机配置 START -------------------
|
|||
|
|
|||
|
def Servo(angle):
|
|||
|
'''
|
|||
|
说明:舵机控制函数
|
|||
|
功能:180度舵机:angle:-90至90 表示相应的角度
|
|||
|
360连续旋转度舵机:angle:-90至90 旋转方向和速度值。
|
|||
|
【duty】占空比值:0-100
|
|||
|
'''
|
|||
|
#PWM通过定时器配置,接到IO17引脚
|
|||
|
tim_pwm = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM)
|
|||
|
S1 = PWM(tim_pwm, freq=50, duty=0, pin=17)
|
|||
|
S1.duty((angle+90)/180*10+2.5)
|
|||
|
|
|||
|
|
|||
|
Servo(0) # 默认向下0度
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
#--------------舵机配置 END -------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#--------------直线检测部分 START -------------------
|
|||
|
|
|||
|
|
|||
|
# 直线灰度图颜色阈值
|
|||
|
LINE_COLOR_THRESHOLD = [(0, 60)] #找黑色
|
|||
|
LINE_COLOR_BAISE=[(60, 255)] #找白色
|
|||
|
#LIGHT_LINE_COLOR_THRESHOLD = [(9, 88)]
|
|||
|
#LINE_COLOR_THRESHOLD = [(0, 52, -19, 0, -1, 14)]
|
|||
|
|
|||
|
# 以实际空间坐标为基准,取样窗口
|
|||
|
'''
|
|||
|
********屏幕ROI区域*******
|
|||
|
* | ------上方----- |
|
|||
|
* 左------中上-----右
|
|||
|
* 侧------中下-----侧
|
|||
|
* | ------下方----- |
|
|||
|
********屏幕ROI区域*******
|
|||
|
'''
|
|||
|
|
|||
|
ROIS = {
|
|||
|
#'left': (0, 0, 320, 50), # 纵向取样-左侧
|
|||
|
#'right': (0, 190, 320, 50), # 纵向取样-右侧
|
|||
|
'left': (0, 0, 180, 50), # 纵向取样-左侧
|
|||
|
'right': (0, 190, 180, 50), # 纵向取样-右侧
|
|||
|
'up': (240, 0, 80, 240), # 横向取样-上方
|
|||
|
'middle_up': (160, 0, 80, 240), # 横向取样-中上
|
|||
|
'middle_down': (80, 0, 80, 240), # 横向取样-中下
|
|||
|
'down': (0, 0, 80, 240), # 横向取样-下方
|
|||
|
}
|
|||
|
#找黑色
|
|||
|
|
|||
|
|
|||
|
ROIS_BAISE = {
|
|||
|
'wleft':(110, 0, 100, 20),
|
|||
|
'wright':(110, 220, 100, 20),
|
|||
|
'wconte':(110, 45, 100, 150), #白色中心区域
|
|||
|
}
|
|||
|
#找白色
|
|||
|
|
|||
|
def find_blobs_in_rois(img):
|
|||
|
'''
|
|||
|
说明:在ROIS中寻找色块,获取ROI中色块的中心区域与是否有色块的信息
|
|||
|
'''
|
|||
|
global ROIS # global定义全局变量 字典数组
|
|||
|
global is_debug # Debug模式开关,打开后方便显示调试信息
|
|||
|
|
|||
|
canvas = img.copy() # 复制给 canvas 实时传输的图片 img类型
|
|||
|
canvas_baise = img.copy() # 判断白色的图片
|
|||
|
|
|||
|
roi_blobs_result = {} # 在各个ROI中寻找色块的结果记录 空的 定义的
|
|||
|
roi_blobs_baise = {} # 定义白色的色块寻找色块的结果记录 空的 定义的
|
|||
|
|
|||
|
for roi_direct in ROIS.keys(): # 赋值初始化键值 黑线
|
|||
|
|
|||
|
roi_blobs_result[roi_direct] = {
|
|||
|
'cx':0,
|
|||
|
'cy':0,
|
|||
|
'w':0,
|
|||
|
'blob_flag': False # 标志位
|
|||
|
}
|
|||
|
for roi_baise in ROIS_BAISE.keys(): # 赋值初始化键值 白色
|
|||
|
|
|||
|
roi_blobs_result[roi_baise] = {
|
|||
|
'wcx':0,
|
|||
|
'wcy':0,
|
|||
|
'ww':0,
|
|||
|
'wblob_baise': False # 标志位
|
|||
|
}
|
|||
|
for roi_direct, roi in ROIS.items(): # 返回键值对 赋值给前两个参数 第一个是键 第二个是值
|
|||
|
blobs=canvas.find_blobs(LINE_COLOR_THRESHOLD, roi=roi,area_threshold=400,merge=True)
|
|||
|
# 查找图像中所有区域黑色色块,并返回一个包括每个色块的色块对象的列表
|
|||
|
# 判断返回列表不为空
|
|||
|
if len(blobs) != 0:
|
|||
|
largest_blob = max(blobs, key=lambda b: b.pixels())
|
|||
|
if largest_blob.area() > 1000: # 判断色块返回面积是否大于1000
|
|||
|
x,y,width,height = largest_blob[:4] # 将列表0到3
|
|||
|
#roi_blobs_result[roi_direct]['cx'] = largest_blob.cy()-40 #存疑为什么-40 #此处XY轴互换
|
|||
|
roi_blobs_result[roi_direct]['cx'] = largest_blob.cy() #存疑为什么-40 #此处XY轴互换,返回色块的外框的中心Y坐标
|
|||
|
roi_blobs_result[roi_direct]['cy'] = largest_blob.cx() #存疑为什么-40 #此处XY轴互换,返回色块的外框的中心X坐标
|
|||
|
roi_blobs_result[roi_direct]['w'] = largest_blob.h()
|
|||
|
roi_blobs_result[roi_direct]['blob_flag'] = True
|
|||
|
if is_debug:
|
|||
|
print('LINE_COLOR_THRESHOLD*****')
|
|||
|
#print(largest_blob[:4] )
|
|||
|
#print('largest_blob内容*****')
|
|||
|
#print(largest_blob)
|
|||
|
#koimg.draw_rectangle((x,y,width, height), color=(0))
|
|||
|
#img.draw_rectangle((0, 0, 180, 50), color=(255))
|
|||
|
else:
|
|||
|
#blobs=canvas.find_blobs(LINE_COLOR_THRESHOLD, roi=roi, merge=True, pixels_area=10)
|
|||
|
continue
|
|||
|
blobs_baise = canvas.find_blobs(LINE_COLOR_BAISE, roi=(0, 0, 60, 240), merge=True)#车载摄像头屏幕下部找白色#宽度200修改为240#用途寻卡,y示例中40修改为0
|
|||
|
blobs_dixing = canvas.find_blobs(LINE_COLOR_BAISE, roi=(125, 0, 60, 240), merge=True)#车载摄像头屏幕中间找白色 #宽度200修改为240,y示例中40修改为0
|
|||
|
blobs_zuo = canvas.find_blobs(LINE_COLOR_THRESHOLD, roi=(0, 0, 180, 50), merge=True)#车载摄像头屏幕左下部找黑色
|
|||
|
blobs_you = canvas.find_blobs(LINE_COLOR_THRESHOLD, roi=(0, 190, 180, 50), merge=True)#车载摄像头屏幕右下部找黑色
|
|||
|
#if len(blobs_baise) != 0:#进行了修改先让摄像头中部区域先碰到白色
|
|||
|
if len(blobs_baise) != 0:
|
|||
|
print("*********进入循环第1步*******")
|
|||
|
largest_baise = max(blobs_baise , key = lambda b:b.pixels())
|
|||
|
wx,wy,wwidth,wwheight = largest_baise[:4]
|
|||
|
#print("宽度",largest_baise[2])
|
|||
|
#print("高度",largest_baise[3])
|
|||
|
#largest_blobs_zuo = max(blobs_zuo , key = lambda b:b.pixels())
|
|||
|
#Bx_L,By_L,Bwidth_L,Bwheight_L = largest_blobs_zuo[:4]
|
|||
|
#arc_L=Bwidth_L*Bwheight_L
|
|||
|
#largest_blobs_you = max(blobs_you , key = lambda b:b.pixels())
|
|||
|
#Bx_R,By_R,Bwidth_R,Bwheight_R = largest_blobs_you[:4]
|
|||
|
#arc_R=Bwidth_R*Bwheight_R
|
|||
|
|
|||
|
if is_debug:
|
|||
|
#print('blobs_baise*****')
|
|||
|
img.draw_rectangle((0, 0, 60, 240), color=(255))
|
|||
|
img.draw_rectangle((125, 0, 60, 240), color=(255))
|
|||
|
|
|||
|
#state_crossing = True #线上为白色准备跨越
|
|||
|
#img.draw_rectangle((wx,wy,wwidth, wwheight), color=(255)) #标注
|
|||
|
arc = wwidth * wwheight
|
|||
|
if arc >= 11000:
|
|||
|
print("*********进入循环第2步*******")
|
|||
|
#UsartSend(data_format_wrapper(0, 1, 0))
|
|||
|
#img.draw_rectangle((wx,wy,wwidth, wwheight), color=(255))#左侧区域
|
|||
|
if len(blobs_dixing) != 0:
|
|||
|
print("*********进入循环第3步*******")
|
|||
|
largest_dixing = max(blobs_dixing , key = lambda b:b.pixels())
|
|||
|
wx,wy,wwidth,wwheight = largest_dixing[:4]
|
|||
|
#state_crossing = True
|
|||
|
#img.draw_rectangle((wx,wy,wwidth, wwheight), color=(255))
|
|||
|
arc = wwidth * wwheight
|
|||
|
if arc >= 11000:
|
|||
|
#UsartSend(data_format_wrapper(0, 1, 0))
|
|||
|
#img.draw_rectangle((wx,wy,wwidth, wwheight), color=(255))#右侧区域
|
|||
|
print('kapian') #首先中部区域识别到白色进入判断地形还是卡片,接着判断下部,如果为白色判断为卡片。
|
|||
|
UsartSend(data_format_wrapper(0, 1, 0))#地形停止命令
|
|||
|
if len(blobs_zuo) != 0 and len(blobs_you) != 0:
|
|||
|
print("ka十字路口")
|
|||
|
UsartSend(data_format_wrapper(1, 1, 0))#地形停止命令
|
|||
|
else:
|
|||
|
print('dixing')
|
|||
|
print(roi_blobs_result) #返回的是黑色色块,各区域中心位置
|
|||
|
UsartSend(data_format_wrapper(0, 1, 0))#地形停止命令
|
|||
|
|
|||
|
|
|||
|
return roi_blobs_result #返回的是黑色色块,各区域中心位置
|
|||
|
def state_deflection_angle(roi_blobs_result):
|
|||
|
'''
|
|||
|
说明:偏转状态值返回
|
|||
|
'''
|
|||
|
# ROI区域权重值
|
|||
|
#ROIS_WEIGHT = [0, 1, 0, 1]
|
|||
|
ROIS_WEIGHT = [1, 0, 0, 1] # ROIS对白色权重的数组
|
|||
|
state_crossing = False
|
|||
|
deflection_angle = 0 # 偏转角
|
|||
|
down_center = 0 # 中下值
|
|||
|
center_num = 0 # 中间值
|
|||
|
|
|||
|
|
|||
|
# 偏转值计算,ROI中心区域X值
|
|||
|
centroid_sum = roi_blobs_result['up']['cx']*ROIS_WEIGHT[0] + roi_blobs_result['middle_up']['cx']*ROIS_WEIGHT[1] \
|
|||
|
+ roi_blobs_result['middle_down']['cx']*ROIS_WEIGHT[2] + roi_blobs_result['down']['cx']*ROIS_WEIGHT[3]
|
|||
|
if roi_blobs_result['up']['blob_flag']:
|
|||
|
center_num += ROIS_WEIGHT[0]
|
|||
|
if roi_blobs_result['middle_up']['blob_flag']:
|
|||
|
center_num += ROIS_WEIGHT[1]
|
|||
|
if roi_blobs_result['middle_down']['blob_flag']:
|
|||
|
center_num += ROIS_WEIGHT[2]
|
|||
|
if roi_blobs_result['down']['blob_flag']:
|
|||
|
center_num += ROIS_WEIGHT[3]
|
|||
|
|
|||
|
center_pos = centroid_sum / (ROIS_WEIGHT[0]+ROIS_WEIGHT[1]+ROIS_WEIGHT[2]+ROIS_WEIGHT[3])
|
|||
|
deflection_angle = (IMG_WIDTH/2)- center_pos
|
|||
|
|
|||
|
# 判断两侧ROI区域检测到黑色线
|
|||
|
if roi_blobs_result['left']['blob_flag'] and roi_blobs_result['right']['blob_flag']:
|
|||
|
# 判断两侧ROI区域检测到黑色线处于图像下方1/3处
|
|||
|
if roi_blobs_result['left']['cy'] <= ((IMG_HEIGHT/3)) or roi_blobs_result['right']['cy'] <= ((IMG_HEIGHT/3)):
|
|||
|
# 当最下方ROI区域的黑线宽度大于140像素(检测到路口)
|
|||
|
if roi_blobs_result['down']['w'] > 140:
|
|||
|
down_center=1#自行修改处 判断识别到十字路口
|
|||
|
print("输出了十字路口标识")
|
|||
|
|
|||
|
# down_center
|
|||
|
if roi_blobs_result['left']['blob_flag'] and roi_blobs_result['right']['blob_flag']:
|
|||
|
# 判断两侧ROI区域检测到黑色线处于图像下方1/3处
|
|||
|
if roi_blobs_result['left']['cy'] <= ((IMG_HEIGHT/3)) or roi_blobs_result['right']['cy'] <= ((IMG_HEIGHT/3)):
|
|||
|
# 当最下方ROI区域的黑线宽度大于140像素(检测到路口)
|
|||
|
if roi_blobs_result['down']['w'] > 140:
|
|||
|
0
|
|||
|
return down_center, state_crossing, deflection_angle
|
|||
|
#--------------直线与路口检测部分 END -------------------
|
|||
|
|
|||
|
|
|||
|
#--------------二维码识别部分 START -------------------
|
|||
|
|
|||
|
def QR_Check():
|
|||
|
'''
|
|||
|
说明:二维码函数
|
|||
|
'''
|
|||
|
global QR_Flag
|
|||
|
if QR_Flag:
|
|||
|
res = img.find_qrcodes() # 寻找二维码 # 固件
|
|||
|
if len(res) > 0:
|
|||
|
# 在图片和终端显示二维码信息
|
|||
|
for index in range(len(res)):
|
|||
|
|
|||
|
img.draw_rectangle(res[index].rect())
|
|||
|
img.draw_string(2,2, res[index].payload(), color=(0,128,0), scale=2)
|
|||
|
print(res[index].payload())
|
|||
|
# 串口发送二维码信息
|
|||
|
uart.write(bytes([0x55]))
|
|||
|
uart.write(bytes([0x02]))
|
|||
|
uart.write(bytes([0x92]))
|
|||
|
uart.write(bytes([0x01]))
|
|||
|
uart.write(bytes([len(res[index].payload())])) # 数据结果长度
|
|||
|
for qrdata in res[index].payload():
|
|||
|
uart.write(bytes([ord(qrdata)]))
|
|||
|
uart.write(bytes([0xbb]))
|
|||
|
|
|||
|
#--------------二维码识别部分 END -------------------
|
|||
|
|
|||
|
#-----------------交通灯识别 START-------------------#
|
|||
|
###################################################################################################
|
|||
|
# 返回值
|
|||
|
# 1、红灯(蒙的答案选项)
|
|||
|
# 2、绿灯
|
|||
|
# 3、黄灯
|
|||
|
#
|
|||
|
# 需要完善部分:
|
|||
|
# 1、过滤掉范围过小和过大部分--》提高识别效率
|
|||
|
# 2、通信协议
|
|||
|
###################################################################################################
|
|||
|
|
|||
|
def tick(timer):
|
|||
|
global times,isCut
|
|||
|
#print(times)
|
|||
|
if(times == 4):
|
|||
|
isCut = False
|
|||
|
tim.deinit() #tim对象反初始化
|
|||
|
times = 0
|
|||
|
else:
|
|||
|
times+=1;
|
|||
|
|
|||
|
def drawTrafficLight(isDraw): #识别红绿灯*******************
|
|||
|
red = (90, 100, -40, -8, -10, 10) #红色阈值(75, 90, 0, 43, 0, 28) (49,76,25,60,-9,36)
|
|||
|
green = (91, 96, -33, -6, -11, 1) #绿色阈值(55, 94 ,-69, -22, -16 ,32)
|
|||
|
yellow = (90, 100, -5, 2, -4, 20) #黄色阈值(92, 100, -16, 43, -6, 17) (83, 100, 6, -28, 13, 73)
|
|||
|
hld = 0x01 #蒙答案
|
|||
|
try:
|
|||
|
#sensor.set_windowing((0,0,280,100))
|
|||
|
#tim.callback(tick) #回调函数的形参是用户函数或者匿名函数都必须有一个位置参数,才可以正常工作(位置参数可能就是一个实例),而且调用时不用些括号
|
|||
|
red_blobs = img.find_blobs([red], merge=True) #寻找红色色块 合并所有重叠的blod
|
|||
|
green_blobs = img.find_blobs([green], merge=True)
|
|||
|
yellow_blobs = img.find_blobs([yellow],merge=True)
|
|||
|
|
|||
|
if (len(red_blobs) != 0):
|
|||
|
x1 = red_blobs[0][0]
|
|||
|
y1 = red_blobs[0][1]
|
|||
|
w1 = red_blobs[0][2]
|
|||
|
h1 = red_blobs[0][3]
|
|||
|
print("红灯")
|
|||
|
if isDraw is True:
|
|||
|
img.draw_rectangle((x1,y1,w1,h1),color=(255,0,0))
|
|||
|
hld = 0x01
|
|||
|
elif (len(green_blobs) != 0):
|
|||
|
x1 = green_blobs[0][0]
|
|||
|
y1 = green_blobs[0][1]
|
|||
|
w1 = green_blobs[0][2]
|
|||
|
h1 = green_blobs[0][3]
|
|||
|
print("绿灯")
|
|||
|
if isDraw is True:
|
|||
|
img.draw_rectangle((x1,y1,w1,h1),color=(0,255,0))
|
|||
|
hld = 0x02
|
|||
|
elif (len(yellow_blobs) != 0):
|
|||
|
x1 = yellow_blobs[0][0]
|
|||
|
y1 = yellow_blobs[0][1]
|
|||
|
w1 = yellow_blobs[0][2]
|
|||
|
h1 = yellow_blobs[0][3]
|
|||
|
print("黄灯")
|
|||
|
if isDraw is True:
|
|||
|
img.draw_rectangle((x1,y1,w1,h1),color=(255,255,255))
|
|||
|
hld = 0x03
|
|||
|
|
|||
|
# 串口发送交通灯信息
|
|||
|
uart.write(bytes([0x55]))
|
|||
|
uart.write(bytes([0x92]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([hld]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0xbb]))
|
|||
|
except Exception as e:
|
|||
|
print("识别红绿灯异常",e)
|
|||
|
# 串口发送交通灯信息
|
|||
|
uart.write(bytes([0x55]))
|
|||
|
uart.write(bytes([0x92]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([hld]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0x03]))
|
|||
|
uart.write(bytes([0xbb]))
|
|||
|
|
|||
|
|
|||
|
#======================交通灯识别 END===========================#
|
|||
|
|
|||
|
|
|||
|
#---------------------MAIN-----------------------
|
|||
|
last_cx = 0
|
|||
|
last_cy = 0
|
|||
|
Flag_track = False
|
|||
|
JTD = True
|
|||
|
#将蓝灯引脚IO12配置到GPIO0,K210引脚支持任意配置
|
|||
|
fm.register(12, fm.fpioa.GPIO0)
|
|||
|
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT) #构建LED对象
|
|||
|
#按键KEY用于清屏
|
|||
|
fm.register(16, fm.fpioa.GPIO1, force=True)
|
|||
|
btn_debug = GPIO(GPIO.GPIO1, GPIO.IN)
|
|||
|
x_num = 0
|
|||
|
while True:
|
|||
|
LED_B.value(0) #点亮LED
|
|||
|
# 串口数据接收处理
|
|||
|
data = uart.read(8)
|
|||
|
if data is not None:
|
|||
|
print(data)
|
|||
|
print(len(data))
|
|||
|
print(binascii.hexlify(data).decode('utf_8'))
|
|||
|
if(len(data) >= 8):
|
|||
|
if((data[1] == 0x02)&(data[7] == 0xBB)):
|
|||
|
# 巡线与控制舵机
|
|||
|
if(data[2] == 0x91):
|
|||
|
if(data[3] == 0x01): # 启动识别
|
|||
|
sensor.set_auto_gain(0, gain_db = 17) # 设置画面增益 17 dB 影响实时画面亮度
|
|||
|
sensor.set_pixformat(sensor.GRAYSCALE) # 设置像素格式为灰色
|
|||
|
Servo(-75)
|
|||
|
print("巡线")
|
|||
|
print("开始识别")
|
|||
|
Flag_track = True
|
|||
|
tim1.start()
|
|||
|
if(data[3] == 0x02):
|
|||
|
sensor.set_auto_gain(0, gain_db = 8) # 设置画面增益 17 dB 影响实时画面亮度
|
|||
|
sensor.set_pixformat(sensor.RGB565) # 设置像素格式为彩色 RGB565
|
|||
|
Servo(0)
|
|||
|
print("巡线")
|
|||
|
print("停止识别")
|
|||
|
Flag_track = False
|
|||
|
tim1.stop() # 停止定时器
|
|||
|
if(data[3] == 0x03): # 舵机调整
|
|||
|
angle = data[5]
|
|||
|
# 判断舵机控制方向
|
|||
|
if data[4] == ord('-'):
|
|||
|
# 限制舵机角度,防止过大损坏舵机
|
|||
|
if angle > 80:
|
|||
|
angle = 80
|
|||
|
angle = -angle
|
|||
|
elif data[4] == ord('+'):
|
|||
|
# 限制舵机角度,防止过大损坏舵机
|
|||
|
if angle > 35:
|
|||
|
angle = 35
|
|||
|
angle = angle
|
|||
|
Servo(angle) # 控制舵机
|
|||
|
time.sleep(1) # 等待舵机角度更新
|
|||
|
# 二维码识别
|
|||
|
if(data[2] == 0x92):
|
|||
|
print("识别二维码")
|
|||
|
# Servo(-15) # 向下-15度
|
|||
|
# time.sleep(1)
|
|||
|
if(data[3] == 0x01): #启动识别
|
|||
|
print("开始识别")
|
|||
|
tim1.start()
|
|||
|
QR_Flag = True
|
|||
|
if(data[3] == 0x02):
|
|||
|
print("停止识别")
|
|||
|
tim1.stop() # 停止定时器
|
|||
|
QR_Flag = False
|
|||
|
if(data[3] == 0x03):
|
|||
|
print("开始识别")
|
|||
|
tim1.start()
|
|||
|
JTD = True
|
|||
|
if(data[3] == 0x04):
|
|||
|
print("停止识别")
|
|||
|
tim1.stop()
|
|||
|
JTD = False
|
|||
|
|
|||
|
# 拍摄图片
|
|||
|
img = sensor.snapshot()
|
|||
|
# 去除图像畸变
|
|||
|
#img.lens_corr(DISTORTION_FACTOR)
|
|||
|
# 二维码识别
|
|||
|
QR_Check()
|
|||
|
#if JTD:
|
|||
|
#drawTrafficLight(img)
|
|||
|
## 巡线
|
|||
|
#Flag_track=1
|
|||
|
if Flag_track:
|
|||
|
roi_blobs_result = find_blobs_in_rois(img)
|
|||
|
down_center, state_crossing, deflection_angle = state_deflection_angle(roi_blobs_result)
|
|||
|
if is_need_send_data:
|
|||
|
dsd = data_format_wrapper(down_center, state_crossing, deflection_angle)
|
|||
|
UsartSend(dsd)
|
|||
|
print("下发指令")
|
|||
|
print("dsd = ", dsd)
|
|||
|
#print(data_format_wrapper(down_center, state_crossing, deflection_angle))
|
|||
|
#time.sleep_ms(10)
|
|||
|
#is_need_send_data = False
|
|||
|
# 在LCD上显示
|
|||
|
lcd.display(img)
|
|||
|
#按键KEY按下。开启或关闭调试,并退出所有任务。
|
|||
|
if btn_debug.value() == 0:
|
|||
|
Flag_track = not Flag_track # 巡线任务退出
|
|||
|
QR_Flag = not QR_Flag # 二维码任务退出
|
|||
|
is_debug = not is_debug # 调试标志位取
|
|||
|
|