目录
一、配置初始化部分
(1)摄像头一些配置功能*
import sensor, image, time, lcd
#摄像头配置
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_contrast(0) #设置对比度图像更加清晰 范围为(-2——2)
sensor.set_brightness(0) #设置亮度 范围为(-2——2)
sensor.set_saturation(0) #设置饱和度 范围为(-2——2)
sensor.set_auto_gain(1,db) #设置自动增益自动调整图像亮度 1为开启,0为关闭 db为关闭自动增益时,设置摄像头得固定增益值,单位为db
sensor.skip_frames(time=2000) # 跳过一些帧,让摄像头稳定
sensor.run(1) # 启动摄像头并开始图像捕获
lcd.init(freq=15000000)# 初始化LCD
while(True):
img = sensor.snapshot().replace(vflip=True,hmirror=False,transpose=True)#设置图像方向
lcd.display(img)
# vflip=False, hmirror=False, transpose=False -> 0 degree rotation
# vflip=True, hmirror=False, transpose=True -> 90 degree rotation
# vflip=True, hmirror=True, transpose=False -> 180 degree rotation
# vflip=False, hmirror=True, transpose=True -> 270 degree rotation
(2)LCD初始化
import sensor, lcd
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1) #指示图像传感器开始工作并,开始捕获图像
sensor.skip_frames()
lcd.init(freq=15000000) #LCD刷新图像的速度15MHz
lcd.rotation(2) #设置屏幕方向
while(True):
img = sensor.snapshot()
lcd.display(img) #显示
(3)led初始化
import utime
from Maix import GPIO
from fpioa_manager import fm
while True:
fm.register(13,fm.fpioa.GPIO0)
fm.register(12,fm.fpioa.GPIO1)
fm.register(14,fm.fpioa.GPIO2)
led_r=GPIO(GPIO.GPIO0,GPIO.OUT) #红(若只设置一个,则其他两个默认打开)
led_g=GPIO(GPIO.GPIO1,GPIO.OUT) #绿
led_b=GPIO(GPIO.GPIO2,GPIO.OUT) #蓝
utime.sleep_ms(500)
led_r.value(1) #灭
led_g.value(1)
led_b.value(1)
utime.sleep_ms(500)
led_r.value(0) #亮
led_g.value(0)
led_b.value(0)
(4)串口(接收与发送)
①串口初始化
from fpioa_manager import fm
from machine import UART
import ustruct
# 串口1 设置 P9 RX P6 TX
fm.register(9, fm.fpioa.UART1_RX, force = True) # 配置 9 脚为 UART1_RX 强制注册
fm.register(6, fm.fpioa.UART1_TX, force = True) # 配置 6 脚为 UART1_TX 强制注册
uart1 = UART(UART.UART1, 115200, 8, 0, 1) # 设置 uart1 为 串口1 波特率 921600 数据位 8位 校验位 0位 停止位 1位
# 串口2 设置 P7 RX P8 TX
fm.register(7, fm.fpioa.UART2_RX, force = True) # 配置 7 脚为 UART2_RX 强制注册
fm.register(8, fm.fpioa.UART2_TX, force = True) # 配置 8 脚为 UART2_TX 强制注册
uart2 = UART(UART.UART2, 115200, 8, 0, 1) # 设置 uart2 为 串口2 波特率 921600 数据位 8位 校验位 0位 停止位 1位
②K210发送
#发送数据(示例)
from fpioa_manager import fm
from machine import UART
import ustruct
# 串口1 设置 P9 RX P6 TX
fm.register(9, fm.fpioa.UART1_RX, force = True) # 配置 9 脚为 UART1_RX 强制注册
fm.register(6, fm.fpioa.UART1_TX, force = True) # 配置 6 脚为 UART1_TX 强制注册
uart = UART(UART.UART1, 115200, 8, 0, 1) # 设置 uart1 为 串口1 波特率 921600 数据位 8位 校验位 0位 停止位 1位
#发送数据
#串口发送函数
def sending_data(cx,cy):
global uart;
data_send = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
0x2C, #帧头1
0x12, #帧头2
int(cx), # up sample by 4 #数据1
int(cy), # up sample by 4 #数据2
0x5B)
uart.write(data_send); #必须要传入一个字节数组
print(data_send)
while(1):
sending_data(9,10)
③接收数据*
#读取串口
if (uart.any()>0): # 检查串口缓冲区中是否有数据可读
read_data=uart.read().decode() # 读取串口数据并转换成字符串
print(read_data)
if read_data[0]=="*" and read_data[3]=="&": # 提取第二个字符并转换成整数
#串口接收函数
data_receive = [0] * 8 # 初始化
x = 0
def UartReceiveDate(): #这个函数不能运行太快,否则会导致串口读取太快导致出错
global Find_Task #用于存储接收到的指令类型,例如42代表*,38代表&
global Target_Num #用于存储目标数,即数据的第三个字节
global x #用于索引数据数组
global data_receive #用于存储接收到的数据
data_receive[0] = uart.readchar() #将接收到的数据装入data_receive
data_receive[1] = uart.readchar()
data_receive[2] = uart.readchar()
data_receive[3] = uart.readchar()
data_receive[4] = uart.readchar()
data_receive[5] = uart.readchar()
data_receive[6] = uart.readchar()
data_receive[7] = uart.readchar()
#判断data数组中第x个位置的值是否为42,第x+3个位置的值是否为38,并且x的值是否小于5
if data_receive[x] == 42 and data_receive[x+3] == 38 and x < 5:
Find_Task = data_receive[x+1]
Target_Num = data_receive[x+2]
Find_Task = Find_Task - 48
Target_Num = Target_Num - 48
print(Find_Task, Target_Num)
x = 0
elif x >= 5: x = 0
x+=1
二、图像处理部分
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
thresholds=(46, 92, -2, 50, -128, -11)
while(True):
img = sensor.snapshot()
#img.to_grayscale(copy=False) #将图像转换为灰度图像 此方法也会修改基础图像像素,以字节为单位更改图像大小,因此只能在灰度图像或RGB565图像上进行。 否则必须为True才能在堆上创建新的修改图像。
#img.to_rgb565(copy=False) #将图像转换为RGB565
#img.binary([thresholds], invert=False, zero=False,lask=None)
#根据像素是否在阈值列表 thresholds 中的阈值内,将图像中的所有像素设置为黑色或白色。
#invert 反转阈值操作,像素在已知颜色范围之外进行匹配,而非在已知颜色范围内。
#设置 zero 为True来使阈值像素为零,并使不在阈值列表中的像素保持不变。
#lask 是另一个用作绘图操作的像素级掩码的图像。掩码应该是一个只有黑色或白色像素的图像,并且应该与你正在绘制的 image 大小相同。 仅掩码中设置的像素被修改。
#返回图像对象,以便您可以使用 . 表示法调用另一个方法。
#img.histeq(adaptive=False, clip_limit=-1)#在图像上运行直方图均衡算法。 直方图均衡化使图像中的对比度和亮度标准化。
#如果 adaptive 传递为True,那么将在图像上运行自适应直方图均衡方法,这通常比非自适应直方图限定更好,但运行时间更长。
#clip_limit 提供了一种限制自适应直方图均衡的对比度的方法。 使用较小的值(例如10)可以生成良好的直方图均衡对比度受限图像。
#img.lens_corr(strength=1.8, zoom=1.0)#进行镜头畸变校正,以去除镜头造成的图像鱼眼效果。
#strength 是一个浮点数,该值确定了对图像进行去鱼眼效果的程度。在默认情况下,首先试用取值1.8,然后调整这一数值使图像显示最佳效果。
#zoom 是在对图像进行缩放的数值。默认值为 1.0 。
三、一维测距
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(10)
sensor.set_auto_whitebal(False)
clock = time.clock() # Tracks FPS.
K=5000 #the value should be measured
red_threshold = (12, 66, 18, 59, -128, 127)
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold])
if len(blobs) == 1:
# Draw a rect around the blob.
b = blobs[0]
img.draw_rectangle(b[0:4]) # rect
img.draw_cross(b[5], b[6]) # cx, cy
Lm = (b[2]+b[3])/2
length = K/Lm
print(length)
四、循迹
import sensor, image, math, time, lcd
import ustruct
from fpioa_manager import fm
from machine import UART
from image import SEARCH_EX, SEARCH_DS
sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565)#设置为彩图
sensor.set_framesize(sensor.QVGA)#设置分辨率
lcd.init(freq=15000000)#设置lcd频率
lcd.rotation(2)#设置屏幕方向
clock = time.clock()
#-----------------------以下是串口,循迹配置配置部分-----------------------------
fm.register(9, fm.fpioa.UART1_TX, force=True)
fm.register(10, fm.fpioa.UART1_RX, force=True)
uart_A = UART(UART.UART1, 115200, 8, 1, 0, timeout=1000, read_buf_len=4096)
GROUND_THRESHOLD1=((19, 0, 127, -128, 127, -128))#循迹阈值
#入口参数x y w h
roi1 = [(10, 90,40, 80), #左1
(55, 90,40, 80), #左2
(100,20,40,50), #中间
(145,90,40,80), #右2
(190,90,40,80)] #右1
a='r'
while(True):
img = sensor.snapshot().replace(vflip=False,hmirror=False,transpose=True) #使用摄像头拍摄一张照片
for rec in roi1:
img.draw_rectangle(rec, color=(255,0,0))#绘制出roi区域
lcd.display(img)
blob1=None
blob2=None
blob3=None
blob4=None
blob5=None
blob1 = img.find_blobs([GROUND_THRESHOLD1], roi=roi1[0])
blob2 = img.find_blobs([GROUND_THRESHOLD1], roi=roi1[1])
blob3 = img.find_blobs([GROUND_THRESHOLD1], roi=roi1[2])
blob4 = img.find_blobs([GROUND_THRESHOLD1], roi=roi1[3])
blob5 = img.find_blobs([GROUND_THRESHOLD1], roi=roi1[4])
if blob4:
a= 'r' #中间检测到红线
if blob5:
a= 't' #右边检测到红线
if blob1:
a= 'q'
if blob3:
a= 'e' #右边检测到红线
if blob2:
a= 'w' #中间检测到红线
print(a)
uart_A.write(a)
五、数字识别
线上训练网站:点我
如何操作:点我
说明:先拍好训练图片,训练,然后将模型下载,取出其中的.kmodel 放入SD中随后即可(如果报错,则需要重新下载固件库“...._minimum_with_ide_support.bin”)
六、舵机控制
from machine import Timer,PWM
import time
tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM)
S1 = PWM(tim, freq=50, duty=0, pin=17)
#def Servo(servo,angle):
# S1.duty((angle+90)/180*10+2.5)
#while True:
# #-90度
# Servo(S1,-90)
# time.sleep(1)
# #-45度
# Servo(S1,-45)
# time.sleep(1)
# #0度
# Servo(S1,0)
# time.sleep(1)
#45度
# Servo(S1,45)
# time.sleep(1)
# #90度
# Servo(S1,90)
# time.sleep(1)
######
a=0
while(1):
if a==0:
for i in range(0,180,1):
S1.duty(i/180*10+2.5)
if i==180:
break
time.sleep(0.05)
if a==1:
for i in range(180,0,-1):
S1.duty(i/180*10+2.5)
time.sleep(0.05)
六、物体识别
(1)色块追踪(find.blob)
import sensor, image, time,math, lcd
import json
import ustruct
from fpioa_manager import fm
from machine import UART
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
sensor.skip_frames(10)#跳过10帧
sensor.set_auto_whitebal(False)#关闭白平衡,默认是开启的
sensor.set_auto_gain(False)#关闭自动增益
#sensor.set_auto_exposure(True)
lcd.init(freq=15000000)
lcd.rotation(2)#设置屏幕方向
red_threshold=(8, 100, -128, -7, 17, 127)
blue_threshold=(12, 64, 7, 127, -128, -33)
fm.register(9, fm.fpioa.UART1_TX, force=True)
fm.register(10, fm.fpioa.UART1_RX, force=True)
uart = UART(UART.UART1, 115200, 8, 1, 0, timeout=1000, read_buf_len=4096)
def find_max(blobs): #定义寻找色块面积最大的函数
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
def sending_data(cx,cy):
global uart;
data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
0x2C, #帧头1
0x12, #帧头2
int(cx), # up sample by 4 #数据1
int(cy), # up sample by 4 #数据2
0x5B)
uart.write(data); #必须要传入一个字节数组
cx=0
cw=0
while(1):
img = sensor.snapshot().replace(vflip=False,hmirror=False,transpose=True)
blobs = img.find_blobs([blue_threshold]) #追踪蓝色
if blobs:
max_b = find_max(blobs)
#如果找到了目标颜色
cw=max_b[2]
cx=max_b[5]
img.draw_rectangle(max_b[0:4]) # rect
img.draw_cross(max_b[5], max_b[6]) # cx, cy
FH = bytearray([0x2C,0x12,cx,cw,0x5B])
uart.write(FH)
for i in range(10):
img.draw_string(20, 40, "(%d,%d)" % (cx,cw), color = (255, 255, 0), scale = 2, mono_space = False,
char_rotation = 0, char_hmirror = False, char_vflip = False,
string_rotation = 0, string_hmirror = False, string_vflip = False)
lcd.display(img)
#blob.x() blobs[0]
#返回色块的边界框的x坐标(int)。
#blob.y() blobs[1]
#返回色块的边界框的y坐标(int)。
#blob.w() blobs[2]
#返回色块的边界框的w坐标(int)。
#blob.h() blobs[3]
#返回色块的边界框的h坐标(int)。
#blob.pixels() blobs[4]
#返回从属于色块(int)一部分的像素数量。
#blob.cx() blobs[5]
#返回色块(int)的中心x位置。
#blob.cy() blobs[6]
#返回色块(int)的中心x位置。
#blob.rotation() blobs[7]
#返回色块的旋转(单位:弧度)。
#如果色块类似铅笔或钢笔,那么这个值就是介于0-180之间的唯一值。
#如果这个色块圆的,那么这个值就没有效用。
#如果这个色块完全不具有对称性,您只能由此得到0-360度的旋转。
#blob.area()
#返回色块周围的边框面积(w * h)
#blob.density()
#返回这个色块的密度比。这是在色块边界框区域内的像素点的数量。
#总的来说,较低的密度比意味着这个对象的锁定得不是很好。
(2)识别矩阵(find.rects)
注:有BUG会检测到小半径的圆(画质不高)
# 这个例子展示了如何使用april标签代码中的四元检测代码在图像中找到矩形。 四元检测算法以非常稳健的方式检测矩形,并且比基于Hough变换的方法好得多。 例如,即使镜头失真导致这些矩形看起来弯曲,它仍然可以检测到矩形。 圆角矩形是没有问题的!
# (但是,这个代码也会检测小半径的圆)...
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
while(True):
img = sensor.snapshot()
# 下面的`threshold`应设置为足够高的值,以滤除在图像中检测到的具有
# 低边缘幅度的噪声矩形。最适用与背景形成鲜明对比的矩形。
for r in img.find_rects(threshold = 10000):#小于threshold得矩阵会被滤除掉
img.draw_rectangle(r.rect(), color = (255, 0, 0))
for p in r.corners():
img.draw_circle(p[0], p[1], 5, color = (0, 255, 0))
print(r)
(3)识别有颜色的圆(find_circles)
import sensor, image, time, lcd
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
lcd.init(freq=15000000)
lcd.rotation(2)#设置屏幕方向
while(True):
img = sensor.snapshot().replace(vflip=False,hmirror=False,transpose=True)
for c in img.find_circles(threshold = 3500, x_margin = 10, y_margin = 10, r_margin = 10,
r_min = 2, r_max = 100, r_step = 2):
area = (c.x()-c.r(), c.y()-c.r(), 2*c.r(), 2*c.r())
#area为识别到的圆的区域,即圆的外接矩形框
statistics = img.get_statistics(roi=area)#像素颜色统计
print(statistics)
#(0,100,0,120,0,120)是红色的阈值,所以当区域内的众数(也就是最多的颜色),范围在这个阈值内,就说明是红色的圆。
#l_mode(),a_mode(),b_mode()是L通道,A通道,B通道的众数。(27, 72, 1, 127, 8, 127)
if 27<statistics.l_mode()<72 and 1<statistics.a_mode()<127 and 8<statistics.b_mode()<127:#if the circle is red
img.draw_circle(c.x(), c.y(), c.r(), color = (255, 0, 0))#识别到的红色圆形用红色的圆框出来
else:
img.draw_rectangle(area, color = (255, 255, 255))
#将非红色的圆用白色的矩形框出来
lcd.display(img)