计算机视觉实验三——图像拼接

一、实验目标

  1. 理解单应性变换中仿射变换的原理,并通过仿射变换实现图像扭曲、嵌入(图中图)等操作
  2. 利用RANSAC算法优化关键点匹配,比较优化前后图像拼接和所生成全景图的差别

二、实验内容

1.理解单应性变换中仿射变换的原理,并通过仿射变换实现图像扭曲、嵌入(图中图)等操作

①图像扭曲

在这里插入图片描述

②实现图像嵌入

在这里插入图片描述
代码实现:

import cv2
import numpy as np

# 读取两张图片
img1 = cv2.imread('img1.jpg')
img2 = cv2.imread('img2.jpg')

# 获取img1的宽度和高度
h1, w1 = img1.shape[:2]

# 定义仿射变换的三个点对
src_points = np.float32([[0, 0], [w1 - 1, 0], [0, h1 - 1]])
dst_points = np.float32([[w1 * 0.2, h1 * 0.1], [w1 * 0.8, h1 * 0.2], [w1 * 0.1, h1 * 0.9]])

# 计算仿射变换矩阵
M = cv2.getAffineTransform(src_points, dst_points)

# 对img1进行仿射变换,得到扭曲后的图像
img3 = cv2.warpAffine(img1, M, (w1, h1))

# 将扭曲后的图像保存为文件
cv2.imwrite('distorted.jpg', img3)

# 获取img2的宽度和高度
h2, w2 = img2.shape[:2]

# 自动计算嵌入位置的左上角坐标,使得扭曲后的图像在img2中居中显示
x = (w2 - w1) // 2  # 可以根据需要修改
y = (h2 - h1) // 2  # 可以根据需要修改

# 判断嵌入位置是否合法,如果不合法则报错并退出
if x < 0 or y < 0:
    print('嵌入位置不合法')
    exit()

# 将扭曲后的图像嵌入到img2中,得到新的img2
img2[y:y+h1, x:x+w1] = img3

# 显示img1、img3和嵌入img3后的img2
cv2.imshow('img1', img1)
cv2.imshow('img3', img3)
cv2.imshow('img2', img2)

# 将嵌入img3后的img2保存为文件
cv2.imwrite('final.jpg', img2)

# 等待按键退出
cv2.waitKey(0)
cv2.destroyAllWindows()

仿射变换是一种在向量空间中进行一次线性变换和一次平移的变换,它可以保持直线的直线性和平行性,但不一定保持原点和角度不变。
仿射变换可以用一个矩阵来表示,例如在二维平面上,一个点 (x,y) 经过仿射变换后变为 (x’,y’),可以写成:
在这里插入图片描述
其中,矩阵的左上角 2x2 的部分表示线性变换,如缩放、旋转、反射、错切等;矩阵的第一行第三列和第二行第三列的部分表示平移变换。所以在实际应用中可以通过对仿射变换矩阵的不同设置,来实现不同的变换效果,比如平移、旋转、缩放、错切等操作。
但是仿射变换只能进行线性变换,不能进行非线性变换。如果需要进行非线性变换,就需要使用更加复杂的变换方式,比如透视变换等。

定义仿射变换的三个点对是为了确定变换矩阵。仿射变换是一种线性变换,可以通过一个2x3的矩阵来表示。这个矩阵可以通过三个点对来计算得到。每个点对包含一个原始图像中的点和一个目标图像中的点。通过这三个点对,可以计算出一个2x3的矩阵,用于将原始图像中的点映射到目标图像中的点。
仿射变换有六个自由度,需要六个参数来确定。而每个点对包含两个点,因此三个点对提供了六个参数,恰好可以确定一个仿射变换矩阵。如果点对的数量不足三个,那么就无法确定一个唯一的仿射变换矩阵。如果点对的数量超过三个,那么就会出现过拟合的问题,导致变换矩阵不稳定。因此,三个点对是确定仿射变换矩阵的最小数量。

2.利用RANSAC算法优化关键点匹配,比较优化前后图像拼接和所生成全景图的差别

原图:
在这里插入图片描述
在这里插入图片描述
优化前的匹配点拼接结果:
在这里插入图片描述
优化后的匹配点拼接结果:
在这里插入图片描述
生成全景图:
在这里插入图片描述
代码实现:

# 读取两幅图像
img1 = cv2.imread('img3.jpg')
img2 = cv2.imread('img4.jpg')

# 转换为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

# 使用SIFT特征检测器和描述子提取器
sift = cv2.SIFT_create()

# 计算两幅图像中的关键点和描述子
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)

# 使用FLANN匹配器进行特征匹配
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)

# 使用比值测试筛选出好的匹配点
good_matches = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good_matches.append(m)

# 获取匹配点对应的坐标
src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

# 使用RANSAC算法优化关键点匹配
ransac = RANSACRegressor(residual_threshold=1, max_trials=1000)
ransac.fit(src_pts.reshape(-1, 2), dst_pts.reshape(-1, 2))
inlier_mask = ransac.inlier_mask_
outlier_mask = np.logical_not(inlier_mask)

# 获取优化后的匹配点对应的坐标
src_pts_opt = src_pts[inlier_mask]
dst_pts_opt = dst_pts[inlier_mask]

# 使用优化后的匹配点计算单应性矩阵
H, status = cv2.findHomography(src_pts_opt, dst_pts_opt, cv2.RANSAC)

# 使用单应性矩阵对图像进行变换和拼接
result = cv2.warpPerspective(img1, H, (img1.shape[1] + img2.shape[1], img1.shape[0]))
result[0:img2.shape[0], 0:img2.shape[1]] = img2

# 显示优化前后的匹配点和拼接结果
cv2.imshow('Before RANSAC', cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None))
cv2.imshow('After RANSAC', cv2.drawMatches(img1, kp1, img2, kp2, np.array(good_matches)[inlier_mask], None))
cv2.imshow('Result', result)

优化前后图像拼接和所生成全景图的差别:
传统的关键点匹配算法(如SIFT、SURF等)可能会出现误匹配的情况,这会导致拼接后的全景图存在明显的拼接痕迹或者部分区域失真;RANSAC算法是一种鲁棒性较强的参数估计方法,它可以通过随机采样和迭代的方式,去除误匹配的点,从而提高匹配的准确性和稳定性。具体来说,RANSAC算法的流程如下:
1.随机选择一组关键点进行匹配;
2.根据这组匹配点,计算出变换矩阵(如仿射变换、透视变换等);
3.利用这个变换矩阵,将所有的关键点进行变换,并计算出变换后的点与原始点之间的距离;
4.根据设定的阈值,判断哪些点是“好”的匹配点,哪些点是误匹配点;
5.如果“好”的匹配点的数量达到了设定的阈值,那么就认为这组匹配点是可靠的,保存下来;
6.重复上述步骤,直到达到设定的迭代次数。

最终,RANSAC算法会输出一组可靠的关键点匹配,这些匹配点可以用来进行图像拼接。相比于传统的关键点匹配算法,利用RANSAC算法优化后的关键点匹配算法可以去除误匹配的点,提高匹配的准确性和稳定性,从而得到更加精确的图像拼接结果和更高质量的全景图。

三、实验小结

在本次实验中遇到的问题:
进行嵌入图像操作时,显示嵌入位置不合法:
在这里插入图片描述
问题解决:嵌入位置不合法的原因是img1的大小超过了img2的大小,或者嵌入位置的坐标超出了img2的范围。可以使用小一点的img1,或者大一点的img2,以及调整嵌入位置的坐标,使得扭曲后的图像能够完全嵌入到img2中。

关于单应性矩阵:
单应性矩阵是一种用于描述透视变换的矩阵。它是一个3x3的矩阵,可以将一个三维空间中的点映射到另一个三维空间中的点。在计算机视觉中,单应性矩阵通常用于图像配准、图像拼接、目标跟踪等应用中。
在图像配准中,单应性矩阵可以用于将两幅图像进行对齐。通过找到两幅图像之间的对应点,可以计算出单应性矩阵,然后使用该矩阵将其中一幅图像映射到另一幅图像的坐标系中。在图像拼接中,单应性矩阵可以用于将多幅图像拼接成一幅大图像。通过计算多幅图像之间的单应性矩阵,可以将它们进行对齐,然后将它们拼接在一起。
单应性矩阵的计算通常使用最小二乘法或RANSAC算法。最小二乘法可以用于计算精确的单应性矩阵,但对噪声和异常值比较敏感。RANSAC算法可以用于鲁棒性更强的单应性矩阵计算,但计算结果可能不够精确。

  • 17
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moonee_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值