SURF/SIFT特征点检测
视频讲解如下:
在本章节中给大家演示SURF/SIFT特征点检测,主要函数:SURF和SIFT。
毛星云的代码为opencv-2.4.9版本的SURF功能演示,可是博主在opencv-2.4.9版本中并未发现SURF功能,目前只能演示SIFT了。
特别注意:OpenCv C++版本的SURF功能据说被作者申请专利了,已经不免费开放了,博主在以下版本的OpenCv中都未查找到xfeatures2d库,导致C++中SURF功能无法使用。
目前暂时只有OpenCvSharp4中带有SURF功能,C++和Python都未查找到SURF功能库。
opencv-2.4.9
opencv-2.4.13.6
opencv-3.3.1
opencv-3.4.0-vc14_vc15
opencv-3.4.1-vc14_vc15
opencv-3.4.2-vc14_vc15
opencv-3.4.3-vc14_vc15
opencv-3.4.4-vc14_vc15
opencv-3.4.5-vc14_vc15
opencv-3.4.6-vc14_vc15
opencv-3.4.7-vc14_vc15
opencv-4.1.1-vc14_vc15
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
首先呢,我们需要准备两张测试图片。(不想下载工程的童鞋,可直接复制下面的图片和代码)

C#版本中SURF和SIFT的演示对比如下,红色是SURF的效果,绿色是SIFT的效果。

C#、C++、Python三个版本的SIFT功能对比效果如下:
从对比结果上看,识别到的角点位置基本一致。

C#版本代码如下:
using OpenCvSharp;
namespace demo
{
internal class Program
{
static void Main(string[] args)
{
demo1();
demo2();
Cv2.WaitKey();
}
/// <summary>
/// SURF
/// </summary>
static void demo1()
{
// 载入源图片并显示
Mat srcImage1 = Cv2.ImRead("../../../images/book2.jpg");
Mat srcImage2 = Cv2.ImRead("../../../images/book3.jpg");
// 定义SURF中的hessian阈值特征点检测算子
int minHessian = 400;
// 定义一个特征检测类对象
var MySurf = OpenCvSharp.XFeatures2D.SURF.Create(minHessian, 4, 3, true, true);
// 模板类是能够存放任意类型的动态数组,能够增加和压缩数据
KeyPoint[] keypoints_1 = MySurf.Detect(srcImage1);
KeyPoint[] keypoints_2 = MySurf.Detect(srcImage2);
// 绘制特征关键点.
Mat img_keypoints_1 = new Mat();
Mat img_keypoints_2 = new Mat();
Cv2.DrawKeypoints(srcImage1, keypoints_1, img_keypoints_1, new Scalar(0, 0, 255), DrawMatchesFlags.Default);
Cv2.DrawKeypoints(srcImage2, keypoints_2, img_keypoints_2, new Scalar(0, 0, 255), DrawMatchesFlags.Default);
// 显示效果图
Cv2.ImShow("SURF特征点检测效果图1", img_keypoints_1);
Cv2.ImShow("SURF特征点检测效果图2", img_keypoints_2);
}
/// <summary>
/// SIFT
/// </summary>
static void demo2()
{
// 载入源图片并显示
Mat srcImage1 = Cv2.ImRead("../../../images/book2.jpg");
Mat srcImage2 = Cv2.ImRead("../../../images/book3.jpg");
// 定义SURF中的hessian阈值特征点检测算子
int minHessian = 400;
// 定义一个特征检测类对象
var MySift = OpenCvSharp.Features2D.SIFT.Create(minHessian);
// 模板类是能够存放任意类型的动态数组,能够增加和压缩数据
KeyPoint[] keypoints_1 = MySift.Detect(srcImage1);
KeyPoint[] keypoints_2 = MySift.Detect(srcImage2);
// 绘制特征关键点.
Mat img_keypoints_1 = new Mat();
Mat img_keypoints_2 = new Mat();
Cv2.DrawKeypoints(srcImage1, keypoints_1, img_keypoints_1, new Scalar(0, 255, 0), DrawMatchesFlags.Default);
Cv2.DrawKeypoints(srcImage2, keypoints_2, img_keypoints_2, new Scalar(0, 255, 0), DrawMatchesFlags.Default);
// 显示效果图
Cv2.ImShow("SIFT特征点检测效果图1", img_keypoints_1);
Cv2.ImShow("SIFT特征点检测效果图2", img_keypoints_2);
}
}
}
C++版本代码如下:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/features2d/features2d.hpp>
using namespace cv;
using namespace std;
int main()
{
//【1】载入图像
Mat srcImage1 = imread("../images/book2.jpg");
Mat srcImage2 = imread("../images/book3.jpg");
//【2】定义SIFT中的hessian阈值特征点检测算子
int minHessian = 400;
Ptr<SIFT> siftDetector = SIFT::create(minHessian);
vector<KeyPoint> keypoints_1, keypoints_2;
//【3】调用detect函数检测出SIFT特征关键点,保存在vector容器中
siftDetector->detect(srcImage1, keypoints_1);
siftDetector->detect(srcImage2, keypoints_2);
//【4】绘制特征关键点
Mat img_keypoints_1;
Mat img_keypoints_2;
drawKeypoints(srcImage1, keypoints_1, img_keypoints_1, Scalar(0,255,0), DrawMatchesFlags::DEFAULT);
drawKeypoints(srcImage2, keypoints_2, img_keypoints_2, Scalar(0, 255, 0), DrawMatchesFlags::DEFAULT);
//【5】显示效果图
imshow("特征点检测效果图1", img_keypoints_1);
imshow("特征点检测效果图2", img_keypoints_2);
waitKey(0);
return 0;
}
Python版本代码如下:
import cv2
import numpy as np
# 【1】载入图像
srcImage1 = cv2.imread("../images/book2.jpg")
srcImage2 = cv2.imread("../images/book3.jpg")
# 定义一个特征检测类对象
sift = cv2.SIFT_create(400)
# 调用detect函数检测出SIFT特征关键点,保存在vector容器中
keypoints_1 = sift.detect(srcImage1)
keypoints_2 = sift.detect(srcImage2)
# 绘制特征关键点
img_keypoints_1 = srcImage1.copy()
img_keypoints_2 = srcImage2.copy()
img_keypoints_1 = cv2.drawKeypoints(srcImage1, keypoints_1, img_keypoints_1, color=(0,255,0))
img_keypoints_2 = cv2.drawKeypoints(srcImage2, keypoints_2, img_keypoints_2, color=(0,255,0))
# 显示效果图
cv2.imshow("img_keypoints_1", img_keypoints_1)
cv2.imshow("img_keypoints_2", img_keypoints_2)
cv2.waitKey(0)
cv2.destroyAllWindows()