图像合并实战演示

图像合并的步骤

(1)读文件并充值尺寸

(2)根据特征点和计算描述子,得到单应性矩阵

(3)图像变换

(4)图像拼接并输出图像

合并相关知识

处理的两张图片:

坐标系

图一

在拼接的上方形成一个坐标轴,如图一

单应性矩阵变换

图二

如图二,我们现在进行旋转的部分图片将会与另一张图片进行拼接,上图中非黑色部分与另一张图的部分内容重合。如图三

图三

此时需要处理一个问题,由于处理的两张图结合后图片大小会变大,所以需要进行窗口放大,如图四。

图四

还需要把第一张图都放在整个图像中,需要进行平移,如图五。

图五

接下来就是进行拼接,找出结合点,把右边的图拼到整个图像中,找出结合点,就是图六中红色虚线部分。 

图六

图七左边图像的宽度就是图二在图像外的区域。

图七

图像拼接实战

第一步:读取文件,改变文件大小

import cv2
import numpy as np

# 第一步,读取文件,将图片设置为相同大小640x480
# 第二步,找特征点,描述子,计算单应性矩阵
# 第三步,根据单应性矩阵对图像进行变换,然后平移
# 第四步,拼接并输出最终结果

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

# 将两张图片设置为相同大小
img1 = cv2.resize(img1, (640, 480))
img2 = cv2.resize(img2, (640, 480))

# 合并显示
inputs = np.hstack((img1, img2))  # 就是把img1,2压到一个栈里
cv2.imshow('input img', inputs)

cv2.waitKey(0)

第二步:找特征点,描述子,计算单应性矩阵

H = get_home(img1, img2)
def get_homo(img1, img2):
    # 1.创建特征转换对象
    # 2.通过特征转换对象获得特征点和描述子
    # 3.创建特征匹配器
    # 4.进行特征匹配
    # 5.过滤特征,找出有效特征匹配点

    # 1.创建特征转换对象 用sift
    sift = cv2.SIFT_create()

    # 2.通过特征转换对象获得特征点和描述子
    k1, d1 = sift.detectAndCompute(img1, None)
    k2, d2 = sift.detectAndCompute(img2, None)

    # 3.创建特征匹配器
    bf = cv2.BFMatcher()
    maches = bf.knnMatch(d1, d2, k=2)  # 选取最接近的2个

    # 4.进行特征匹配
    varify_ratio = 0.8
    varify_matches = []

    for m1, m2 in maches:
        if m1.distance < 0.8 * m2.distance:
            varify_matches.append(m1)

    min_matches = 8
    if len(varify_matches) > min_matches:
        img1_pts = []
        img2_pts = []

        for m in varify_matches:
            # 获得图像一和二的坐标点
            img1_pts.append(k1[m.queryIdx].pt)
            img2_pts.append(k2[m.trainIdx].pt)
            # 上两行得到的是[(x1,y1),(x2,y2),……]
            # 而findHomography需要的是[[x1,y1],[x2,y2],……]

        img1_pts = np.float32(img1_pts).reshape(-1, 1, 2)
        img2_pts = np.float32(img2_pts).reshape(-1, 1, 2)

        H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0)
        return H

    else:
        print('err:Not enough matches!')
        exit()

 第三步:根据单应性矩阵进行图像变换,然后平移

def stitch_img(img1, img2, H):
    # 1.获得图像的四个角点
    # 2.对图片进行变换(单应性矩阵进行旋转和平移)
    # 3.创建一张大图,将两张图片拼接在一起
    # 4.将结果输出

    # 1.获得图像的四个角点
    # 获得原始图的高宽
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]

    img1_dims = np.float32([[0, 0], [0, h1], [w1, h1], [w1, 0]]).reshape(-1, 1, 2)  # 逆时针选点的 左上是第一个点
    img2_dims = np.float32([[0, 0], [0, h2], [w2, h2], [w2, 0]]).reshape(-1, 1, 2)

    # 2.对图片进行变换(单应性矩阵进行旋转和平移)
    img1_transform = cv2.perspectiveTransform(img1_dims, H)  # img1_dims在合并后的图中的位置

    # print(img1_dims)
    # print(img2_dims)
    # print(img1_transform)

    result_dims = np.concatenate((img2_dims, img1_transform), axis=0)  # axis=0横向拼接
    # print(result_dims)

    # result_dims.min() #这样获得的是最小的值,但是我们需要的是x和y分别的最小值
    [x_min, y_min] = np.int32(result_dims.min(axis=0).ravel() - 0.5)  # 获得了x,y的最小值 是二维表示出来的 .ravel()变成一维
    [x_max, y_max] = np.int32(result_dims.max(axis=0).ravel() + 0.5)

    # 平移的距离
    transform_dist = [-x_min, -y_min]

    # [1,0,dx]
    # [0,1,dy]
    # [0,0,1]
    transform_array = np.array([[1, 0, transform_dist[0]],
                                [0, 1, transform_dist[1]],
                                [0, 0, 1]])

    result_img = cv2.warpPerspective(img1, transform_array.dot(H), (x_max - x_min, y_max - y_min))
    return result_img
result_img = stitch_img(img1, img2, H)

第四步:拼接

 result_img[transform_dist[1]:transform_dist[1] + h2,
    transform_dist[0]:transform_dist[0] + w2] = img2

总:

import cv2
import numpy as np


def get_homo(img1, img2):
    # 1.创建特征转换对象
    # 2.通过特征转换对象获得特征点和描述子
    # 3.创建特征匹配器
    # 4.进行特征匹配
    # 5.过滤特征,找出有效特征匹配点

    # 1.创建特征转换对象 用sift
    sift = cv2.SIFT_create()

    # 2.通过特征转换对象获得特征点和描述子
    k1, d1 = sift.detectAndCompute(img1, None)
    k2, d2 = sift.detectAndCompute(img2, None)

    # 3.创建特征匹配器
    bf = cv2.BFMatcher()
    maches = bf.knnMatch(d1, d2, k=2)  # 选取最接近的2个

    # 4.进行特征匹配
    varify_ratio = 0.8
    varify_matches = []

    for m1, m2 in maches:
        if m1.distance < 0.8 * m2.distance:
            varify_matches.append(m1)

    min_matches = 8
    if len(varify_matches) > min_matches:
        img1_pts = []
        img2_pts = []

        for m in varify_matches:
            # 获得图像一和二的坐标点
            img1_pts.append(k1[m.queryIdx].pt)
            img2_pts.append(k2[m.trainIdx].pt)
            # 上两行得到的是[(x1,y1),(x2,y2),……]
            # 而findHomography需要的是[[x1,y1],[x2,y2],……]

        img1_pts = np.float32(img1_pts).reshape(-1, 1, 2)
        img2_pts = np.float32(img2_pts).reshape(-1, 1, 2)

        H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0)
        return H

    else:
        print('err:Not enough matches!')
        exit()


def stitch_img(img1, img2, H):
    # 1.获得图像的四个角点
    # 2.对图片进行变换(单应性矩阵进行旋转和平移)
    # 3.创建一张大图,将两张图片拼接在一起
    # 4.将结果输出

    # 1.获得图像的四个角点
    # 获得原始图的高宽
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]

    img1_dims = np.float32([[0, 0], [0, h1], [w1, h1], [w1, 0]]).reshape(-1, 1, 2)  # 逆时针选点的 左上是第一个点
    img2_dims = np.float32([[0, 0], [0, h2], [w2, h2], [w2, 0]]).reshape(-1, 1, 2)

    # 2.对图片进行变换(单应性矩阵进行旋转和平移)
    img1_transform = cv2.perspectiveTransform(img1_dims, H)  # img1_dims在合并后的图中的位置

    # print(img1_dims)
    # print(img2_dims)
    # print(img1_transform)

    result_dims = np.concatenate((img2_dims, img1_transform), axis=0)  # axis=0横向拼接
    # print(result_dims)

    # result_dims.min() #这样获得的是最小的值,但是我们需要的是x和y分别的最小值
    [x_min, y_min] = np.int32(result_dims.min(axis=0).ravel() - 0.5)  # 获得了x,y的最小值 是二维表示出来的 .ravel()变成一维
    [x_max, y_max] = np.int32(result_dims.max(axis=0).ravel() + 0.5)

    # 平移的距离
    transform_dist = [-x_min, -y_min]

    # [1,0,dx]
    # [0,1,dy]
    # [0,0,1]
    transform_array = np.array([[1, 0, transform_dist[0]],
                                [0, 1, transform_dist[1]],
                                [0, 0, 1]])

    result_img = cv2.warpPerspective(img1, transform_array.dot(H), (x_max - x_min, y_max - y_min))
    result_img[transform_dist[1]:transform_dist[1] + h2,
    transform_dist[0]:transform_dist[0] + w2] = img2
    return result_img


# 第一步,读取文件,将图片设置为相同大小640x480
# 第二步,找特征点,描述子,计算单应性矩阵
# 第三步,根据单应性矩阵对图像进行变换,然后平移
# 第四步,拼接并输出最终结果

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

# 将两张图片设置为相同大小
img1 = cv2.resize(img1, (640, 480))
img2 = cv2.resize(img2, (640, 480))

# 合并显示
inputs = np.hstack((img1, img2))  # 就是把img1,2压到一个栈里

# 获取单应性矩阵
H = get_homo(img1, img2)

# 进行图像拼接
result_img = stitch_img(img1, img2, H)

cv2.imshow('input img', result_img)

cv2.waitKey(0)

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值