CV2 Python - 基于单应性矩阵的图像合并 - 合并错误
我正在做一个项目,需要合并一些(超过1000张)正射影像。首先,我想知道我有哪些选择,因为我觉得我还没有找到所有的解决方案。
其次,我遇到了一个具体的问题。我的问题是,当我想把第二张图片添加到第一张图片上时,背景(原本是透明的)把第三张图片遮住了。我觉得我的错误在于放置方法。
我的最终目标是使用QGIS把这张图片放到地图上,但一个一个地处理并不是最好的方法,合并成更少的部分会更好。
这段代码生成的图片像第一张:
import cv2
import numpy as np
# Load the images
img1 = cv2.imread('out1-163.png')
img2 = cv2.imread('out1-160.png')
# Load the images
image2 = img1
image1 = img2
# Define the size of the border
top, bottom, left, right = [100]*4 # Adjust these values as needed
# Convert image1 to 4-channel RGBA
image1_rgba = cv2.cvtColor(image1, cv2.COLOR_BGR2BGRA)
# Create a transparent border around image1
image1_bordered = image1_rgba
# Convert image2 to 4-channel RGBA
image2_rgba = cv2.cvtColor(image2, cv2.COLOR_BGR2BGRA)
# Create a transparent border around image2
image2_bordered = image2_rgba
# Convert images to grayscale
gray1 = cv2.cvtColor(image1_bordered, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2_bordered, cv2.COLOR_BGR2GRAY)
# Initialize the feature detector and extractor (e.g., SIFT)
sift = cv2.SIFT_create()
# Detect keypoints and compute descriptors for both images
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)
# Initialize the feature matcher using brute-force matching
bf = cv2.BFMatcher()
# Match the descriptors using brute-force matching
matches = bf.match(descriptors1, descriptors2)
# Select the top N matches
num_matches = 50
matches = sorted(matches, key=lambda x: x.distance)[:num_matches]
# Extract matching keypoints
src_points = np.float32([keypoints1[match.queryIdx].pt for match in matches]).reshape(-1, 1, 2)
dst_points = np.float32([keypoints2[match.trainIdx].pt for match in matches]).reshape(-1, 1, 2)
# Estimate the homography matrix
homography, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5.0)
# Calculate the size of the new image
corners = np.array([
[0, 0],
[0, image1_bordered.shape[0]],
[image1_bordered.shape[1], 0],
[image1_bordered.shape[1], image1_bordered.shape[0]]
], dtype=np.float32)
corners = cv2.perspectiveTransform(corners.reshape(-1, 1, 2), homography).reshape(-1, 2)
min_x, min_y = corners.min(axis=0).astype(int)
max_x, max_y = corners.max(axis=0).astype(int)
width = max(max_x, image2_bordered.shape[1]) - min_x
height = max(max_y, image2_bordered.shape[0]) - min_y
# Adjust the homography matrix to shift the image to the right place
homography[0, 2] -= min_x
homography[1, 2] -= min_y
# Warp image1 to image2 using the adjusted homography matrix
result = cv2.warpPerspective(image1_bordered, homography, (width, height))
# Overlay image2 on the warped image1
startY = max(-min_y, 0)
startX = max(-min_x, 0)
endY = startY + image2_bordered.shape[0]
endX = startX + image2_bordered.shape[1]
# Replace the corresponding pixels in the first image with the pixels from the second image
result[startY:endY, startX:endX] = image2_bordered[:endY-startY, :endX-startX]
# Save the result
cv2.imwrite('merged.png', result)
这是第三张图片合并的代码:
import cv2
import numpy as np
# Load the images
img1 = cv2.imread('merged.png', cv2.IMREAD_UNCHANGED)
img2 = cv2.imread('out1-164.png')
# Load the images
image2 = img1
image1 = img2
# Define the size of the border
top, bottom, left, right = [100]*4 # Adjust these values as needed
# Convert image1 to 4-channel RGBA
image1_rgba = cv2.cvtColor(image1, cv2.COLOR_BGR2BGRA)
# Create a transparent border around image1
image1_bordered = image1_rgba
# Convert image2 to 4-channel RGBA
image2_rgba = cv2.cvtColor(image2, cv2.COLOR_BGR2BGRA)
# Create a transparent border around image2
image2_bordered = image2_rgba
# Convert images to grayscale
gray1 = cv2.cvtColor(image1_bordered, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2_bordered, cv2.COLOR_BGR2GRAY)
# Initialize the feature detector and extractor (e.g., SIFT)
sift = cv2.SIFT_create()
# Detect keypoints and compute descriptors for both images
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)
# Initialize the feature matcher using brute-force matching
bf = cv2.BFMatcher()
# Match the descriptors using brute-force matching
matches = bf.match(descriptors1, descriptors2)
# Select the top N matches
num_matches = 50
matches = sorted(matches, key=lambda x: x.distance)[:num_matches]
# Extract matching keypoints
src_points = np.float32([keypoints1[match.queryIdx].pt for match in matches]).reshape(-1, 1, 2)
dst_points = np.float32([keypoints2[match.trainIdx].pt for match in matches]).reshape(-1, 1, 2)
# Estimate the homography matrix
homography, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5.0)
# Calculate the size of the new image
corners = np.array([
[0, 0],
[0, image1_bordered.shape[0]],
[image1_bordered.shape[1], 0],
[image1_bordered.shape[1], image1_bordered.shape[0]]
], dtype=np.float32)
corners = cv2.perspectiveTransform(corners.reshape(-1, 1, 2), homography).reshape(-1, 2)
min_x, min_y = corners.min(axis=0).astype(int)
max_x, max_y = corners.max(axis=0).astype(int)
width = max(max_x, image2_bordered.shape[1]) - min_x
height = max(max_y, image2_bordered.shape[0]) - min_y
# Adjust the homography matrix to shift the image to the right place
homography[0, 2] -= min_x
homography[1, 2] -= min_y
# Warp image1 to image2 using the adjusted homography matrix
result = cv2.warpPerspective(image1_bordered, homography, (width, height))
# Overlay image2 on the warped image1
startY = max(-min_y, 0)
startX = max(-min_x, 0)
endY = startY + image2_bordered.shape[0]
endX = startX + image2_bordered.shape[1]
# Ensure endY and endX do not exceed the size of the result image
endY = min(endY, result.shape[0])
endX = min(endX, result.shape[1])
# Replace the corresponding pixels in the first image with the pixels from the second image
result[startY:endY, startX:endX] = image2_bordered[:(endY-startY), :(endX-startX)]
# Create a mask of image2_bordered
mask = image2_bordered[..., 3] > 0
# Create a mask of non-transparent pixels in image2_bordered
mask = image2_bordered[..., 3] > 0
# Replace the non-transparent pixels in the first image with the pixels from the second image
for c in range(0, 3):
result[startY:endY, startX:endX, c] = np.where(mask[:(endY-startY), :(endX-startX)],
image2_bordered[:(endY-startY), :(endX-startX), c],
result[startY:endY, startX:endX, c])
# Save the result
cv2.imwrite('merged2_image.png', result)
我创建的第一张图片:
提前谢谢你们!
0 个回答
暂无回答