目录
一、初始配置
(1)摄像头配置
#常用头文件
import sensor, image, time, ustruct
from pyb import LED, Timer
from pyb import Pin #补光灯需要
import math, json
#传感器配置
#对比度和增益在低光场合使用
sensor.set_contrast(1) #设置图像传感器的对比度:最大值1
sensor.set_gainceiling(16) #设置图像传感器的增益上限:16
#传感器配置
sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.GRAYSCALE)#设置图像色彩格式,有RGB565色彩图和GRAYSCALE灰度图两种
sensor.set_framesize(sensor.QQVGA)# QQ:120*160,Q最大240x320,QQQ最小60x80
sensor.skip_frames(time=2000) # 跳过10帧,使新设置生效
sensor.set_auto_whitebal(False) # 关闭自动白平衡功能(颜色识别需用)
sensor.set_auto_gain(False) # 关闭图像传感器的自动增益(颜色识别需用)
#sensor.set_vflip(True)#垂直翻转
#sensor.set_hmirror(True)#水平翻转
clock = time.clock() #创建定时对象clock
while(True):
clock.tick() # 计算帧率
img =sensor.其他初始函数.lens_corr(1.8) #畸变矫正(形状识别需要,但会吃运行内存)
(2)LED初始化
import time, pyb
from pyb import LED, Timer
from pyb import Pin #补光灯需要
#补光灯
light = Timer(2, freq=50000).channel(1, Timer.PWM, pin=Pin("P6"))
light.pulse_width_percent(5) # 控制亮度 0~100
#单灯定义与使用
led = pyb.LED(3) #Red(红)LED = 1,Green(绿)LED = 2,Blue(蓝)LED = 3,IR LEDs = 4.
led.toggle() #LED闪烁
led.on() #LED亮
led.off() #LED灭
#————————————————————————————————————其他花操作————————————————————————————————————
usb = pyb.USB_VCP() #串口通信
while(not usb.isconnected()):#如果没有连接电脑,则执行以下操作
led.on()
time.sleep_ms(150) #延时150ms
while(usb.isconnected()): #如果连接上电脑,则执行
led.on()
(3)绘制框选
img = sensor.snapshot() #获取图片
img.draw_line((80, 50, 100, 100), color=(255,0,0)) #画一条红色线
img.draw_rectangle((20, 30, 41, 51), color=(255,0,0)) #画一个红色矩形
img.draw_circle(50, 50, 30) #画一个圆
img.draw_cross(90,60,size=10) #画一个十字线
(4)串口初始化+发送+接收
import time
from pyb import UART
import ustruct
import json
uart = UART(3,115200) #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
#——————————————————————————————发送数据(方法一):包括浮点数——————————————————————————
def sending_data(find_shizi,output):
global uart
# 转换output为4字节的二进制形式
output_bytes = struct.pack('f', output)
# 构建数据包
data_send = bytearray([0xA5, 0xA6, find_shizi]) + output_bytes + bytearray([0xFF])
uart.write(data_send); #必须要传入一个字节数组
#————————————————————————————————————发送数据(方法二)————————————————————————————————
#串口发送函数
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)
#——————————————————————————————————————串口接收——————————————————————————————————
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
二、图像处理部分
(1)畸变矫正
解释:在二维码/条形码/矩形码检测时需要使用此方法,使用畸变矫正方法来修复图像失真问题
# zoom是在对图像进行缩放的数值。默认值为1。
while(True):
img = sensor.snapshot().lens_corr(strength = 1.7, zoom = 1.0)
(2)设置图像和lcd方向
解释:翻转与镜像;
sensor.vflip(True) #垂直翻转
sensor.hmirror(True) #水平镜像
(3)图像二值化
解释:这个脚本展示了二值图像滤波,可以传递二进制任意的阈值来分割图像;
#设置颜色阈值,如果是rgb图像,六个数字分别为(minL, maxL, minA, maxA, minB, maxB);
#如果是灰度图,则只需设置(min, max)两个数字即可。
red_threshold = (0, 40, 18, 127, -128, 127) # L A B阈值
#使用工具 - >机器视觉 - >阈值编辑器选择更好的阈值。
while(True):
clock.tick()
img = sensor.snapshot()
img.binary([red_threshold])
(4)图像滤波
①边缘检测
解释:这个程序示范了在图像上使用morph函数来进行边缘检测;
import sensor, image, time
#设置核函数滤波,核内每个数值值域为[-128,127],核需为列表或元组
kernel_size = 1 # kernel width = (size*2)+1, kernel height = (size*2)+1
kernel = [-1, -1, -1,\
-1, +8, -1,\
-1, -1, -1]
thresholds = [(100, 255)] # 设置阈值
# 在OV7725 sensor上, 边缘检测可以通过设置sharpness/edge寄存器来增强。
# 注意:这将在以后作为一个函数实现
if (sensor.get_id() == sensor.OV7725):
sensor.__write_reg(0xAC, 0xDF)
sensor.__write_reg(0x8F, 0xFF)
while(True):
img = sensor.snapshot() # 拍一张照片,返回图像
img.morph(kernel_size, kernel)
#morph(size, kernel, mul=Auto, add=0),morph变换,mul根据图像对比度
#进行调整,mul使图像每个像素乘mul;add根据明暗度调整,使得每个像素值加上add值。
#如果不设置则不对morph变换后的图像进行处理。
img.binary(thresholds)#利用binary函数对图像进行分割
img.erode(1, threshold = 2)# 腐蚀像素小于2邻居使用3x3图像内核
#侵蚀函数erode(size, threshold=Auto),去除边缘相邻处多余的点。threshold
#用来设置去除相邻点的个数,threshold数值越大,被侵蚀掉的边缘点越多,边缘旁边
#白色杂点少;数值越小,被侵蚀掉的边缘点越少,边缘旁边的白色杂点越多。
②彩图“光线除去”
解释:此示例显示如何从图像中删除明亮的灯光,您可以使用带有“zero =”参数的binary()方法执行此操作。从图像中删除明亮的光线允许您在图像上使用histeq(), 而不会使图像的过饱和部分的异常值破坏算法;
import sensor, image, time
thresholds = (90, 100, -128, 127, -128, 127)
while(True):
img = sensor.snapshot().binary([thresholds], invert=False, zero=True)
③核滤波
解释:核可以用于图像处理中的边缘检测,它会突出图像中的边缘
import sensor, image, time
kernel_size = 1 # 3x3==1, 5x5==2, 7x7==3, etc.
kernel = [-2, -1, 0, \
-1, 1, 1, \
0, 1, 2]
while(True):
img = sensor.snapshot() # 拍一张照片,返回图像
img.morph(kernel_size, kernel)# 在图像的每个像素上运行核
④环境对比度自适应
解释:此示例展示了如何使用自适应直方图均衡来改善图像中的对比度。自适应直方图均衡将图像分割成区域,然后均衡这些区域中的直方图,以改善图像对比度与全局直方图均衡化。此外,您可以指定剪辑限制以防止对比度变得狂野。
import sensor, image, time
while(True):
# clip_limit <0为您提供正常的自适应直方图均衡,这可能会导致大量的对比噪音...
# clip_limit=1 什么都不做。为获得最佳效果,请略高于1,如下所示。
# 越高,越接近标准自适应直方图均衡,并产生巨大的对比度波动。
img = sensor.snapshot().histeq(adaptive=True, clip_limit=3)#通过改变clip_limit的值来改变对比度的自适应效果
#img = sensor.snapshot().histeq()
⑤模糊滤波
解释:用于对图像进行平滑处理,去除图像中的噪声或细节;
import sensor, image, time
while(True):
img = sensor.snapshot() # 拍一张照片,返回图像
img.gaussian(1) #值越大,滤波效果越明显,图像越模糊
三、模板匹配
import pyb, sensor, image, math, time
from image import SEARCH_EX, SEARCH_DS
template1 = image.Image("/0.pgm")
while(True):
clock.tick()
img = sensor.snapshot()
r1=0
r1 = img.find_template(template1, 0.70, step=4, search=SEARCH_EX) #, roi=(10, 0, 60, 60))
if r1:
img.draw_rectangle(r1)
print(r1)
uart.write("0")
#—————————————————————————————多模板匹配(危)—————————————————————————————————————————
# 这个例子展示了如何使用OpenMV凸轮的NCC功能将小部分图像与图像的各个部分
# 进行匹配...期望获得极其可控的环境NCC并不是全部有用的。
import time, sensor, image
from image import SEARCH_EX, SEARCH_DS
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
templates = ["/0.pgm", "/1.pgm", "/2.pgm", "/6.pgm"] #保存多个模板
#加载模板图片
clock = time.clock()
# Run template matching
while (True):
clock.tick()
img = sensor.snapshot()
#多模板匹配
for t in templates:
template = image.Image(t)
#对每个模板遍历进行模板匹配
r = img.find_template(template, 0.70,roi=(10,15,70,40) ,step=4 ,search=SEARCH_EX) #, roi=(10, 0, 60, 60))
if r != None: #模板识别
find_biaozhi=1
print(find_biaozhi)
img.draw_rectangle(r, color=220)
else:
find_biaozhi=0
四、色块追踪
red = (xxx,xxx,xxx,xxx,xxx,xxx)
blue = (xxx,xxx,xxx,xxx,xxx,xxx)
yellow = (xxx,xxx,xxx,xxx,xxx,xxx)
img=sensor.snapshot()
red_blobs = img.find_blobs([red])
color_blobs = img.find_blobs([red,blue, yellow]) #多颜色寻找
(1)色块追踪
import sensor, image, time,math,pyb
from pyb import UART,LED
import json
import ustruct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_whitebal(False) # 自动白平衡功能(颜色识别需用)
sensor.set_auto_gain(False) # 关闭图像传感器的自动增益(颜色识别需用)
clock = time.clock()
red_threshold=(63, 91, -67, -23, 40, 78) #目标颜色阈值
uart = UART(3,115200) #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
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
cx=0
cy=0
w=0
h=0
s=0
while(1):
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold])
if blobs: #如果找到了目标颜色
max_b = find_max(blobs)
w=max_b[1]
h=max_b[2]
cx=max_b[5]
cy=max_b[6]
s=w*h
img.draw_rectangle(max_b[0:4]) # 框选色块
img.draw_cross(max_b[5], max_b[6]) # 色块的中心坐标
FH = bytearray([0x2C,0x12,cx,cy,s,0x5B])
uart.write(FH)
(2)色块追踪(另一种方式)
import sensor, image, time
red_threshold_01 = (40, 52, 40, 50, 0, 50) #阈值
# 初始化设置
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
sensor.set_auto_whitebal(False) # 自动白平衡功能(颜色识别需用)
sensor.set_auto_gain(False) # 关闭图像传感器的自动增益(颜色识别需用)
clock = time.clock()
#变量定义
last_blobs = None # 初始化last_blobs
#色块追踪(改进版)封装代码
def color_detection(img, threshold, last_blobs=None, roi_offset=7, roi_extend=12, area_threshold=1000):
if last_blobs:
for b in last_blobs:
x1 = b[0] - roi_offset
y1 = b[1] - roi_offset
w1 = b[2] + roi_extend
h1 = b[3] + roi_extend
roi2 = (x1, y1, w1, h1)
blobs = img.find_blobs([threshold], roi=roi2, area_threshold=area_threshold)
else:
blobs = img.find_blobs([threshold], area_threshold=area_threshold)
if blobs:
for b in blobs:
img.draw_rectangle(b[0:4])
img.draw_cross(b[5], b[6]) # 绘制色块中心点的十字标记
print("色块中心坐标:", b[5], b[6]) # 打印色块中心点的x、y坐标
return blobs
while True:
clock.tick()
img = sensor.snapshot()
# 调用改进的颜色检测函数
blobs = color_detection(img, red_threshold_01, last_blobs)
last_blobs = blobs # 更新last_blobs
#print("帧率:", clock.fps())
(3)双色跟踪
import sensor, image, time, math, pyb
from pyb import UART, LED
import json
import ustruct
# 在颜色识别中需要关闭“白平衡”和“自动增益”
sensor.set_auto_whitebal(False)
sensor.set_auto_gain(False)
# 设置两种颜色的阈值
red_threshold = (63, 91, -67, -23, 40, 78)
green_threshold = (your_green_threshold_values)
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
def find_max(blobs):
max_size = 0
max_blob = None
for blob in blobs:
if blob.pixels() > max_size:
max_blob = blob
max_size = blob.pixels()
return max_blob
while True:
img = sensor.snapshot()
# 找到红色色块
red_blobs = img.find_blobs([red_threshold])
if red_blobs:
max_red_blob = find_max(red_blobs)
red_w = max_red_blob[1]
red_h = max_red_blob[2]
red_cx = max_red_blob[5]
red_cy = max_red_blob[6]
red_s = red_w * red_h
img.draw_rectangle(max_red_blob[0:4]) # 框选红色色块
img.draw_cross(max_red_blob[5], max_red_blob[6]) # 红色色块的中心坐标
sending_data(red_cx, red_cy, red_s)
# 找到绿色色块
green_blobs = img.find_blobs([green_threshold])
if green_blobs:
max_green_blob = find_max(green_blobs)
green_w = max_green_blob[1]
green_h = max_green_blob[2]
green_cx = max_green_blob[5]
green_cy = max_green_blob[6]
green_s = green_w * green_h
img.draw_rectangle(max_green_blob[0:4]) # 框选绿色色块
img.draw_cross(max_green_blob[5], max_green_blob[6]) # 绿色色块的中心坐标
sending_data(green_cx, green_cy, green_s)
五、舵机控制追踪物体
需要用上:PID
import sensor, image, time
from pid import PID
from pyb import Servo
pan_servo=Servo(1)
tilt_servo=Servo(2)
pan_servo.calibration(500,2500,500)
tilt_servo.calibration(500,2500,500)
red_threshold = (13, 49, 18, 61, 6, 47)
#pan_pid = PID(p=0.07, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
#tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
pan_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
tilt_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.
#筛选出最大的色块
def find_max(blobs):
max_size=0
for blob in blobs:
if blob[2]*blob[3] > max_size:
max_blob=blob
max_size = blob[2]*blob[3]
return max_blob
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
blobs = img.find_blobs([red_threshold])
if blobs:
max_blob = find_max(blobs)
pan_error = max_blob.cx()-img.width()/2
tilt_error = max_blob.cy()-img.height()/2
print("pan_error: ", pan_error)
img.draw_rectangle(max_blob.rect()) # rect
img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy
pan_output=pan_pid.get_pid(pan_error,1)/2
tilt_output=tilt_pid.get_pid(tilt_error,1)
print("pan_output",pan_output)
#控制舵机
pan_servo.angle(pan_servo.angle()+pan_output) #水平移动
tilt_servo.angle(tilt_servo.angle()-tilt_output) #垂直移动
(2)双色红绿舵机
import sensor, image, time
from pid import PID
from pyb import Servo
pan_servo = Servo(1)
tilt_servo = Servo(2)
pan_servo.calibration(500, 2500, 500)
tilt_servo.calibration(500, 2500, 500)
red_threshold = (13, 49, 18, 61, 6, 47)
green_threshold = (37, 100, -64, -25, -17, 38)
pan_pid = PID(p=0.1, i=0, imax=90)
tilt_pid = PID(p=0.1, i=0, imax=90)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(10)
sensor.set_auto_whitebal(False)
clock = time.clock()
# 筛选出最大的色块
def find_max(blobs):
max_size = 0
for blob in blobs:
if blob[2] * blob[3] > max_size:
max_blob = blob
max_size = blob[2] * blob[3]
return max_blob
while True:
clock.tick()
img = sensor.snapshot()
# 分别找到红色和绿色色块
red_blobs = img.find_blobs([red_threshold])
green_blobs = img.find_blobs([green_threshold])
# 选择要追踪的物体,比如选择红色物体
if red_blobs:
max_blob = find_max(red_blobs)
elif green_blobs:
max_blob = find_max(green_blobs)
else:
max_blob = None
if max_blob:
pan_error = max_blob.cx() - img.width() / 2
tilt_error = max_blob.cy() - img.height() / 2
print("pan_error: ", pan_error)
img.draw_rectangle(max_blob.rect())
img.draw_cross(max_blob.cx(), max_blob.cy())
pan_output = pan_pid.get_pid(pan_error, 1) / 2
tilt_output = tilt_pid.get_pid(tilt_error, 1)
# 控制舵机
pan_servo.angle(pan_servo.angle() + pan_output)
tilt_servo.angle(tilt_servo.angle() - tilt_output)
六、线性循迹
(1)巡线--彩图转黑白
THRESHOLD = (0, 40, -128, 11, -6, 46) # 设置阈值
threshold = 100
import sensor, image, time
from pyb import LED
from pid import PID
from image import SEARCH_EX, SEARCH_DS #模板识别
#如果要制作巡线小车的话,只需利用本程序得到的line对象的theta返回值和rho,
#theta代表返回线段的角度, rho代表偏移的距离),利用theta和rho来控制小车角度即可。
#rho更重要一些,如果不用theta,只用rho也是可以的。
rho_pid = PID(p=0.4, i=0) #rho代表偏移的距离
theta_pid = PID(p=0.001, i=0) #theta代表返回线段的角度:小车可以利用直线返回的角度控制移动
#通过角度偏移对左右两边的电机进行速度的控制
sensor.set_pixformat(sensor.RGB565)
while(True):
img = sensor.snapshot().binary([THRESHOLD])# 获取图像的快照,并将其二值化处理,根据之前定义的阈值将图像转换为二值图像
#巡线
line = img.get_regression([(100,100)], robust = True)#在二值图像中检测线条
if (line): #get_regression函数返回一个线条对象,包含了线条的信息,如位置、角度和长度
rho_err = abs(line.rho())-img.width()/2 #计算线条距离图像中心的偏差
if line.theta()>90: #检查线条的角度是否大于90度。
theta_err = line.theta()-180 #将角度限制在-90度到90度的范围内
else:
theta_err = line.theta() #将线条的角度赋值给theta_err变量
img.draw_line(line.line(),color = 127) #在图像上绘制检测到的线条(蓝线)
print(rho_err,line.magnitude(),rho_err) #打印线条距离中心的偏差值,线条的长度,距离中心的偏差值
if line.magnitude()>8: #检查线条的长度是否大于8
rho_output = rho_pid.get_pid(rho_err,1) #使用PID控制器,计算线条距离中心的偏差的输出值
theta_output = theta_pid.get_pid(theta_err,1) #使用PID控制器,计算角度偏差的输出值
output = rho_output+theta_output #将线条距离中心的偏差输出值和角度偏差输出值相加,得到最终的输出值
print(output)
(2)快速线性回归--灰度转黑白(可与模板匹配一起用)
解释:这被称为快速线性回归,因为我们使用最小二乘法来拟合线。然而,这种方法对于任何具有很多(或者甚至是任何)异常点的图像都是不好的,这会破坏线条拟合.
GRAYSCALE_THRESHOLD = (0, 40, -128, 11, -6, 46)#设置阈值,(0,100)检测黑色线
BINARY_VISIBLE = True # 首先执行二进制操作,以便您可以看到正在运行的线性回归...虽然可能会降低FPS。
import sensor, image, time
from pyb import UART
import struct
def sending_data(x1,y1,x2,y2):
data =struct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
0x2C, #帧头1
0x12, #帧头2
int(x1), # up sample by 4 #数据1,低位在前
int(y1), # up sample by 4 #数据2
int(x2),
int(y2),
)
uart.write(data); #必须要传入一个字节数组
print(data)
sensor.set_pixformat(sensor.GRAYSCALE) #(重要)让图像一开始就是灰度的
#其他配置
uart = UART(3, 115200)
while(True):
img = sensor.snapshot().histeq()
img.mean(2)#进行平均滤波
img.binary([GRAYSCALE_THRESHOLD])#对图像进行黑白分割
img.erode(1)
# 函数返回回归后的线段对象line,有x1(), y1(), x2(), y2(), length(), theta(), rho(), magnitude()参数。
# x1 y1 x2 y2分别代表线段的两个顶点坐标,length是线段长度,theta是线段的角度。
# magnitude表示线性回归的效果,(0,+∞)范围内,其中0代表一个圆。越好值越大。
line = img.get_regression([(255,255) if BINARY_VISIBLE else THRESHOLD])
if (line):
img.draw_line(line.line(), color = 255)
sending_data(line.x1(),line.y1(),line.x2(),line.y2())
print("x1 = %d, y1 = %d, x2 = %d, y2 = %d" % (line.x1(), line.y1(), line.x2(), line.y2() if (line) else "N/A"))
#利用顶点坐标循迹
# 关于负rho值:
# A [theta+0:-rho]元组与[theta+180:+rho]相同
七、测距
import sensor, image, time
#画面动他就检测
red_threshold = (0, 15, -40, 0, 0, 40)
#yellow_threshold = ( 56, 83, 5, 57, 63, 80)
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # 关闭白平衡(因为是色块识别)
clock = time.clock() # Tracks FPS.
K=5000 #需要测量后重新定义
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]) #使用矩形的坐标绘制一个矩形框在图像上
img.draw_cross(b[5], b[6]) #绘制一个十字形在图像上
Lm = (b[2]+b[3])/2
length = K/Lm
print(length) #距离 = 一个常数 / 直径的像素(小球)
八、形状识别
(1)综合矩形+圆形识别
import sensor, image, time
# 初始化相机设置
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time=2000)
sensor.set_auto_gain(False)
sensor.set_auto_whitebal(False)
clock = time.clock()
while True:
clock.tick()
#lens_corr(1.8)畸变矫正
img = sensor.snapshot()
# 寻找圆形
for c in img.find_circles(threshold=3500, x_margin=20, y_margin=20, r_margin=20, r_min=2, r_max=100):
img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 0)) # 画圆
print("圆形:x={}, y={}, r={}".format(c.x(), c.y(), c.r()))
# 寻找矩形
for r in img.find_rects(threshold=35000): # 降低阈值,提高矩形的检测敏感性
img.draw_rectangle(r.rect(), color=(0, 255, 0)) # 画矩形
print("矩形:x={}, y={}, w={}, h={}".format(r.x(), r.y(), r.w(), r.h()))
print("FPS: ", clock.fps())
(2)识别特定大小的矩形
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time=2000)
sensor.set_auto_gain(False)
sensor.set_auto_whitebal(False)
clock = time.clock()
endbox_num=0
while(True):
img = sensor.snapshot()
# 下面的`threshold应设置为足够高的值,以滤除在图像中检测到的具有低边缘幅度的噪声矩形
# 最适用与背景形成鲜明对比的矩形。
for r in img.find_rects(threshold = 10000):
endbox_size = r.magnitude()
if (endbox_size<24000 and r.h()<25 and r.w()<25) :
endbox_num = endbox_num + 1
img.draw_rectangle(r.rect(), color = (255, 0, 0))
print(r.x())
print(endbox_num)
九、混合项目
(1)颜色形状同时识别
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot().lens_corr(1.8)
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通道的众数。
if 0<statistics.l_mode()<100 and 0<statistics.a_mode()<127 and 0<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))
#将非红色的圆用白色的矩形框出来
(2)颜色与模板匹配同时识别
# 多颜色多模板匹配示例
import sensor, image, time
from image import SEARCH_EX, SEARCH_DS
# 颜色跟踪阈值(L Min, L Max, A Min, A Max, B Min, B Max)
# 下面的阈值跟踪一般红色/绿色的东西。你不妨调整他们...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds
(30, 100, -64, -8, -32, 32), # generic_green_thresholds
(0, 15, 0, 40, -80, -20)] # generic_blue_thresholds
# 不要超过16个颜色阈值
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()
templates = ["/0.pgm", "/1.pgm", "/2.pgm", "/6.pgm"] #保存多个模板
while(True):
clock.tick()
img = sensor.snapshot()
for blob in img.find_blobs(thresholds, pixels_threshold=200, area_threshold=200):
#img.draw_rectangle(blob.rect())
#img.draw_cross(blob.cx(), blob.cy())
#print(blob.code())
img = img.to_grayscale()
for t in templates:
template = image.Image(t)
#对每个模板遍历进行模板匹配
r = img.find_template(template, 0.70, step=4, search=SEARCH_EX) #, roi=(10, 0, 60, 60))
#find_template(template, threshold, [roi, step, search]),threshold中
#的0.7是相似度阈值,roi是进行匹配的区域(左上顶点为(10,0),长80宽60的矩形),
#注意roi的大小要比模板图片大,比frambuffer小。
#把匹配到的图像标记出来
if r:
img.draw_rectangle(r, color=0)
print(blob.code(), t) #打印模板名字
#如果为红色, blob.code()==1; 如果为绿色, blob.code==2.
#如果为数字0, t=="0.pgm"; 如果为数字1, t=="1.pgm".