当前位置: 首页 > news >正文

OpenCV 特征点检测与匹配

一 OpenCV特征场景

①图像搜索,如以图搜图;
②拼图游戏;
③图像拼接,将两长有关联得图拼接到一起;

1 拼图方法

寻找特征
特征是唯一的
可追踪的
能比较的

二 角点

在特征中最重要的是角点
灰度剃度的最大值对应的像素
两条线的角点
极值点(一阶导数最大值,但二阶导数为0)

三 Harris角点

哈里斯角点检测
在这里插入图片描述
Harris点
① 光滑地区,无论向哪里移动,衡量系数不变;
②边缘地址,垂直边缘移动时,衡量系统变换剧烈;
③在交点处,往哪个方向移动,衡量系统都变化剧烈;

1 Harris角点检测API

cornerHarris(img,dst,blockSize,ksize,k)
blockSize:检测窗口大小
ksize:Sobel的卷积核
k:权重系数,经验值,一般取0.02~0.04之间。
import cv2
import numpy as npblockSize=2ksize=1k=0.04img=cv2.imread('chess.jpg')#灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#Harris角点检测
dst=cv2.cornerHarris(gray,blockSize,ksize,k)#Harris角点的展示
img[dst>0.04*dst.max()]=[0,0,255]
cv2.imshow('img',img)
cv2.waitKey(0)

四 Shi_Tomasi交点检测

Shi-Tomasi是Harris角点检测的改进;
Harris角点检测的稳定性和K有关,而k是个经验值,不好设定最佳值。

1 Shi-Tomasi角点检测API

goodFeaturesToTrack(img,maxCorners,...)
maxCorners:角点的最大数,值为0表示无限制
qualityLevel:小于1.0的正数,一般在0.01~0.1之间
minDistance:角之间最小欧式距离,忽略小于此距离的点。
mask:感兴趣的区域
blockSize:检测窗口
useHarrisDetector:是否使用Harris算法
k:默认是0.04
import cv2
import numpy as npmaxCorners=100
ql=0.01img=cv2.imread('./chess.jpg')
cv2.imshow('img',img)
#灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# Shi-Tomasi
corners=cv2.goodFeaturesToTrack(gray,maxCorners,ql,10)
print(corners)
corners=np.int32(corners)
# Shi-Tomasi绘制角点
for i in corners:x,y=i.ravel()cv2.circle(img,(x,y),3,(255,0,0),-1)cv2.imshow('img',img)
cv2.waitKey(0)

五 SIFT(Scale-Invariant Feature Transform)

SIFT出现的原因:
harris 角点具有旋转不变的特性;
但缩放后,原来的角点有可能就不是角点了;

图放大
在这里插入图片描述

使用SIFT的步骤

①创建SIFT对象
②进行检测,kp=sift.detect(img,…)
③绘制关键点,drawKeypoints(gray,kp,img)

from email.mime import imageimport cv2
import numpy as npimg=cv2.imread('./chess.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)sift=cv2.xfeatures2d.SIFT_create()kp=sift.detect(gray,None)cv2.drawKeypoints(gray,kp,img)cv2.imshow('img',img)
cv2.waitKey(0)

在这里插入图片描述

六 SIFT计算描述子

关键点和描述子
关键点:位置,大小和方向
关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换、光照变换等影响。

计算描述子

kp,des=sift.compute(img,kp)
其作用是进行特征匹配

同时计算关键点和描述

kp,des=sift.detectAndCompute(img,...)
mask:指明对img中哪个区域进行计算
import cv2
import numpy as npimg=cv2.imread('./chess.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)sift=cv2.xfeatures2d.SIFT_create()kp,des=sift.detectAndCompute(gray,None)
print(des)
cv2.drawKeypoints(gray,kp,img)cv2.imshow('img',img)
cv2.waitKey(0)

在这里插入图片描述

七 SURF特征检测

SURF的优点
SIFT最大的问题是速度慢,因此才有SURF

使用SURF的步骤

surf=cv2.xfeatures2d.SUFR_create()
kp,des=surf.detectAndCompute(img,mask)
import cv2
import numpy as npimg=cv2.imread('./chess.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)surf=cv2.xfeatures2d.SURF_create()kp,des=surf.detectAndCompute(gray,None)print(des[0])cv2.drawKeypoints(gray,kp,img)cv2.imshow('img',img)
cv2.waitKey(0)

八 ORB(Oriented FAST and Rotated BRIEF)特征检测

1 ORB 优势

①ORB可以做到实时检测
②ORB=Oriented FAST+Rotated BRIEF

2 FAST

可以做到特征点的实时检测

3 BRIEF

BRIEF是对已检测到的特征点进行描述,它加快了特征描述符建立的速度。同时也极大的降低了特征匹配的时间。

3 ORB使用步骤

orb=cv2.ORB_create()
kp,des=orb.detectAndCompute(img,mask)
import cv2
import numpy as npimg=cv2.imread('./chess.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)orb=cv2.ORB_create()kp,des=orb.detectAndCompute(gray,None)cv2.drawKeypoints(gray,kp,img)cv2.imshow('img',img)
cv2.waitKey(0)

在这里插入图片描述

九 暴力特征匹配

1 特征匹配方法

①BF(Brute-Force),暴力特征匹配方法;
②FLANN最快邻近区特征匹配方法;
它使用第一组中的每个特征的描述子与第二组中的所有特征描述子进行匹配计算它们之间的差距,然后将最接近一个匹配返回。

2 OpenCV特征匹配步骤

创建匹配器,BFMatcher(normType,crossCheck)
进行特征匹配,bf.match(des1,des2)
绘制匹配点,cv2.drawMatches(img1,kp1,img2,k2,...)
BFMatcher
normType:NORM_L1,NORM_L2,HAMMING1....
crossCheck:是否进行交叉匹配,默认为false
Match方法
参数为SIFT,SURF,OBR等计算的描述子
对两幅图的描述子进行计算
drawMatches
搜索img,kp
匹配图img,kp
match()方法返回的匹配结果
import cv2
import numpy as npimg=cv2.imread('./opencv_search.png')
img1=cv2.imread('./opencv_orig.png')gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray1=cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)sift=cv2.xfeatures2d.SIFT_create()kp1,des1=sift.detectAndCompute(gray,None)
kp2,des2=sift.detectAndCompute(gray1,None)bf=cv2.BFMatcher(cv2.NORM_L1)
match=bf.match(des1,des2)img3=cv2.drawMatches(img,kp1,img1,kp2,match,None)cv2.imshow('img3',img3)
cv2.waitKey(0)

在这里插入图片描述

十 FLANN特征匹配

1 FLANN优缺点

在进行批量特征匹配时,FLANN速度更快;
由于它使用的是邻近近似值,所以精度较差;

2 使用FLANN特征匹配的步骤

①创建FLANN匹配器,FlannBasedMatcher(...)
②进行特征匹配,flann.match/knnMatch(...)
③绘制匹配点,cv2.drawMathes/drawMatchesKnn(...)
FlannBasedMathcer
index_params字典:匹配算法KDTREE、LSH
search_params字典:指定KETREE算法中遍历树的次数
KDTREE
index_params=dict(algorithmFLANN_INDEX_KETREE,trees=5)
search_params
search_params=dict(checks=50)
knnMatch方法
参数为SIFT、SURF、ORB等计算的描述子;
k,表示取欧式距离最近的前k个关键点;
返回的是匹配的结果DMatch对象;
DMatch的内容
distance,描述子之间的距离,值越低越好;
queryIdx,第一个图像的描述子索引值;
trainIdx,第二个图的描述子索引值;
imgIdx,第二个图的索引值;drawMatchesKnn
搜索img,kp
匹配图img,kp
match()方法返回的匹配结果

十一 实战FLANN特征匹配

import cv2
import numpy as npimg1=cv2.imread('opencv_search.png')
img2=cv2.imread('opencv_orig.png')gray1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)#创建SIFT特征
sift=cv2.xfeatures2d.SIFT_create()#计算描述子与特征
kp1,des1=sift.detectAndCompute(img1,None)
kp2,des2=sift.detectAndCompute(img2,None)# 创建匹配器
index_params=dict(algorithm=1,trees=5)
search_params=dict(checks=50)
flann=cv2.FlannBasedMatcher(index_params,search_params)#对描述子进行匹配计算
matchs=flann.knnMatch(des1,des2,k=2)good=[]
for i,(m,n)in enumerate(matchs):if m.distance<0.7*n.distance:good.append(m)ret=cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)cv2.imshow('result',ret)
cv2.waitKey(0)

在这里插入图片描述

十二 图像查找

1 图像查找

特征匹配+单应性矩阵

什么是单应性矩阵
在这里插入图片描述

import cv2
import numpy as npimg1=cv2.imread('opencv_search.png')
img2=cv2.imread('opencv_orig.png')gray1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)#创建SIFT特征
sift=cv2.xfeatures2d.SIFT_create()#计算描述子与特征
kp1,des1=sift.detectAndCompute(img1,None)
kp2,des2=sift.detectAndCompute(img2,None)# 创建匹配器
index_params=dict(algorithm=1,trees=5)
search_params=dict(checks=50)
flann=cv2.FlannBasedMatcher(index_params,search_params)#对描述子进行匹配计算
matchs=flann.knnMatch(des1,des2,k=2)good=[]for i,(m,n) in enumerate(matchs):if m.distance<0.7*n.distance:good.append(m)if len(good)>=4:#print(len(good.trainIdx))srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)H, _ = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)h, w = img1.shape[:2]pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)dst = cv2.perspectiveTransform(pts, H)cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))
else:print('the number of god is less than 4')exit()ret=cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)cv2.imshow('resutl',ret)cv2.waitKey(0)

十三 图像拼接

1 图像合并的步骤

读文件并重置尺寸;
根据特征点和计算描述子,得到单应性矩阵;
图像变换;
图像拼接并输出图像;

import cv2
import numpy as np#第一步 读取文件,将图片设置成一样大小640x640
#第二步 找特征点,描述子,计算单应性矩阵
#第三步 根据单应性矩阵对图像进行变换,然后平移
#第四步 拼接并输出最终结果#读取两张图片
img1=cv2.imread('map1.png')
img2=cv2.imread('map2.png')#将两张同样图片设置成同样大小
img1=cv2.resize(img1,(640,480))
img2=cv2.resize(img2,(640,480))inputs=np.hstack((img1,img2))
cv2.imshow('input img',inputs)
cv2.waitKey(0)
import cv2
import numpy as npdef stitch_image(img1,img2,H):
#获得每张图片的四个角点
#对图片进行变换(单应性矩阵使图进行旋转,平移)
#创建一张大图,将两张图拼接到一起
#将结果输出#获得原始图的高/宽h1,w1=img1.shape[:2]h2,w2=img2.shape[:2]img1_dims=np.float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)img2_dims=np.float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)img1_transform=cv2.perspectiveTransform(img1_dims,H)result_dims=np.concatenate((img2_dims,img1_transform),axis=0)[x_min, y_min] = np.int32(result_dims.min(axis=0).ravel() - 0.5)[x_max, y_max] = np.int32(result_dims.max(axis=0).ravel() + 0.5)#平移的距离transform_dist=[-x_min,-y_min]transform_array=np.array([[1,0,transform_dist[0]],[0,1,transform_dist[1]],[0,0,1]])result_img=cv2.warpPerspective(img1,transform_array.dot(H),(x_max-x_min,y_max-y_min))result_img[transform_dist[1]:transform_dist[1]+h2,transform_dist[0]:transform_dist[0]+w2]=img2return result_img#第一步 读取文件,将图片设置成一样大小640x640
#第二步 找特征点,描述子,计算单应性矩阵
#第三步 根据单应性矩阵对图像进行变换,然后平移
#第四步 拼接并输出最终结果def get_homo(img1,img2):
#创建特征转换对象
#通过特征转换对象获得特征点和描述子
#创建特征匹配器
#进行特征匹配
#过滤特征,找出有效的特征匹配点sift=cv2.xfeatures2d.SIFT_create()k1,d1=sift.detectAndCompute(img1,None)k2,d2=sift.detectAndCompute(img2,None)#创建特征匹配bf=cv2.BFMatcher()matches=bf.knnMatch(d1,d2,k=2)
#过滤特征,找出有效的特征匹配点verify_ratio=0.8verify_matches=[]for m1,m2 in matches:if m1.distance<0.8*m2.distance:verify_matches.append(m1)min_matches=8if len(verify_matches)>min_matches:img1_pts=[]img2_pts=[]for m in verify_matches:img1_pts.append(k1[m.queryIdx].pt)img2_pts.append(k2[m.trainIdx].pt)img1_pts=np.float32(img1_pts).reshape(-1,1,2)img2_pts=np.float32(img2_pts).reshape(-1,1,2)H,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0)return Helse:print("err:Not enough matches!")exit()
#第一步 读取文件,将图片设置成一样大小640x480
#第二步 找特征点,描述子,计算单应性矩阵
#第三步 根据单应性矩阵对图像进行变换,然后平移
#第四步 拼接并输出最终结果#读取两张图片
img1=cv2.imread('map1.png')
img2=cv2.imread('map2.png')#将两张同样图片设置成同样大小
img1=cv2.resize(img1,(640,480))
img2=cv2.resize(img2,(640,480))inputs=np.hstack((img1,img2))#获得单应性矩阵
H=get_homo(img1,img2)#进行图像拼接
result_image=stitch_image(img1,img2,H)cv2.imshow('input img',inputs)
cv2.waitKey(0)
http://www.lryc.cn/news/380095.html

相关文章:

  • css布局之flex应用
  • 树莓派4B设置AP热点步骤
  • Java程序之百鸡百钱问题
  • Mybatis——动态sql
  • 可视化大屏开发系列——页面布局
  • Python statistics 模块
  • wireshark常见使用表达式
  • 用Java获取键盘输入数的个十百位数
  • 第10章 启动过程组 (制定项目章程)
  • html侧导航栏客服栏
  • Clonable接口和拷贝
  • 关于小蛋の编程和小蛋编程为同一作者的说明
  • 大数据平台之Spark
  • How to use ModelSim
  • 【专业英语 复习】第8章 Communications and Networks
  • 运行vue3项目相关报错
  • 2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等
  • Centos Stream9 和Centos Stream10的下载网址
  • chrome 录制器及性能分析工具的使用
  • 如何打造稳定、好用的 Android LayoutInspector?
  • C++ Thead互斥量死锁,mutex如何防止死锁---C++11多线程快速学习
  • Ubuntu 之Glade图形化设计器
  • 152. 乘积最大子数组
  • proactor模式
  • Charles抓包工具
  • RabbitMQ如何保证消息可靠
  • 学习笔记——路由网络基础——路由的高级特性
  • 网络编程之XDP、TC和IO_URING以及DPDK
  • 晶谷高温烧结导电浆料用低熔点玻璃粉 晶谷耐高温导电漆导电油墨高温玻璃粉
  • 【Mysql】DQL操作单表、创建数据库、排序、聚合函数、分组、limit关键字