1. sift.detectAndComputer(gray, None)  # 计算出图像的关键点和sift特征向量

参数说明:gray表示输入的图片

2.cv2.findHomography(kpA, kpB, cv2.RANSAC, reproThresh) # 计算出单应性矩阵

参数说明:kpA表示图像A关键点的坐标, kpB图像B关键点的坐标, 使用随机抽样一致性算法来进行迭代,reproThresh表示每次抽取样本的个数

3.cv2.warpPespective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))  # 获得根据单应性矩阵变化后的图像

参数说明:image表示输入图像,H表示单应性的矩阵,(imageA.shape[1] + imageB.shape[1], imageA.shape[0])表示矩阵变化后的维度

4. cv2.line(imageA, kpsA, imageB, kpsB, (0,0,255), 2)   进行画出直线的操作
参数说明:imageA和imageB表示输入图片, kpsA和kpsB表示关键点的坐标(x, y) ,(0, 0, 255)表示颜色, 2表示直线的宽度

RANSAC算法(随机抽样一致性算法), 对于左边的图,可以看到使用最小二乘法尽可能多的满足点可以分布在拟合曲线周围,减小均分根误差,因此拟合的曲线在一定程度上容易发生偏离,而RANSAC却不会出现这种情况

RANSCA原理, 因为拟合一条直线只需要两个点,因此我们每次随机选取两个点,做出直线,划定一个距离,判断落在直线周围距离范围点的个数,不断的迭代,直到找出拟合的直线,使得点落在上面最多的拟合曲线

图像拼接的关键是在于对图像进行变化,变化后的点与需要拼接的图片中的sift点,越接近,即欧式距离越短,对图像拼接的过程中,至少需要有4对特征点,求取变化矩阵Hi

我们使用RANSAC不断去取随机从两个图像中取4对的sift特征点,计算出H,定义损失值,即x’,与x的距离,即y‘与y的距离之和是否是最小值,不断迭代,找出最佳的H

上述就是计算出来了H值,也就是变化矩阵

代码思路:

第一步:对图像进行灰度化,使用sift.detectAndCompute(image, None) 进行ksp关键点,dpSIFT特征向量,将kps进行向量化操作,即kps.pt

第二步:构建BMFmatch匹配器,获得符合条件的匹配值,matches获得的是ksp关键点的匹配值得索引,使用索引获得符合条件的kspA和kspB

第三步:使用cv2.findHomography(kpA, kpB, cv2.RANSAC,reproThresh) 随机抽取4个点,求得最合适的H变化矩阵

第四步:使用获得的变化矩阵H, cv.warpPerspective 对imageA求取变化后的图像

第五步:将imageB加入到变化后的图像获得最终图像

第六步:如果需要进行展示,构造新的图像,尺寸为imageA.shape[0], imageB.shape[1] +imageA.shape[1], 使用matches的索引,使用cv2.line将符合条件的点进行连接

第七步:返回最终的结果,进行画图展示

import cv2
import numpy as np
import matplotlib.pyplot as plt class Stitcher: def stitch(self, imgs, ratio=0.75, reproThresh=4, showMathes = False): (imageB, imageA) = imgs
# 第一步:计算kpsA和dpsA
(kpsA, dpsA) = self.detectandcompute(imageA)
(kpsB, dpsB) = self.detectandcompute(imageB)
# 获得变化的矩阵H
M = self.matchKeypoint(kpsA, dpsA, kpsB, dpsB, ratio, reproThresh) if M is None:
return None
(matches, H, status) = M # 第四步:使用cv2.warpPerspective获得经过H变化后的图像
result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageB.shape[0])) # 第五步:将图像B填充到进过H变化后的图像,获得最终的图像
result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB if showMathes:
# 第六步:对图像的关键点进行连接
via = self.showMatches(imageA, imageB, kpsA, kpsB, matches, status) return (via, result) return result # 进行画图操作 def showMatches(self, imageA, imageB, kpsA, kpsB, matches, status):
# 将两个图像进行拼接
# 根据图像的大小,构造全零矩阵
via = np.zeros((max(imageB.shape[0], imageA.shape[0]), imageA.shape[1] + imageB.shape[1], 3), np.uint8)
# 将图像A和图像B放到全部都是零的图像中
via[0:imageA.shape[0], 0:imageA.shape[1]] = imageA
via[0:imageB.shape[0], imageA.shape[1]:] = imageB
# 根据matches中的索引,构造出点的位置信息
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] + imageA.shape[1]), int(kpsB[trainIdx][1]))
# 使用cv2.line进行画图操作
cv2.line(via, ptA, ptB, (0, 255, 0), 1) return via def matchKeypoint(self, kpsA, dpsA, kpsB, dpsB, ratio, reproThresh): # 第二步:实例化BFM匹配, 找出符合添加的关键点的索引
bf = cv2.BFMatcher() matcher = bf.knnMatch(dpsA, dpsB, 2) matches = [] for match in matcher: if len(match) == 2 and match[0].distance < match[1].distance * ratio:
# 加入match[0]的索引
matches.append((match[0].trainIdx, match[0].queryIdx))
#第三步:使用cv2.findHomography找出符合添加的H矩阵
if len(matches) > 4:
# 根据索引找出符合条件的位置
kpsA = np.float32([kpsA[i] for (_, i) in matches])
kpsB = np.float32([kpsB[i] for (i, _) in matches])
(H, status) = cv2.findHomography(kpsA, kpsB, cv2.RANSAC, reproThresh) return (matches, H, status)
return None def cv_show(self, img, name):
cv2.imshow(name, img) def detectandcompute(self, image):
# 进行灰度值转化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#实例化sift函数
sift = cv2.xfeatures2d.SIFT_create()
# 获得kps关键点和dps特征向量sift
kps, dps = sift.detectAndCompute(gray, None)
# 获得特征点的位置信息, 并转换数据类型
kps = np.float32([kp.pt for kp in kps]) return (kps, dps)

使用cv2.warpPesctive即根据H变化后的图片                                  经过图像拼接后的result图片                                          经过图片关键点连接的图片

机器学习进阶-案例实战-图像全景拼接-图像全景拼接(RANSCA) 1.sift.detectAndComputer(获得sift图像关键点) 2.cv2.findHomography(计算单应性矩阵H) 3.cv2.warpPerspective(获得单应性变化后的图像) 4.cv2.line(对关键点位置进行连线画图)的更多相关文章

  1. 机器学习进阶-案例实战-答题卡识别判 1.cv2.getPerspectiveTransform(获得投射变化后的H矩阵) 2.cv2.warpPerspective(H获得变化后的图像) 3.cv2.approxPolyDP(近似轮廓) 4.cv2.threshold(二值变化) 7.cv2.countNonezeros(非零像素点个数)6.cv2.bitwise_and(与判断)

    1.H = cv2.getPerspectiveTransform(rect, transform_axes) 获得投射变化后的H矩阵 参数说明:rect表示原始的位置左上,右上,右下,左下, tra ...

  2. 机器学习进阶-案例实战-图像全景拼接-书籍SIFT特征点连接 1.cv2.drawMatches(对两个图像的关键点进行连线操作)

    1.cv2.drawMatches(imageA, kpsA, imageB, kpsB, matches[:10], None, flags=2)  # 对两个图像关键点进行连线操作 参数说明:im ...

  3. 机器学习进阶-案例实战-停车场车位识别-keras预测是否停车站有车

    import numpy import os from keras import applications from keras.preprocessing.image import ImageDat ...

  4. webpack4入门到进阶案例实战课程

    愿景:"让编程不在难学,让技术与生活更加有趣" 更多教程请访问xdclass.net 第一章 webpack4前言 第一集 webpack4入门到进阶案例实战课程介绍 简介:讲述w ...

  5. 机器学习进阶-项目实战-信用卡数字识别 1.cv2.findContour(找出轮廓) 2.cv2.boudingRect(轮廓外接矩阵位置) 3.cv2.threshold(图片二值化操作) 4.cv2.MORPH_TOPHAT(礼帽运算突出线条) 5.cv2.MORPH_CLOSE(闭运算图片内部膨胀) 6. cv2.resize(改变图像大小) 7.cv2.putText(在图片上放上文本)

    7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick) # 参数说明:img表示输入图片,text表示需要填写的 ...

  6. 机器学习进阶-直方图与傅里叶变换-傅里叶变换(高低通滤波) 1.cv2.dft(进行傅里叶变化) 2.np.fft.fftshift(将低频移动到图像的中心) 3.cv2.magnitude(计算矩阵的加和平方根) 4.np.fft.ifftshift(将低频和高频移动到原来位置) 5.cv2.idft(傅里叶逆变换)

    1. cv2.dft(img, cv2.DFT_COMPLEX_OUTPUT) 进行傅里叶变化 参数说明: img表示输入的图片, cv2.DFT_COMPLEX_OUTPUT表示进行傅里叶变化的方法 ...

  7. 机器学习进阶-目标跟踪-KCF目标跟踪方法 1.cv2.multiTracker_create(构造选框集合) 2. cv2.TrackerKCF_create(获得KCF追踪器) 3. cv2.resize(变化图像大小) 4.cv2.selectROI(在图像上框出选框)

    1. tracker = cv2.multiTracker_create() 获得追踪的初始化结果 2.cv2.TrackerKCF_create() 获得KCF追踪器 3.cv2.resize(fr ...

  8. 机器学习进阶-图像基本操作-数值计算 1.cv2.add(将图片进行加和) 2.cv2.resize(图片的维度变换) 3.cv2.addWeighted(将图片按照公式进行重叠操作)

    1.cv2.add(dog_img, cat_img)  # 进行图片的加和 参数说明: cv2.add将两个图片进行加和,大于255的使用255计数 2.cv2.resize(img, (500, ...

  9. 机器学习进阶-背景建模-(帧差法与混合高斯模型) 1.cv2.VideoCapture(进行视频读取) 2.cv2.getStructureElement(构造形态学的卷积) 3.cv2.createBackgroundSubtractorMOG2(构造高斯混合模型) 4.cv2.morpholyEx(对图像进行形态学的变化)

    1. cv2.VideoCapture('test.avi') 进行视频读取 参数说明:‘test.avi’ 输入视频的地址2. cv2.getStructureElement(cv2.MORPH_E ...

随机推荐

  1. Hadoop概念学习系列之Hadoop新手学习指导之入门需知(二十)

    不多说,直接上干货! 零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.从一开始什么都不懂,到能够搭建集群,开发.整个过程,只要有Linux基础,虚拟机化和java基础,其实hadoo ...

  2. JS中模态窗口(showModalDialog)的详细使用

    基本介绍: showModalDialog() (IE + 支持) showModelessDialog() (IE + 支持) window.showModalDialog() 方法用来创建一个显示 ...

  3. react基础

    上一篇文章主要是记录了自己是如何创建react项目的,今天则主要是总结一下react中的一个基础入门知识,包括数据定义和绑定.属性绑定.数组循环等等. 组件继承和挂载 当我们使用脚手架或者命令行创建一 ...

  4. tesseract-ocr4.0 安装部署及训练验证码识别

    1.  下载最新版本的leptonica,  leptonica-1.74.1.tar.gz   2. 编译安装 tar -zxvf leptonica-.tar.gz cd leptonica- . ...

  5. Android多线程下载

    所用知识点: 1.设置http协议字段Range “bytes=“start+”-”+end conn.addRequestProperty("Range", "byte ...

  6. c#类的继承与包含的关系

    基础例子 class Dept { private string name; private Emp emp; public string getName() { return this.name; ...

  7. KPPW2.5 漏洞利用--SQL注入

    KPPW2.5 漏洞利用--SQL注入 SQL注入--布尔型盲注 环境搭建 1,集成环境简单方便,如wamp,phpstudy.... 2,KPPW v2.2源码一份(文末有分享)放到WWW目录下面 ...

  8. 解决ExtNET ExtJS 特定日期选择月份跳转导致无法选择月份的问题

    背景 项目使用 Ext.NET 2.2.0.40838 , 对应Ext JS4.2版本. 结果 2017/3/31 号的时候偶然间点日历选择控件选择2月,10月等月份突然就跳到3月份,9月份之类. 就 ...

  9. python基础知识-(1)语法基础知识总结(转载)

    1.Python标识符 在 Python 里,标识符有字母.数字.下划线组成. 在 Python 中,所有标识符可以包括英文.数字以及下划线(_),但不能以数字开头. Python 中的标识符是区分大 ...

  10. windows下解决python输出utf-8中文

    class UnicodeStreamFilter: def __init__(self, target): self.target = target self.encoding = 'utf-8' ...