Fork me on GitHub

OpenCV之feature2d组件

角点检测

特征检测与匹配

角点检测

Harris角点检测

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
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;

int main()
{
//以灰度模式载入图像并显示
Mat srcImage = imread("4.jpg", 0);
imshow("srcImage", srcImage);

//进行Harris角点检测找出角点
Mat cornerStrength;
cornerHarris(srcImage, cornerStrength, 2, 3, 0.01);

//对灰度图进行阈值操作,得到二值图并显示
Mat harrisCorner;
threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);
imshow("harrisCorner", harrisCorner);

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;

#define WINDOW_NAME1 "dstImage"
#define WINDOW_NAME2 "scaledImage"

Mat srcImage, dstImage, grayImage;
int thresh = 30; //当前阈值
int max_thresh = 175; //最大阈值

static void on_CornerHarris(int , void *);
void Show();

int main()
{
Show();

srcImage = imread("4.jpg");
if (!srcImage.data)
{
printf("Oh, no, srcImage is error");
return -1;
}
imshow("srcImage", srcImage);

dstImage = srcImage.clone();
cvtColor(dstImage, grayImage, CV_BGR2GRAY);

//imshow("grayImage", grayImage);

//创建窗口和滚动条
namedWindow(WINDOW_NAME1, CV_WINDOW_AUTOSIZE);
createTrackbar("CornerHarris", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
on_CornerHarris(0, 0);

waitKey(0);
return 0;
}

void Show()
{
printf("\n\n\n\t\t\t【欢迎来到Harris角点检测示例程序~】\n\n");
printf("\n\n\n\t请调整滚动条观察图像效果\n\n");
printf("\n\n\t\t\t\t\t\t\t\t\t\t by 晴宝");
}

static void on_CornerHarris(int, void *)
{
//1.定义一些局部变量
Mat n_dstImage;//目标图
Mat normImage;//归一化后的图
Mat scaledImage;//线性变换后的八位无符号整型的图

//2.初始化
//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
n_dstImage = Mat::zeros(srcImage.size(), CV_32FC1);
dstImage = srcImage.clone();

//3.正式检测
//进行角点检测
cornerHarris(grayImage, n_dstImage, 2, 3, 0.04, BORDER_DEFAULT);
//归一化与转换
normalize(n_dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
//将归一化的图像线性变换成8位无符号整型
convertScaleAbs(normImage, scaledImage);

//4.进行绘制
//将检测到的,且符合阈值条件的角点绘制出来
for (int j = 0; j < normImage.rows; j++)
{
for (int i = 0; i < normImage.cols; i++)
{
if ((int) normImage.at<float>(j, i) > thresh + 80)
{
circle(dstImage, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0);
circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
}


}
}

imshow(WINDOW_NAME1, dstImage);
imshow(WINDOW_NAME2, scaledImage);
}

特征检测与匹配

SURF特征点检测

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//SURF特征点检测
/*
1.使用FeatureDetector接口发现兴趣点
2.使用SurFeatureDetector以及其函数detect来实现检测过程
3.使用函数drawKeypoints绘制检测到的关键点
*/
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/core/core.hpp>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;

void Show();

int main()
{
Show();
Mat srcImage1 = imread("4.jpg");
Mat srcImage2 = imread("5.jpg");
if (!srcImage1.data || !srcImage2.data)
{
printf("Oh, no, srcImage is error");
return false;
}

imshow("srcImage1", srcImage1);
imshow("srcImage2", srcImage2);

//定义需要用到的变量和类
int minHessian = 400; //定义SURF中的hessian阈值特征值检测算子
//SurfFeatureDetector detector(minHessian);//定义一个SurfFeatureDetector(SURF)特征检测对象
Ptr<SURF> surfDetector = SURF::create(2000);
vector<KeyPoint> keypoints_1, keypoints_2;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据

//调用detect函数检测出SURF特征关键点,保存在vector容器中
//detector.detect(srcImage1, keypoints_1);
//detector.detect(srcImage2, keypoints_2);

surfDetector->detect(srcImage1, keypoints_1);
surfDetector->detect(srcImage2, keypoints_2);

//绘制特征关键点
Mat img_keypoints_1, img_keypoints_2;
drawKeypoints(srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
drawKeypoints(srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT);

imshow("img_keypoints_1", img_keypoints_1);
imshow("img_keypoints_2", img_keypoints_2);

waitKey(0);
return 0;
}

void Show()
{
printf("\n\n\n\t欢迎来到【SURF特征检测】示例程序~\n\n");
printf("\n\n\t按键操作说明:\n\n"
"\t\t键盘按键任意键 - 退出程序\n\n"
"\n\n\t\t\t\t\t\t\t\t by 晴宝\n\n\n");

}
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
///*
//程序的核心思想:
// 1.使用DescriptorExtractor接口来寻找关键点对应的特征向量
// 2.使用SurfdescriptorExtractor以及它的函数compute来完成特定的计算
// 3.使用BruteForceMatcher来匹配特征向量
// 4.使用函数drawMatches来绘制检测到的匹配点
//*/
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/core/core.hpp>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;

void Show();

int main()
{
Show();

Mat srcImage1 = imread("4.jpg");
Mat srcImage2 = imread("5.jpg");
if (!srcImage1.data || !srcImage2.data)
{
printf("Oh, no, srcImage is error");
return -1;
}

//使用SURF算子检测关键点
int minHessian = 700;
//Ptr<SIFT> SiftDescriptor = SIFT::create();
Ptr<SURF> surfDetector = SURF::create(2000); //海塞矩阵阈值,在这里调整精度,值越大点越少,越精准
vector<KeyPoint> keyPoints1, keyPoints2;

//调用detect函数检测出SURF特征关键点,保存在vector容器中
surfDetector->detect(srcImage1, keyPoints1);
surfDetector->detect(srcImage2, keyPoints2);

//计算描述符(特征向量)
//特征点描述,为下边的特征点匹配做准备
Ptr<SURF> SurfDescriptor = SURF::create();
Mat descriptors1, descriptors2;
SurfDescriptor->compute(srcImage1, keyPoints1, descriptors1);
SurfDescriptor->compute(srcImage2, keyPoints2, descriptors2);

//使用BruteForce进行匹配
//实例化一个匹配器
//BruteForceMatcher<L2<float>> matcher;
BFMatcher matcher;
vector<DMatch> matches;
//匹配两幅图中的描述子(descriptors)
matcher.match(descriptors1, descriptors2, matches);

//绘制从两个图像中匹配出的关键点
Mat imgMatches;
//进行绘制
drawMatches(srcImage1, keyPoints1, srcImage2, keyPoints2, matches, imgMatches);

imshow("imgMatches", imgMatches);
waitKey(0);

return 0;
}

void Show()
{
printf("\n\n\n\t欢迎来到【SURF特征描述】示例程序~\n\n");
printf("\n\n\t\t\t\t\t\t\t by 晴宝\n\n\n");
}
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include"opencv2/flann.hpp"
#include"opencv2/xfeatures2d.hpp"
#include"opencv2/ml.hpp"
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
using namespace cv::ml;

int main()
{
Mat a = imread("4.jpg", IMREAD_GRAYSCALE); //读取灰度图像
Mat b = imread("5.jpg", IMREAD_GRAYSCALE);

Ptr<SURF> surf; //创建方式和2中的不一样
surf = SURF::create(800);

BFMatcher matcher;
Mat c, d;
vector<KeyPoint>key1, key2;
vector<DMatch> matches;

surf->detectAndCompute(a, Mat(), key1, c);
surf->detectAndCompute(b, Mat(), key2, d);

matcher.match(c, d, matches); //匹配

sort(matches.begin(), matches.end()); //筛选匹配点
vector< DMatch > good_matches;
int ptsPairs = std::min(50, (int)(matches.size() * 0.15));
cout << ptsPairs << endl;
for (int i = 0; i < ptsPairs; i++)
{
good_matches.push_back(matches[i]);
}
Mat outimg;
drawMatches(a, key1, b, key2, good_matches, outimg, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); //绘制匹配点

std::vector<Point2f> obj;
std::vector<Point2f> scene;

for (size_t i = 0; i < good_matches.size(); i++)
{
obj.push_back(key1[good_matches[i].queryIdx].pt);
scene.push_back(key2[good_matches[i].trainIdx].pt);
}

std::vector<Point2f> obj_corners(4);
obj_corners[0] = Point(0, 0);
obj_corners[1] = Point(a.cols, 0);
obj_corners[2] = Point(a.cols, a.rows);
obj_corners[3] = Point(0, a.rows);
std::vector<Point2f> scene_corners(4);

Mat H = findHomography(obj, scene, RANSAC); //寻找匹配的图像
perspectiveTransform(obj_corners, scene_corners, H);

line(outimg, scene_corners[0] + Point2f((float)a.cols, 0), scene_corners[1] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA); //绘制
line(outimg, scene_corners[1] + Point2f((float)a.cols, 0), scene_corners[2] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
line(outimg, scene_corners[2] + Point2f((float)a.cols, 0), scene_corners[3] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
line(outimg, scene_corners[3] + Point2f((float)a.cols, 0), scene_corners[0] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
imshow("aaaa", outimg);
cvWaitKey(0);
}