Почему размер изображения постепенно уменьшается при использовании матрицы гомографии? - PullRequest
0 голосов
/ 13 апреля 2020

Я хочу найти панорамное изображение, используя матрицу гомографии. У меня есть набор картинок и картинок одинакового размера.

Во-первых, я нахожу матрицу гомографии для первых двух изображений и склеиваю их вместе. После этого я нахожу матрицу гомографии для предыдущего сшиваемого изображения и третьего изображения и повторяю этот шаг до последнего изображения.

Однако на этих шагах размеры изображения постепенно уменьшаются, и, наконец, матрица гомографии дает неверный результат.

Вот мой код:

import cv2
import numpy as np
import os
import glob

def generateRandom(src_Pts, dest_Pts, N): # This function generates random points for Ransac.
    r = np.random.choice(len(src_Pts), N)
    src = [src_Pts[i] for i in r]
    dest = [dest_Pts[i] for i in r]
    return np.asarray(src, dtype=np.float32), np.asarray(dest, dtype=np.float32)


def findH(src, dest, N): # This function calculate Homography Matrix.
    A = []
    for i in range(N):
        x, y = src[i][0], src[i][1]
        xp, yp = dest[i][0], dest[i][1]
        A.append([x, y, 1, 0, 0, 0, -x * xp, -xp * y, -xp])
        A.append([0, 0, 0, x, y, 1, -yp * x, -yp * y, -yp])
    A = np.asarray(A)
    U, S, Vh = np.linalg.svd(A)
    L = Vh[-1, :] / Vh[-1, -1]
    H = L.reshape(3, 3)
    return H


def ransacHomography(src_Pts, dst_Pts, ransacThreshold=0.995, maxIter=1000): # This function find Homography Matrix using Ransac algorithm.
    maxI = 0
    maxSrcIn = []
    maxDstIn = []
    for i in range(maxIter):
        srcP, destP = generateRandom(src_Pts, dst_Pts, 4)
        H = findH(srcP, destP, 4)
        inlines = 0
        srcIn = []
        dstIn = []
        for p1, p2 in zip(src_Pts, dst_Pts):
            p1U = (np.append(p1, 1)).reshape(3, 1)
            p2e = H.dot(p1U)
            p2e = (p2e / p2e[2])[:2].reshape(1, 2)[0]
            if cv2.norm(p2 - p2e) < ransacThreshold:
                inlines += 1
                srcIn.append(p1)
                dstIn.append(p2)
        if inlines >= maxI:
            maxI = inlines
            maxSrcIn = srcIn.copy()
            maxSrcIn = np.asarray(maxSrcIn)
            maxDstIn = dstIn.copy()
            maxDstIn = np.asarray(maxDstIn)
    FH = findH(maxSrcIn, maxDstIn, maxI)
    return FH


def warpTwoImages(img1, img2, H, maxSize): # This function stitch two images.
    height, width = maxSize
    img3 = np.zeros((height, width), dtype=np.uint8)
    img3[0:img1.shape[0], 0:img1.shape[1]] = img1

    for i in range(len(img2[0])):
        for j in range(len(img2[1])):
            pp = H.dot(np.array([[i], [j], [1]]))
            pp = (pp / pp[2]).reshape(1, 3)[0]
            if int(round(pp[1])) >= height or int(round(pp[0])) >= width or int(round(pp[1])) < 0 or int(round(pp[0])) < 0:
                continue
            img3[int(round(pp[1])), int(round(pp[0]))] = img2[j, i]
    return img3


def detectAndMatchFeature(img1, img2): # This function detect keypoints and compute matches.
    orb = cv2.ORB_create(nfeatures=100000)

    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)

    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)

    des1 = np.float32(des1)
    des2 = np.float32(des2)

    matches = flann.knnMatch(des1, des2, k=2)

    goodMatches = []

    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            goodMatches.append(m)

    dst_pts = np.float32([kp1[m.queryIdx].pt for m in goodMatches]).reshape(-1, 2)
    src_pts = np.float32([kp2[m.trainIdx].pt for m in goodMatches]).reshape(-1, 2)

    return src_pts, dst_pts


def readPanoUtil(pano_files, N, img1): # This function create panorama image.
    if N >= len(pano_files) - 1:
        return img1
    img2 = cv2.imread(pano_files[N], cv2.IMREAD_GRAYSCALE)
    src_pts, dst_pts = detectAndMatchFeature(img1, img2)
    H = ransacHomography(src_pts, dst_pts)
    img3 = warpTwoImages(img1, img2, H, (500, 1000+((N-1)*150)))
    cv2.imshow("xx"+str(N), img3)
    cv2.waitKey(0)
    return readPanoUtil(pano_files, N+1, img3)

Вот результаты для панорамного изображения шаг за шагом:

1. step:

2. step:

3. step:

4. step:

5. step:

6. step:

7. step:

8. step:

Как я могу решить эту проблему?

Как правильно сшивать изображения, используя Homography Matrix?

...