opencv-099-SIFT特征提取之描述子生成

知识点

SIFT特征提取是图像特征提取中最经典的一个算法,归纳起来SIFT特征提取主要有如下几步:

  • 构建高斯多尺度金字塔
  • 关键点查找/过滤与精准定位
  • 窗口区域角度方向直方图
  • 描述子生成

前面我们已经详细解释了SIFT特征点是如何提取的,有了特征点之后,我们对特征点周围的像素块计算角度方向直方图,在计算直方图之前首先需要对图像进行梯度计算,这里可以使用SOBEL算子,然后根据dx与dy计算梯度和与角度。

SIFT特征提取具有空间尺度不变性、迁移不变性、光照不变性,一定要理解SIFT的精髓,如何实现了这几种不变性。

代码(c++,python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>

using namespace cv;
using namespace cv::xfeatures2d;
using namespace std;

void find_known_object(Mat &box, Mat &box_scene);
int main(int argc, char** argv) {

Mat box = imread("D:/images/box.bmp");
Mat scene = imread("D:/images/scene.jpg");
imshow("box image", box);
imshow("scene image", scene);
find_known_object(box, scene);

//Mat gray;
//cvtColor(src, gray, COLOR_BGR2GRAY);
auto detector = SIFT::create();
vector<KeyPoint> keypoints_box, keypoints_scene;
Mat descriptor_box, descriptor_scene;
detector->detectAndCompute(box, Mat(), keypoints_box, descriptor_box);
detector->detectAndCompute(scene, Mat(), keypoints_scene, descriptor_scene);

Ptr<FlannBasedMatcher> matcher = FlannBasedMatcher::create();
vector<DMatch> matches;
matcher->match(descriptor_box, descriptor_scene, matches);
Mat dst;
drawMatches(box, keypoints_box, scene, keypoints_scene, matches, dst);
imshow("match-demo", dst);


waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""
SIFT特征提取 – 描述子生成
"""

import cv2 as cv

box = cv.imread("D:/images/box.png")
box_in_sence = cv.imread("D:/images/box_in_scene.png")
cv.imshow("box", box)
cv.imshow("box_in_sence", box_in_sence)

# 创建sift特征检测器
sift = cv.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(box,None)
kp2, des2 = sift.detectAndCompute(box_in_sence,None)

# 暴力匹配
bf = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE)
matches = bf.match(des1,des2)

# 绘制匹配
matches = sorted(matches, key = lambda x:x.distance)
result = cv.drawMatches(box, kp1, box_in_sence, kp2, matches[:15], None)
cv.imshow("orb-match", result)
cv.waitKey(0)
cv.destroyAllWindows()

结果

代码地址

github