OpenCv高阶(七)——图像拼接

目录

一、图像拼接的原理过程

1. 特征检测与描述(Feature Detection & Description)

2. 特征匹配(Feature Matching)

3. 图像配准(Image Registration)

4. 图像变换与投影(Warping)

5. 图像融合(Blending)

二、图像拼接的简单实现

1、 匹配方法

2、实现上述两个图片的拼接

(1)导入opencv的库以及sys库

(2)定义cv_show()函数

(3)创建特征检测函数detectAndDescribe()

(4)读取待拼接的两张图片并显示在窗口中 

(5)调用detectAndDescribe()函数,获得两个图像的关键点信息,关键点坐标、描述符信息

(6)创建暴力匹配器,进行关键点之间的匹配

(7)绘制匹配成功的关键点之间的连线,使用drawMatchesKnn()匹配方法

(8)透视变换

(9)将图片A填充到指定位置


OpenCV中的图像拼接(Image Stitching)主要基于计算机视觉和图像处理技术,将多张具有重叠区域的图像拼接成一张全景图。其核心原理可以分为以下几个步骤:


一、图像拼接的原理过程

1. 特征检测与描述(Feature Detection & Description)

  • 目标:在不同图像中检测关键特征点(如角点、边缘等),并生成特征描述子。

  • 常用算法

    • SIFT(尺度不变特征变换):对旋转、尺度、光照变化具有鲁棒性。

    • SURF(加速版SIFT):计算速度更快。

    • ORB(Oriented FAST and Rotated BRIEF):轻量级,适合实时应用。

  • 输出:每张图像的特征点坐标及其对应的描述子(特征向量)。

  • 过程:图像拼接的第一步是检测并描述图像中的关键特征点。通过使用如SIFT、SURF或ORB等算法,系统能够提取对尺度、旋转和光照变化具有鲁棒性的特征点(如角点或边缘)。这些算法不仅定位特征点的位置,还会生成对应的特征描述子(如128维的SIFT向量),用于后续的特征匹配。例如,SIFT通过高斯差分金字塔检测极值点并赋予方向,ORB则结合FAST关键点检测和BRIEF二进制描述子以提升效率,从而适应不同场景的需求。下图就是通过sift特征提取找到图像中特征相同的位置。


2. 特征匹配(Feature Matching)

  • 目标:在不同图像的特征点之间建立对应关系。

  • 方法

    • 暴力匹配(Brute-Force Matcher):直接比较所有特征描述子的距离(如欧式距离或汉明距离)。

    • FLANN(快速最近邻搜索):适合大规模数据集,效率更高。

  • 筛选策略

    • 比率测试(Ratio Test):保留匹配距离比值(最近邻/次近邻)小于阈值的匹配对。

    • RANSAC(随机采样一致性):通过迭代剔除误匹配,估计最优几何变换模型(如单应性矩阵)。

  • 过程:在获取特征点后,需在不同图像间建立特征点的对应关系。暴力匹配法直接计算所有特征描述子间的距离(如欧氏距离或汉明距离),而FLANN通过构建高效的数据结构加速最近邻搜索。为排除误匹配,通常会采用比率测试(保留最近邻与次近邻距离比值小于阈值的结果)和RANSAC算法。RANSAC通过随机采样一致性迭代估计最优单应性矩阵,同时剔除不符合几何约束的异常点,确保匹配的准确性。

3. 图像配准(Image Registration)

  • 目标:计算图像间的几何变换关系,对齐图像。

  • 单应性矩阵(Homography Matrix)

    • 描述两个平面之间的透视变换关系(3×3矩阵)。

    • 通过匹配的特征点对求解(至少需要4对点)。

    • 使用 RANSAC 或 LMEDS 算法鲁棒地估计单应性矩阵。

  • 变换模型

    若相机仅旋转(无平移),单应性矩阵能完美对齐图像。若存在视差(如平移),可能需要更复杂的模型(如Bundle Adjustment)。
  • 过程:配准的目标是计算图像间的几何变换关系,通常使用单应性矩阵(3×3矩阵)描述平面间的透视变换。通过至少4对匹配点可求解该矩阵,RANSAC在此过程中进一步优化模型的鲁棒性。若相机仅绕光心旋转(如全景拍摄),单应性矩阵能精确对齐图像;若存在视差(如平移拍摄),则需引入光束法平差(Bundle Adjustment)等优化方法,联合调整多图像的相机参数以减少投影误差。

4. 图像变换与投影(Warping)

  • 目标:将图像投影到同一坐标系(全景画布)。

  • 方法

    • 使用 cv2.warpPerspective() 对图像应用单应性矩阵变换。

    • 根据所有图像的变换结果,计算全景图的尺寸和偏移量。

  • 优化

    • 曝光补偿:调整不同图像的亮度差异。

    • 相机参数优化:若已知相机参数(如焦距),可提升对齐精度。

  • 配准后,需将图像投影到统一坐标系以构建全景画布。使用cv2.warpPerspective()对图像应用单应性变换,并根据所有图像的变换结果计算全景图的尺寸和偏移量。例如,若将第二张图像投影到第一张的坐标系中,需扩展画布以容纳所有像素。此外,需处理因曝光差异导致的亮度不一致问题,可能通过直方图匹配或全局优化调整颜色平衡。


5. 图像融合(Blending)

  • 目标:消除拼接处的缝隙和光照差异,实现平滑过渡。

  • 常用方法

    • 简单混合(Alpha Blending):在重叠区域对像素进行线性加权平均。

    • 多频段融合(Multi-Band Blending)

      • 将图像分解为不同频率的子带(如拉普拉斯金字塔)。

      • 对各频段分别融合,避免高频细节(如边缘)错位。

    • 光照一致性处理:调整重叠区域的亮度和颜色。

  • 最后一步是消除拼接缝隙与光照差异。简单线性混合(Alpha Blending)在重叠区域对像素加权平均,但可能导致模糊。多频段融合则通过拉普拉斯金字塔分解图像,对不同频率的子带分别融合:低频(如光照)平滑过渡,高频(如边缘)保留细节,从而避免重影和错位。对于动态物体(如行人),可通过分割掩模或运动检测排除干扰,进一步提升视觉效果。

二、图像拼接的简单实现

1、 匹配方法

特征匹配的方法: 关键点A与找到的两个关键点 X、Y的欧氏距离分别 d1、d2,且d1<d2。 欧氏距离(关键点A,关键点X)=d1。 欧氏距离(关键点A,关键点Y)=d2。         (1)d1<d2,比值较大:可能不是匹配点,通常是由噪声引起的。         (2)d1<d2,比值较小:是匹配点。

2、实现上述两个图片的拼接

(1)导入opencv的库以及sys库

import cv2
import numpy as np
import sys

(2)定义cv_show()函数

在做opencv项目时,如果想显示一张图片,总会使用到cv2.imshow()和cv2.waitKey()这两个函数,因此,为了方便将该功能封装成一个小的函数方便使用。

def cv_show(name,value):cv2.imshow(name,value)cv2.waitKey(0)

(3)创建特征检测函数detectAndDescribe()

def detectAndDescribe(image):#将输入的图片转化为灰度图gray=cv2.cvtColor(image,cv2.COLOR_BGRA2GRAY)#创建SIFT特征检测器describe=cv2.SIFT_create()#使用SIFT特征检测器,调用detectAndCompute()函数,获得关键特征点的坐标kps和描述符des(kps,des)=describe.detectAndCompute(gray,None)#使用列表生成式将获得到的坐标信息转化为32位的浮点数kps_float=np.float32([kp.pt for kp in kps])#返回关键点、关键点浮点数坐标、描述符return (kps,kps_float,des)

(4)读取待拼接的两张图片并显示在窗口中 

imageA=cv2.imread("../data/imageA.jpg")
cv_show("imageA",imageA)
imageB=cv2.imread("../data/imageB.jpg")
cv_show("imageB",imageB)

(5)调用detectAndDescribe()函数,获得两个图像的关键点信息,关键点坐标、描述符信息

#计算图片特征点及描述符
(kpsA,kps_floatA,desA)=detectAndDescribe(imageA)
(kpsB,kps_floatB,desB)=detectAndDescribe(imageB)

(6)创建暴力匹配器,进行关键点之间的匹配

这里的匹配器会在指纹识别、指验证项目中详细讲解,其中有关Knnmatch()为什么要选择两个点会详细讲解。

#建立暴力匹配器BFmatcher,在匹配大训练集和时使用flannbasematcher
matcher=cv2.BFMatcher()#使用KNN匹配器,使用B去匹配图片A,每次会选取两个结果,一个最近的点一个次近邻的点
rawMatches=matcher.knnMatch(desB,desA,2)good=[]
matches=[]
for m in rawMatches:if len(m)==2 and m[0].distance < 0.65* m[1].distance:good.append(m)matches.append((m[0].queryIdx,m[0].trainIdx))print(len(good))
print(matches)

        这里进行条件判断,判断m的长度是否为2,m是对rawMatches的遍历,所以取到的每个值都会有两个点的信息,所以长度为2,当某一个图中匹配的关键点缺失时就会出现长度小于2的情况。
         并且如果最近点距离当前点的距离小于次近点的距离当前点距离的0.65,则认定这个点是一个比较优秀的点,并将该点保存到good这个列表中,将最近点的两个索引值放到matches这个列表中,这两个索引分别代表,因为是使用图片B去匹配图片A中的点,所以这里表示的是第一个索引queryIdx表示匹配图片中关键点的索引,第二个索引trainIdx则是待匹配的图片A中的关键点索引。

(7)绘制匹配成功的关键点之间的连线,使用drawMatchesKnn()匹配方法

vis=cv2.drawMatchesKnn(imageB,kpsB,imageA,kpsA,good,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show('Keypoint Matches',vis)

(8)透视变换

因为图片拍摄角度的不同所以,使用透视变换将图片扶正,将图片转换成同一个弯曲程度的图像

"""透视变换"""
if len(matches)>4:ptsB=np.float32([kps_floatB[i] for (i,_) in matches])ptsA=np.float32([kps_floatA[i] for (_,i) in matches])(H,mask)=cv2.findHomography(ptsB,ptsA,cv2.RANSAC,10)
else:print("图片未找到四个以上的匹配点")sys.exit()result=cv2.warpPerspective(imageB,H,(imageB.shape[1]+imageA.shape[1],imageB.shape[0]))
cv_show('resultB',result)

 

因为透视变换是四个点进行匹配,所以这里使用条件判断,当图片A和B之间有四个以上的匹配点时则依次取出图片A和B中的坐标点信息,matches这个列表中,这两个索引分别代表,因为是使用图片B去匹配图片A中的点,所以这里表示的是第一个索引queryIdx表示匹配图片B中关键点的索引,第二个索引trainIdx则是待匹配的图片A中的关键点索引。因此上面使用列表生成式分别取出图片A和B中的关键点,findHomography函数计算变化矩阵,H是变化矩阵,mask是指外点和内点值,图片的宽变成两图片的宽相加。

(9)将图片A填充到指定位置

result[0:imageA.shape[0],0:imageA.shape[1]]=imageA
cv_show('result',result)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Native层Trace监控性能

一、基础实现方法 1.1 头文件引用 #include <utils/Trace.h> // 基础版本 #include <cutils/trace.h> // 兼容旧版本1.2 核心宏定义 // 区间追踪&#xff08;推荐&#xff09; ATRACE_BEGIN("TraceTag"); ...被监控代码... ATRACE_END();// 函数级自…

金融行业微服务架构设计与挑战 - Java架构师面试实战

金融行业微服务架构设计与挑战 - Java架构师面试实战 本文通过模拟一位拥有十年Java研发经验的资深架构师马架构与面试官之间的对话&#xff0c;深入探讨了金融行业项目在微服务架构下的技术挑战与解决方案。 第一轮提问 面试官&#xff1a; 马架构&#xff0c;请介绍一下您…

服务器虚拟化:技术解析与实践指南

在信息技术飞速发展的今天,企业对服务器资源的需求日益增长,传统物理服务器存在资源利用率低、部署周期长、管理成本高等问题。服务器虚拟化技术应运而生,它通过将物理服务器的计算、存储、网络等资源进行抽象和整合,划分成多个相互隔离的虚拟服务器,从而提高资源利用率、…

OpenCV 图形API(54)颜色空间转换-----将图像从 RGB 色彩空间转换到 HSV色彩空间RGB2HSV()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 RGB 色彩空间转换为 HSV。该函数将输入图像从 RGB 色彩空间转换到 HSV。R、G 和 B 通道值的常规范围是 0 到 255。 输出图像必须是 8 位…

Spring Boot的优点:赋能现代Java开发的利器

Spring Boot 是基于 Spring 框架的快速开发框架&#xff0c;自 2014 年发布以来&#xff0c;凭借其简洁性、灵活性和强大的生态系统&#xff0c;成为 Java 后端开发的首选工具。尤其在 2025 年&#xff0c;随着微服务、云原生和 DevOps 的普及&#xff0c;Spring Boot 的优势更…

基于强化学习的智能交通控制系统设计

标题:基于强化学习的智能交通控制系统设计 内容:1.摘要 随着城市交通流量的不断增长&#xff0c;传统交通控制方法在应对复杂多变的交通状况时逐渐显现出局限性。本文旨在设计一种基于强化学习的智能交通控制系统&#xff0c;以提高交通运行效率、减少拥堵。通过构建强化学习模…

数据挖掘技术与应用课程论文——数据挖掘中的聚类分析方法及其应用研究

数据挖掘中的聚类分析方法及其应用研究 摘要 聚类分析是数据挖掘技术中的一个重要组成部分,它通过将数据集中的对象划分为多个组或簇,使得同一簇内的对象具有较高的相似性,而不同簇之间的对象具有较低的相似性。 本文系统地研究了数据挖掘中的多种聚类分析方法及其应用。首先…

Java基础语法10分钟速成

Java基础语法10分钟速成&#xff0c;记笔记版 JDKhello world变量字符串 类&#xff0c;继承&#xff0c;多态&#xff0c;重载 JDK JDK即Java development key&#xff0c;Java环境依赖包 在jdk中 编译器javac将代码的Java源文件编译为字节码文件&#xff08;.class&#xff…

在WSL2+Ubuntu22.04中通过conda pack导出一个conda环境包,然后尝试导入该环境包

如何导出一个离线conda环境&#xff1f;有两种方式&#xff0c;一种是导出env.yml即环境配置&#xff0c;一种是通过conda pack导出为一个环境包&#xff0c;前者只是导出配置&#xff08;包括包名、版本等&#xff09;&#xff0c;而后者是直接将环境中所有的内容打包&#xf…

盈达科技:登顶GEO优化全球制高点,以AICC定义AI时代内容智能优化新标杆

一、技术制高点——全球独创AICC系统架构&#xff0c;构建AI内容优化新范式 作为全球首个实现AI内容全链路优化的技术供应商&#xff0c;盈达科技凭借AICC智能协同中心&#xff08;自适应内容改造、智能数据投喂、认知权重博弈、风险动态响应四大引擎&#xff09;&#…

设计看似完美却测不过? Intra-Pair Skew 是「讯号完整性(Signal Integrity)」里最隐形的杀手

各位不知道有没有遇过&#xff0c;一对很长的差分走线&#xff0c;看起来很正常&#xff0c;但是测试结果偶尔会fail偶尔会pass&#xff0c;不像是软件问题&#xff0c;也不像是制程问题。 看了一下Layout&#xff0c;发现阻抗匹配控制的非常好&#xff0c;TDR测试也显示阻抗好…

介绍常用的退烧与消炎药

每年春夏交替之季&#xff0c;是感冒发烧、咳嗽、咽喉肿痛、支气管炎、扁桃体炎的高发期。在家里或公司&#xff0c;常备几种预防感冒发烧、咳嗽、流鼻涕、咽喉发炎的药品&#xff0c;是非常必要的。下面介绍几款效果非常明显的中成药、西药&#xff0c;具体如下。 1 莲芝消炎…

Redis为什么不直接使用C语言中的字符串?

因为C语言字符串存在问题&#xff1a; 获取字符串长度需要进行运算(获取字符串长度需要遍历整个字符串&#xff0c;直到遇到终止符 \0&#xff0c;时间复杂度为 O(n))非二进制安全&#xff08;结束标识符\0可能在一些二进制格式的数据处理时字符串时产生错误&#xff09;不可修…

直线模组精度测试的标准是什么?

直线模组的精度测试是确保其性能和稳定性的重要环节。那么&#xff0c;大家知道直线模组精度测试的标准是什么吗&#xff1f; 1、定位精度&#xff1a;以最大行程为基准长度&#xff0c;用从基准位置开始实际移动的距离与指令值之间的最大误差的绝对值来表示。一般来说&#xf…

开源AI视频FramePack发布:6GB显卡本地运行

您现在可以在自己的笔记本电脑上免费生成完整的离线AI视频。 只有GPU和纯粹的创造力。 这到底是什么? 一个名为FramePack的新型离线AI视频生成器几天前在GitHub上发布 — 几乎没人在谈论它。这很奇怪,因为这个工具真的很厉害。 它允许您从静态图像和提示词在自己的机器上…

Tailwind CSS 实战:基于 Kooboo 构建个人博客页面

在现代 web 开发中&#xff0c;Tailwind CSS 作为一款实用优先的 CSS 框架&#xff0c;能让开发者迅速搭建出具有良好视觉效果的页面&#xff1b;Kooboo 则是一个强大的快速开发平台&#xff0c;提供了便捷的页面管理和数据处理功能。本文将详细介绍如何结合 Tailwind CSS 和 K…

嵌入式面试核心考点:从 C 语言基础到芯片资源深度剖析

嵌入式系统开发涉及知识面广&#xff0c;面试题常涵盖 C 语言基础、Linux 操作、内存管理、通信协议等。本文针对常见面试题&#xff0c;逐题解析&#xff0c;助力新手系统掌握核心知识点。 1. 用预处理指令交换两个参数的值 在 C 语言中&#xff0c;我们可以利用预处理指令 …

Java 程序运行和类路径处理

PS D:\java_test> java .\java\Dog 错误: 找不到或无法加载主类 .\java\Dog 原因: java.lang.ClassNotFoundException: /\java\DogJava 程序运行和类路径处理 问题描述 在运行 Java 程序时&#xff0c;可能会遇到 ClassNotFoundException 错误&#xff0c;这是因为 Java 虚…

测试OMS(订单管理系统)时,对Elasticsearch(ES)数据和算法数据进行测试(如何测试几百万条数据)

1. 测试目标 在测试OMS中的ES数据和算法数据时&#xff0c;主要目标包括&#xff1a; 数据完整性 数据完整性&#xff1a;确保所有需要的数据都被正确采集、存储和索引。 数据准确性&#xff1a;确保数据内容正确无误&#xff0c;符合业务逻辑。 性能&#xff1a;确保系统在处…

19.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--当前项目拆分规划

随着业务规模的不断扩大和系统复杂度的提升&#xff0c;孢子记账系统需要进行微服务架构的转型。本文将详细规划从单体应用向微服务架构迁移的具体方案&#xff0c;包括功能模块分析、服务拆分、技术选型以及实施步骤等内容。通过合理的服务拆分和架构设计&#xff0c;未来我们…