Обнаружение ключевых точек и сшивание изображений

Вывод кода [! [] [1] 2

Таким образом, как показано на рисунке ниже, у меня есть ключевые точки, обнаруженные на изображении, но выходное изображение после перспективы обтекания игнорирует первое изображение на левой стороне, не могу понять, почему!

    import numpy as np
    import imutils
    import cv2

class Stitcher:
def __init__(self):
    # determine if we are using OpenCV v3.X
    self.isv3 = imutils.is_cv3()

def stitch(self, imageA,imageB, ratio=0.75, reprojThresh=10.0,
    showMatches=False):
    # unpack the images, then detect keypoints and extract
    # local invariant descriptors from them
    #(imageB, imageA) = images
    (kpsA, featuresA) = self.detectAndDescribe(imageA)
    (kpsB, featuresB) = self.detectAndDescribe(imageB)

    # match features between the two images
    M = self.matchKeypoints(kpsA, kpsB,
        featuresA, featuresB, ratio, reprojThresh)

    # if the match is None, then there aren't enough matched
    # keypoints to create a panorama
    if M is None:
        return None

    # otherwise, apply a perspective warp to stitch the images
    # together
    (matches, H, status) = M
    #print(M)
    #print(matches)
    #print(H)
    #print(status)
    #cv2.imwrite('intermediate.jpg',matches)
    result = cv2.warpPerspective(imageA, H,
        (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
    result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
    #cv2.imshow('intermediate',result)

    # check to see if the keypoint matches should be visualized
    if showMatches:
        vis = self.drawMatches(imageA, imageB, kpsA, kpsB, matches,
            status)

        # return a tuple of the stitched image and the
        # visualization
        return (result, vis)

    # return the stitched image
    return result

def detectAndDescribe(self, image):
    # convert the image to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # check to see if we are using OpenCV 3.X
    if self.isv3:
        # detect and extract features from the image
        #SIFT Algorithm
        descriptor = cv2.xfeatures2d.SIFT_create()
        #SURF Algorithm
        #descriptor = cv2.xfeatures2d.SURF_create()# 400 is hesian threshold, optimum values should be around 300-500
        #upright SURF: faster and can be used for panorama stiching i.e our case.
        #descriptor.upright = True
        print(descriptor.descriptorSize())
        (kps, features) = descriptor.detectAndCompute(image, None)
        print(len(kps),features.shape)

    # otherwise, we are using OpenCV 2.4.X
    else:
        # detect keypoints in the image
        detector = cv2.FeatureDetector_create("SIFT")
        kps = detector.detect(gray)

        # extract features from the image
        extractor = cv2.DescriptorExtractor_create("SIFT")
        (kps, features) = extractor.compute(gray, kps)

    # convert the keypoints from KeyPoint objects to NumPy
    # arrays
    kps = np.float32([kp.pt for kp in kps])

    # return a tuple of keypoints and features
    #print("features",features)
    return (kps, features)

def matchKeypoints(self, kpsA, kpsB, featuresA, featuresB,
    ratio, reprojThresh):
    # compute the raw matches and initialize the list of actual
    # matches
    matcher = cv2.DescriptorMatcher_create("BruteForce")
    rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
    matches = []

    # loop over the raw matches
    for m in rawMatches:
        # ensure the distance is within a certain ratio of each
        # other (i.e. Lowe's ratio test)
        if len(m) == 2 and m[0].distance < m[1].distance * ratio:
            matches.append((m[0].trainIdx, m[0].queryIdx))
    print(len(matches))

    # computing a homography requires at least 4 matches
    if len(matches) > 4:
        # construct the two sets of points
        ptsA = np.float32([kpsA[i] for (_, i) in matches])
        ptsB = np.float32([kpsB[i] for (i, _) in matches])

        # compute the homography between the two sets of points
        (H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC,
            reprojThresh)

        # return the matches along with the homograpy matrix
        # and status of each matched point
        return (matches, H, status)

    # otherwise, no homograpy could be computed
    return None

def drawMatches(self, imageA, imageB, kpsA, kpsB, matches, status):
    # initialize the output visualization image
    (hA, wA) = imageA.shape[:2]
    (hB, wB) = imageB.shape[:2]
    vis = np.zeros((max(hA, hB), wA + wB, 3), dtype="uint8")
    vis[0:hA, 0:wA] = imageA
    vis[0:hB, wA:] = imageB

    # loop over the matches
    for ((trainIdx, queryIdx), s) in zip(matches, status):
        # only process the match if the keypoint was successfully
        # matched
        if s == 1:
            # draw the match
            ptA = (int(kpsA[queryIdx][0]), int(kpsA[queryIdx][1]))
            ptB = (int(kpsB[trainIdx][0]) + wA, int(kpsB[trainIdx][1]))
            cv2.line(vis, ptA, ptB, (0, 255, 0), 1)

    # return the visualization
    return vis

Выше приведен код, используемый для обнаружения и сшивания ключевых точек,

Еще один вопрос, может ли кто-нибудь помочь мне с вертикальным сшиванием изображений, кроме поворота изображений и выполнения горизонтального сшивания.

Большое спасибо!

Я изменил свой код и использовал функцию @Alexander padtransf.warpPerspectivePadded, чтобы выполнять обтекание и смешивание! Можете ли вы помочь мне получить равномерное освещение для выходного изображения?

1 ответ

Решение

У меня была эта проблема сама. Если я не ошибаюсь, вы используете этот блог в качестве ссылки.

Проблема заключается в warpPerspective в отношении линии:

result = cv2.warpPerspective(imageA, H,
        (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
    result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB

Этот метод является всенаправленным. Под этим я подразумеваю, что вы просто накладываете imageA поверх imageB, заменяя значения пикселей на основе ширины и высоты, представленных .shape[0] а также .shape[1], Я решил это в C++, и поэтому у меня нет кода для отображения на Python, но он может дать вам представление о том, что должно быть сделано.

  1. Получите четыре угла каждого из изображений, которые вы используете.
  2. Получите минимальные и максимальные углы для каждого изображения, найденного в шаге 1.
  3. Создайте коврик "HTR", который будет использоваться для отображения изображения один, чтобы привести в соответствие с уже деформированным изображением два HTR.at(0,2) представляет местоположение в матрице 3x3 матов. Numpy, вероятно, то, что вам нужно использовать здесь.
Mat Htr = Mat::eye(3,3,CV_64F);
    if (min_x < 0){
        max_x = image2.size().width - min_x;
        Htr.at<double>(0,2)= -min_x;
    }
    if (min_y < 0){
        max_y = image2.size().height - min_y;
        Htr.at<double>(1,2)= -min_y;
    }
  1. Выполните перспективное преобразование по четырем углам каждого изображения, чтобы увидеть, где они окажутся в пространстве.
perspectiveTransform(vector<Point2f> fourPointImage1, vector<Point2f> image1dst, Htr*homography);
perspectiveTransform(vector<Point2f> fourPointImage2, vector<Point2f> image2dst, Htr);
  1. Получите минимальное и максимальное значения из image1dst четыре угла и iamge2dst четыре угла.
  2. Получите минимум и максимум image1dst а также iamge2dst и использовать для создания нового blank image правильного размера, чтобы держать окончательно сшитые изображения.
  3. Повторите шаг 3 на этот раз, чтобы определить translation необходимо отрегулировать четыре угла каждого изображения, чтобы убедиться, что они перемещаются в виртуальное пространство blank image
  4. Наконец добавьте фактические изображения со всеми омографиями, которые вы нашли / сделали.
warpPerspective(image1, blankImage, (translation*homography),result.size(), INTER_LINEAR,BORDER_CONSTANT,(0));
warpPerspective(image2, image2Updated, translation, result.size(), INTER_LINEAR, BORDER_CONSTANT,   (0));

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

Другие вопросы по тегам