本例程利用 FAST/AGAST 算法进行特征提取,并且进行目标追踪,仅支持灰度图。
注意:本例程会把程序运行最开始的十秒左右出现的物体作为目标特征,请在程序运行的最开始,将目标物体放在摄像头中央识别,直至出现特征角点,证明已经识别记录目标特征。
匹配过程中,如果画面出现十字和矩形框,证明匹配成功。
1 # Object tracking with keypoints example.
2 # Show the camera an object and then run the script. A set of keypoints will be extracted
3 # once and then tracked in the following frames. If you want a new set of keypoints re-run
4 # the script. NOTE: see the docs for arguments to tune find_keypoints and match_keypoints.
5 import sensor, time, image
6
7 # Reset sensor
8 sensor.reset()
9
10 # Sensor settings
11 sensor.set_contrast(3)
12 sensor.set_gainceiling(16)
13 sensor.set_framesize(sensor.VGA)
14 sensor.set_windowing((320, 240))
15 sensor.set_pixformat(sensor.GRAYSCALE)
16
17 sensor.skip_frames(time = 2000)
18 sensor.set_auto_gain(False, value=100)
19
20 def draw_keypoints(img, kpts):
21 if kpts:
22 print(kpts)
23 img.draw_keypoints(kpts)
24 img = sensor.snapshot()
25 time.sleep(1000)
26
27 kpts1 = None
28 # NOTE: uncomment to load a keypoints descriptor from file
29 #kpts1 = image.load_descriptor("/desc.orb")
30 #img = sensor.snapshot()
31 #draw_keypoints(img, kpts1)
32
33 clock = time.clock()
34 while (True):
35 clock.tick()
36 img = sensor.snapshot()
37 if (kpts1 == None):
38 # NOTE: By default find_keypoints returns multi-scale keypoints extracted from an image pyramid.
39 kpts1 = img.find_keypoints(max_keypoints=150, threshold=10, scale_factor=1.2)
40 draw_keypoints(img, kpts1)
41 else:
42 # NOTE: When extracting keypoints to match the first descriptor, we use normalized=True to extract
43 # keypoints from the first scale only, which will match one of the scales in the first descriptor.
44 kpts2 = img.find_keypoints(max_keypoints=150, threshold=10, normalized=True)
45 if (kpts2):
46 match = image.match_descriptor(kpts1, kpts2, threshold=85)
47 if (match.count()>10):
48 # If we have at least n "good matches"
49 # Draw bounding rectangle and cross.
50 img.draw_rectangle(match.rect())
51 img.draw_cross(match.cx(), match.cy(), size=10)
52
53 print(kpts2, "matched:%d dt:%d"%(match.count(), match.theta()))
54 # NOTE: uncomment if you want to draw the keypoints
55 #img.draw_keypoints(kpts2, size=KEYPOINTS_SIZE, matched=True)
56
57 # Draw FPS
58 img.draw_string(0, 0, "FPS:%.2f"%(clock.fps()))
sensor.
reset
()
初始化相机传感器。
sensor.
snapshot
()
使用相机拍摄一张照片,并返回 image
对象。 OpenMV有两个图像存储区。用于正常MicroPython处理的经典堆栈/堆区可以将小图像存储在堆中。 但是,MicroPython堆只有大约100KB,这不足以存储更大的图像。因此,您的OpenMV Cam有一个辅助帧缓冲存储区, 用于存储 sensor.snapshot() 所拍摄的图像。 图像存储在该存储区域的底部。 剩下的任何内存都可供帧缓冲区堆栈使用,OpenMV Cam的固件使用它来保存用于图像处理算法的大型临时数据结构。
如果你需要空间来容纳多个帧,你可以通过调用 sensor.alloc_extra_fb() 来“偷走”帧缓冲区空间。
sensor.
skip_frames
([n, time])
使用 n
个快照,让相机图像在改变相机设置后稳定下来。 n
作为普通参数传输, 例如: skip_frames(10)
跳过 10
帧。您应在改变相机设置后调用该函数。
或者,您可通过关键字参数 time
来跳过几毫秒的帧数,例如: kip_frames(time = 2000)
,跳过2000毫秒的帧。
若 n
和 time
皆未指定,该方法跳过300毫秒的帧。
若二者皆指定,该方法会跳过 n
数量的帧,但将在 time
毫秒后超时。
sensor.
set_pixformat
(pixformat)
设置相机模块的像素模式。
- sensor.GRAYSCALE: 8-bits per pixel.
- sensor.RGB565: 16-bits per pixel.
- sensor.BAYER: 8-bits per pixel bayer pattern.
sensor.
set_pixformat
(pixformat)
设置相机模块的像素模式。
- sensor.GRAYSCALE: 8-bits per pixel.
- sensor.RGB565: 16-bits per pixel.
- sensor.BAYER: 8-bits per pixel bayer pattern.
sensor.
set_framesize
(framesize)
设置相机模块的帧大小。
- sensor.QQCIF: 88x72
- sensor.QCIF: 176x144
- sensor.CIF: 352x288
- sensor.QQSIF: 88x60
- sensor.QSIF: 176x120
- sensor.SIF: 352x240
- sensor.QQQQVGA: 40x30
- sensor.QQQVGA: 80x60
- sensor.QQVGA: 160x120
- sensor.QVGA: 320x240
- sensor.VGA: 640x480
- sensor.HQQQVGA: 80x40
- sensor.HQQVGA: 160x80
- sensor.HQVGA: 240x160
sensor.B64X32
: 64x32 (for use with image.find_displacement())sensor.B64X64
: 64x64 (for use with image.find_displacement())sensor.B128X64
: 128x64 (for use with image.find_displacement())sensor.B128X128
: 128x128 (for use with image.find_displacement())- sensor.LCD: 128x160 (for use with the lcd shield)
- sensor.QQVGA2: 128x160 (for use with the lcd shield)
- sensor.WVGA: 720x480
- sensor.WVGA2:752x480
- sensor.SVGA: 800x600 (only in JPEG mode for the OV2640 sensor)
- sensor.SXGA: 1280x1024 (only in JPEG mode for the OV2640 sensor)
- sensor.UXGA: 1600x1200 (only in JPEG mode for the OV2640 sensor)
sensor.
set_windowing
(roi)
将相机的分辨率设置为当前分辨率的子分辨率。例如:将分辨率设置为 sensor.VGA ,然后将windowing设置为(120, 140, 200, 200), 设置 sensor.snapshot() 以捕捉由相机传感器输出的VGA分辨率的200x200中心像素。您可使用窗口来获得定制的分辨率。另外, 当你在更大分辨率下使用窗口时,实际上是进行数字缩放。
roi
是矩形区域元组 (x, y, w, h). 然而,你可以只传递 (w,h),而 roi
将会在图像中居中。
sensor.
set_gainceiling
(gainceiling)
设置相机图像增益上限。2, 4, 8, 16, 32, 64, 128。
sensor.
set_contrast
(constrast)
设置相机图像对比度。-3至+3
sensor.
set_auto_gain
(enable[, gain_db=-1[, gain_db_ceiling]])
enable
打开(True)或关闭(False)自动增益。默认打开。 value
强迫增益值。更多细节请参见摄像头数据表。
如果 enable
为False,则可以使用 gain_db
设置固定增益,单位为分贝。
如果 enable
为True,您可以使用``gain_db_ceiling``设置自动增益控制算法的最大增益上限,以分贝为单位。
注解
若您想追踪颜色,则需关闭白平衡。
image.
draw_keypoints
(keypoints[, color[, size=10[, thickness=1[, fill=False]]]])
在图像上画出一个特征点对象的各个点。
color
是用于灰度或RGB565图像的RGB888元组。默认为白色。但是,您也可以传递灰度图像的基础像素值(0-255)或RGB565图像的字节反转RGB565值。
size
控制特征点的大小。
thickness
控制线的粗细像素。
将 fill
设置为True以填充特征点。
返回图像对象,以便您可以使用 .
表示法调用另一个方法。
不支持压缩图像和bayer图像。
mage.
find_keypoints
([roi[, threshold=20[, normalized=False[, scale_factor=1.5[, max_keypoints=100[, corner_detector=image.CORNER_AGAST]]]]]])
从ROI元组(x, y, w, h)中提取ORB键点。您可以使用 image.match_descriptor 函数来比较两组关键点,以获取匹配区域。若未发现关键点,则返回None。
roi
是感兴趣区域的矩形元组(x,y,w,h)。如果未指定,ROI即整个图像的图像矩形。 操作范围仅限于 roi
区域内的像素。
threshold
是控制提取的数量的数字(取值0-255)。对于默认的AGAST角点检测器,该值应在20左右。 对于FAST角点检测器,该值约为60-80。阈值越低,您提取的角点越多。
normalized
是布尔值。若为True,在多分辨率下关闭提取键点。 若您不关心处理扩展问题,且希望算法运行更快,就将之设置为True。
scale_factor
是一个必须大于1.0的浮点数。较高的比例因子运行更快,但其图像匹配相应较差。理想值介于1.35-1.5之间。
max_keypoints
是一个键点对象所能容纳的键点最大数量。若键点对象过大导致内存问题,请降低该值。
corner_detector
是从图像中提取键点所使用的角点检测器算法。 可为 image.CORNER_FAST或 image.CORNER_AGAST 。FAST角点检测器运行速度更快,但其准确度较低。
仅支持灰度图像
image.
match_descriptor
(descritor0, descriptor1[, threshold=70[, filter_outliers=False]])
对于LBP描述符来说,这个函数返回的是一个体现两个描述符之间区别的整数。这一距离测度尤为必要。这个距离是对相似度的一个度量。这个测度值越接近0,LBPF特征点匹配得就越好。
对于ORB描述符来说,这个函数返回的是kptmatch对象。见上。
threshold
是用来为ORB键点过滤不明确匹配服务的。
一个较低的 threshold
值将紧扣关键点匹配算法。 threshold
值位于0-100 (int)。默认值为70。
filter_outliers
是用来为ORB键点过滤异常值服务的。 特征点允许用户提高 threshold
值。默认设置为False。
模板匹配和特征点检测的比较:
- 模板匹配(find_temolate)采用的是ncc算法,只能匹配与模板图片大小和角度基本一致的图案。局限性相对来说比较大,视野中的目标图案稍微比模板图片大一些或者小一些就可能匹配不成功。
- 模板匹配适应于摄像头与目标物体之间距离确定,不需要动态移动的情况。比如适应于流水线上特定物体的检测,而不适应于小车追踪一个运动的排球(因为运动的排球与摄像头的距离是动态的,摄像头看到的排球大小会变化,不会与模板图片完全一样)。
- 多角度多大小匹配可以尝试保存多个模板,采用多模板匹配。
- 特征点检测(find_keypoint): 如果是刚开始运行程序,例程提取最开始的图像作为目标物体特征,kpts1保存目标物体的特征。默认会匹配目标特征的多种比例大小和角度,而不仅仅是保存目标特征时的大小角度,比模版匹配灵活,也不需要像多模板匹配一样保存多个模板图像。
- 特征点检测,也可以提前保存目标特征,之前是不推荐这么做的,因为环境光线等原因的干扰,可能导致每次运行程序光线不同特征不同,匹配度会降低。但是最新版本的固件中,增加了对曝光度、白平衡、自动增益值的调节,可以人为的定义曝光值和白平衡值,相对来说会减弱光线的干扰。也可以尝试提前保存目标特征。