как сделать панорамный вид серии изображений с использованием дескрипторов python, opencv, orb и ransac из opencv

#python #opencv #affinetransform #panoramas #orb

Вопрос:

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

  1. изображение 1 и изображение 2
  2. изображение 2 и изображение 3

Затем я знаю , как вычислить и найти панорамный вид только между 2 изображениями, и я делаю это между img1 и img2, а также между img2 и img3. Но затем на последнем шаге я хочу найти панорамный вид этих 3 изображений , используя аффинную трансформацию с помощью алгоритма Ransac из opencv. И я не знаю, как это сделать ( панорамный вид на 3 фотографии. Итак, я должен, конечно, выбрать изображение 2 в качестве центра панорамы

Я не нашел хорошего объяснения или достаточно хорошего объяснения для себя, чтобы вычислить и отточить панорамный вид фотографий тезисов 3. Кто-нибудь может помочь мне, пожалуйста, реализовать то, что мне нужно, пожалуйста ?

вот мой код, в котором я печатаю панораму между img1 и img2, а также между img2 и img3:

 import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
from matplotlib.pyplot import imshow, show, subplot, title, axis


# draw matches
def draw_matches(img1, kpt1, img2, kpt2, matches):
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]

    # Create a blank image with the size of the first image   second image
    new_img = np.zeros((max([h1, h2]), w1   w2, 3), dtype='uint8')
    new_img[:h1, :w1, :] = np.dstack([img1, img1, img1])
    new_img[:h2, w1:w1   w2, :] = np.dstack([img2, img2, img2])

    # extract the match keypoints
    for m in matches:
        (x1, y1) = kpt1[m.queryIdx].pt
        (x2, y2) = kpt2[m.trainIdx].pt

        # Draw circles on the keypoints
        cv.circle(new_img, (int(x1), int(y1)), 4, (0, 255, 0), 1)
        cv.circle(new_img, (int(x2)   w1, int(y2)), 4, (0, 255, 0), 1)

        # Connect the same keypoints
        cv.line(new_img, (int(x1), int(y1)), (int(x2)   w1, int(y2)), (255, 0, 255), 1)

return new_img


def warpImages(img1, img2, M):
    # get the corner coordinates of the "query" and "train" image
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]
    pts_corners_src = np.float32([[0, 0], [0, h1], [w1, h1], [w1, 0]]).reshape(-1, 1, 2)
    pts_corners_temp = np.float32([[0, 0], [0, h2], [w2, h2], [w2, 0]]).reshape(-1, 1, 2)

    # When we have established a homography we need to warp perspective
    # perform perspective tranform using previously calculated matrix and the corners of  
    "query" image#
    # Change field of view
    pts_corners_dst = cv.perspectiveTransform(pts_corners_temp, M)

    ListOfPoints = np.concatenate((pts_corners_src, pts_corners_dst), axis=0)

    [x_min, y_min] = np.int32(ListOfPoints.min(axis=0).ravel() - 0.5)
    [x_max, y_max] = np.int32(ListOfPoints.max(axis=0).ravel()   0.5)

    translation_dist = [-x_min, -y_min]

    H_translation = np.array([[1, 0, translation_dist[0]], [0, 1, translation_dist[1]], [0, 0, 
1]])

    new_img = cv.warpPerspective(img2, H_translation.dot(M), (x_max - x_min, y_max - y_min))
    new_img[translation_dist[1]:h1   translation_dist[1], translation_dist[0]:w1   translation_dist[0]] = img1

return new_img


def find_homography(kpt1, kpt2, matches):
    # Find an Homography matrix between two pictures
    # Transforming keypoints to list of points
    src_pts = np.float32([kpt1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
    dst_pts = np.float32([kpt2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)

    # Compute a rigid transformation (without depth, only scale   rotation   translation) /affine transformation
    transformation_rigid_matrix, rigid_mask = cv.estimateAffinePartial2D(src_pts, dst_pts)
    affine_row = [0, 0, 1]
    transformation_rigid_matrix = np.vstack((transformation_rigid_matrix, affine_row))

return transformation_rigid_matrix


# Read images
img1 = cv.imread('1.jpg', 1)
img2 = cv.imread('2.jpg', 1)
img3 = cv.imread('3.jpg', 1)
img1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY)
img2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
img3 = cv.cvtColor(img3, cv.COLOR_BGR2GRAY)

# Initiate ORB detector, that it will be our detector object.
orb = cv.ORB_create()

# find the keypoints and compute the descriptors with ORB for images
kpts1, des1 = orb.detectAndCompute(img1, None)
kpts2, des2 = orb.detectAndCompute(img2, None)
kpts3, des3 = orb.detectAndCompute(img3, None)

# Create a BFMatcher object.
bf = cv.BFMatcher_create(cv.NORM_HAMMING)

# match descriptor
matches1to2 = bf.knnMatch(des1, des2, k=2)
matches2to3 = bf.knnMatch(des2, des3, k=2)

# draw matches
good1to2 = []
for m, n in matches1to2:
    if m.distance < 0.6 * n.distance:
        good1to2.append(m)

# draw matches
good2to3 = []
for m, n in matches2to3:
    if m.distance < 0.6 * n.distance:
        good2to3.append(m)

# find  affine transformation and panoramic view between 1 to 2
trans_affine_matrix1to2 = find_homography(kpts2, kpts1, good1to2)
img1to2 = warpImages(img1, img2, trans_affine_matrix1to2)

# find homography matrix and transformation 2 to 3
trans_affine_matrix2to3 = find_homography(kpts2, kpts3, good2to3)
img2to3 = warpImages(img3, img2, trans_affine_matrix2to3)

title1 = "panoramic between img1 and img2"
title2 = "panoramic between img2 and img3"
subplot(1, 2, 1)
imshow(img1to2)
axis('off')
title(title1)

subplot(1, 2, 2)
imshow(img2to3)
axis('off')
title(title2)
show()
 

Спасибо всем вам за вашу помощь.
Вот мои фотографии: 1.jpg 2.jpg 3.jpg

Ответ №1:

Вместо того, чтобы создавать панорамы из изображений 1 и 2 и изображений 2 и 3, а затем комбинировать их, попробуйте делать это последовательно. Так вроде этого:

  1. Возьмите изображения 1 и 2, вычислите их соответствующие параметры.
  2. Вычислите гомографию, связывающую изображение 2 с изображением 1.
  3. Деформируйте изображение 2, используя эту гомографию, чтобы сшить его с изображением 1. Это дает вам промежуточный результат 1.
  4. Возьмите этот промежуточный результат 1 в качестве первого изображения и повторите шаг 1-3 для следующего изображения в последовательности.

Хороший пост в блоге о том же, чтобы начать, находится здесь: https://kushalvyas.github.io/stitching.html

Чтобы сравнить производительность вашего алгоритма, вы можете увидеть результат из класса opencv-stitcher: результат класса opencv-сшивщик