大佬,程序卡死,运行不了,急急急,感谢
-
#----------------------------------------------------------------------------
系统硬件配置初始化
#----------------------------------------------------------------------------
import sensor,time,pyb,image
from pyb import Timer,UART,Pin,LED#---摄像头硬件初始化
#复位
sensor.reset()#设置为灰度图像
sensor.set_pixformat(sensor.GRAYSCALE)#设置彩色
#sensor.set_pixformat(sensor.RGB565)#设置图像大小
sensor.set_framesize(sensor.QQVGA)#相机自检几张图片
sensor.skip_frames(50)
#sensor.set_windowing((144, 144)) #取中间的640*80区域#关闭白平衡
sensor.set_auto_whitebal(False)
red_led = pyb.LED(1)#打开时钟,主要负责统计帧率
clock = time.clock()#---发送函数
def tick(timer):
uart.write(uart_buf) #发送函数#---利用回调函数来进行计时
def circle_time(timer):
global run_time
run_time += 1 #用于计算openmv运算一次所需的时间#---定时器2,timer数据发送配置
senddata = Timer(2, freq = 20) #发送频率是50HZ,20ms跑一次
senddata.callback(tick) #回调串口发送函数#---定时器4计时
circle_tmp = Timer(4, freq = 100) #定时器4,定时10ms,用于计时
circle_tmp.callback(circle_time)#---串口三配置,负责发送数据
uart = UART(3, 115200, timeout_char = 1000)
uart.init(115200, bits=8, parity=None, stop=1)#---发送数据协议格式
uart_buf = bytearray([0xFE,0,0,0,0,0,0,0,0,0,0,0,0])#----------------------------------------------------------------------------
用户自定义值初始化
#----------------------------------------------------------------------------
#---阈值初始化
black_threshold = [(0, 130)] #阈值初始化#---循线三个取样区域的权值初始化
r1 = 0.1
r2 = 0.2
r3 = 0.3
r4 = 0.4#---循线三个取样区域的位置、大小初始化
#roi代表三个取样区域,(x,y,w,h,weight),代表左上顶点(x,y)宽高分别为w和h的矩形,
#weight为当前矩形的权值。注意本例程采用的QQVGA图像大小为160x120,
ROIS = [ # [ROI, weight] #摄像头反装(头朝后,芯片朝前),左上角定点(0,0)
(30, 00, 100, 15,r1), #上方方框
(30, 35, 100, 15,r2), #中上方框
(30, 70, 100, 15,r3), #中下方框
(30, 105,100, 15,r4) #下方方框
]#三个矩形的阈值要根据实际情况进行调整,离机器人视野最近的矩形权值要最大,
#如上图的最下方的矩形,即(0, 100, 160, 20, 0.7)
weight_sum = 0#---定时器值初始化
run_time = 0 #运行时间,统计代码运行一次所需时间#---接收发送函数值初始化
tmp_data = 0 #接收函数中转值
flag = 0 #巡线标志位
anla_cricle_sure = 0 #识别到圆标志位(0没有识别 1识别完成)
threshold_sure = 0 #阈值确认标志位#---定义偏移中心点的位置的变量初始化
err_x = 0 #误差值
err_y = 0
prior_x = 0 #前一次误差值
prior_y = 0
x_speed = 0 #误差速度
y_speed = 0
center_x_sum = 0#循线3区域值和
center_y_sum = 0
centroid_sum = 0
center_x = 0 #权值计算后的最终值
center_y = 0
send_err_x = 0 #串口最终发送值,通过分段计算后所得
send_err_y = 0
send_x_speed = 0
send_y_speed = 0
send_times = 0 #发送次数,通过对20ms处理的算法,用来统计发送次数
auto_threshold = [0,130]#自动阈值初始化
times_threshold = 0 #阈值运算次数
thr = 0 #获取当前阈值
thr_1 = 0 #平均阈值
threshold_sum = 0 #阈值累加和#----------------------------------------------------------------------------
扩宽roi,找圆范围
#----------------------------------------------------------------------------
def expand_roi(roi):
extra = 5
win_size = (160, 120)
(x, y, width, height) = roi
new_roi = [x-extra, y-extra, width+2extra, height+2extra]if new_roi[0] < 0: new_roi[0] = 0 if new_roi[1] < 0: new_roi[1] = 0 if new_roi[2] > win_size[0]: new_roi[2] = win_size[0] if new_roi[3] > win_size[1]: new_roi[3] = win_size[1] return tuple(new_roi)
#----------------------------------------------------------------------------
flag模式选择函数
接收飞控的指定,相当于switch case语句
#----------------------------------------------------------------------------
def fun(temp):
return{
'97': 0, #定圆
'98': 1, #调节阈值
'99': 2, #循线
'100': 3, #反向循线
'101': 4, #循线找圆
'102': 5, #反向循线找圆
'103': 6, #单独找圆
'104': 7, #降落定点
}.get(temp,0)#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
循环代码
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
while(True):
#run_time = 0 #将计时清零
#----------------------------------------------------------------------------
if uart.any(): #判断飞控有无数据发送
tmp_data = uart.readchar() #接收数据
#print("接收数据 %d"%tmp_data)
num = str(tmp_data)
flag = fun(num) #调用flag模式函数
# print(flag)#权值赋值 if flag == 2 or flag == 4: #正向循线权值 r1 = 0.1 r2 = 0.2 r3 = 0.3 r4 = 0.4 if flag == 3 or flag == 5: #反向循线权值 r1 = 0.4 r2 = 0.3 r3 = 0.2 r4 = 0.1
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
图像处理
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
img = sensor.snapshot().lens_corr(1.7) #拍照并返回图像.#----------------------------------------------------------------------------
定点:先找最大的色块,再在色块中找圆,图像中黑色色块越小帧率越高,黑色色块越大速度越慢
#----------------------------------------------------------------------------
if flag == 0 or flag == 1:
blobs = img.find_blobs(black_threshold,area_threshold=150,x_stride=12,y_stride=12)
anla_cricle_sure = 0 #找圆标志位清零
threshold_sure = 0 #调制阈值标志位清零
if blobs:
#print("定圆")
#如果找到了目标颜色
#print(blobs)
for blob in blobs:
#迭代找到的目标颜色区域
is_circle = False
max_circle = None
max_radius = -1new_roi = expand_roi(blob.rect()) for c in img.find_circles(threshold = 3800, x_margin = 25, y_margin = 25, r_margin = 25, roi=new_roi): is_circle = True #img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 255)) if c.r() > max_radius: max_radius = c.r() max_circle = c if is_circle: #print("定到圆") #如果有对应颜色的圆形,标记外框 #img.draw_rectangle(new_roi) #rect #img.draw_rectangle(blob.rect()) #rect err_y = int(60 - max_circle.y()) err_x = int(max_circle.x() - 80) #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r(), color = (255, 255, 255)) #err_y = int(60-blob.cy()) #err_x = int(blob.cx() - 80) x_speed = err_x - prior_x y_speed = err_y - prior_y prior_x = err_x prior_y = err_y #用矩形标记出目标颜色区域 #img.draw_cross(blob[5], blob[6]) # cx, cy #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r(), color = (0, 255, 0)) #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r() + 1, color = (0, 255, 0)) else: err_x=0 err_y=0 x_speed = 0 y_speed = 0
#----------------------------------------------------------------------------
自动阈值计算
#----------------------------------------------------------------------------
if flag == 1 and run_time > 10: #寻线时打开阈值测量
histogram = img.get_histogram()
thresholds = histogram.get_threshold()
thr = thresholds.value() #获取当前阈值
times_threshold += 1 #计算10次
threshold_sum += thr #阈值之和
run_time = 0
if(times_threshold == 10):
thr_1 = threshold_sum//10 #求平均
auto_threshold[1] = thr_1 #得到的阈值写成列表形式
black_threshold = [tuple(auto_threshold)] #阈值赋值
times_threshold = 0 #阈值计算次数清零
threshold_sum = 0 #阈值和清零
threshold_sure = 1 #告诉飞控,阈值调节完毕
print("threshold_sure=%d"%threshold_sure)
print(black_threshold)
flag = 8
#----------------------------------------------------------------------------双轴正向循线:通过判断三个取样色块权值来计算xy轴偏离的距离,从而实现巡线。
#----------------------------------------------------------------------------
if flag == 2 or flag == 4:
center_x_sum = 0
center_y_sum = 0
centroid_sum = 0
weight_sum = 0
#print("双轴循线")for r in ROIS: blobs = img.find_blobs(black_threshold, roi=r[0:4], merge=True,x_stride=10) # r[0:4] is roi tuple. #找到视野中的线,merge=true,将找到的图像区域合并成一个 if blobs: most_pixels = 0 largest_blob = 0 for i in range(len(blobs)): #目标区域找到的颜色块(线段块)可能不止一个,找到最大的一个,作为本区域内的目标直线 if blobs[i].pixels() > most_pixels: most_pixels = blobs[i].pixels() #merged_blobs[i][4]是这个颜色块的像素总数,如果此颜色块像素总数大于#most_pixels,则把本区域作为像素总数最大的颜色块。更新most_pixels和largest_blob largest_blob = i #将此区域的像素数最大的颜色块画矩形和十字形标记出来 #img.draw_rectangle(blobs[largest_blob].rect()) #img.draw_cross(blobs[largest_blob].cx(),blobs[largest_blob].cy()) center_x_sum += blobs[largest_blob].cx()*r[4] center_y_sum += blobs[largest_blob].cy()*r[4] weight_sum += r[4] center_x = int(center_x_sum/weight_sum) center_y = int(center_y_sum/weight_sum) #img.draw_cross(center_x,center_y) err_x = center_x - 80 err_y = int((60 - center_y)*0.3) #乘0.3,减小往前走的速度 x_speed = err_x - prior_x y_speed = err_y - prior_y prior_x = err_x prior_y = err_y #print("循到线")
#----------------------------------------------------------------------------
双轴反向循线:将y轴的值取反,通过判断三个取样色块权值来计算xy轴偏离
#----------------------------------------------------------------------------
if flag == 3 or flag == 5:
center_x_sum = 0
center_y_sum = 0
centroid_sum = 0
#print("双轴循线")for r in ROIS: blobs = img.find_blobs(black_threshold, roi=r[0:4], merge=True,x_stride=10) # r[0:4] is roi tuple. #找到视野中的线,merge=true,将找到的图像区域合并成一个 if blobs: most_pixels = 0 largest_blob = 0 for i in range(len(blobs)): #目标区域找到的颜色块(线段块)可能不止一个,找到最大的一个,作为本区域内的目标直线 if blobs[i].pixels() > most_pixels: most_pixels = blobs[i].pixels() #merged_blobs[i][4]是这个颜色块的像素总数,如果此颜色块像素总数大于#most_pixels,则把本区域作为像素总数最大的颜色块。更新most_pixels和largest_blob largest_blob = i #将此区域的像素数最大的颜色块画矩形和十字形标记出来 #img.draw_rectangle(blobs[largest_blob].rect()) #img.draw_cross(blobs[largest_blob].cx(),blobs[largest_blob].cy()) center_x_sum += blobs[largest_blob].cx()*r[4] center_y_sum += blobs[largest_blob].cy()*r[4] weight_sum += r[4] center_x = int(center_x_sum/weight_sum) center_y = int(center_y_sum/weight_sum) #img.draw_cross(center_x,center_y) err_x = center_x - 80 err_y = int((center_y - 60)*0.3) #乘0.3,减小往前走的速度 x_speed = err_x - prior_x y_speed = err_y - prior_y prior_x = err_x prior_y = err_y #print("循到线")
if flag == 4 or flag == 5 or flag == 6: blobs = img.find_blobs(black_threshold,area_threshold=150,x_stride=12,y_stride=12) if blobs: #如果找到了目标颜色 #print(blobs) #print("找圆") for blob in blobs: #迭代找到的目标颜色区域 is_circle = False max_circle = None max_radius = -1 new_roi = expand_roi(blob.rect()) for c in img.find_circles(threshold = 3800, x_margin = 25, y_margin = 25, r_margin = 25, roi=new_roi): is_circle = True #img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 255)) if c.r() > max_radius: max_radius = c.r() max_circle = c if is_circle: #如果有对应颜色的圆形,标记外框 #img.draw_rectangle(new_roi) #rect #img.draw_rectangle(blob.rect()) #rect #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r(), color = (255, 255, 255)) #用矩形标记出目标颜色区域 #img.draw_cross(blob[5], blob[6]) # cx, cy #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r(), color = (0, 255, 0)) #img.draw_circle(max_circle.x(), max_circle.y(), max_circle.r() + 1, color = (0, 255, 0)) anla_cricle_sure = 1 #告诉飞控找到圆 #print("找到圆") flag = 0 # 开始定圆,关闭巡线
#----------------------------------------------------------------------------
if flag == 7: blobs = img.find_blobs(black_threshold) if blobs: #print("降落定点") #如果找到了目标颜色 most_pixels = 0 largest_blob = 0 for i in range(len(blobs)): red_led.off() #目标区域找到的颜色块可能不止一个,找到最大的一个 if blobs[i].pixels() > most_pixels: most_pixels = blobs[i].pixels() largest_blob = i err_x = int(blobs[largest_blob].cx() - 80) err_y = int(60-blobs[largest_blob].cy()) #img.draw_cross(blobs[largest_blob].cx(),blobs[largest_blob].cy())#调试使用 x_speed = err_x - prior_x y_speed = err_y - prior_y prior_x = err_x prior_y = err_y else: err_x = 0 err_y = 0 x_speed = 0 y_speed = 0
#发送值计算 #send_times = round(run_time/20,2) #四舍五入法,保留两位小数 #send_err_x = int(err_x/send_times) #send_err_y = int(err_y/send_times) #send_x_speed = int(x_speed/send_times) #send_y_speed = int(y_speed/send_times) send_err_x = err_x send_err_y = err_y send_x_speed = x_speed send_y_speed = y_speed print("值为=%d"%threshold_sure) uart_buf = bytearray([0xFE,send_err_x>>8,send_err_x,send_err_y>>8,send_err_y, send_x_speed>>8,send_x_speed,send_y_speed>>8,send_y_speed, (send_err_x+send_err_y+send_x_speed+send_y_speed)>>8, (send_err_x+send_err_y+send_x_speed+send_y_speed),anla_cricle_sure,threshold_sure])
#----------------------------------------------------------------------------
数据测试,打开终端观察数据,便于调试
#----------------------------------------------------------------------------
#flag = 1
#帧率值计算,即1S内代码跑了多少次,实际比仿真快一倍
#print("FPS %f" %clock.fps()) #打印帧率
#clock.tick()#打印测试值 #print(black_threshold) print("flag %d"%flag) #print("threshold_sure=%d"%threshold_sure) #print("run_time %d"%run_time) #print("send_times %f"%send_times) print("err_x %d"%err_x) print("err_y %d"%err_y) #print("x_speed %d"%x_speed) #print("y_speed %d"%y_speed) #print("send_err_x %d"%send_err_x) #print("send_err_y %d"%send_err_y) #print("send_x_speed %d"%send_x_speed) #print("send_y_speed %d"%send_y_speed) #print("weight_sum %d" %weight_sum) print("")
-
你这个程序的目的是什么?
你遇到了什么问题?
-
我这个程序时用来寻迹的,摄像头用来巡线。但是巡线的阈值我使用的是自动阈值,就是openmv自动测量出当前环境下的阈值(black_threshold),把测试所得到阈值作为巡线的阈值,但是因为加入了自动阈值的检测后,程序有时跑到中途就卡死了,有时系统会提示是定时器2中断的问题,有时仿真时IDE就直接卡死也不提示到底出现了什么错误。我不明白为什么程序会突然卡死?
-
我觉得有可能你的代码太长了,建议分多个模块调用。
-
但是我单独测试了一下定时器程序也会跑死?分模块调用,应该如何弄呢?
-
tick函数里,uart_buf不是global的。
而且你那个利用回调函数来进行计时,真的很没必要。。。
https://docs.singtown.com/micropython/zh/latest/openmvcam/openmvcam/quickref.html#id2
内置了utime.ticks_ms函数。。。
-
我回调函数主要的作用是用来串口发送数据的,就算我把计时部分去掉也会卡死