前言
OpenMV是嵌入式图像处理,其摄像头是一款小巧,低功耗,低成本的电路板,它帮助轻松的完成机器视觉(machine vision)应用。
可以通过高级语言Python脚本(准确的说是 MicroPython ),而不是C/C++。Python的高级数据结构使你很容易在机器视觉算法中处理复杂的输出。但是,你仍然可以完全控制OpenMV,包括IO引脚。
可以很容易的使用外部终端触发拍摄或者或者执行算法,也可以把算法的结果用来控制IO引脚。
简单的来说,OpenMV是一个可编程的摄像头,通过MicroPython语言,可以实现逻辑。而且摄像头本身内置了一些图像处理算法,很容易使用。那么后期就可以使用OpenMV做一些计算机机器视觉的好玩项目了。
星瞳科技是OpenMV中国官方代理,还做了好多中文视频,特别适合我这种小白。bilibili观看地址:https://space.bilibili.com/22215525/#/
色块监测 例子如下,也太贴心了,每行都有注释。
# 色块监测 例子
#
# 这个例子展示了如何通过find_blobs()函数来查找图像中的色块
# 这个例子查找的颜色是深绿色
import sensor, image, time
# 颜色追踪的例子,一定要控制环境的光,保持光线是稳定的。
green_threshold = ( 0, 80, -70, -10, -0, 30)
#设置绿色的阈值,括号里面的数值分别是L A B 的最大值和最小值(minL, maxL, minA,
# maxA, minB, maxB),LAB的值在图像左侧三个坐标图中选取。如果是灰度图,则只需
#设置(min, max)两个数字即可。
sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 格式为 RGB565.
sensor.set_framesize(sensor.QQVGA) # 使用 QQVGA 速度快一些
sensor.skip_frames(time = 2000) # 跳过2000s,使新设置生效,并自动调节白平衡
sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的,在颜色识别中,一定要关闭白平衡。
sensor.set_auto_whitebal(False)
#关闭白平衡。白平衡是默认开启的,在颜色识别中,一定要关闭白平衡。
clock = time.clock() # 追踪帧率
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # 从感光芯片获得一张图像
blobs = img.find_blobs([green_threshold])
#find_blobs(thresholds, invert=False, roi=Auto),thresholds为颜色阈值,
#是一个元组,需要用括号[ ]括起来。invert=1,反转颜色阈值,invert=False默认
#不反转。roi设置颜色识别的视野区域,roi是一个元组, roi = (x, y, w, h),代表
#从左上顶点(x,y)开始的宽为w高为h的矩形区域,roi不设置的话默认为整个图像视野。
#这个函数返回一个列表,[0]代表识别到的目标颜色区域左上顶点的x坐标,[1]代表
#左上顶点y坐标,[2]代表目标区域的宽,[3]代表目标区域的高,[4]代表目标
#区域像素点的个数,[5]代表目标区域的中心点x坐标,[6]代表目标区域中心点y坐标,
#[7]代表目标颜色区域的旋转角度(是弧度值,浮点型,列表其他元素是整型),
#[8]代表与此目标区域交叉的目标个数,[9]代表颜色的编号(它可以用来分辨这个
#区域是用哪个颜色阈值threshold识别出来的)。
if blobs:
#如果找到了目标颜色
for b in blobs:
#迭代找到的目标颜色区域
# Draw a rect around the blob.
img.draw_rectangle(b[0:4]) # rect
#用矩形标记出目标颜色区域
img.draw_cross(b[5], b[6]) # cx, cy
#在目标颜色区域的中心画十字形标记
print(clock.fps()) # 注意: 你的OpenMV连到电脑后帧率大概为原来的一半
#如果断开电脑,帧率会增加
电源
OpenMV有两个电源输入端:VIN(有时也会标识为VCC)和USB输入。
VIN输入为3.6V~5V,推荐5V。
USB和VIN可以同时供电。
OpenMV有一个电源输出端:3.3V,这个电压是OpenMV的稳压器输出的,用于给其他传感器供电。
注意:不要给3.3V直接供电,没有内部芯片的保护,很容易烧毁。
SD卡
如果代码太多,flash装不下,就可以使用SD卡,这个是OpenMv自带的,SD卡也是一个文件系统,当上电的时候,如果插入SD卡,那么SD卡的文件系统就会自动取代内置的Flash文件系统,每次上电,就会运行SD卡中的main.py。SD卡最大支持32G的容量。
图像处理背景
感光元件
从物理学和数学我们都接触过小孔成像,这是一种理想的相机模型,图像透过镜头,照在一个感光芯片上,感光芯片可以把光照的波长和强度等信息转成计算机(数字电路)可以识别的数字信号。
感光元件如下,摄像头用螺丝固定在感光元件正上方就好,如果感光元件上面有灰尘什么的就用棉签擦一下。
像素
感光元件是有很多个感光点构成的,比如有640*480个点,每个点就是一个像素。
分辨率
把每个点的像素收集整理起来,就是一副图片,那么这张图片的分辨率就是640*480。
帧率
每秒钟处理的图片数量。
颜色
不同波长的电磁波。
LAB亮度-对比度
这个是在查找指定颜色模块时要用的,a的正数代表红色,负端代表绿色;b的正数代表黄色,负端代表蓝色。
Python
这个是此板块必学的,这里再回顾一下常用语法吧,把自己不熟练的地方也总结了一下。
使用好处
OpenMV可以使用Python来进行二次开发。有几个好处:
1.上手简单。
2.不用考虑内存的申请和释放。
3.有很多MicroPython库可以直接用(并不兼容PC上的Python模块)。
4.开发团队开发了OpenMV的各种算法和模块可供调用。
REPL和串口
OpenMV的IDE自带一个串口助手,用于连接OpenMV,也可以连接其他的串口,比如Arduino,pyboard,esp8266。这个串口可以直接从IDE到达,然后就可以到达终端了。
从这里进入
选择连接serial port
到达终端
语法
print()函数
print()函数也可以接受多个字符串,用逗号“,”隔开,就可以连成一串输出,但是print()会依次打印每个字符串,遇到逗号“,”会输出一个空格。
print()可以打印整数,也可以直接计算结果。
print(100 + 200)
或者
print('100 + 200 =', 100 + 200)
输出
100 + 200 = 300
其中的’100 + 200 ='是字符串而非数学公式,是Python解释器自动计算出的。
变量
如下,就是将静态语言赋值给动态语言。
a = 'ABC' # a变为字符串
注:静态语言在定义变量时必须指定变量类型。
list列表
list是一种数据结构,一种有序的集合,可以随时添加和删除其中的元素。
1.获取元素个数
以下的变量classmates就是一个list。用len()函数可以获得list元素的个数为三,那如果一个list中一个元素也没有,就是一个空的list,它的长度为0。
classmates = ['Michael', 'Bob', 'Tracy']
len(classmates)
2.索引访问
可以用索引来访问list中每一个位置的元素,但是要记得索引是从0开始的,要确保索引不要越界。
索引还可以倒着写,比如最后一个元素:classmates[-1],以此类推。那classmates[-2]就是倒数第二个元素。
3.插入
把元素插入到指定的位置
classmates.insert(1, 'Jack')
4.删除
删除list末尾的元素
classmates.pop()
5.替换
classmates[1] = 'Sarah'
6.数据类型
list里面的元素的数据类型也可以不同的哦。
tuple元组
这也是一种有序列表。
注:tuple一旦初始化就不能修改,就是不能赋值,替换什么的了。
也就是说,当定义一个tuple的时候,tuple的元素就必须被确定下来。如果只有1个元素的tuple定义时必须加一个逗号,,来消除是数学意义上小括号的歧义。
t = (1,)
条件判断
这里有用到elif,直接进行下一个条件判断,并且不用加分号。
切记加冒号。
if语句的完整形式是:
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
循环
1.for x in 循环
就是把每个元素代入变量x,然后执行缩进块的语句。
range(101)就可以生成0-100的整数序列,计算如下:
sum = 0
for x in range(101):
sum = sum + x
print(sum)
2.while循环
这个是C语言里面也接触过的,但是这里运用可以不加分号。
数据类型转换
比如int()函数可以把其他数据类型转换为整数,float-小数(浮点数),double-极大或极小的浮点数,char-字符型。
定义函数
def power(x):#函数名,参数
return x * x#一定要缩进,函数体
注:定义的函数体一定要缩进。
在power(x)函数中,参数x就是一个位置参数。若像power(x, n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数x和n。
切片
如L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。如果第一个索引是0,还可以省略:L[:3]。
注:tuple和list切片后数据类型不变。
'ABCDEFG'[:3]
'ABC'#还是字符不变