标题: MicroPython openmv识别直角 [打印本页]

作者: 孙权跑    时间: 2018-5-14 21:23
标题: MicroPython openmv识别直角
openmv 识别直角


  1. import sensor
  2. import image
  3. import time
  4. import math
  5. import pyb
  6. from pyb import Pin, Timer, UART,LED
  7. from GeometryFeature import GeometryFeature

  8. # 当光线弱的时候,用于补光
  9. LED(4).on()

  10. # 是否开启debug模式
  11. # 如果是False就不print, 不进行可视化绘制,可以提高帧率
  12. is_debug = True
  13. #--------------感光芯片配置  START -------------------

  14. DISTORTION_FACTOR = 1.5 # 设定畸变系数
  15. IMG_WIDTH  = 64
  16. IMG_HEIGHT = 64
  17. def init_sensor():
  18.     '''
  19.     初始化感光芯片
  20.     '''
  21.     sensor.reset()
  22.     sensor.set_pixformat(sensor.GRAYSCALE)
  23.     sensor.set_framesize(sensor.B64X64)                  # 分辨率为B64X64
  24.     sensor.skip_frames(time=2000)
  25.     sensor.set_auto_gain(False)                         # 颜色追踪关闭自动增益
  26.     sensor.set_auto_whitebal(False)                     # 颜色追踪关闭白平衡

  27. init_sensor()
  28. #--------------感光芯片配置  END -------------------



  29. #--------------定时器部分 START -------------------

  30. is_need_send_data = False # 是否需要发送数据的信号标志
  31. def uart_time_trigger(timer):
  32.     '''
  33.     串口发送数据的定时器,定时器的回调函数
  34.     '''
  35.     global is_need_send_data
  36.     is_need_send_data = True

  37. # 初始化定时器 频率为20HZ 每秒执行20次
  38. tim = Timer(4, freq=20)
  39. # 设定定时器的回调函数
  40. tim.callback(uart_time_trigger)
  41. #--------------定时器部分 END -------------------


  42. #--------------直线与直角检测部分 START -------------------

  43. INTERSERCT_ANGLE_THRESHOLD = (45,90)

  44. # 直线灰度图颜色阈值
  45. LINE_COLOR_THRESHOLD = [(0, 120)]
  46. # 如果直线是白色的,阈值修改为:
  47. # LINE_COLOR_THRESHOLD = [(128, 255)]

  48. # 取样窗口
  49. ROIS = {
  50.     'down': (0, 55, 64, 8), # 横向取样-下方 1
  51.     'middle': (0, 28, 64, 8), # 横向取样-中间 2
  52.     'up': (0, 0, 64, 8), # 横向取样-上方 3
  53.     'left': (0, 0, 8, 64), # 纵向取样-左侧 4
  54.     'right': (56, 0, 8, 64) # 纵向取样-右侧 5
  55. }


  56. BLOB_MAX_WIDTH = 15 # 色块的最大宽度
  57. BLOB_MIN_WIDTH = 5 # 色块的最小宽度
  58. BLOB_MAX_HEIGHT = 15 # 色块的最大高度
  59. BLOB_MIN_HEIGHT = 5 # 色块的最小宽度


  60. def find_blobs_in_rois(img):
  61.     '''
  62.     在ROIS中寻找色块,获取ROI中色块的中心区域与是否有色块的信息
  63.     '''
  64.     global ROIS
  65.     global is_debug

  66.     roi_blobs_result = {}  # 在各个ROI中寻找色块的结果记录
  67.     for roi_direct in ROIS.keys():
  68.         roi_blobs_result[roi_direct] = {
  69.             'cx': -1,
  70.             'cy': -1,
  71.             'blob_flag': False
  72.         }
  73.     for roi_direct, roi in ROIS.items():
  74.         blobs=img.find_blobs(LINE_COLOR_THRESHOLD, roi=roi, merge=True, pixels_area=10)
  75.         if len(blobs) == 0:
  76.             continue

  77.         largest_blob = max(blobs, key=lambda b: b.pixels())
  78.         x,y,width,height = largest_blob[:4]

  79.         if not(width >= BLOB_MIN_WIDTH and width <= BLOB_MAX_WIDTH and height >= BLOB_MIN_HEIGHT and height <= BLOB_MAX_HEIGHT):
  80.             # 根据色块的宽度进行过滤
  81.             continue

  82.         roi_blobs_result[roi_direct]['cx'] = largest_blob.cx()
  83.         roi_blobs_result[roi_direct]['cy'] = largest_blob.cy()
  84.         roi_blobs_result[roi_direct]['blob_flag'] = True

  85.         if is_debug:
  86.             img.draw_rectangle((x,y,width, height), color=(255))

  87.     return roi_blobs_result

  88. def visualize_result(canvas, cx_mean, cx, cy, is_turn_left, is_turn_right, is_t, is_cross):
  89.     '''
  90.     可视化结果
  91.     '''
  92.     if not(is_turn_left or is_turn_right or is_t or is_cross):
  93.         mid_x = int(canvas.width()/2)
  94.         mid_y = int(canvas.height()/2)
  95.         # 绘制x的均值点
  96.         canvas.draw_circle(int(cx_mean), mid_y, 5, color=(255))
  97.         # 绘制屏幕中心点
  98.         canvas.draw_circle(mid_x, mid_y, 8, color=(0))
  99.         canvas.draw_line((mid_x, mid_y, int(cx_mean), mid_y), color=(255))

  100.     turn_type = 'N' # 啥转角也不是

  101.     if is_t or is_cross:
  102.         # 十字形或者T形
  103.         canvas.draw_cross(int(cx), int(cy), size=10, color=(255))
  104.         canvas.draw_circle(int(cx), int(cy), 5, color=(255))

  105.     if is_t:
  106.         turn_type = 'T' # T字形状
  107.     elif is_cross:
  108.         turn_type = 'C' # 十字形
  109.     elif is_turn_left:
  110.         turn_type = 'L' # 左转
  111.     elif is_turn_right:
  112.         turn_type = 'R' # 右转

  113.     canvas.draw_string(0, 0, turn_type, color=(0))




  114. #--------------直线与直角检测部分 END -------------------


  115. #---------------------MAIN-----------------------
  116. last_cx = 0
  117. last_cy = 0

  118. while True:
  119.     if not is_need_send_data:
  120.         # 不需要发送数据
  121.         continue
  122.     is_need_send_data = False

  123.     # 拍摄图片
  124.     img = sensor.snapshot()
  125.     # 去除图像畸变
  126.     img.lens_corr(DISTORTION_FACTOR)
  127.     # 创建画布
  128.     # canvas = img.copy()
  129.     # 为了IDE显示方便,直接在代码结尾 用IMG绘制

  130.     # 注意:林林的代码里 计算直线之间的交点的代码没有用到
  131.     lines = img.find_lines(threshold=1000, theta_margin = 50, rho_margin = 50)
  132.     # 寻找相交的点 要求满足角度阈值
  133.     intersect_pt = GeometryFeature.find_interserct_lines(lines, angle_threshold=(45,90), window_size=(IMG_WIDTH, IMG_HEIGHT))
  134.     if intersect_pt is None:
  135.         # 直线与直线之间的夹角不满足阈值范围
  136.         intersect_x = 0
  137.         intersect_y = 0
  138.     else:
  139.         intersect_x, intersect_y = intersect_pt

  140.     reslut = find_blobs_in_rois(img)

  141.     # 判断是否需要左转与右转
  142.     is_turn_left = False
  143.     is_turn_right = False


  144.     if (not reslut['up']['blob_flag'] ) and reslut['down']['blob_flag']:
  145.         if reslut['left']['blob_flag']:
  146.             is_turn_left = True
  147.         if reslut['right']['blob_flag']:
  148.             is_turn_right = True


  149.     # 判断是否为T形的轨道
  150.     is_t = False
  151.     # 判断是否十字形轨道
  152.     is_cross = False

  153.     cnt = 0
  154.     for roi_direct in ['up', 'down', 'left', 'right']:
  155.         if reslut[roi_direct]['blob_flag']:
  156.             cnt += 1
  157.     is_t = cnt == 3
  158.     is_cross = cnt == 4

  159.     # cx_mean 用于确定视角中的轨道中心
  160.     # 用于表示左右偏移量
  161.     cx_mean = 0
  162.     for roi_direct in ['up', 'down', 'middle']:
  163.         if reslut[roi_direct]['blob_flag']:
  164.             cx_mean += reslut[roi_direct]['cx']
  165.         else:
  166.             cx_mean += IMG_WIDTH / 2
  167.     cx_mean /= 3

  168.     # cx, cy 只有在T形区域检测出来的时候才有用,
  169.     # 用于确定轨道中圆形的大致区域, 用于定点, 是计算圆心的一种近似方法

  170.     cx = 0
  171.     cy = 0

  172.     if is_cross or is_t:
  173.         # 只在出现十字形或者T字形才计算圆心坐标
  174.         cnt = 0
  175.         for roi_direct in ['up', 'down']:
  176.             if reslut[roi_direct]['blob_flag']:
  177.                 cnt += 1
  178.                 cx += reslut[roi_direct]['cx']
  179.         if cnt == 0:
  180.             cx = last_cx
  181.         else:
  182.             cx /= cnt

  183.         cnt = 0
  184.         for roi_direct in ['left', 'right']:
  185.             if reslut[roi_direct]['blob_flag']:
  186.                 cnt += 1
  187.                 cy += reslut[roi_direct]['cy']
  188.         if cnt == 0:
  189.             cy = last_cy
  190.         else:
  191.             cy /= cnt


  192.     last_cx = cx
  193.     last_cy = cy

  194.     if is_debug:
  195.         visualize_result(img, cx_mean, cx, cy, is_turn_left, is_turn_right, is_t, is_cross)
复制代码

所有资料51hei提供下载:
源代码.rar (7.31 KB, 下载次数: 160)



作者: 棉城乖宝宝    时间: 2019-4-14 20:26
感谢楼主,正在做整个边缘的识别,希望能有所启发。
作者: plj213    时间: 2019-4-29 13:24

感谢楼主分享。。。
作者: 逍遥捷    时间: 2019-5-13 16:38
GeometryFeature
这个库没有找到,是在哪里呢?
作者: 船长Fengi    时间: 2019-5-23 21:02
感谢楼主
作者: wu123456789    时间: 2019-7-30 14:29
有无详细介绍
作者: tytytyty......    时间: 2019-10-7 08:49
plj213 发表于 2019-4-29 13:24
感谢楼主分享。。。

请问这个你知道了吗?

作者: 孟祥平    时间: 2020-4-21 09:47
逍遥捷 发表于 2019-5-13 16:38
GeometryFeature
这个库没有找到,是在哪里呢?

下载楼主提供的附件压缩文件
作者: 当地的方言    时间: 2022-7-3 17:23
感谢楼主,正在做相关十字检测
作者: refghkl    时间: 2023-3-13 17:27
感谢楼主、




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1