当前位置: 首页 > 知识库问答 >
问题:

opencv通过拉伸关键点对齐两个图像

邹宏峻
2023-03-14

我有两张照片

图像1(对象):

没有标记关键点的原始图像:

图2为白色图片(500x500)

在图1和图2中,我标记了关键点。我想按关键点对齐图像2上的图像1。因此,目标是使两个关键点与拉伸、缩放和变换图像重叠2。

这是我的关键点(csv文件)。图像1中的图像1和图像2的坐标是x和y。

object1_x,object1_y,image_x,image_y
0,0,80,137
286,0,409,42
286,198,416,390
174,198,331,384
158,116,291,119
0,97,111,311

如何使用opencv和python实现这一点?因此,结果图像应如下所示(没有红点,红点仅用于演示关键点):

共有1个答案

轩辕弘雅
2023-03-14

从第一组关键点提取3个索引集,当从两组关键点索引时,这些关键点将形成三角形。使用索引,我们可以从两组关键点获得相应的三角形,从而可以逐个三角形构建扭曲图像三角形(有关更多详细信息,请参阅使用OpenCV将一个三角形扭曲到另一个三角形):

image1.png(附加点):

image2.png(附加点):

结果(有加分)

import cv2
import numpy as np

def triangles(points):
    points = np.where(points, points, 1)
    subdiv = cv2.Subdiv2D((*points.min(0), *points.max(0)))
    subdiv.insert(list(points))
    for pts in subdiv.getTriangleList().reshape(-1, 3, 2):
        yield [np.where(np.all(points == pt, 1))[0][0] for pt in pts]

def crop(img, pts):
    x, y, w, h = cv2.boundingRect(pts)
    img_cropped = img[y: y + h, x: x + w]
    pts[:, 0] -= x
    pts[:, 1] -= y
    return img_cropped, pts

def warp(img1, img2, pts1, pts2): 
    for indices in triangles(pts1):
        img1_cropped, triangle1 = crop(img1, pts1[indices])
        img2_cropped, triangle2 = crop(img2, pts2[indices])
        transform = cv2.getAffineTransform(np.float32(triangle1), np.float32(triangle2))
        img2_warped = cv2.warpAffine(img1_cropped, transform, img2_cropped.shape[:2][::-1], None, cv2.INTER_LINEAR, cv2.BORDER_REFLECT_101)
        mask = np.zeros_like(img2_cropped)
        cv2.fillConvexPoly(mask, np.int32(triangle2), (1, 1, 1), 16, 0)
        img2_cropped *= 1 - mask
        img2_cropped += img2_warped * mask

img1 = cv2.imread("image1.png")
img2 = cv2.imread("image2.png")

pts1 = np.array([[0, 0], [286, 0], [286, 198], [174, 198], [158, 116], [0, 97]])
pts2 = np.array([[80, 37], [409, 42], [416, 390], [331, 384], [291, 119], [111, 311]])

warp(img1, img2, pts1, pts2)

for pt in pts2:
    cv2.circle(img2, tuple(pt), 15, (0, 0, 255), -1)

cv2.imshow("Original", img1)
cv2.imshow("Transformed", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 导入必要的库:
import cv2
import numpy as np
def triangles(points):
    points = np.where(points, points, 1)
    subdiv = cv2.Subdiv2D((*points.min(0), *points.max(0)))
    subdiv.insert(list(points))
    for pts in subdiv.getTriangleList().reshape(-1, 3, 2):
        yield [np.where(np.all(points == pt, 1))[0][0] for pt in pts]
def crop(img, pts):
    x, y, w, h = cv2.boundingRect(pts)
    img_cropped = img[y: y + h, x: x + w]
    pts[:, 0] -= x
    pts[:, 1] -= y
    return img_cropped, pts
def warp(img1, img2, pts1, pts2): 
    for indices in triangles(pts1):
        img1_cropped, triangle1 = crop(img1, pts1[indices])
        img2_cropped, triangle2 = crop(img2, pts2[indices])
        transform = cv2.getAffineTransform(np.float32(triangle1), np.float32(triangle2))
        img2_warped = cv2.warpAffine(img1_cropped, transform, img2_cropped.shape[:2][::-1], None, cv2.INTER_LINEAR, cv2.BORDER_REFLECT_101)
        mask = np.zeros_like(img2_cropped)
        cv2.fillConvexPoly(mask, np.int32(triangle2), (1, 1, 1), 16, 0)
        img2_cropped *= 1 - mask
        img2_cropped += img2_warped * mask
img1 = cv2.imread("image1.png")
img2 = cv2.imread("image2.png")

pts1 = np.array([[0, 0], [286, 0], [286, 198], [174, 198], [158, 116], [0, 97]])
pts2 = np.array([[80, 37], [409, 42], [416, 390], [331, 384], [291, 119], [111, 311]])
warp(img1, img2, pts1, pts2)

for pt in pts2:
    cv2.circle(img2, tuple(pt), 15, (0, 0, 255), -1)

cv2.imshow("Original", img1)
cv2.imshow("Transformed", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
 类似资料:
  • 我试图在一个div中放两个跨度,每边一个,都与div的底部对齐,而不使用绝对定位(因为这忽略了填充等,我总是在使用它后感觉不好)。右跨度中的文本比左跨度中的文本高。如果我使用垂直对齐来定位它们,如果它们都是浮动的,就不会受到影响,但是如果它们都没有浮动,它们就不会正确地水平对齐。我不能保证两个跨度中的哪一个会有更多的文本。 http://jsfiddle.net/gsvfn07f/

  •     最后我们再来谈谈minificationFilter和magnificationFilter属性。总得来讲,当我们视图显示一个图片的时候,都应该正确地显示这个图片(意即:以正确的比例和正确的1:1像素显示在屏幕上)。原因如下: 能够显示最好的画质,像素既没有被压缩也没有被拉伸。 能更好的使用内存,因为这就是所有你要存储的东西。 最好的性能表现,CPU不需要为此额外的计算。     不过有时

  • 问题内容: 我的项目是对齐航空照片,以制作出一张马赛克地图。我的计划是从两张照片开始,将第二张照片与第一张照片对齐,然后从两张对齐的图像中创建一个“初始镶嵌”。完成此操作后,我将第三张照片与初始镶嵌图对齐,然后将第四张照片与该图的结果对齐,以此类推,从而逐步构建地图。 我有两种技术可以做到这一点,但是使用的更精确的技术仅适用于两个图像阶段,因为两个输入图像的大小必须相同。因此,我尝试了一种新的解决

  • 问题内容: 尝试查看是否有任何JavaScript库功能可以合并两个json对象的特定键的值 使用$ .extend和$ .merge给出以下结果 我正在寻找的是 问题答案: 您想深入扩展

  • 我已经创建了两个Javafx网格窗格,我希望它们处于相同的位置,第二个网格窗格必须位于第一个网格窗格旁边的相同位置。因为我跑步时一个接一个。这是我的代码:

  • 我正在尝试使用Glide在Listview中加载一些图像。如果加载图像时未使用占位符,则图像将正确加载。然而,当我试图设置占位符时,我正在通过网络加载的图像似乎被拉伸了。这仅在使用占位符图像的情况下发生。如果我离开屏幕并返回(因此没有加载占位符图像),则图像会正确显示。 这是我的简单Glide实现: