Как сшить два изображения, используя матрицу гомографии в OpenCv?

Я хочу сшить два панорамных изображения, используя матрицу гомографии в OpenCv. Я нашел матрицу гомографии 3x3, но не могу сшить два изображения. Я должен сшить два изображения вручную (без встроенной функции). Вот мой код:

import cv2
import numpy as np

MIN_MATCH_COUNT = 10

img1 = cv2.imread("pano1/cyl_image00.png")
img2 = cv2.imread("pano1/cyl_image01.png")

orb = cv2.ORB_create()

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)

src_pts = 0
dst_pts = 0
if len(goodMatches) > MIN_MATCH_COUNT:
    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)


def generateRandom(src_Pts, dest_Pts, N):
    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):
    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):
    maxI = 0
    maxLSrc = []
    maxLDest = []
    for i in range(70):
        srcP, destP = generateRandom(src_Pts, dst_Pts, 4)
        H = findH(srcP, destP, 4)
        inlines = 0
        linesSrc = []
        lineDest = []
        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) < 10:
                inlines += 1
                linesSrc.append(p1)
                lineDest.append(p2)
        if inlines > maxI:
            maxI = inlines
            maxLSrc = linesSrc.copy()
            maxLSrc = np.asarray(maxLSrc, dtype=np.float32)
            maxLDest = lineDest.copy()
            maxLDest = np.asarray(maxLDest, dtype=np.float32)
    Hf = findH(maxLSrc, maxLDest, maxI)
    return Hf


H = ransacHomography(src_pts, dst_pts)

Все идет нормально. Я нашел матрицу гомографии (H).

Далее я попытался сшить два панорамных изображения. Сначала я создаю большой массив для сшивания изображений (img3). Я скопировал img1 в первую половину img3. Я попытался найти новые координаты для img2 через матрицу гомографии и скопировал новые координаты img2 в img3.

Вот мой код:

height1, width1, rgb1 = img1.shape
height2, width2, rgb2 = img2.shape

img3 = np.empty((height1, width1+width2, 3))

img3[:, 0:width1] = img1/255.0


for i in range(len(img2)):
    for j in range(len(img2[0])):
        pp = H.dot(np.array([[i], [j], [1]]))
        pp = (pp / pp[2]).reshape(1, 3)[0]
        img3[int(round(pp[0])), int(round(pp[1]))] = img2[i, j]/255.0

Но эта часть не работает. Как я могу решить эту проблему?


person Erhan    schedule 10.04.2020    source источник


Ответы (1)


Когда у вас есть матрица гомографии, вам нужно преобразовать одно из изображений, чтобы оно имело ту же перспективу, что и другое. Это делается с помощью функции warpPerspective в OpenCV. После того, как вы сделали преобразование, пришло время соединить изображения.

Допустим, вы хотите преобразовать img_1 в перспективу img_2 и у вас уже есть матрица гомографии H

dst = cv2.warpPerspective(img_1, H, ((img_1.shape[1] + img_2.shape[1]), img_2.shape[0])) #wraped image

# now paste them together
dst[0:img_2.shape[0], 0:img_2.shape[1]] = img_2
dst[0:img_1.shape[0], 0:img_1.shape[1]] = img_1

Также обратите внимание, что OpenCV уже имеет встроенный поисковик RANSAC Homography.

H, masked = cv2.findHomography(src, dst, cv2.RANSAC, 5.0)

Таким образом, это может сэкономить вам много кода.

Ознакомьтесь с этим руководством для более подробной информации

https://medium.com/@navekshasood/image-stitching-to-create-a-panorama-5e030ecc8f7

https://medium.com/analytics-vidhya/image-stitching-with-opencv-and-python-1ebd9e0a6d78

person Omri Bahat Treidel    schedule 11.04.2020