我们都知道特征检测和匹配是计算机视觉领域中的重要任务,它们在许多应用中发挥着关键作用,比如slam、sfm、ar、vr等许多算法都需要稳定精确的特征检测和匹配。
特征检测算法的意义在于从图像或视频中提取出具有独特性质的特征点,这些特征点可以代表图像中的关键信息。这些特征点通常具有旋转、尺度和光照变化的不变性,使得它们在图像的不同位置和角度下都能够被准确地检测到。
特征匹配算法的意义在于将两个或多个图像中的特征点进行对应,以实现图像间的关联和匹配。通过将特征点进行匹配,可以进行目标跟踪、图像配准、三维重建等任务。
目前个人认为特征检测和匹配的研究点包括但不限于以下几个方面:
1.特征点检测算法的设计和改进,提高特征点的鲁棒性和准确性。
2.特征描述子的设计和优化,提高特征点的区分度和匹配性能。
3.多尺度和多模态特征检测与匹配,适应不同尺度、视角和传感器条件下的图像数据。
4.大规模特征点检测和匹配算法,用于处理大规模图像数据库或视频流。
5.深度学习在特征检测和匹配中的应用,如使用卷积神经网络提取图像特征和进行匹配。
特征检测和匹配的应用广泛,包括但不限于以下几个方面:
1.目标识别和跟踪:通过检测和匹配图像中的特征点,可以实现目标在视频中的跟踪和定位,如自动驾驶中的目标识别和跟踪。
2.图像配准和拼接:通过匹配图像中的特征点,可以将多幅图像进行配准和拼接,生成全景图像或三维重建模型。
3.增强现实(ar)和虚拟现实(vr):特征检测和匹配可用于将虚拟对象与真实世界进行对齐和融合,实现更逼真的ar和vr体验。
4.图像检索和分类:通过匹配图像中的特征点,可以对图像进行相似性搜索和分类,用于图像检索和内容识别。
5.三维重建和建模:通过匹配多个视角的图像中的特征点,可以进行三维重建和场景建模,用于计算机辅助设计、虚拟现实等领域。
6.视频处理和分析:特征检测和匹配在视频处理中可以用于运动估计、目标跟踪、动作识别等任务。
所以,本篇文章针对不同的实际应用需求,对三种特征检测和匹配算法进行总结并进行代码实践:
1.最传统的且应用最为广泛的sift特征检测匹配算法。
2.速度和精度之间的平衡,注重实时性的slam中常用的orb特征检测和匹配算法。
3.最新且效果很好的基于深度学习的特征检测和匹配算法superpoint+superglue。
1.sift特征检测和匹配算法
关于sift的算法原理及解释网上有很多资料,如果想深入理解还可以找来原论文读一读,所以这里就简单介绍下sift特征检测和匹配算法。
sift是找到图像中的一些“稳定点”,这些点是一些十分突出的点,比如角点、边缘点、暗区域的亮点以及亮区域的点,其算法假设两幅图像中有相同的景物,那么使用某种方法分别提取各自的稳定点,这些点之间会有相互对应的匹配点。
sift算法找稳定点的方法是找灰度图的局部最值,由于数字图像是离散的,想求导和求最值这些操作都是使用滤波器,而滤波器是有尺寸大小的,使用同一尺寸的滤波器对两幅包含有不同尺寸的同一物体的图像求局部最值将有可能出现一方求得最值而另一方却没有的情况,sift的精妙之处在于采用图像金字塔的方法解决这一问题,我们可以把两幅图像想象成是连续的,分别以它们作为底面作四棱锥,就像金字塔,那么每一个截面与原图像相似,那么两个金字塔中必然会有包含大小一致的物体的无穷个截面,但应用只能是离散的,所以我们只能构造有限层,层数越多当然越好,但处理时间会相应增加,层数太少不行,因为向下采样的截面中可能找不到尺寸大小一致的两个物体的图像。有了图像金字塔就可以对每一层求出局部最值,但是这样的稳定点数目将会很多,所以需要使用某种方法抑制去除一部分点,但又使得同一尺度下的稳定点得以保存。
这里用c++和python各自实现一遍:
c++版本:
这里需要自己安装配置opencv3哈,很简单。安装链接:https://blog.csdn.net/qq_43193873/article/details/126144636
在ubuntu20.04lts下编译执行,首先是cmakelists.txt的编写
cmake_minimum_required(version 2.8)set(cmake_build_type debug)set(dcmake_build_type debug)project(keypointsextractionandmatche)find_package(opencv 3 required)include_directories(${opencv_include_dirs})## cuda(可选择,sift可以进行gpu加速)# find_package(cuda)# if(cuda_found)# set (extra_inc_dirs# ${cuda_include_dirs}# ${cuda_sdk_include_dir}# )# cuda_include_directories(${extra_inc_dirs} ${cmake_current_binary_dir})# set (extra_libraries# ${cuda_libs}# ${cuda_cublas_library}# )# endif(cuda_found)add_executable(keypointsextractionandmatche main.cpp)target_link_libraries(keypointsextractionandmatche ${opencv_libs})
代码:
#include #include #include #include #include #include using namespace std;int main(){ //图像名,自己实践时替换成自己的路径 string image_name1=/home/ccy/code_test/img1.jpg; string image_name2=/home/ccy/code_test/img2.jpg; //先读一个彩色图像用于后续绘制特征点匹配对 cv::mat color_img1 = cv::imread(image_name1, 1); cv::mat color_img2 = cv::imread(image_name2, 1); //将图像转换为灰度图像,用于sift特征提取和匹配 cv::mat gray_img1 = cv::imread(image_name1, 0); cv::mat gray_img2 = cv::imread(image_name2, 0); //计算sift特征检测和匹配的时间 double start = static_cast(cv::gettickcount()); //提取两幅图像的sift特征点并筛选出匹配的特征点 vector keypoints1,keypoints2; cv::mat descriptors1,descriptors2; cv::ptr detector=cv::create(); cv::ptr descriptor=cv::create(); cv::ptr matcher=cv::create(bruteforce); //----------------------------------------------------------------------------------------------------// //opencv3里提供了两种匹配算法,分别是bruteforce和flannbased,bruteforce是暴力匹配,flannbased是基于近似最近邻的匹配。 //bruteforce:通过计算两个特征描述子之间的欧氏距离或其他相似性度量来确定匹配程度。 //bruteforce_l1:这种匹配类型使用l1范数(曼哈顿距离)作为特征描述子之间的距离度量方式。l1范数是将两个向量各个对应元素的差的绝对值求和作为距离的度量方式。 //bruteforce_hamming:这种匹配类型使用汉明距离作为特征描述子之间的距离度量方式。汉明距离是将两个向量各个对应元素的差的绝对值求和作为距离的度量方式。 //bruteforce_hamminglut:这种匹配类型使用汉明距离作为特征描述子之间的距离度量方式。汉明距离是将两个向量各个对应元素的差的绝对值求和作为距离的度量方式。这种匹配类型使用了查找表(lut)来加速汉明距离的计算。 //bruteforce_sl2:这种匹配类型使用平方欧氏距离作为特征描述子之间的距离度量方式。平方欧氏距离是将两个向量各个对应元素的差的平方求和作为距离的度量方式。 //flannbased:基于近似最近邻的匹配,使用快速最近邻搜索包(flann)来计算。 //----------------------------------------------------------------------------------------------------// detector->detect(gray_img1,keypoints1); detector->detect(gray_img2,keypoints2); descriptor->compute(gray_img1,keypoints1,descriptors1); descriptor->compute(gray_img2,keypoints2,descriptors2); //匹配 vector matches; matcher->match(descriptors1,descriptors2,matches); //筛选匹配点 double min_dist=10000,max_dist=0; //找出所有匹配之间的最小距离和最大距离,即是最相似的和最不相似的两组点之间的距离 for(int i=0;i
结果:
python实现:
import cv2# 读取彩色图像image1_color = cv2.imread('/home/ccy/code_test/img1.jpg', 1)image2_color = cv2.imread('/home/ccy/code_test/img2.jpg', 1)# 读取灰度图像image1 = cv2.imread('/home/ccy/code_test/img1.jpg', 0)image2 = cv2.imread('/home/ccy/code_test/img2.jpg', 0)# 计算sift特征检测和匹配的时间start = cv2.gettickcount()# 创建sift对象sift = cv2.sift_create()# 检测关键点和计算描述子keypoints1, descriptors1 = sift.detectandcompute(image1, none)keypoints2, descriptors2 = sift.detectandcompute(image2, none)# 创建flann匹配器flann = cv2.flannbasedmatcher()# 进行特征匹配matches = flann.knnmatch(descriptors1, descriptors2, k=2)# 筛选匹配结果good_matches = []for m, n in matches: if m.distance detectandcompute(image1_gray, cv::noarray(), keypoints1, descriptors1); orb->detectandcompute(image2_gray, cv::noarray(), keypoints2, descriptors2); // 创建flann匹配器 //注意:bruteforce_hamming匹配类型适用于二进制特征描述子,如orb(oriented fast and rotated brief)和brief。 //这种匹配类型使用汉明距离(hamming distance)作为特征描述子之间的距离度量方式。汉明距离是计算两个二进制向量之间不同位的数量。 cv::ptr matcher = cv::bruteforce_hamming); // 进行特征匹配 std::vector matches; matcher->match(descriptors1, descriptors2, matches); // 筛选匹配结果 std::vector goodmatches; double mindist = 100.0; double maxdist = 0.0; for (int i = 0; i < descriptors1.rows; i++) { double dist = matches[i].distance; if (dist maxdist) maxdist = dist; } double thresholddist = 0.6 * maxdist; for (int i = 0; i < descriptors1.rows; i++) { if (matches[i].distance < thresholddist) goodmatches.push_back(matches[i]); } double time = ((double)cv::gettickcount() - start) / cv::gettickfrequency(); cout<=1.1
git clone --recursive https://github.com/cvg/hierarchical-localization/cd hierarchical-localization/python -m pip install -e .
代码:
from hloc import extract_features, match_featuresfrom tqdm import tqdmfrom pathlib import pathimport argparsefrom hloc.utils.parsers import parse_retrievalfrom hloc.utils.io import get_keypoints, get_matchesimport cv2import numpy as npimport timeif __name__ == '__main__': #添加参数,在运行时输入自己的--base_dir,比如我的运行代码是'python spsgtest.py --base_dir /home/ccy/code_test' parser = argparse.argumentparser() parser.add_argument('--base_dir', type=path, required=true) args = parser.parse_args() #图像所在路径 images = args.base_dir / 'images/' #输出路径 outputs=args.base_dir /'output/' #要匹配的图像对所在路径,里面每行的内容为:img1name img2name loc_pairs=args.base_dir / 'loc_pairs.txt' #计时 start = time.time() #提取特征和匹配特征的配置文件 feature_conf = extract_features.confs['superpoint_max'] matcher_conf = match_features.confs['superglue'] #提取特征和匹配特征,利用预训练模型 features = extract_features.main(feature_conf, images, outputs) loc_matches = match_features.main(matcher_conf, loc_pairs, feature_conf['output'], outputs) retrieval_dict = parse_retrieval(loc_pairs) end = time.time() print('time:',end-start) #遍历每一对图像,画出匹配点对和匹配线 for img1 in tqdm(retrieval_dict): img2 = retrieval_dict[img1] for img2name in img2: matches,_ = get_matches(loc_matches, img1, img2name) kpts0= get_keypoints(features, img1) kpts1= get_keypoints(features, img2name) #找出匹配点对的坐标 kpts0 = kpts0[matches[:,0]] kpts1 = kpts1[matches[:,1]] #画出匹配点对 img1=cv2.imread(str(images/img1)) img2=cv2.imread(str(images/img2name)) for i in range(len(kpts0)): cv2.circle(img1,(int(kpts0[i][0]),int(kpts0[i][1])),2,(0,0,255),-1) cv2.circle(img2,(int(kpts1[i][0]),int(kpts1[i][1])),2,(0,0,255),-1) img3=np.zeros((max(img1.shape[0],img2.shape[0]),img1.shape[1]+img2.shape[1],3),np.uint8) img3[:img1.shape[0],:img1.shape[1]]=img1 img3[:img2.shape[0],img1.shape[1]:]=img2 #画出所有匹配线 for i in range(len(kpts0)): cv2.line(img3,(int(kpts0[i][0]),int(kpts0[i][1])),(int(kpts1[i][0])+img1.shape[1],int(kpts1[i][1])),(0,255,0),1) cv2.imwrite('/home/ccy/code_test/result.jpg',img3)
结果:
可以看到sp+sg的结果又快又准!
传感器连接器该怎么选择?
3D芯片堆栈技术解决数据中心分析数据量增长速度问题
英飞凌推出新款高能效IPOL DC-DC降压稳压电源模块
知名厂商大啖可穿戴商机 新一轮芯片热战即将引爆
静态分析:对代码质量至关重要
基于计算机视觉领域中的特征检测和匹配研究
电机定子槽满率是否越高越好?
5g技术会带来哪些问题 5g技术应用于哪些领域
三星和台积电将在扇出型封装展开大战
微生物致病菌检测仪使用说明
三星有望代工苹果M1芯片
智能手机的蓝牙、NFC功能全天开着真的会很耗电吗?
高增益单级运放和增益自举电路设计
空调不制热的原因及解决方法
山东省物联网协会参加2020年山东省科协年会
国产DSP教学实验箱:LCD图片显示实验(工具转换图片)
数字经济的未来发展趋势如何?
工厂企业为什么选择无人自动叉车,它的优势是什么
拆解报告:HiVi惠威 AW-71 TWS真无线蓝牙耳机
家庭网络布线与办公网络布线的区别