在电脑视觉中,我们经常需要侦测或判断两个物件相似程度?该物件是否出现在相片中?在那里地方?例如下图中的这个City Café…
电脑是否能判断上图的咖啡与我手上的这杯是相同品牌?亦或,能否知道这杯就是City Café?
对于我们人类来说,这应该是直觉又简单不过的事,但对于电脑可不是这样了,从物件中找出像素变化的规则与异同是它看待世界的方式。在下面的范例中,我们将透过机器学习方式,搭配Feature matching技术来授与电脑辨识及比对物体的能力。
Feature matching
要辨识某物体的条件就是先掌握其特征!由于我们要辨识的是某个物件而非整张相片,因此需要提取所谓称为「Local features」的特征,作法是先在影像中选取重要的特征点,接着以其为base取得周围的特征(即local features),这些来自不同相片的local features会透过稍后会说明的Feature matching功能来比对是否有相同的物件。
例如当我们孩提时第一次看到兔子,它那深具特色的长耳朵形象会立刻深植在我们脑海中,往后看到其它不同的兔子时,虽然是在不同的时空环境,但是那长耳朵的特征会立刻唤醒我们它可能是一只兔子的记忆。在这例子中,长耳朵对于我们来说就是辨识兔子的局部特征,那么电脑呢?它是如何透过特征点→局部特征→Feature matching的方式来看待这只兔子?
特征点的选取
要解释电脑如何看待特征之前,我们先看一下这些局部影像:
| | | | |
A | B | C | D | E |
您能分辨这些局部影像出自于下面这张图片的那一部份吗?
A、C图 →很难判别,平淡的局部影像,没有明显的特性可供识别,图片中很多地方都与其类似。
B图 →容易一些,我们可从图片中物件的边缘找到线索,它应该位于兔子周围的区域,但兔子的边缘仍过于广泛,必须逐一比对后才能确定。
E图 →较容易,我们可以确定是在兔子下半身与杂草交界处的某区域。
F图 →最容易,马上就能明确的知道在眼睛的区域,因为它包含一个明确的区块。
有没有发现其实上述的这些特性可用edges、corners、blobs等组合来描述!B图有edges,E图有corners,F图则具有blobs,因此,我们只要从感兴趣的物件中设定具有这些特性的区域为关键点keypoints,再针对各关键点计算并提取该区域的features,就能用来比对及辨识物体。事实上,基本的影像辨识,如上所述的特征点→局部特征→Feature matching步骤,所执行的动作依序是:Keypoint detection、Feature extraction以及Feature matching。
- Keypoint detection:
在图片中取得感兴趣的关键点(可能为edges、corners或blobs)。
- Feature extraction:
针对各关键点提取该区域的features(我们称为local features)。
- 关键点筛选并进行Feature matching。
我们可将上述的步骤归纳如下:
首先,在图片A与B分别找出Keypoints,再依据各个keypoints取出其local features(主要为梯度和角度所组成的Histogram),两张图片的local features进行feature matching,计算并match各个距离最小的keypoint 。
接下来分别针对A) Keypoint detection、B) Feature extraction以及C) Feature matching这三个步骤作说明,下方先介绍A) Keypoint detection,B)与C)步骤将会在下一篇文章中介绍。
-
Keypoint detection关键点侦测
Keypoint detection的演算法有很多,openCV便提供了十一种方法:
“FAST" – FastFeatureDetector
“STAR" – StarFeatureDetector
“SIFT" – SIFT (nonfree module)
“SURF" – SURF (nonfree module)
“ORB" – ORB
“BRISK" – BRISK
“MSER" – MSER
“GFTT" – GoodFeaturesToTrackDetector
“HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled
“Dense" – DenseFeatureDetector
“SimpleBlob" – SimpleBlobDetector
还有以下二种Grid和Pyramid的方式,可合并以上各方法来使用:
“Grid" – GridAdaptedFeatureDetector
“Pyramid" – PyramidAdaptedFeatureDetector
后方再append上述的各个feature detector name即可,
例如: “GridFAST", “PyramidSTAR" .
Keypoints关键点除了用来比对或辨识物件之外,也经常用于拼接(stitch)图像以制作全景图。以下说明并实作各种关键点侦测。
原理:以FAST为例
不同的keypoint detector有其不同的演算方式,下面以FAST为例:
FAST方法认为,一个以c为中心、半径为r的圆形,若它位于一个所谓的corner上,那么该圆的圆周上必有连续n个点,其强度值大于或小于中心点c加上一个指定的threshold门槛的强度值。如果是的话,该中心点c便被认为是keypoint。
各种Keypoint detector技术
FAST
- 原理简单
- 执行速度相当快
- 主要用于侦测corners,亦可侦测blob。
- 适用于要求速度的real-time analysis
- 适用于速度慢或较低阶的执行环境。
- 使用度极高,尤其在需要即时的realtime环境。
程式范例
detector = cv2.FeatureDetector_create(“FAST")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到1,458个特征点
Harris
- 速度相当快,但仍较FAST慢,不过侦测corner比起FAST准确一些。
- 广泛应用于侦测edges及corners
程式范例
detector = cv2.FeatureDetector_create(“HARRIS")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到350个特征点
GFTT
- GFTT为Harris keypoint detector的再修正。
- 针对edges/corner detect的准确率与速度有所提升,但实际上使用感觉差异不大。
程式范例
detector = cv2.FeatureDetector_create(“GFTT")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到922个特征点
DoG (SIFT)
- 原理较为复杂。
- 主要针对blob 侦测,不过亦可侦测corners。
- 可适应物件的scale(大小变化)及angle(旋转角度)等情况。
- 在DoG模型中,使用了不同尺寸影像并套用高斯模糊,比较不同模糊比例之间的变化,来决定是否为keypoint。
- 由于计算量大,DoG的执行速度较慢,不适用于realtime的环境。
- SIFT已广泛的应用于电脑视觉领域,并成为评定新keypoint detecter的效率指标。
程式范例
detector = cv2.FeatureDetector_create(“SIFT")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到553个特征点
Fast Hessian (SURF)
- 基于DoG(SIFT)模型而发展,改善其速度慢的缺点。
- 可使用于realtime的环境,但速度仍比不上FAST等keypoint detector。
- 与DoG相同,用于侦测corners以及明显材质纹路的textures。
程式范例
detector = cv2.FeatureDetector_create(“SURF")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到927个特征点
STAR
- 使用于侦测blog area。
- 与DoG相同,亦使用高斯模糊计算,但由于其演算方式相当复杂,目前并不常被使用。
- 侦测速度相当快,可应用于realtime分析,但效果并不如FAST。
程式范例
detector = cv2.FeatureDetector_create(“STAR")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到171个特征点
MSER
1. 使用于侦测blog area
2. 判断的依据(需满足此三点),则认定为blog area:
a. 相连的像素
b. 相似的像素强度
c. 与背景成对比
3. 对于小区域且对比明显的area侦测效果良好。
4. 不适用分析模糊的影像。
5. 不适合使用于要求速度的realtime环境。
6. 输入的影像符合其要求的三种条件,则侦测速度可加快。
程式范例
detector = cv2.FeatureDetector_create(“MSER")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到147个特征点
Dense
- Dense是最简单的keypoint detector。
- 它的原理是先设定一个K值,然后均匀的在整张图面上以每隔K pixels的距离布置一个keypoint,因此严格来说,Dense并没有detect的动作。
- 在某些情况下(如风景类图片),Dense的效果其实不会比FAST 、Harris 、 DoG等其它detector差。
- Dense算法虽然简单,但也是其缺点,因为过于简单而产生过多的keypoints,甚至于超过图片中实际的数量,过多的keypoints需要更多的记忆体、储存及运算量。
- 单纯的Dense无法适用于不同尺寸的图像,因此需在Keypoints上加入不同半径大小的侦测点(Multiple radii)才能应用不同的尺寸大小(scale invariant)。
- 资源耗用大,因此Dense不适用于realtime及运行于小型装置。
- 适合用于机器学习的影像分类及基于内容的影像搜索。
Dense分为单一radii及多重radii两种方法,其中后者可适应尺寸变化的情况。
单一radii:
下方范例K值为9,使用单一radii(固定半径的侦测点),此方式无法应付尺寸大小变化的情况。
程式范例
detector = cv2.FeatureDetector_create(“Dense")
detector.setInt(“initXyStep", 9)
kps = detector.detect(gray)
抓取到3,350个特征点
多重Radii:
使用不同半径的keypoint(multi radii),以适应图像尺寸变化的情况。
下方范例K值为36,每个keypoint取三种半径3, 9, 15 pixels
程式范例
detector = cv2.FeatureDetector_create(“Dense")
detector.setInt(“initXyStep", 36)
rawKps = detector.detect(gray)
kps = []
for rawKp in rawKps:
for r in (3, 9, 15):
kp = cv2.KeyPoint(x= rawKp.pt [0], y= rawKp.pt [1], _size=r * 2)
kps.append(kp)
抓取到663个特征点
BRISK
- FAST keypoint detectorh的强化,主要是针对尺寸缩放的部份(scale space invariance)。
- 会先以pyramid方式产生尺寸大小不同的影像,再针对每一层进行FAST运算及取值。
- 速度快,适用于realtime的环境。
- 适用于侦测Corners。
程式范例
detector = cv2.FeatureDetector_create(“BRISK")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到176个特征点
ORB
- 与BRISK相同,ORB亦是针对FAST的强化,但除了scale space invariance,亦加入了旋转不变性(rotation invariance).。
- ORB原理有三大步骤:
- Pyramid图像尺寸并进行各尺寸的FAST计算。
- 使用Harris keypoint detector的方法计算每个keypoint分数(是否近似corner?),并进行排序,最多仅取500个keypoints,其余则丢弃。
- 于此第三步中加入旋转不变性,使用「intensity centroid」计算每个keypoint的rotation。
- ORB与BRISK相同,继承了FAST运算快速的特性,可适用于realtime分析。
抓取到500个特征点
不同特征点的合并使用
GridAdaptedFeatureDetector与FAST并用为例:
程式范例
detector = cv2.FeatureDetector_create(“GridFAST")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到570个特征点
PyramidAdaptedFeatureDetector与STAR并用为例
程式范例
detector = cv2.FeatureDetector_create(“PyramidSTAR")
kps = detector.detect(gray)
print(“# of keypoints: {}".format(len(kps)))
抓取到213个特征点
最后
本文中我们介绍了这么多种(十种)的图像关键点侦测方法,到底要采用何种方法才是最好的呢?,其实并没有一定的标准,不同图像与专案环境有其适合的方法,必须视情况而定,我们也可以每种都尝试看看,再从中选择最佳的方式。
现在我们透过Keypoint detection得到了keypoints,接下来,就可以开始透过Feature extraction以及Feature matching来进行影像片辨识比对了。