【电设控制与图像训练题】【激光打靶】【openmv测试代码以及效果】

   日期:2020-09-06     浏览:116    评论:0    
核心提示:# Edge detection with Canny:## This example demonstrates the Canny edge detector.import sensor, image, timesensor.reset() # Initialize the camera sensor.sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.RGB565 565sensor.set_framesize(sensor.QQVGA)
9.4加入串口通讯,送出靶心坐标、激光坐标、激光所在环数、方位;加入防误判操作

目录

    • 规则
    • 坐标系
    • 代码
    • 总结
    • 相关openmv使用文档:

规则




坐标系

代码

# 激光打靶 openmv测试代码
# author:DYY
# 识别靶心和激光坐标并计算两者距离
# 靶子与摄像头距离为67厘米
#9.4号增加防误判操作以及串口通信
import sensor, image, time
import math
from pyb import UART
import json
import ustruct
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.RGB565 565
sensor.set_framesize(sensor.QQVGA) # or sensor.QVGA (or others)
sensor.skip_frames(30) # Let new settings take affect.
sensor.set_gainceiling(8)




#参数初始化
canny_thred=5
fps_cnt=0
fps_cnt_set=10000
show_fps_set=50
last_target_x=0
last_target_y=0
last_graylight_X=0
last_graylight_Y=0
target_x=0
target_y=0
graylight_x=0
graylight_y=0
distance=0
direction=0
two_point_angle=0
times=0
last_times=0
PI=3.14159
exist_time=0
not_exist_times=0
real_exist_times=0
set_target_X=0
set_target_Y=0
#靶心阈值
target_thred=(0,70)
#激光阈值
graylight_thred=(230,255)

#获取靶心坐标函数
def get_target(grayMat,paint):
   #计算连通域
   center_X=0
   center_Y=0
   for blob in grayMat.find_blobs([target_thred], pixels_threshold=100, area_threshold=100, merge=True, margin=10):
    pixels=blob.pixels()
    #利用圆度来限制
    Roundness= blob.roundness()
    '''if(fps_cnt%show_fps_set==0): print("靶子圆形度",Roundness) print("靶子像素个数",pixels)'''
    if Roundness>=0.6 and pixels<=400:
        center_X=blob.cx()
        center_Y=blob.cy()
        #paint.draw_circle(center_X,center_Y,6, color =255, thickness = 8, fill = True)
   return (center_X,center_Y)
#获取激光坐标函数
def get_graylight(grayMat,paint):
   #global real_exist_times
   #mask1=grayMat.binary([graylight_thred])
   #计算连通域
   center_X=0
   center_Y=0
   for blob in grayMat.find_blobs([graylight_thred], pixels_threshold=0, area_threshold=0, merge=True, margin=0):
    pixels=blob.pixels()
    Roundness= blob.roundness()
    '''if(fps_cnt%show_fps_set==0): print("圆形度",Roundness) print("像素个数",pixels)'''
    #光亮像素过大或者圆形度过小视作无
    if pixels>=60 :
        center_X=0
        center_Y=0
    else:
        center_X=blob.cx()
        center_Y=blob.cy()
        #paint.draw_circle(center_X,center_Y,4, color =0, thickness = 3, fill = True)
   return (center_X,center_Y)
#获取两个点之间的距离
def get_distance(point1_X,point1_Y,point2_X,point2_Y):
    #获取距离
    dx = abs(point1_X - point2_X)
    dy = abs(point1_Y - point2_Y)
    distance =math.sqrt(dx * dx + dy * dy)
    return distance
#计算两点方位,返回point1在point2的哪个方位
def get_direction(point1_X,point1_Y,point2_X,point2_Y):
    direct =0
    dx = point1_X - point2_X
    dy = point1_Y - point2_Y
    if dx==0 and dy==0:
        direct = 1  #重合
    elif dx == 0 and dy > 0:
        direct = 2  #正下方
    elif dx == 0 and dy < 0:
        direct = 3  #正上方
    elif dx > 0 and dy == 0:
        direct = 4  #正右方
    elif dx > 0 and dy > 0:
        direct = 5  #右下方
    elif dx > 0 and dy < 0:
        direct = 6  #右上方
    elif dx < 0 and dy == 0:
        direct = 7  #正左方
    elif dx < 0 and dy > 0:
        direct = 8  #左下方
    elif dx < 0 and dy < 0:
        direct = 9  #左上方
    else:
        direct = 0  #无方向
    return direct
#计算角度
def get_angle(point1_X,point1_Y,point2_X,point2_Y):
    dx = point1_X - point2_X
    dy = point1_Y - point2_Y
    angle=0
    if dx==0 and dy>=0 :
        angle=0
    elif dx==0 and dy<0:
        angle=180
    elif dy==0 and dx>0:
        angle=90
    elif dy==0 and dx<0:
        angle =270
    elif dx>0 and dy>0:
        angle=math.atan(dx/dy)*180/PI
    elif dx<0 and dy>0:
        angle=360+math.atan(dx/dy)*180/PI
    elif dx<0 and dy<0:
        angle=180+math.atan(dx/dy)*180/PI
    elif dx>0 and dy<0:
        angle=180+math.atan(dx/dy)*180/PI
    return angle
#计算两点方位,返回point1在point2的哪个方位
def get_direction_with_angle(angle):
    direct =0
    if (angle>=0 and angle<=22.5) or (angle>337.5 and angle<=360):
        direct = 1  #正下
    elif angle>22.5 and angle<=67.5:
        direct = 2  #右下
    elif angle>67.5 and angle<=112.5:
        direct = 3  #正右
    elif angle>112.5 and angle<=157.5:
        direct = 4  #右上
    elif angle>157.5 and angle<=202.5:
        direct = 5  #正上
    elif angle>202.5 and angle<=247.5:
        direct = 6  #左上
    elif angle>247.5 and angle<=292.5:
        direct = 7  #正左
    elif angle>292.5 and angle<=337.5:
        direct = 8  #左下
    else:
        direct = 0  #无方向
    return direct





#显示方位信息
def show_direction(direct):
    if direct==1 :
        print("正下")
    elif direct==2 :
        print("右下")  #正下方
    elif direct==3 :
        print("正右")  #正上方
    elif direct==4 :
        print("右上")  #正右方
    elif direct==5 :
        print("正上")  #右下方
    elif direct==6 :
        print("左上")  #右上方
    elif direct==7 :
        print("正左")  #正左方
    elif direct==8 :
        print("左下")  #左下方
    else:
        print("无方向")  #无方向


#防误判靶心
def Prevent_misjudgment(point1_X,point1_Y,lastpoint1_X,lastpoint1_Y,set_X,set_Y):
    global exist_time
    if abs(lastpoint1_X-point1_X)<=30 and abs(lastpoint1_Y-point1_Y)<=30 and point1_X!=0 and point1_Y!=0:
        exist_time+=1
        if(exist_time>=4):
            set_X=point1_X
            set_Y=point1_Y
    if exist_time>=5 and (point1_X==0 or point1_Y==0):
        point1_X=set_X
        point1_Y=set_Y
    return point1_X,point1_Y,set_X,set_Y
#防丢激光 如果上一帧有值,这帧没值,或者上一帧有值且两者坐标相差太大,则这帧的坐标延续上一帧
#如果连续当前5帧没有找到激光,则认为脱靶
def Prevent_missgraylight(point1_X,point1_Y,lastpoint1_X,lastpoint1_Y):
    global not_exist_times
    global last_times
    if point1_X==0 and point1_Y==0:
        not_exist_times+=1
    if point1_X==0 and point1_Y==0 and lastpoint1_X!=0 and lastpoint1_Y!=0:
        point1_X=lastpoint1_X
        point1_Y=lastpoint1_Y
    if lastpoint1_X!=0 and lastpoint1_Y!=0 and (abs(lastpoint1_X-point1_X)>=70 or abs(lastpoint1_Y-point1_Y)>=70):
        point1_X=lastpoint1_X
        point1_Y=lastpoint1_Y
    if not_exist_times>=5 and last_times<=6:
        point1_X=0
        point1_Y=0
        not_exist_times=0
    return point1_X,point1_Y
#获取所在环数
''' 弃用代码 def get_ring_nums(paintMat,cannyMat,oldimg,method): mask=oldimg.clear() times=0 for i in range(1,cannyMat.height()-1): for j in range(1,cannyMat.width()-1): if cannyMat.get_pixel(i,j)==255 and paintMat.get_pixel(i,j)==0: mask.set_pixel(i,j,255) times=times+1 if times>0: print("次数",times) #判断每个格子八领域是否有白色的,如果有,消除掉 if (mask.get_pixel(i - 1, j - 1)==255 or mask.get_pixel(i - 1, j )==255 or mask.get_pixel(i - 1, j + 1)==255 or mask.get_pixel(i , j - 1)==255 or mask.get_pixel(i , j + 1)==255 or mask.get_pixel(i + 1 , j - 1)==255 or mask.get_pixel(i + 1 , j)==255 or mask.get_pixel(i + 1 , j + 1)==255): mask.set_pixel(i,j,0) times=times-1 return times '''
def get_ring_nums_type2(distance,dis1,dis2,dis3,dis4,dis5,dis6):
    ring=0
    if distance <=dis1:
        ring=10
    elif distance >dis1 and distance <=dis2:
        ring=9
    elif distance >dis2 and distance <=dis3:
        ring=8
    elif distance >dis3 and distance <=dis4:
        ring=7
    elif distance >dis4 and distance <=dis5:
        ring=6
    elif distance >dis5 and distance <=dis6:
        ring=5
    else:
        ring=0
    return ring

clock = time.clock() # Tracks FPS.


#设置串口
uart = UART(3,115200)   #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=0) # init with given parameters


#我们要传送的数据有:靶心坐标、激光坐标、环数、方位、以及回车
def sending_data(cx,cy,gx,gy,rings,direct):    #发送函数(我这里没用的,还是留着吧)
    global uart
    data = ustruct.pack("<bbbbbbbb",
                   cx,
                   cy,
                   gx,
                   gy,
                   rings,
                   direct,
                   0x0D,
                   0x0A)
    uart.write(data)

def recive_data():   #接收函数
    global uart
    if uart.any():
        tmp_data = uart.readline().decode()
        print(tmp_data)

#图像循环
while(True):
    clock.tick() # Track elapsed milliseconds between snapshots().
    #获取彩图
    srcimg = sensor.snapshot() # Take a picture and return the image.
    fps_cnt=fps_cnt+1
    #转成灰度
    grayimg =srcimg.to_grayscale()
    paintimg = grayimg
    #前fps_cnt_set帧找靶心,用来定位
    if(fps_cnt<=fps_cnt_set):
        #找到靶心的位置并且画出来get_target
        (target_x,target_y)=get_target(grayimg,paintimg)
        #防误判程序加入
        (target_x,target_y,set_target_X,set_target_Y)=Prevent_misjudgment(target_x,target_y,last_target_x,last_target_y,set_target_X,set_target_Y)
    #找到激光的位置并且画出来
    (graylight_x,graylight_y)=get_graylight(grayimg,paintimg)
    (graylight_x,graylight_y)=Prevent_missgraylight(graylight_x,graylight_y,last_graylight_X,last_graylight_Y)
    #当激光和靶心都存在的时候
    if target_x!=0 and target_y!=0 and graylight_x!=0 and graylight_y!=0:
        #计算两者距离
        distance = get_distance(target_x,target_y,graylight_x,graylight_y)
        #获取方位
        #direction =get_direction(graylight_x,graylight_y,target_x,target_y)
        #获取角度
        two_point_angle=get_angle(graylight_x,graylight_y,target_x,target_y)
        #获取方位
        direction=get_direction_with_angle(two_point_angle)
        #canny检测
        #cannyimg=grayimg.find_edges(image.EDGE_CANNY, threshold=(canny_thred,canny_thred*2))
        #画出直线
        paintimg.draw_line(target_x,target_y,graylight_x,graylight_y, color = 0, thickness = 1)
        #获取环数
        #method1
        #times=get_ring_nums(paintimg,cannyimg,srcimg)
        #method2
        times=get_ring_nums_type2(distance,10,20,30,40,50,60)
        #每30帧显示一组数据
        if(fps_cnt%show_fps_set==0):
            print("靶心坐标",target_x,target_y)
            print("两点距离",distance)
            #显示方位
            show_direction(direction)
            #显示环数
            print("环数",times)
            #print("环数",(10-times))
    else:
        distance=0
        times=0
        #每30帧显示一组数据
        if(fps_cnt%show_fps_set==0):
            print("没有找到靶点或者激光")
            print("脱靶")
    #发送和接收数据
    #recive_data()
    sending_data(target_x,target_y,graylight_x,graylight_y,times,direction)
    #更新数据
    if(fps_cnt%show_fps_set==0):
        print(target_x,target_y,graylight_x,graylight_y)
    last_target_x=target_x
    last_target_y=target_y
    last_graylight_X=graylight_x
    last_graylight_Y=graylight_y
    last_times=times
    # Faster simpler edge detection
    #img.find_edges(image.EDGE_SIMPLE, threshold=(100, 255))
    #print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while


总结

之前用的opencv写的测试代码,转用openmv时出现了不少问题。有些地方做了简化。
之前的opencv代码:
https://blog.csdn.net/qq_42604176/article/details/108342679

相关openmv使用文档:

https://docs.openmv.io/library/omv.image.html?highlight=rgb_to_grayscale#image.image.rgb_to_grayscale
https://singtown.com/learn/50029/

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服