繁体   English   中英

在 Python 中使用 CV2 将两个图像拼接在一起

[英]Stitching two images together using CV2 in Python

所以我想知道是否有一种方法可以使用关键点和单应矩阵在右侧 position 拼接图像的两个部分。

作为示例,这里有两个图像。

图片的第一部分

图像的第二部分

所以对于关键点检测,我使用的是“Superpoint”,我得到了以下结果。

关键点匹配结果

所以我正在寻找一种可能使用 cv2.warpAffine function 将图像对齐在一起的方法,到目前为止我的所有尝试都没有奏效。 目标是让程序决定将第二张图片放在第一张图片的哪个位置。

这是我正在使用的代码:

enter code here
import argparse
from pathlib import Path

import cv2
import numpy as np
import tensorflow as tf  # noqa: E402

from superpoint.settings import EXPER_PATH  # noqa: E402
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def extract_superpoint_keypoints_and_descriptors(keypoint_map, descriptor_map,
                                             keep_k_points=1000):

    def select_k_best(points, k):
        """ Select the k most probable points (and strip their proba).
        points has shape (num_points, 3) where the last coordinate is the proba. """
        sorted_prob = points[points[:, 2].argsort(), :2]
        start = min(k, points.shape[0])
        return sorted_prob[-start:, :]

    # Extract keypoints
    keypoints = np.where(keypoint_map > 0)
    prob = keypoint_map[keypoints[0], keypoints[1]]
    keypoints = np.stack([keypoints[0], keypoints[1], prob], axis=-1)

    keypoints = select_k_best(keypoints, keep_k_points)
    keypoints = keypoints.astype(int)

    # Get descriptors for keypoints
    desc = descriptor_map[keypoints[:, 0], keypoints[:, 1]]

    # Convert from just pts to cv2.KeyPoints
    keypoints = [cv2.KeyPoint(p[1], p[0], 1) for p in keypoints]

    return keypoints, desc
def match_descriptors(kp1, desc1, kp2, desc2):
    # Match the keypoints with the warped_keypoints with nearest neighbor search
    bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)

    matches = bf.match(desc1, desc2)
    matches_idx = np.array([m.queryIdx for m in matches])

    m_kp1 = [kp1[idx] for idx in matches_idx]
    matches_idx = np.array([m.trainIdx for m in matches])
    m_kp2 = [kp2[idx] for idx in matches_idx]

    return m_kp1, m_kp2, matches


def compute_homography(matched_kp1, matched_kp2):
    matched_pts1 = cv2.KeyPoint_convert(matched_kp1)
    matched_pts2 = cv2.KeyPoint_convert(matched_kp2)
    H, inliers = cv2.findHomography(matched_pts1[:, [1, 0]],
                                matched_pts2[:, [1, 0]],cv2.RANSAC,5.0)
    inliers = inliers.flatten()
    print(H)
    return H, inliers


def preprocess_image(img_file, img_size):
    img = cv2.imread(img_file, cv2.IMREAD_COLOR)
    img = cv2.resize(img, img_size)
    img_orig = img.copy()

    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = np.expand_dims(img, 2)
    img = img.astype(np.float32)
    img_preprocessed = img / 255.

return img_preprocessed, img_orig
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser = argparse.ArgumentParser(description='Compute the homography \
        between two images with the SuperPoint feature matches.')
    parser.add_argument('weights_name', type=str)
    parser.add_argument('img1_path', type=str)
    parser.add_argument('img2_path', type=str)
    parser.add_argument('--H', type=int, default=480,
                    help='The height in pixels to resize the images to. \
                            (default: 480)')
    parser.add_argument('--W', type=int, default=640,
                    help='The width in pixels to resize the images to. \
                            (default: 640)')
    parser.add_argument('--k_best', type=int, default=1000,
                    help='Maximum number of keypoints to keep \
                    (default: 1000)')
    args = parser.parse_args()

    weights_name = args.weights_name
    img1_file = args.img1_path
    img2_file = args.img2_path
    img_size = (args.W, args.H)
    keep_k_best = args.k_best

    weights_root_dir = Path(EXPER_PATH, 'saved_models')

    weights_root_dir.mkdir(parents=True, exist_ok=True)
    weights_dir = Path(weights_root_dir, weights_name)

    graph = tf.Graph()
    with tf.Session(graph=graph) as sess:
        tf.saved_model.loader.load(sess,
                               [tf.saved_model.tag_constants.SERVING],
                               str(weights_dir))

        input_img_tensor = graph.get_tensor_by_name('superpoint/image:0')
        output_prob_nms_tensor = graph.get_tensor_by_name('superpoint/prob_nms:0')
        output_desc_tensors = graph.get_tensor_by_name('superpoint/descriptors:0')

        img1, img1_orig = preprocess_image(img1_file, img_size)
        out1 = sess.run([output_prob_nms_tensor, output_desc_tensors],
                    feed_dict={input_img_tensor: np.expand_dims(img1, 0)})
        keypoint_map1 = np.squeeze(out1[0])

        descriptor_map1 = np.squeeze(out1[1])
        kp1, desc1 = extract_superpoint_keypoints_and_descriptors(
            keypoint_map1, descriptor_map1, keep_k_best)
    
        img2, img2_orig = preprocess_image(img2_file, img_size)
        out2 = sess.run([output_prob_nms_tensor, output_desc_tensors],
                    feed_dict={input_img_tensor: np.expand_dims(img2, 0)})
        keypoint_map2 = np.squeeze(out2[0])
        descriptor_map2 = np.squeeze(out2[1])
        kp2, desc2 = extract_superpoint_keypoints_and_descriptors(
            keypoint_map2, descriptor_map2, keep_k_best)

        # Match and get rid of outliers
    
        m_kp1, m_kp2, matches = match_descriptors(kp1, desc1, kp2, desc2)


        H, inliers= compute_homography(m_kp1, m_kp2)

        matches = np.array(matches)[inliers.astype(bool)].tolist()
        matched_img = cv2.drawMatches(img1_orig, kp1, img2_orig, kp2, matches,
                                  None, matchColor=(0, 255, 0),
                                  singlePointColor=(0, 0, 255))

我感谢您的帮助!

所以对于闭合来说,使用单应性或仿射变换将这两幅图像拼接在一起并不是正确的做法。 每个部分之间有太多的候选兴趣点是高度模糊的,这将不允许这种拼接成功。

唯一可行的方法是,如果您的特征匹配是在两个图像彼此断开连接的边界处指定的。 然而,这些点永远不会是兴趣点,因为当地社区不提供任何独特的信息。 此外,根据定义,边缘不是兴趣点,因此任何检测器都不会将它们作为适当的点。

如果这不是您要找的答案,我深表歉意!

这应该是你正在寻找的。 addWeighted function就是cv2中合并图片的function

import cv2


img1 = cv2.imread('7FgBZ.jpg',1)
img2 = cv2.imread('qqiH8.jpg',1)
print(img2)
dst = cv2.addWeighted(img1,0.2,img2,0.2,0)



print(dst)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM