SIFT特征点检测以及图像拼接

结合SIFT、单应性变换、RANSAC和SVD分解等算法实现指定几幅图像之间的拼接

1. SIFT特征点检测,得到特征点以及特征向量

如果要实现图像之间的特征点匹配,要通过特征描述子集之间比对完成。常见的匹配器有暴力匹配器快速近似最邻近算法匹配器。暴力匹配器就是将两幅图像中的特征描述子全都匹配一遍,得到最优的结果,它的优点是精度高,但是缺点也是显而易见的,在大量的匹配时,匹配时间会很长。快速近似最邻近算法匹配器,故名思意,它只搜索邻近的点,找到邻近的最优匹配,它的匹配准确度会比暴力匹配器低,但是它的匹配时间大大的缩减了。

cv2.xfeatures2d.SIFT_create(nfeatures=None, nOctaveLayers=None, contrastThreshold=None, edgeThreshold=None, sigma=None)-->descriptor函数用于创建一个用于提取SIFT特征的描述符
* nfeatures,保留的最佳特性的数量。特征按其得分进行排序(以SIFT算法作为局部对比度进行测量);
* nOctavelLayers,高斯金字塔最小层级数,由图像自动计算出;
* constrastThreshold,对比度阈值用于过滤区域中的弱特征。阈值越大,检测器产生的特征越少;
* edgeThreshold ,用于过滤掉类似边缘特征的阈值。 请注意,其含义与contrastThreshold不同,即edgeThreshold越大,滤出的特征越少
* sigma,高斯输入层级, 如果图像分辨率较低,则可能需要减少数值
def detectAndDescribe(self, image):# 转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 建立SIFT生成器descriptor = cv2.xfeatures2d.SIFT_create()# 检测特征点并计算描述子kps, features = descriptor.detectAndCompute(gray, None)kps = np.float32([kp.pt for kp in kps])return kps, features

通过SIFT_create()实例化SIFT对象,调用detectAndCompute方法得到特征点和特征向量

2. 使用KNN得到和图像A中一个点最接近的前K的点在B中的位置

这里使用RANSAC方法,找到和一个点在另一张图片上最相似的两个点,如果第一个点的近似程度远远大于第二个点,那么才认为第一个点是可靠的匹配点。

rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
参数:
* featureA和featureB 表示两个特征向量集;
* K 表示按knn匹配规则输出的最优的K个结果
在该算法中,输出的结果是:featureA(检测图像)中每个点与被匹配对象featureB(样本图像)中特征向量进行运算的匹配结果。
则,rawMatches中共有featureA条记录,每一条有最优K个匹配结果。
每个结果中包含三个非常重要的数据分别是queryIdx,trainIdx,distance- queryIdx:特征向量的特征点描述符的下标(第几个特征点描述符),同时也是描述符对应特征点的下标
- trainIdx:样本特征向量的特征点描述符下标,同时也是描述符对应特征点的下标
- distance:代表匹配的特征点描述符的欧式距离,数值越小也就说明俩个特征点越相近
def matchKeypoints(self, kpsA, kpsB, featureA, featureB, ratio, reprojThresh):# 建立暴力匹配器matcher = cv2.BFMatcher()# 使用KNN检测来自AB图的SIFT特征匹配rawMatches = matcher.knnMatch(featureA, featureB, 2)# 过滤matches = []for m in rawMatches:if len(m) == 2 and m[0].distance < m[1].distance * ratio:matches.append((m[0].trainIdx, m[0].queryIdx))if len(matches) > 4:# 获取匹配对的点坐标ptsA = np.float32([kpsA[i] for (_, i) in matches])ptsB = np.float32([kpsB[i] for (i, _) in matches])

3. 通过点对计算H矩阵

cv2.findHomography(srcPoints, dstPoints, method=None, ransacReprojThreshold=None, mask=None, maxIters=None, confidence=None) --> (H, status)
计算多个二维点对之间的最优单映射变换矩阵H(3*3),status为可选的输出掩码,0/1 表示在变换映射中无效/有效
* method(0, RANSAC, LMEDS, RHO)
* ransacReprojThreshold 最大允许冲投影错误阈值(限方法RANSAC和RHO)
* mask可选输出掩码矩阵,通常由鲁棒算法(RANSAC或LMEDS)设置,是不需要设置的
* maxIters为RANSAC算法的最大迭代次数,默认值为2000
* confidence可信度值,取值范围为0到1.
# 计算H矩阵H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, reprojThresh)

4. 利用单应矩阵对图片进行变换拼接

cv.warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None) --> result
将图像按照变换映射M执行后返回变换后的图像result。
# 将图片A进行视角变换 中间结果result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))# 将图片B传入]result[0:imageB.shape[0], 0:imageB.shape[1]] = imageBself.cv_show('result', result)

tip:两张图片分左右

源图片:


目标图像:

源代码:

main文件:

from Stitcher import Stitcher
import cv2# 读取图片
img1 = cv2.imread('img1.jpg')
img2 = cv2.imread('img2.jpg')# 图片拼接
stitcher = Stitcher()
result, vis = stitcher.stitch([img1, img2], showMatches=True)cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('keypoints matches', vis)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyWindow()

Stitcher文件:

import  numpy as np
import cv2class Stitcher:# 拼接函数def stitch(self, images, ratio = 0.75, reprojThresh = 4.0, showMatches = False):# 读取图像imageB, imageA = images# 计算特征点和特征向量kpsA, featureA = self.detectAndDescribe(imageA)kpsB, featureB = self.detectAndDescribe(imageB)# 匹配两张图片的特征点M = self.matchKeypoints(kpsA, kpsB, featureA, featureB, ratio, reprojThresh)# 没有匹配点,退出if not M:return Nonematches, H, status = M# 将图片A进行视角变换 中间结果result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))# 将图片B传入]result[0:imageB.shape[0], 0:imageB.shape[1]] = imageBself.cv_show('result', result)# 检测是否需要显示图片匹配if showMatches:# 生成匹配图片vis = self.drawMatches(imageA, imageB, kpsA, kpsB, matches, status)# 返回结果return result, vis# 返回匹配结果return resultdef detectAndDescribe(self, image):# 转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 建立SIFT生成器descriptor = cv2.xfeatures2d.SIFT_create()# 检测特征点并计算描述子kps, features = descriptor.detectAndCompute(gray, None)kps = np.float32([kp.pt for kp in kps])return kps, featuresdef matchKeypoints(self, kpsA, kpsB, featureA, featureB, ratio, reprojThresh):# 建立暴力匹配器matcher = cv2.BFMatcher()# 使用KNN检测来自AB图的SIFT特征匹配rawMatches = matcher.knnMatch(featureA, featureB, 2)# 过滤matches = []for m in rawMatches:if len(m) == 2 and m[0].distance < m[1].distance * ratio:matches.append((m[0].trainIdx, m[0].queryIdx))if len(matches) > 4:# 获取匹配对的点坐标ptsA = np.float32([kpsA[i] for (_, i) in matches])ptsB = np.float32([kpsB[i] for (i, _) in matches])# 计算H矩阵H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, reprojThresh)return matches, H, status# 展示图像def cv_show(self,name, img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()def drawMatches(self, imageA, imageB, kpsA, kpsB, matches, status):# 初始化可视化图片,将A、B图左右连接到一起hA, wA = imageA.shape[:2]hB, wB = imageB.shape[:2]vis = np.zeros((max(hA, hB), wA + wB, 3), dtype="uint8")vis[0:hA, 0:wA] = imageAvis[0:hB, wA:] = imageB# 联合遍历,画出匹配对for ((trainIdx, queryIdx), s) in zip(matches, status):# 当点对匹配成功时,画到可视化图上if s == 1:# 画出匹配对ptA = (int(kpsA[queryIdx][0]), int(kpsA[queryIdx][1]))ptB = (int(kpsB[trainIdx][0]) + wA, int(kpsB[trainIdx][1]))cv2.line(vis, ptA, ptB, (0, 255, 0), 1)# 返回可视化结果return vis

图像拼接——python相关推荐

  1. python+opencv图像拼接-python opencv 图像拼接的实现方法

    初级的图像拼接为将两幅图像简单的粘贴在一起,仅仅是图像几何空间的转移与合成,与图像内容无关.高级图像拼接也叫作基于特征匹配的图像拼接,拼接时消去两幅图像相同的部分,实现拼接合成全景图. 具有相同尺寸的 ...

  2. 图像拼接 python c++

    https://github.com/AlessandroMinervini/Mosaic-creation-through-the-stitching-of-aerial-rectified-ima ...

  3. 用python完成图形输出设备_使用numpy进行9宫格图像拼接 - Python

    本节内容要用到opencv-python模块,请先行安装.本例程中使用到的图片保存在pictures子目录下.本例的任务是要将9张JPG格式图片按三行三列拼接成下述九宫格. 微实践:九宫格图像拼接 本 ...

  4. python 图像拼接 检测_图像处理之图像拼接(python)

    一.算法目的 在同一位置拍摄两张以上图片,这些图片是单应性相关的,即图片之间有相同的拍摄区域.基于此将图片进行缝补,拼成一个大的图像来创建全景图像. 二.基本原理 要实现两张图片的简单拼接,其实只需找 ...

  5. centos搜查文件_警察在种族歧视方面的制止和搜查

    centos搜查文件 抽象 (ABSTRACT) This report aims to investigate whether the police force is racially biased ...

  6. Python图像拼接:创建全景图

    Python图像拼接:创建全景图 算法原理 基础流程 几何原理 核心步骤(RANSAC算法) 源代码 结果分析 综述 夜景(中华城) 室内(引桐楼) 多建筑(鹭江道周边) 单调场景(海滩) 复杂场景( ...

  7. python 全景图像拼接( python3.6 + opencv3.4.2.16) 融合

    全景图像拼接 全景图像拼接的手动实现 环境: python3.6 + opencv3.4.2.16 ## 示例图片 本次实验使用的图像拼接素材为以下三张图像: https://andreame.com ...

  8. python图像拼接过渡自然_python实现图像拼接功能

    利用Python将Market1501的分割图片和原图两张图片进行拼接成一左一右一张图片,并将图片的像素值调整成256*128. 所有文件夹: 文件夹下的所有原图: 文件夹下的所有的分割图片: 代码如 ...

  9. python实现单张图像拼接与批量图片拼接

    本文实例为大家分享了python实现图像拼接的具体代码,供大家参考,具体内容如下 一.效果  很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例 ...

最新文章

  1. 看完微软大神写的求平均值代码,我意识到自己还是too young了
  2. 添加Page_Init事件
  3. 前端进阶-Position
  4. linux里hba状态_在Linux/Unix平台查看HBA卡的WWN号 和状态
  5. gcc / -L 和 -Wl,-rpath 区别
  6. 190313每日一句
  7. 开发一个App要100万? 太扯淡
  8. Vision Transformer模型/论文详解
  9. K线形态识别—多K线之卖出型多日K线组合
  10. 费马小定理 欧拉定理 逆元
  11. 终于解决“Git Windows客户端保存用户名与密码”的问题zhz
  12. Chrome vimium 插件
  13. 最新解决谷歌翻译无法使用的教程
  14. csapp实验摘选 I Data Lab ——小小菜下士的第一篇博客
  15. 如何才能让你的网店生意好到爆?
  16. C语言 平面向量加法
  17. 如何查看主机名和IP地址
  18. Linux游戏 0 A.D安装及汉化
  19. IDE(ATA),SATA,SCSI的区别
  20. 【Android休眠】之PowerKey唤醒源实现

热门文章

  1. 优麒麟系统中QtCreator无法输入中文
  2. h5获取pdf文件实现预览
  3. jakarta ee_Jakarta EE 8发布@ Eclipse Foundation
  4. 【经典案例】银行的绩效考核方案设计
  5. ocv特性_基于SOC-OCV曲线特征的SOH估计方法研究
  6. 此URL不支持Http方法POST
  7. 新媒体运营P2笔记-02.新媒体人的三种境界(能力进阶)
  8. 顶尖游戏公司介绍---暴雪
  9. 淘宝新品破零到爆款打造的流程和思路
  10. 【Ethernet】以太网卡LAN8720A分析和使用