删除图像拼接中的黑色虚线

4

我正在拼接多张图片。在拼接两张图片时,会在拼接之间显示虚线黑线如下所示。 enter image description here

有没有人知道怎么去掉或摆脱这条黑色虚线?

这是拼接代码的主要部分,它将两个图像拼接在一起,并使用前面拼接图像的结果调用下一个图像,直到所有图像都结束:

detector = cv2.xfeatures2d.SURF_create(400)
gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)
ret1, mask1 = cv2.threshold(gray1,1,255,cv2.THRESH_BINARY)
kp1, descriptors1 = detector.detectAndCompute(gray1,mask1)

gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)
ret2, mask2 = cv2.threshold(gray2,1,255,cv2.THRESH_BINARY)
kp2, descriptors2 = detector.detectAndCompute(gray2,mask2)

keypoints1Im = cv2.drawKeypoints(image1, kp1, outImage = cv2.DRAW_MATCHES_FLAGS_DEFAULT, color=(0,0,255))
util.display("KEYPOINTS",keypoints1Im)
keypoints2Im = cv2.drawKeypoints(image2, kp2, outImage = cv2.DRAW_MATCHES_FLAGS_DEFAULT, color=(0,0,255))
util.display("KEYPOINTS",keypoints2Im)

matcher = cv2.BFMatcher()
matches = matcher.knnMatch(descriptors2,descriptors1, k=2)

good = []
for m, n in matches:
    if m.distance < 0.55 * n.distance:
        good.append(m)

print (str(len(good)) + " Matches were Found")

if len(good) <= 10:
    return image1

matches = copy.copy(good)

matchDrawing = util.drawMatches(gray2,kp2,gray1,kp1,matches)
util.display("matches",matchDrawing)

src_pts = np.float32([ kp2[m.queryIdx].pt for m in matches ]).reshape(-1,1,2)
dst_pts = np.float32([ kp1[m.trainIdx].pt for m in matches ]).reshape(-1,1,2)

A = cv2.estimateRigidTransform(src_pts,dst_pts,fullAffine=False)

if A is None:
    HomogResult = cv2.findHomography(src_pts,dst_pts,method=cv2.RANSAC)
    H = HomogResult[0]

height1,width1 = image1.shape[:2]
height2,width2 = image2.shape[:2]

corners1 = np.float32(([0,0],[0,height1],[width1,height1],[width1,0]))
corners2 = np.float32(([0,0],[0,height2],[width2,height2],[width2,0]))

warpedCorners2 = np.zeros((4,2))

for i in range(0,4):
    cornerX = corners2[i,0]
    cornerY = corners2[i,1]
    if A is not None: #check if we're working with affine transform or perspective transform
        warpedCorners2[i,0] = A[0,0]*cornerX + A[0,1]*cornerY + A[0,2]
        warpedCorners2[i,1] = A[1,0]*cornerX + A[1,1]*cornerY + A[1,2]
    else:
        warpedCorners2[i,0] = (H[0,0]*cornerX + H[0,1]*cornerY + H[0,2])/(H[2,0]*cornerX + H[2,1]*cornerY + H[2,2])
        warpedCorners2[i,1] = (H[1,0]*cornerX + H[1,1]*cornerY + H[1,2])/(H[2,0]*cornerX + H[2,1]*cornerY + H[2,2])

allCorners = np.concatenate((corners1, warpedCorners2), axis=0)

[xMin, yMin] = np.int32(allCorners.min(axis=0).ravel() - 0.5)
[xMax, yMax] = np.int32(allCorners.max(axis=0).ravel() + 0.5)

translation = np.float32(([1,0,-1*xMin],[0,1,-1*yMin],[0,0,1]))
warpedResImg = cv2.warpPerspective(image1, translation, (xMax-xMin, yMax-yMin))


if A is None:
    fullTransformation = np.dot(translation,H) #again, images must be translated to be 100% visible in new canvas
    warpedImage2 = cv2.warpPerspective(image2, fullTransformation, (xMax-xMin, yMax-yMin))

else:
    warpedImageTemp = cv2.warpPerspective(image2, translation, (xMax-xMin, yMax-yMin))
    warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin))

result = np.where(warpedImage2 != 0, warpedImage2, warpedResImg)

请帮我一下,谢谢。
编辑:
输入图像1(调整大小)

enter image description here

输入图像2(已调整大小)

enter image description here

结果(已调整大小)

enter image description here

更新:

@fmw42回答后的结果:

enter image description here


2
我猜测你最后一行的代码是 "warpedImage2 != 0",这可能导致了楼梯状伪影。两侧的边缘可能被插值的黑色抗锯齿处理过,所以它们混合了一些黑色和实际颜色。你可以尝试一些测试。使用最近邻插值进行warpAffine,并查看这些接缝处会发生什么。此外,你可以尝试使用 "warpedImage2 < threshold",看看是否有帮助或者使情况变得更糟。尝试不同的低阈值。 - fmw42
@fmw42 感谢您的回复。我不是这方面的专业人士,所以没有完全理解您的评论。但是,我已经尝试了 warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin),cv2.INTER_NEAREST)ret1, mask1 = cv2.threshold(gray1,120,255,cv2.THRESH_BINARY),但那条黑线仍未被移除。请告诉我如果可能的话需要改变和测试什么。 - ganesh
一个值得尝试的方法是在cv2.warpAffine()中使用不同的标志(插值)。请参阅https://docs.opencv.org/4.1.1/da/d54/group__imgproc__transform.html#gaf73673a7e8e18ec6963e3774e6a94b87和https://docs.opencv.org/4.1.1/da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb。 - fmw42
另一个尝试的方法是将 warpedImage2 != 0 更改为 warpedImage2 <T,在 result = np.where(warpedImage2 != 0, warpedImage2, warpedResImg) 中设置 T 为不同的值。从32开始尝试,看看会发生什么。然后将其加倍或减半,看看会发生什么。 - fmw42
@ fmw42 使用 T=64 及以上的参数,结果图像如问题所示。进行其他更改时,无法获得正确的结果。 - ganesh
显示剩余7条评论
2个回答

3
问题出现的原因是当你进行图像变形时,图像的边界像素会与黑色背景像素重新采样/插值。这会在合并其他图像时产生一个非零边界,其值不同,表现为虚线暗线。这是因为你的合并测试是二进制的,使用!= 0 进行测试。
所以你可以在Python/OpenCV中对变形后的图像进行掩码处理,从图像外部的黑色背景中获取其边界,然后腐蚀掩码。然后使用掩码来腐蚀图像边界。可以通过以下更改你代码的最后几行来实现这一点:
if A is None:
    fullTransformation = np.dot(translation,H) #again, images must be translated to be 100% visible in new canvas
    warpedImage2 = cv2.warpPerspective(image2, fullTransformation, (xMax-xMin, yMax-yMin))

else:
    warpedImageTemp = cv2.warpPerspective(image2, translation, (xMax-xMin, yMax-yMin))
    warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin))
    mask2 = cv2.threshold(warpedImage2, 0, 255, cv2.THRESH_BINARY)[1]
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
    mask2 = cv2.morphologyEx(mask2, cv2.MORPH_ERODE, kernel)
    warpedImage2[mask2==0] = 0

result = np.where(warpedImage2 != 0, warpedImage2, warpedResImg)

我只是在您的代码中添加了以下代码行:
mask2 = cv2.threshold(warpedImage2, 0, 255, cv2.THRESH_BINARY)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask2 = cv2.morphologyEx(mask2, cv2.MORPH_ERODE, kernel)
warpedImage2[mask2==0] = 0

如果需要更多侵蚀作用,您可以增加内核大小。

这是前后对比的结果。请注意,我没有使用SURF并尝试使用ORB,但对齐效果不佳。因此,您的道路不对齐。但由于错位导致的不匹配强调了问题,如虚线黑色边框线所示。ORB无法工作或者我没有适合从上面获取的正确代码并不重要。掩码实现了我认为您想要的效果,并且可以扩展到处理您的所有图像。

enter image description here

与上述方法相结合的另一种方法是对蒙版进行羽化处理,然后使用蒙版逐渐混合两个图像。这可以通过模糊蒙版(稍微多一点)并将值拉伸到模糊边界的内部一半,并使斜坡仅在模糊边界的外部一半上进行来完成。然后,使用斜坡蒙版及其反向混合两个图像,方法与上面相同。
    if A is None:
        fullTransformation = np.dot(translation,H) #again, images must be translated to be 100% visible in new canvas
        warpedImage2 = cv2.warpPerspective(image2, fullTransformation, (xMax-xMin, yMax-yMin))
    
    else:
        warpedImageTemp = cv2.warpPerspective(image2, translation, (xMax-xMin, yMax-yMin))
        warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin))
        mask2 = cv2.threshold(warpedImage2, 0, 255, cv2.THRESH_BINARY)[1]
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
        mask2 = cv2.morphologyEx(mask2, cv2.MORPH_ERODE, kernel)
        warpedImage2[mask2==0] = 0
        mask2 = cv2.blur(mask2, (5,5))
        mask2 = skimage.exposure.rescale_intensity(mask2, in_range=(127.5,255), out_range=(0,255)).astype(np.float64)
    
    result = (warpedImage2 * mask2 +  warpedResImg * (255 - mask2))/255
    result = result.clip(0,255).astype(np.uint8)

cv2.imwrite("image1_image2_merged3.png", result)

与原复合材料相比的结果如下:

enter image description here

加法

我已经纠正了我的ORB代码,以反转图像的使用方式,现在它对齐了。因此,这里是所有三种技术:原始技术、仅使用二进制掩模的技术和使用斜坡掩模进行混合的技术(如上所述)。

enter image description here

ADDITION2

这里是三张所请求的图片:原始图像、二进制掩膜和斜坡掩膜混合。

enter image description here

enter image description here

enter image description here

这是我针对上述最新版本的ORB代码。
我尽量保持您的代码不做太多修改,只是在最后不得不使用了ORB,并且需要交换image1和image2的名称。
import cv2
import matplotlib.pyplot as plt
import numpy as np
import itertools
from scipy.interpolate import UnivariateSpline
from skimage.exposure import rescale_intensity


image1 = cv2.imread("image1.jpg")
image2 = cv2.imread("image2.jpg")

gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# Detect ORB features and compute descriptors.
MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15
orb = cv2.ORB_create(MAX_FEATURES)

keypoints1, descriptors1 = orb.detectAndCompute(gray1, None)
keypoints2, descriptors2 = orb.detectAndCompute(gray2, None)

# Match features.
matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
matches = matcher.match(descriptors1, descriptors2, None)

# Sort matches by score
matches.sort(key=lambda x: x.distance, reverse=False)

# Remove not so good matches
numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
matches = matches[:numGoodMatches]

# Draw top matches
imMatches = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches, None)
cv2.imwrite("/Users/fred/desktop/image1_image2_matches.png", imMatches)

# Extract location of good matches
points1 = np.zeros((len(matches), 2), dtype=np.float32)
points2 = np.zeros((len(matches), 2), dtype=np.float32)

for i, match in enumerate(matches):
    points1[i, :] = keypoints1[match.queryIdx].pt
    points2[i, :] = keypoints2[match.trainIdx].pt

print(points1)
print("")
print(points2)

A = cv2.estimateRigidTransform(points1,points2,fullAffine=False)
#print(A)

if A is None:
    HomogResult = cv2.findHomography(points1,points2,method=cv2.RANSAC)
    H = HomogResult[0]

height1,width1 = image1.shape[:2]
height2,width2 = image2.shape[:2]

corners1 = np.float32(([0,0],[0,height1],[width1,height1],[width1,0]))
corners2 = np.float32(([0,0],[0,height2],[width2,height2],[width2,0]))

warpedCorners2 = np.zeros((4,2))

# project corners2 into domain of image1 from A affine or H homography
for i in range(0,4):
    cornerX = corners2[i,0]
    cornerY = corners2[i,1]
    if A is not None: #check if we're working with affine transform or perspective transform
        warpedCorners2[i,0] = A[0,0]*cornerX + A[0,1]*cornerY + A[0,2]
        warpedCorners2[i,1] = A[1,0]*cornerX + A[1,1]*cornerY + A[1,2]
    else:
        warpedCorners2[i,0] = (H[0,0]*cornerX + H[0,1]*cornerY + H[0,2])/(H[2,0]*cornerX + H[2,1]*cornerY + H[2,2])
        warpedCorners2[i,1] = (H[1,0]*cornerX + H[1,1]*cornerY + H[1,2])/(H[2,0]*cornerX + H[2,1]*cornerY + H[2,2])

allCorners = np.concatenate((corners1, warpedCorners2), axis=0)

[xMin, yMin] = np.int32(allCorners.min(axis=0).ravel() - 0.5)
[xMax, yMax] = np.int32(allCorners.max(axis=0).ravel() + 0.5)

translation = np.float32(([1,0,-1*xMin],[0,1,-1*yMin],[0,0,1]))
warpedResImg = cv2.warpPerspective(image2, translation, (xMax-xMin, yMax-yMin))


if A is None:
    fullTransformation = np.dot(translation,H) #again, images must be translated to be 100% visible in new canvas
    warpedImage2 = cv2.warpPerspective(image2, fullTransformation, (xMax-xMin, yMax-yMin))

else:
    warpedImageTemp = cv2.warpPerspective(image1, translation, (xMax-xMin, yMax-yMin))
    warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin))
    mask2 = cv2.threshold(warpedImage2, 0, 255, cv2.THRESH_BINARY)[1]
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
    mask2 = cv2.morphologyEx(mask2, cv2.MORPH_ERODE, kernel)
    warpedImage2[mask2==0] = 0
    mask2 = cv2.blur(mask2, (5,5))
    mask2 = rescale_intensity(mask2, in_range=(127.5,255), out_range=(0,255)).astype(np.float64)

result = (warpedImage2 * mask2 +  warpedResImg * (255 - mask2))/255
result = result.clip(0,255).astype(np.uint8)

cv2.imwrite("image1_image2_merged2.png", result)

你有以下内容。请注意,名称image1和image2在上面的代码中与它们的使用方式不同。
warpedResImg = cv2.warpPerspective(image1, translation, (xMax-xMin, yMax-yMin))


if A is None:
    fullTransformation = np.dot(translation,H) #again, images must be translated to be 100% visible in new canvas
    warpedImage2 = cv2.warpPerspective(image2, fullTransformation, (xMax-xMin, yMax-yMin))

else:
    warpedImageTemp = cv2.warpPerspective(image2, translation, (xMax-xMin, yMax-yMin))
    warpedImage2 = cv2.warpAffine(warpedImageTemp, A, (xMax-xMin, yMax-yMin))

你能否发布一张非gif版本的最终结果图片,这样人们就可以进行比较而不会头痛吗? - Lukas S
谢谢你的回答。我尝试了你的代码。现在没有黑线了,但是我仍然有轻微的错位和拼接边缘效果,就像我在问题中更新的那样。这是因为你使用ORB而我使用SURF吗?我尝试了ORB,但它只给我提供了不到10个匹配点,所以无法拼接图像。我该如何改进呢?我已经使用了你的代码部分,但是没有得到像你那样的结果。 - ganesh
由于使用ORB可能会出现差异。如果正确设置,SURF或SIFT应该是可以的。我额外添加的代码与这些技术无关。它只是混合而不进行任何几何调整,除了在混合前轻微地移除图像周围的一行暗像素。由于我没有安装SURF,我现在无法测试您的代码。你发布的代码有些奇怪,因为在最后我不得不交换image1和image2才能使它们对齐,就像我提到的那样。为什么会这样?你的代码实际上适用于上面的例子吗? - fmw42
@fmw42 我使用了你的代码并更改了我的代码中的那部分( if else 部分)。所以黑线已经被移除,但是在你的 ADDITION2 中提到的斜坡遮罩混合并没有出现在我的结果中,就像问题更新中显示的那样。如果您能够提供您的整个代码,那么我可以检查有什么差异。我正在执行多张图像的代码。设置 SURF/SIFT 的正确方式是什么意思?另外,如果您能够提供我可以学习这些技术的参考资料,那将非常有帮助。谢谢。 - ganesh
你在哪里交换了图片?如果你能在代码中加上注释,说明它的作用,那将更容易理解。抱歉,我是新手,正在学习这些东西,所以我有很多问题,这些术语和技巧并不容易理解。 - ganesh
我会发布我的更正代码。如果我运行你的代码,图像不会对齐。我没有分析你的代码来理解你所做的一切。我只是在两个地方简单地交换了名称image1和image2的使用。你的代码给出了完全不对齐的答案结果。在交换名称后,我得到了对齐的代码。 - fmw42

0

水平粘合

我将专注于其中一种切割作为概念证明。我同意评论中提到的,你的代码有点冗长且难以处理。因此,第一步是自己粘合图片。

import cv2
import matplotlib.pyplot as plt
import numpy as np
import itertools
from scipy.interpolate import UnivariateSpline

upper_image = cv2.cvtColor(cv2.imread('yQv6W.jpg'), cv2.COLOR_BGR2RGB)/255
lower_image = cv2.cvtColor(cv2.imread('zoWJv.jpg'), cv2.COLOR_BGR2RGB)/255

result_image = np.zeros((466+139,700+22,3))
result_image[139:139+lower_image.shape[0],:lower_image.shape[1]] = lower_image
result_image[0:upper_image.shape[0], 22:22+upper_image.shape[1]] = upper_image
plt.imshow(result_image)

naive glue

好的,没有虚线,但我承认也不完美。所以下一步是至少对齐图片最右边的街道和小路。为此,我需要将图片缩小到非整数大小,然后将其转换回网格。我将使用类似于knn的方法。

编辑:根据评论中的要求,我将更详细地解释缩小过程,因为它必须再次手动完成另一个拼接。神奇的事情发生在这行代码中(我用它的值替换了n)

f = UnivariateSpline([0,290,510,685],[0,310,530,700])

我首先尝试将下方图片在x方向上缩放,以使极右侧的小路与上方图像相匹配。不幸的是,这样街道就无法适应了。因此,我根据上述函数进行缩小。在像素0处,我仍希望有像素零,在290处,我希望拥有曾经在310处的内容,依此类推。 请注意,290,510和310,530分别是粘合高度处街道和小路的新旧x坐标。

class Image_knn():
    def fit(self, image):
        self.image = image.astype('float')

    def predict(self, x, y):
        image = self.image
        weights_x = [(1-(x % 1)).reshape(*x.shape,1), (x % 1).reshape(*x.shape,1)]
        weights_y = [(1-(y % 1)).reshape(*x.shape,1), (y % 1).reshape(*x.shape,1)]
        start_x = np.floor(x).astype('int')
        start_y = np.floor(y).astype('int')
        return sum([image[np.clip(np.floor(start_x + x), 0, image.shape[0]-1).astype('int'),
                          np.clip(np.floor(start_y + y), 0, image.shape[1]-1).astype('int')] * weights_x[x]*weights_y[y] 
                    for x,y in itertools.product(range(2),range(2))])

image_model = Image_knn()
image_model.fit(lower_image)

n = 685
f = UnivariateSpline([0,290,510,n],[0,310,530,700])
np.linspace(0,lower_image.shape[1],n)
yspace = f(np.arange(n))

result_image = np.zeros((466+139,700+22, 3))
a,b = np.meshgrid(np.arange(0,lower_image.shape[0]), yspace)
result_image[139:139+lower_image.shape[0],:n] = np.transpose(image_model.predict(a,b), [1,0,2])
result_image[0:upper_image.shape[0], 22:22+upper_image.shape[1]] = upper_image
plt.imshow(result_image, 'gray')

gluing with alignment

好多了,没有黑线了,但也许我们还可以稍微平滑一下切割边缘。我想如果我在切割处取上下两张图片的凸组合,效果会更好。

result_image = np.zeros((466+139,700+22,3))
a,b = np.meshgrid(np.arange(0,lower_image.shape[0]), yspace)
result_image[139:139+lower_image.shape[0],:n] = np.transpose(image_model.predict(a,b), [1,0,2])

transition_range = 10
result_image[0:upper_image.shape[0]-transition_range, 22:22+upper_image.shape[1]] = upper_image[:-transition_range,:]
transition_pixcels = upper_image[-transition_range:,:]*np.linspace(1,0,transition_range).reshape(-1,1,1)
result_image[upper_image.shape[0]-transition_range:upper_image.shape[0], 22:22+upper_image.shape[1]] *= np.linspace(0,1,transition_range).reshape(-1,1,1)
result_image[upper_image.shape[0]-transition_range:upper_image.shape[0], 22:22+upper_image.shape[1]] += transition_pixcels
plt.imshow(result_image)
plt.savefig('text.jpg')

Final Gluing

倾斜粘合

为了完整起见,这里也有一个在顶部粘合并带有倾斜底部的版本。我在一个点上附上图片,并以几度角围绕该固定点旋转。最后,我再次纠正一些非常轻微的不对齐问题。为了获得其坐标,我使用jupyter lab和%matplotlib widget

fixed_point_upper = np.array([139,379])
fixed_point_lower = np.array([0,400])
angle = np.deg2rad(2)
down_dir = np.array([np.sin(angle+np.pi/2),np.cos(angle+np.pi/2)])
right_dir = np.array([np.sin(angle),np.cos(angle)])

result_image_height = np.ceil((fixed_point_upper+lower_image.shape[0]*down_dir+(lower_image.shape[1]-fixed_point_lower[1])*right_dir)[0]).astype('int')
right_shift = np.ceil(-(fixed_point_upper+lower_image.shape[0]*down_dir-fixed_point_lower[1]*right_dir)[1]).astype('int')
result_image_width = right_shift+upper_image.shape[1]
result_image = np.zeros([result_image_height, result_image_width,3])
fixed_point_result = np.array([fixed_point_upper[0],fixed_point_upper[1]+right_shift])

lower_top_left = fixed_point_result-fixed_point_lower[1]*right_dir
result_image[:upper_image.shape[0],-upper_image.shape[1]:] = upper_image

# calculate points in lower_image
result_coordinates = np.stack(np.where(np.ones(result_image.shape[:2],dtype='bool')),axis=1)
lower_coordinates = np.stack([(result_coordinates-lower_top_left)@down_dir,(result_coordinates-lower_top_left)@right_dir],axis=1)
mask = (0 <= lower_coordinates[:,0]) & (0 <= lower_coordinates[:,1]) \
    & (lower_coordinates[:,0] <= lower_image.shape[0]) & (lower_coordinates[:,1] <= lower_image.shape[1])
result_coordinates = result_coordinates[mask]
lower_coordinates = lower_coordinates[mask]

# COORDINATES ON RESULT IMAGE
# left street 254
# left sides of houses 295, 420, 505
# right small street, both sides big street 590,635,664

# COORDINATES ON LOWER IMAGE
# left street 234
# left sides of houses 280, 399, 486
# right small street, both sides big street 571, 617, 642

def coord_transform(y): 
    return (y-lower_top_left[1])/right_dir[1]
y = tuple(map(coord_transform, [lower_top_left[1], 254, 295, 420, 505, 589, 635, 664]))
f = UnivariateSpline(y,[0, 234, 280, 399, 486, 571, 617, 642])
result_image[result_coordinates[:,0],result_coordinates[:,1]] = image_model.predict(lower_coordinates[:,0],np.vectorize(f)(lower_coordinates[:,1]))

Tilted Gluing


将切口平滑处理是有效的,但当您的切口为水平时更容易。当您的切口为不规则曲线且在变形一张或两张图像后不是直线时,您能做到吗?这就是困难所在。当您试图在图像的极端处合并它们时,如果它们不重叠甚至在重叠时,这并不是一个简单的过程。 - fmw42
谢谢您的回答。结果拼接很好,但我们能否获得图像的原始颜色?这段代码适用于多张图像拼接吗? - ganesh
这里我展示了两张图像的结果。实际上,我正在拼接多个具有高分辨率的图像。在您的代码中使用的整数值,比如在拼接时,是否也适用于其他输入的拼接? - ganesh
以上代码适用于多张图片吗?我正在寻找适用于多张图像拼接的解决方案。 - ganesh
@ganesh 噢,我不明白为什么它不能适用于多个。 - Lukas S
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接