此示例展示了如何使用自适应直方图均衡来改善图像中的对比度。
自适应直方图均衡将图像分割成区域,然后均衡这些区域中的直方图,以改善图像对比度与全局直方图均衡化。 还可以指定剪辑限制以防止对比度变得狂野。
clip_limit <0提供正常的自适应直方图均衡,这可能会导致大量的对比噪音。
clip_limit=1 什么都不做。
为获得最佳效果,clip_limit应略高于1,越高,越接近标准自适应直方图均衡,并产生巨大的对比度波动。
如:img = sensor.snapshot().histeq(adaptive=True, clip_limit=3)
效果如下,感觉和素描加油画一个感觉。
如:img.morph(kernel_size, kernel)
卡通化滤波通过连接图像的相似像素区域并用区域平均值替换这些区域中的像素来工作。
到这里感觉还是蛮好玩的,想起来最近很火的编程作画。
简单的说,就是让区域中的颜色变平来去除图像中的纹理。
注:seed_threshold控制着色区域的最大区域增长。 将其放大会合并更多像素。
floating_threshold控制增长区域时的最大像素到像素的差异。设置高的值将快速组合图像中的所有像素。应该使其小一些。
cartoon() 将增长同时两个限制都满足的区域。
如:img = sensor.snapshot().cartoon(seed_threshold=0.05, floating_thresholds=0.05)
双边滤波器使图像平滑,同时保持图像中的边缘。
如:每一个图片都运行,彩图双边滤波
img.bilateral(3, color_sigma=0.1, space_sigma=1)
在灰度图像上使用双边滤波同理,使图像平滑,同时保持图像中的边缘。修改sensor.set_pixformat(sensor.GRAYSCALE)即可。
说白了就是从图像中删除明亮的灯光。
如:i**mg = sensor.snapshot().binary([thresholds], invert=False, zero=True)**此函数将在thresholds内的图像部分的全部像素变为1白,将在阈值外的部分全部像素变为0黑。invert将图像的0 1(黑 白)进行反转,默认为false不反转。
若invert=1,将黑白反转。
使用带有“zero =”参数的binary()方法执行此操作。从图像中删除明亮的光线允许您在图像上使用histeq(),而不会使图像的过饱和部分的异常值破坏算法。
灰度图双边滤波从图像中删除明亮的灯光同理,修改sensor.set_pixformat(sensor.GRAYSCALE)即可。
高级帧间差分,看起来就是背景图片会实时更新。有点像相机里面的叠影。需要建立temp和bg两个文件夹分别储存图片。(摄像头要一直移动)
如: img.difference(“temp/bg.bmp”)
之所以叫做简单的帧间查分,是因为背景图片没有更新。所以,随着时间的推移,背景图片可能会改变,导致问题。
利用颜色特征对图像进行分割,传递二进制任意的阈值来分割图像。
设置颜色阈值,如果是rgb图像,六个数字分别为(minL, maxL, minA, maxA, minB, maxB);
如果是灰度图,则只需设置(min, max)两个数字即可。
注:使用工具 - >机器视觉 - >阈值编辑器选择更好的阈值。
简单来说,就是从原图->白invert = False->黑invert = 1
如:img.laplacian(1) 在图像的每个像素上运行内核
运行图如下:
关闭伽玛校正以使图像更亮。伽马校正方法也可以固定对比度和亮度。
伽玛,对比度和亮度校正应用于每个颜色通道。这些值按比例缩放到每个图像类型的每个颜色通道的范围。
image.gamma_corr([gamma=1.0, [contrast=1.0, [brightness=0.0])
快速改变图像的伽马、对比度和亮度。请用这个方法代替 image.mul 或 image.div 用于混合以调整像素值。
gamma 值(伽马),是数码图像中的每个像素都有的光亮程度,如果大于1.0,那么图像以非线性方式变暗;而小于1.0则使图像变亮。通过将所有像素的颜色通道缩放到[0:1)之间, 然后在缩小之前在所有像素上重新映射 pow(pixel, 1/gamma),将gamma值应用于图像。
contrast值大于1.0,则图像以线性方式变亮;值小于1.0则使图像变暗。通过将所有像素的颜色通道缩放到[0:1)之间, 然后在缩小之前对所有像素重新映射
pixel * contrast ,将对比度值应用于图像。
brightness值大于0.0将使图像以恒定的方式变亮,而小于0.0将使图像变暗。将所有像素的颜色通道缩放到[0:1)之间, 然后在缩小之前对所有像素重新映射
pixel + brightness ,将亮度值应用到图像上。
返回图像对象,因此可以使用.
符号调用另一个方法。
不支持压缩图像或bayer图像。
如:img = sensor.snapshot().gamma_corr(gamma = 0.5, contrast = 1.0, brightness = 0.0) #使图片变亮,下了两天雨,今天天气还可。
这个程序示范了在图像上使用morph函数来进行边缘检测。然后在进行阈值和滤波。
需要设置核函数滤波,核内每个数值值域为[-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]
这个一个高通滤波器。见这里有更多的kernel
http://www.fmwconcepts.com/imagemagick/digital_image_filtering.pdf
在OV7725 sensor上,边缘检测可以通过设置sharpness/edge寄存器来增强。这将在以后作为一个函数来实现。
if (sensor.get_id() == sensor.OV7725):
sensor.__write_reg(0xAC, 0xDF)
sensor.__write_reg(0x8F, 0xFF)
morph(size, kernel, mul=Auto, add=0)
morph变换,mul根据图像对比度进行调整,mul使图像每个像素乘mul;add根据明暗度调整,使得每个像素值加上add值。如果不设置则不对morph变换后的图像进行处理。
如:img.morph(kernel_size, kernel)
侵蚀函数erode(size, threshold=Auto)
去除边缘相邻处多余的点。threshold用来设置去除相邻点的个数,threshold数值越大,被侵蚀掉的边缘点越多,边缘旁边白色杂点少;数值越小,被侵蚀掉的边缘点越少,边缘旁边的白色杂点越多。
如:img.erode(1, threshold = 2)
此示例显示使用线性极坐标变换重新投影图像。 线性极化图像是有用的,因为旋转变为X方向上的平移,并且标度的线性变化变为Y方向上的线性平移。
如:img = sensor.snapshot().linpolar(reverse=False)
旋转成为X方向上的平移,并且刻度的指数变化(x2,x4等)变为Y方向上的线性平移。
边缘检测后原图:
erode函数腐蚀后,可以看出图像的边缘不再明显,被黑色覆盖:
dilate函数膨胀后,边缘变粗:
使用畸变矫正方法来修复图像失真问题。在二维码/条形码/矩形码检测时需要使用此方法。增加下面的strength直到直线在视图中。zoom是在对图像进行缩放的数值。默认值为1。如:img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)
传感器模块可以在图像读取期间执行一些基本的图像处理而无需额外的开销。
目的是对图像进行均值滤波,使图像达到模糊的效果(就是近视眼的感觉,啊巴拉巴拉),均值滤波是最快的滤波。
image.mean(size),
size为核的大小,size=1则是3x3的核,size=2则是5x5的核,不应该使用大于2的值。
如:均值滤波
img.mean(1)
当mean(threshold = True)时,mean()方法通过比较像素周围的像素的平均值减去偏移量来自适应阈值图像。
如:平均自适应阈值滤波
img.mean(1, threshold=True, offset=5, invert=True)
Size 是内核的大小。取1 (3x3 内核)、2 (5x5 内核)或更高值。
threshold=True 参数来启动图像的自适应阈值处理, 他根据环境像素的亮度(核函数周围的像素的亮度有关),将像素设置为1或者0。 负数 offset 值将更多像素设置为1,而正值仅将最强对比度设置为1。 设置 invert 以反转二进制图像的结果输出。
当median(threshold=True) 时, median()方法通过比较像素周围的像素的中值减去偏移量来自适应阈值图像。
如:img.median(1, percentile=0.5, threshold=True, offset=5, invert=True)
意思是内核为一,每个元素都是用原来的第五十个百分位数替换,启动图像的自适应阈值处理,将对比度设置为5,以反转二进制图像的结果输出。
中值滤波用其NxN邻域的中位数替换每个像素。中值滤波对于在保留边缘的同时去除图像中的噪声是很好的。
此时用 img.median(1, percentile=0.5)
中点滤波用NxN邻域的最小和最大像素值的平均值代替每个像素。
如:img.midpoint(1, bias=0.5)
意为内核大小取一,图像混合程度0.5
使用自适应阈值处理的中点滤波。 当midpoint(threshold=True) 时,midpoint()方法通过比较像素周围的像素的中值减去偏移量来自适应阈值图像。
原图:
运行效果图:
众数滤波是一种高度非线性的操作,它用每个像素周围像素的NxN邻# 域的众数取代每个像素。
避免在RGB565图像上使用众数过滤器。 它会在图像边缘造成伪影.
使用自适应阈值处理的众数滤波。 当mode(threshold=True) 时,mode()方法通过比较像素周围的像素的众数减去偏移量来自适应阈值图像。
使用rotation_corr()在图像上放大和缩小三维的视角旋转。
可以使用此功能来修复与OpenMV的安装相关的透视问题。
如:img = sensor.snapshot().rotation_corr(x_rotation = x_rotation_counter,
y_rotation = y_rotation_counter,
z_rotation = z_rotation_counter,
x_translation = X_OFFSET,
y_translation = Y_OFFSET,
zoom = ZOOM_AMOUNT)
运行效果如下:就是整张图片旋转起来的效果,就和小动画一样。
锐化的效果就是改变图像清晰度。
对每一个图像都起效果:
img.laplacian(1, sharpen=True)
使用guassian过滤器来消除锐化蒙版过滤器图像。
垂直翻转 - 水平镜像 - 转置图像
注意:
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
需要SD卡来运行此示例。可以使用OpenMV来保存修改的图像文件。
浮雕化图片:
img.morph(1, [+2, +1, +0, +1, +1, -1,+0, -1, -2])
保存:
img.save(“example.jpg”)
保存截取到的图片到SD卡
print("You're on camera!")
sensor.snapshot().save("example.jpg")
灯光闪烁就和照相机拍照的一样。
红灯灭,蓝灯亮
pyb.LED(RED_LED_PIN).off()
pyb.LED(BLUE_LED_PIN).on()
在OpenMV Cam上使用面部追踪来拍照。就是只有在识别出来人脸的时候,才会进行拍照,这个例程让我怀疑我的长相,只有在微微低头的时候才可以拍照成功。
加载人脸检测HaarCascade。 这是OpenMV Cam可以使用下面 **find_features()**方法来检测人脸的对象。 OpenMV具有HaarCascade内置的人脸模型。 默认情况下,HaarCascade的所有阶段都被加载。
但是,可以调整阶段的数量来加快处理速度,但要以准确性为代价。 HaarCascade的前面有25个阶段。
如:face_cascade = image.HaarCascade(“frontalface”, stages=25)
threshold是介于0.0-1.0的阈值,较低值会同时提高检出率和假阳性率。相反,较高值会同时降低检出率和假阳性率。
scale是一个必须大于1.0的浮点数。较高的比例因子运行更快,但其图像匹配相应较差。理想值介于1.35-1.5之间。
如:faces = img.find_features(face_cascade, threshold=0.5, scale_factor=1.5)
拍的照片如下:
拒绝打开
保存图片
sensor.snapshot().save("snapshot-%d.jpg" % pyb.rng())
使用OpenMV的帧差异来进行运动检测(锁定物体,保存对比图片bg)。运动检测后,OpenMV将拍摄照片snapshot(根据帧差异跟踪物体)。
state[5]是照明颜色通道的最大值。当整个图像的最大光照高于20时触发下面的代码。照明差异最大值应该为零。
if (stats[5] > 20):
diff -= 1
将两个图像彼此按像素取绝对值,取值。
img.difference("temp/bg.bmp")
stats = img.statistics()
使用OpenMV Cam拍摄延时照片,并使用RTC模块和定时器中断来实现极低功耗操作。
注:如果在相机拍照时仍然插入USB,则每次都会运行引导加载程序。
应从USB以外的其他设备为相机供电,以免运行引导加载程序。
创建并初始化RTC对象。 这将允许我们设置RTC的当前时间,让我们设置一个中断以便稍后唤醒。
rtc = pyb.RTC()
newFile = False
如果日志文件不存在,则设置RTC并将newFile设置为真实日期时间格式:年,月,日,工作日(星期一= 1,星期日= 7),小时(24小时制),分钟,秒,亚秒( 从255减少到0)
rtc.datetime((2018, 3, 9, 5, 13, 0, 0, 0))
newFile = True
每10秒启用一次RTC中断,相机将在从深睡眠模式唤醒后重置。
rtc.wakeup(10000)
进入深度睡眠模式(即,除RTC外,OpenMV Cam有效关闭)
machine.deepsleep()
建立动图对象
g = gif.Gif("example.gif", loop=True)
gif.Gif(filename, width=Auto, height=Auto, color=Auto, loop=True)
创建一个gif对象,filename为保存gif动图的文件路径。
添加图片
g.add_frame(sensor.snapshot(), delay=10) # centiseconds.
gif.add_frame(image, delay=10)
向gif动图中添加图片,delay=10指每隔10分秒添加一张图。
您可以使用OpenMV Cam来录制gif文件。可以用于RGB565图或灰度图。
使用像GIMP这样的照片编辑软件在将GIF上传到网络之前对其进行压缩和优化。
这个例子演示了如何在OpenMV Cam上使用面部追踪来获取gif。录制效果要比当时的动作慢一些。
使用OpenMV的帧差异来进行运动检测。检测到运动后,OpenMV摄像机将拍摄视频。
使用图像读取器对象来重放OpenMV在Image Writer对象中保存的用于测试机器视觉算法的快照。
如:对图像进行机器视觉算法
img = sensor.snapshot() if snapshot_source else img_reader.next_frame(copy_to_fb=True, loop=True)
需要先写入二进制视频才可。也就是先进行下一个例程。
使用Image Writer对象来记录OpenMV Cam在使用Image Reader对象进行后续分析时所看到的快照。
通过Image Writer对象写入磁盘的图像以OpenMV Cam可以读取的简单文件格式存储。
运行效果,是很大。
可以使用OpenMV Cam来录制mjpeg文件。
可以为记录器对象提供JPEG帧或RGB565 /灰度帧。
一旦你完成了一个Mjpeg文件的录制,你可以使用VLC来播放它。 如果你在Ubuntu上,那么内置的视频播放器也可以工作。
mjpeg.Mjpeg(filename, width=Auto, height=Auto)
创建一个mjpeg对象,filename为保存mjpeg动图的文件路径
如:m = mjpeg.Mjpeg(“example.mjpeg”)
mjpeg.add_frame(image, quality=50)
向mjpeg视频中中添加图片,quality为视频压缩质量。
如:m.add_frame(sensor.snapshot())
使用面部跟踪来获取mjpeg
录制视频:**m.add_frame(sensor.snapshot())
m.close(clock.fps())
录制动图: g.add_frame(sensor.snapshot(), delay=int(clock.avg()/10))
g.close()
对比动图和视频的例程,只有以上三句语法不同,其他的同理。
同上
人脸检测通过在图像上使用Haar Cascade特征检测器来工作。
haar级联是一系列简单的区域对比检查。 对于内置的前表面探测器,有25个阶段的检查,每个阶段有数百个检查一块。
Haar Cascades运行速度很快,因为只有在 以前的阶段过去后才会评估后期阶段。
OpenMV使用称为整体图像的数据结构来在恒定时间内快速执行每个区域对比度检查。
人脸识别只能用灰度图。因为整体图像的空间需求。
image.HaarCascade(path, stages=Auto)
加载一个haar模型。haar模型是二进制文件,这个模型如果是自定义的,则引号内为模型文件的路径;也可以使用内置的haar模型,比如“frontalface” 人脸模型或者“eye”人眼模型。stages值未传入时使用默认的stages。stages值设置的小一些可以加速匹配,但会降低准确率。
如:face_cascade = image.HaarCascade(“frontalface”, stages=25)
之前已实现。
用LBP特征进行人脸识别,图片格式为pgm,图像大小最好为92*112。需要在均匀的背景下进行采集,多表情和多细节拍摄。
先设置 n个NUM_SUBJECTS文件夹,文件夹中为m张NUM_SUBJECTS_IMGS人脸照片。
下载AT&T faces数据库http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip 提取并复制orl_faces目录到SD卡根目录。
或者通过人脸识别建立自己需要的数据库。
该脚本的第一部分使用前面Haar Cascade在图像中找到一张脸。
之后,脚本使用关键点功能自动学习你的脸并跟踪它。
关键点可以用来自动追踪任何东西。
默认情况下,这将使用所有阶段,较低的阶段更快但不太准确。
face_cascade = image.HaarCascade("frontalface", stages=25)
1、寻找人脸
如:objects = img.find_features(face_cascade, threshold=0.5, scale=1.25)
2、使用检测面大小作为ROI提取关键点
kpts1 = img.find_keypoints(threshold=10, scale_factor=1.1, max_keypoints=100, roi=face)
img.draw_keypoints(kpts1, size=24)
4、从整个帧中提取关键点
kpts2 = img.find_keypoints(threshold=10, scale_factor=1.1, max_keypoints=100, normalized=True)
5、将第一组关键点与第二组关键点匹配
c=image.match_descriptor(kpts1, kpts2, threshold=85)