当前位置:   article > 正文

23. Opencv——图像拼接项目_cv2.surf_create()

cv2.surf_create()

特征检测的基本概念

应用场景:

1.图像搜索,如以图搜图,提取图片中的主要特征点进行搜索

2.拼图游戏

3.图像拼接,将两张有关联的图拼接到一起

拼图方法:

1.寻找特征

2.特征点唯一,可追踪,能比较

3.平坦部分很难找到它在原图中的位置

4.边缘相比平坦要好找一些,但也不能一下确定具体位置

5.角点可以一下就能找到其在原图的位置

什么是特征?

图像特征就是指有意义的图像区域,具有独特性、易于识别性,比如角点,斑点以及高密度区

角点

在特征中最重要的是角点

灰度梯度的最大值对应的像素、两条线的交点、极值点(一阶导数最大值,但二阶导数为0)

Harris角点(常用的方法)

第一种情况:对于这个窗口来说,它可以朝任何方向进行移动,如果在这个窗口范围内它向任何一块方向移动之后,窗口内的像素没有任何的变化,说明这是一个平坦的图片,也就是说在这张图片中没有角点。

第二种情况:如果这个检测窗口在一条边沿上移动,虽然这个边缘与周围的像素不同,但是由于它上下移动,所以其中心点像素不会发生改变,线上及左右两边也不会发生改变,当检测窗口左右移动时像素有变化,则为一条边缘。

第三种情况:检测窗口在一个焦点上

  • 光滑地区:无论向哪里移动,衡量系数不变
  • 边缘处:垂直边缘移动时,衡量系数变化剧烈
  • 在交叉点处,无论往那个方向移动,衡量系数都变化剧烈

Harris角点检测API

注:角点检测应为一张灰度图

cornerHarris(img, dst, blockSize, ksize, k)

dst        输出结果(检测到焦点时,输出矩阵)

blockSize        检测窗口的大小,设置的窗口越大,敏感度越高

ksize        Sobel(索贝尔)的卷积核,朝着横向或者纵向进行卷积,卷积核一般设置为3

k        权重系数,经验值,一般取0.02~0.04之间

  1. import cv2
  2. from matplotlib.pyplot import gray
  3. import numpy as np
  4. blockSize = 2
  5. ksize = 3
  6. k = 0.04
  7. img = cv2.imread("E:\\chess.png")
  8. # 灰度化
  9. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  10. # Harris角点检测
  11. dst = cv2.cornerHarris(gray, blockSize, ksize, k)
  12. # 角点展示,取dst中的最大值进行判断,大于阈值的全被显示出来
  13. img[dst > 0.01*dst.max()] = [0,0,255] # 红色显示
  14. cv2.imshow('harris',img)
  15. cv2.waitKey(0)

shi—Tomasi角点检测

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

默认采用false不使用Harris角点检测,若使用Harris角点检测(true),则需要设置K,默认为0.04

在实际使用中,填写前4个参数即可

  1. import cv2
  2. from cv2 import cornerSubPix
  3. from matplotlib.pyplot import gray
  4. import numpy as np
  5. # tomasi
  6. maxCorners = 1000
  7. qualityLevel = 0.01
  8. minDistance = 10 # 距离越大,检测的角数越少
  9. img = cv2.imread("E:\\chess.png")
  10. # 灰度化
  11. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  12. corners = cv2.goodFeaturesToTrack(gray, maxCorners, qualityLevel, minDistance)
  13. corners = np.int0(corners) # 将浮点型转换为整型
  14. # shi_Tomasi 绘制角点
  15. for i in corners:
  16. x,y = i.ravel() #转换为一维数组
  17. cv2.circle(img, (x,y), 3, (0,0,255),-1)
  18. cv2.imshow('shi_Tomasi',img)
  19. cv2.waitKey(0)

    shi—Tomasi角点检测是更常用的角点检测方法

SIFT关键点检测

Scale-Invariant Feature Transform(SIFI)  与缩放无关的角点检测,也是OPENCV中获取角点的一个重要方法。

sift出现的原因:

Harris角点具有旋转不变的特性,但缩放后,原来的角点有可能就不是角点了

sift优点:原来检测的为角,放大后检测的还是一个角

harris检测:原来检测的为角,但是放大后,检测的就变为了边缘,不是一个角。

使用SIFT的步骤

  1. 创建SIFT对象
  2. 进行检测,获取关键点  kp = sift.detect(img, ...)
  3. 绘制关键点, drawKeypoints(gray, kp, img)
  1. import cv2
  2. from cv2 import cornerSubPix
  3. from matplotlib.pyplot import gray
  4. import numpy as np
  5. img = cv2.imread("E:\\chess.png")
  6. # 灰度化
  7. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. # 创建sift对象
  9. sift = cv2.SIFT_create()
  10. kp = sift.detect(gray, None) # 第二个参数为mask区域
  11. # 绘制角点,第三个参数为在那张图上进行绘制
  12. cv2.drawKeypoints(gray, kp, img)
  13. cv2.imshow('img',img)
  14. cv2.waitKey(0)

SIFI算法的报错处理

将    sift = cv2.xfeatures2d.SIFT_create() 

改为    sift = cv2.SIFT_create()    即可

SIFT计算描述子

关键点和描述子

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

计算描述子

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

 在实际使用中,常用该API进行计算

  1. kp, des = sift.detectAndCompute(gray, None)
  2. print(des) #打印描述子

 描述子主要用在特征匹配上

SURF特征检测

Speeded-Up Robust Features(SURF)  :加速的鲁棒性特征检测

SIFT最大的优点:进行检测时,特征点检测的特别准确,描述子也描述的非常详细

SURF的优点:SIFT最大的问题是速度慢,因此才有SURF,进行一系列图片检测时,处理速度非常慢,SURF保留了SIFT的优点

使用SURF的步骤

  1. import cv2
  2. import numpy as np
  3. img = cv2.imread("E:\\chess.png")
  4. # 灰度化
  5. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6. # 创建surf对象
  7. surf = cv2.xfeatures2d.SURF_create() #surf检测
  8. # 使用surf进行检测
  9. kp, des = surf.detectAndCompute(gray, None)
  10. # print(des) #打印描述子
  11. # 绘制角点,第三个参数为在那张图上进行绘制
  12. cv2.drawKeypoints(gray, kp, img)
  13. cv2.imshow('img',img)
  14. cv2.waitKey(0)

解决SIFT和SURF由于专利原因报错的方法

  1. 卸载高版本的python,安装python3.6
  2. 复制以下两条命令到控制端进行安装:
  3. pip install opencv-python==3.4.2.16
    pip install opencv-contrib-python==3.4.2.16

经过以上步骤,即可解决程序报错问题

ORB特征检测

Oriented FAST and Rotated BRIEF   特征点检测与描述子计算的结合

需要抛弃部分数据,才能提升速度,检测准确度有所下降,当检测大量数据时采用该方法。

注:ORB没有版权问题,是开源的

FAST        可以做到特征点的实时检测,不带方向

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

  1. # 创建orb对象
  2. orb = cv2.ORB_create()
  3. kp, des = orb.detectAndCompute(gray, None)

小结

SIFT        计算准确率最高,但是速度较慢

SURF        准确率略低于SIFT,但是速度块

ORB        可以进行实时检测,速度更快,但是准确性没有前两者好

暴力特征匹配

经过以上几节的特征点检测的学习,接下来进行两张图片的特征点匹配学习

特征匹配方法:

BF(Brute- Force)        暴力特征匹配方法,通过枚举的方式实现

FLANN        最快邻近区特征匹配方法

暴力特征匹配原理

它使用第一组中的每个特征的描述子,与第二组中的所有特征描述子进行匹配,计算他们之间的差距,然后将最接近一个匹配返回

OPENCV特征匹配步骤

  • 创建匹配器  BFMatcher(normType, crossCheck)        第一个参数为匹配类型,第二个参数为交叉检查
  • 进行特征匹配      bf.match(des1,des2)     第一幅图的描述子与第二幅图进行匹配
  • 绘制匹配点    cv2.drawMatches(img1,kp1,img2,kp2,...)

 

 

  1. import cv2
  2. import numpy as np
  3. img1 = cv2.imread('E:\\opencv_photo\\opencv_search.png')
  4. img2 = cv2.imread('E:\\opencv_photo\\opencv_orig.png')
  5. # 灰度化
  6. gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
  7. gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
  8. # 创建surf对象
  9. surf = cv2.xfeatures2d.SURF_create()
  10. # 计算特征点和描述子
  11. kp1, des1 = surf.detectAndCompute(gray1, None)
  12. kp2, des2 = surf.detectAndCompute(gray2, None)
  13. # 创建匹配器
  14. bf = cv2.BFMatcher(cv2.NORM_L1)
  15. # 进行特征匹配
  16. match = bf.match(des1, des2)
  17. img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)
  18. cv2.imshow('img3',img3)
  19. cv2.waitKey(0)

 FLANN特征匹配

 

 当选择SIFT和SURF时,选择KDTREE,若为ORB选择LSH

经验值,一般KDTREE设为5

 

 

  1. # FLANN特征匹配
  2. import cv2
  3. import numpy as np
  4. img1 = cv2.imread('E:\\opencv_photo\\opencv_search.png')
  5. img2 = cv2.imread('E:\\opencv_photo\\opencv_orig.png')
  6. # 灰度化
  7. gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
  8. gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
  9. # 创建surf对象
  10. surf = cv2.xfeatures2d.SURF_create()
  11. # 计算特征点和描述子
  12. kp1, des1 = surf.detectAndCompute(gray1, None)
  13. kp2, des2 = surf.detectAndCompute(gray2, None)
  14. # 创建匹配器
  15. index_params = dict(algorithm = 1, trees = 5)
  16. search_params = dict(checks = 50)
  17. flann = cv2.FlannBasedMatcher(index_params, search_params)
  18. #对描述子进行匹配计算
  19. matchs = flann.knnMatch(des1, des2, k=2)
  20. # 过滤,对所有匹配点进行优化
  21. good = []
  22. for i, (m,n) in enumerate(matchs):
  23. if m.distance < 0.7 * n.distance:
  24. good.append(m)
  25. ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
  26. cv2.imshow('result',ret)
  27. cv2.waitKey()

 

 结果与暴力匹配类似,但是速度更快,暴力匹配的精度更高一点

 图像查找

用到两种技术:特征匹配+单应性矩阵

 单应性矩阵作用:获取到一个矩阵,这个矩阵与图像A进行运算,可以得到图像2的位置

图像2经过计算可以得到原始的位置

把图片转正

 抠图,贴图

步骤:

首先进行特征点匹配,计算单应性矩阵,计算透视变换

  1. # 图像查找
  2. import cv2
  3. import numpy as np
  4. img1 = cv2.imread('E:\\opencv_photo\\opencv_search.png')
  5. img2 = cv2.imread('E:\\opencv_photo\\opencv_orig.png')
  6. # 灰度化
  7. gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
  8. gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
  9. # 创建surf对象
  10. surf = cv2.xfeatures2d.SURF_create()
  11. # 计算特征点和描述子
  12. kp1, des1 = surf.detectAndCompute(gray1, None)
  13. kp2, des2 = surf.detectAndCompute(gray2, None)
  14. # 创建匹配器
  15. index_params = dict(algorithm = 1, trees = 5)
  16. search_params = dict(checks = 50)
  17. flann = cv2.FlannBasedMatcher(index_params, search_params)
  18. #对描述子进行匹配计算
  19. matchs = flann.knnMatch(des1, des2, k=2)
  20. # 过滤,对所有匹配点进行优化
  21. good = []
  22. for i, (m,n) in enumerate(matchs):
  23. if m.distance < 0.7 * n.distance:
  24. good.append(m)
  25. # ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
  26. # 匹配点必须大于等于4
  27. if len(good) >= 4:
  28. # 查找单应性矩阵
  29. srcpts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
  30. #对数组进行重新变换,有无数行,每一行有1个元素,每个元素由2个子元素组成
  31. dstpts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
  32. H,_ = cv2.findHomography(srcpts, dstpts, cv2.RANSAC, 5.0)
  33. # 第三个参数是对匹配点进行过滤,随机抽样获取规律,最后一个参数为阈值
  34. # 第一个返回值为单应性矩阵,第二个参数为其掩码,不需要显示,所以用_代替
  35. # 透视变换
  36. h,w = img1.shape[:2]
  37. pts = np.float32([[0,0],[0,h-1], [w-1, h-1], [w-1, 0]]).reshape(-1,1,2) # 四个角点,左上角,左下角,右下角,右上角
  38. dst = cv2.perspectiveTransform(pts, H)
  39. # 用多边形框起来
  40. cv2.polylines(img2, [np.int32(dst)], True,(0,255,255))
  41. else:
  42. print('the number of good is less than 4.')
  43. exit()
  44. # 绘制图像
  45. ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
  46. cv2.imshow('result',ret)
  47. cv2.waitKey()

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/81188?site
推荐阅读
相关标签
  

闽ICP备14008679号