openmv 識別直角
- import sensor
- import image
- import time
- import math
- import pyb
- from pyb import Pin, Timer, UART,LED
- from GeometryFeature import GeometryFeature
- # 當光線弱的時候,用于補光
- LED(4).on()
- # 是否開啟debug模式
- # 如果是False就不print, 不進行可視化繪制,可以提高幀率
- is_debug = True
- #--------------感光芯片配置 START -------------------
- DISTORTION_FACTOR = 1.5 # 設定畸變系數
- IMG_WIDTH = 64
- IMG_HEIGHT = 64
- def init_sensor():
- '''
- 初始化感光芯片
- '''
- sensor.reset()
- sensor.set_pixformat(sensor.GRAYSCALE)
- sensor.set_framesize(sensor.B64X64) # 分辨率為B64X64
- sensor.skip_frames(time=2000)
- sensor.set_auto_gain(False) # 顏色追蹤關閉自動增益
- sensor.set_auto_whitebal(False) # 顏色追蹤關閉白平衡
- init_sensor()
- #--------------感光芯片配置 END -------------------
- #--------------定時器部分 START -------------------
- is_need_send_data = False # 是否需要發送數據的信號標志
- def uart_time_trigger(timer):
- '''
- 串口發送數據的定時器,定時器的回調函數
- '''
- global is_need_send_data
- is_need_send_data = True
- # 初始化定時器 頻率為20HZ 每秒執行20次
- tim = Timer(4, freq=20)
- # 設定定時器的回調函數
- tim.callback(uart_time_trigger)
- #--------------定時器部分 END -------------------
- #--------------直線與直角檢測部分 START -------------------
- INTERSERCT_ANGLE_THRESHOLD = (45,90)
- # 直線灰度圖顏色閾值
- LINE_COLOR_THRESHOLD = [(0, 120)]
- # 如果直線是白色的,閾值修改為:
- # LINE_COLOR_THRESHOLD = [(128, 255)]
- # 取樣窗口
- ROIS = {
- 'down': (0, 55, 64, 8), # 橫向取樣-下方 1
- 'middle': (0, 28, 64, 8), # 橫向取樣-中間 2
- 'up': (0, 0, 64, 8), # 橫向取樣-上方 3
- 'left': (0, 0, 8, 64), # 縱向取樣-左側 4
- 'right': (56, 0, 8, 64) # 縱向取樣-右側 5
- }
- BLOB_MAX_WIDTH = 15 # 色塊的最大寬度
- BLOB_MIN_WIDTH = 5 # 色塊的最小寬度
- BLOB_MAX_HEIGHT = 15 # 色塊的最大高度
- BLOB_MIN_HEIGHT = 5 # 色塊的最小寬度
- def find_blobs_in_rois(img):
- '''
- 在ROIS中尋找色塊,獲取ROI中色塊的中心區域與是否有色塊的信息
- '''
- global ROIS
- global is_debug
- roi_blobs_result = {} # 在各個ROI中尋找色塊的結果記錄
- for roi_direct in ROIS.keys():
- roi_blobs_result[roi_direct] = {
- 'cx': -1,
- 'cy': -1,
- 'blob_flag': False
- }
- for roi_direct, roi in ROIS.items():
- blobs=img.find_blobs(LINE_COLOR_THRESHOLD, roi=roi, merge=True, pixels_area=10)
- if len(blobs) == 0:
- continue
- largest_blob = max(blobs, key=lambda b: b.pixels())
- x,y,width,height = largest_blob[:4]
- if not(width >= BLOB_MIN_WIDTH and width <= BLOB_MAX_WIDTH and height >= BLOB_MIN_HEIGHT and height <= BLOB_MAX_HEIGHT):
- # 根據色塊的寬度進行過濾
- continue
- roi_blobs_result[roi_direct]['cx'] = largest_blob.cx()
- roi_blobs_result[roi_direct]['cy'] = largest_blob.cy()
- roi_blobs_result[roi_direct]['blob_flag'] = True
- if is_debug:
- img.draw_rectangle((x,y,width, height), color=(255))
- return roi_blobs_result
- def visualize_result(canvas, cx_mean, cx, cy, is_turn_left, is_turn_right, is_t, is_cross):
- '''
- 可視化結果
- '''
- if not(is_turn_left or is_turn_right or is_t or is_cross):
- mid_x = int(canvas.width()/2)
- mid_y = int(canvas.height()/2)
- # 繪制x的均值點
- canvas.draw_circle(int(cx_mean), mid_y, 5, color=(255))
- # 繪制屏幕中心點
- canvas.draw_circle(mid_x, mid_y, 8, color=(0))
- canvas.draw_line((mid_x, mid_y, int(cx_mean), mid_y), color=(255))
- turn_type = 'N' # 啥轉角也不是
- if is_t or is_cross:
- # 十字形或者T形
- canvas.draw_cross(int(cx), int(cy), size=10, color=(255))
- canvas.draw_circle(int(cx), int(cy), 5, color=(255))
- if is_t:
- turn_type = 'T' # T字形狀
- elif is_cross:
- turn_type = 'C' # 十字形
- elif is_turn_left:
- turn_type = 'L' # 左轉
- elif is_turn_right:
- turn_type = 'R' # 右轉
- canvas.draw_string(0, 0, turn_type, color=(0))
- #--------------直線與直角檢測部分 END -------------------
- #---------------------MAIN-----------------------
- last_cx = 0
- last_cy = 0
- while True:
- if not is_need_send_data:
- # 不需要發送數據
- continue
- is_need_send_data = False
- # 拍攝圖片
- img = sensor.snapshot()
- # 去除圖像畸變
- img.lens_corr(DISTORTION_FACTOR)
- # 創建畫布
- # canvas = img.copy()
- # 為了IDE顯示方便,直接在代碼結尾 用IMG繪制
- # 注意:林林的代碼里 計算直線之間的交點的代碼沒有用到
- lines = img.find_lines(threshold=1000, theta_margin = 50, rho_margin = 50)
- # 尋找相交的點 要求滿足角度閾值
- intersect_pt = GeometryFeature.find_interserct_lines(lines, angle_threshold=(45,90), window_size=(IMG_WIDTH, IMG_HEIGHT))
- if intersect_pt is None:
- # 直線與直線之間的夾角不滿足閾值范圍
- intersect_x = 0
- intersect_y = 0
- else:
- intersect_x, intersect_y = intersect_pt
- reslut = find_blobs_in_rois(img)
- # 判斷是否需要左轉與右轉
- is_turn_left = False
- is_turn_right = False
- if (not reslut['up']['blob_flag'] ) and reslut['down']['blob_flag']:
- if reslut['left']['blob_flag']:
- is_turn_left = True
- if reslut['right']['blob_flag']:
- is_turn_right = True
- # 判斷是否為T形的軌道
- is_t = False
- # 判斷是否十字形軌道
- is_cross = False
- cnt = 0
- for roi_direct in ['up', 'down', 'left', 'right']:
- if reslut[roi_direct]['blob_flag']:
- cnt += 1
- is_t = cnt == 3
- is_cross = cnt == 4
- # cx_mean 用于確定視角中的軌道中心
- # 用于表示左右偏移量
- cx_mean = 0
- for roi_direct in ['up', 'down', 'middle']:
- if reslut[roi_direct]['blob_flag']:
- cx_mean += reslut[roi_direct]['cx']
- else:
- cx_mean += IMG_WIDTH / 2
- cx_mean /= 3
- # cx, cy 只有在T形區域檢測出來的時候才有用,
- # 用于確定軌道中圓形的大致區域, 用于定點, 是計算圓心的一種近似方法
- cx = 0
- cy = 0
- if is_cross or is_t:
- # 只在出現十字形或者T字形才計算圓心坐標
- cnt = 0
- for roi_direct in ['up', 'down']:
- if reslut[roi_direct]['blob_flag']:
- cnt += 1
- cx += reslut[roi_direct]['cx']
- if cnt == 0:
- cx = last_cx
- else:
- cx /= cnt
- cnt = 0
- for roi_direct in ['left', 'right']:
- if reslut[roi_direct]['blob_flag']:
- cnt += 1
- cy += reslut[roi_direct]['cy']
- if cnt == 0:
- cy = last_cy
- else:
- cy /= cnt
- last_cx = cx
- last_cy = cy
- if is_debug:
- visualize_result(img, cx_mean, cx, cy, is_turn_left, is_turn_right, is_t, is_cross)
復制代碼
所有資料51hei提供下載:
源代碼.rar
(7.31 KB, 下載次數: 160)
2018-5-14 21:22 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|