در لیگ RCJ Soccer یکی از چالشهای اصلی، داشتن دید ۳۶۰ درجه برای تشخیص توپ و دروازههاست. یک روش ساده و کاربردی برای این کار، استفاده از آینه کاتادیوپتریک (Catadioptric Mirror) و دوربین OpenMV است.

در لیگ RCJ Soccer یکی از چالشهای اصلی، داشتن دید ۳۶۰ درجه برای تشخیص توپ و دروازههاست. یک روش ساده و کاربردی برای این کار، استفاده از آینه کاتادیوپتریک (Catadioptric Mirror) و دوربین OpenMV است. در شکل زیر دید کاتادیوپتریک یا دید 360 درجه با استفاده از یک آینه محدب و یک دوربین OpenMV مشاهده میکنید.

این ترکیب به ربات اجازه میدهد که با یک دوربین ساده، تمام زمین فوتبال را ببیند و موقعیت توپ و دروازهها را شناسایی کند.
در این آموزش یاد میگیریم:
تنظیم دوربین OpenMV برای دید ۳۶۰ درجه
ردیابی توپ (رنگ نارنجی)
ردیابی دروازه زرد و آبی
ارسال مختصات تشخیص داده شده به ربات از طریق I2C
دوربین OpenMV H7 یا H7 Plus
آینه کاتادیوپتریک ۳۶۰ درجه (مخصوص رباتهای فوتبالیست)
ربات RCJ Soccer با میکروکنترلر (مثل STM32 یا آردوینو)
کابل USB برای پروگرام کردن OpenMV
نصب نرمافزار OpenMV IDE روی لپتاپ
اتصال دوربین به کامپیوتر از طریق USB
انتخاب QVGA (320×240) بهعنوان رزولوشن تصویر
خاموش کردن تنظیمات خودکار:
Auto Gain
Auto White Balance
چون برای ردیابی رنگ باید این موارد ثابت باشند.
برای پیدا کردن اجسام، باید محدوده رنگ تعریف کنیم:
گاهی چند لکه همرنگ دیده میشوند. ما باید بزرگترین Blob را بهعنوان هدف انتخاب کنیم:
در حلقه اصلی، هر بار تصویر گرفته میشود و رنگها بررسی میشوند:
سپس برای هر کدام (اگر پیدا شدند) مختصات مرکز محاسبه میشود:
برای دیباگ و تست، روی تصویر مستطیل یا دایره میکشیم:
در پایان مختصات تشخیص داده شده از طریق I2C فرستاده میشود:
data = ustruct.pack("
pixels_threshold و area_threshold را بالاتر ببرید.با این روش، ربات شما میتواند با دید ۳۶۰ درجه توپ و دروازهها را شناسایی کند و مختصات آنها را به کنترلر اصلی بفرستد. در ادامه میتوان الگوریتمهای مسیریابی و تاکتیکهای فوتبالی را روی این دادهها پیادهسازی کرد.
import sensor
import time
import pyb
import ustruct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=100)
# sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(True) # must be turned off for color tracking
sensor.set_auto_exposure(False, exposure_us=5000) # Adjust exposure time in microseconds
sensor.set_auto_gain(False, gain_db=10)
# Initialize I2C
i2c = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x42)
# Values to send
x_ball = 0
y_ball = 0
x_yellow = 0
y_yellow = 0
x_blue = 0
y_blue = 0
clock = time.clock()
threshold_Ball = [-30, 60, 20, 60, 10, 80]
threshold_Yellow = [60, 80, -30, 10, 50, 100]
threshold_Blue = [30, 30, -20, 10, -50, -20]
tr = [
threshold_Ball,
threshold_Yellow,
threshold_Blue
]
def bigest(blobs):
m = blobs[0].area()
b = blobs[0]
for blob in blobs:
if blob.area() > m:
m = blob.area()
b = blob
return b
while True:
clock.tick()
img = sensor.snapshot()
yellow_blobs = img.find_blobs([threshold_Yellow], pixels_threshold=3, area_threshold=3, merge=True, margin=10)
blue_blobs = img.find_blobs([threshold_Blue], pixels_threshold=3, area_threshold=3, merge=True, margin=10)
orenge_blobs = img.find_blobs([threshold_Ball], pixels_threshold=5, area_threshold=10, merge=True, margin=10)
if len(yellow_blobs) > 0:
goaly = bigest(yellow_blobs)
img.draw_rectangle(goaly.rect(), (250,250,0), fill=True)
x_yellow = int(goaly.x() + goaly.w()/2)
y_yellow = int(goaly.y() + goaly.h()/2)
else:
x_yellow = 0
y_yellow = 0
if len(blue_blobs) > 0:
goalb = bigest(blue_blobs)
img.draw_rectangle(goalb.rect(), (0,0,250), fill=True)
x_blue = int(goalb.x() + goalb.w()/2)
y_blue = int(goalb.y() + goalb.h()/2)
else:
x_blue = 0
y_blue = 0
if len(orenge_blobs) > 0:
ball = bigest(orenge_blobs)
r = int(ball.w()/2)
x_ball = int(ball.x() + ball.w()/2)
y_ball = int(ball.y() + ball.h()/2)
img.draw_circle(x_ball, y_ball, r, (250,100,0), fill=True)
else:
x_ball = 0
y_ball = 0
try:
data = ustruct.pack("