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

Python opencv通过拉伸关键点对齐两个图像,python,opencv,image-processing,Python,Opencv,Image Processing,我有两张照片 图像1(对象): ] 未标记关键点的原始图像: 图2为白色图片(500x500) 在图1和图2中,我标记了关键点。 我想按关键点对齐图像2上的图像1。因此,目标是使两个关键点与拉伸、缩放和变换图像重叠2 这是我的关键点(csv文件)。对于图像1中的图像1和图像2中的图像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,11

我有两张照片

图像1(对象):

]

未标记关键点的原始图像:

图2为白色图片(500x500)

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

这是我的关键点(csv文件)。对于图像1中的图像1和图像2中的图像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实现这一点? 因此,结果图像应如下所示(没有红点,红点仅用于演示关键点):

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

image1.png
(添加点):

image2.png
(添加点):

结果(增加分数)

代码 输出

解释
  • 导入必要的库:
  • 定义一个函数,
    三角形
    ,该函数将接受一个坐标数组,
    ,并生成三角形数组的3个索引列表,这些三角形将覆盖原始坐标数组的区域:
  • 定义一个函数,
    crop
    ,该函数将接收一个图像数组,
    img
    ,以及一个三坐标数组,
    pts
    。它将返回图像的一个矩形段,该矩形段刚好足够大以适合由三个点形成的三角形,并返回传输到图像左上角的三个坐标的数组:
  • 定义一个函数
    warp
    ,该函数将接受两个图像数组
    img1
    img2
    ,以及两个坐标数组
    pts1
    pts2
    。它将利用在迭代第一个坐标数组中的三角形之前定义的
    triangles
    函数,以及之前定义的
    crop
    函数在对应于三角形索引的坐标处裁剪两幅图像,并使用
    cv2.warpAffine()
    在迭代的当前三角形处扭曲图像的方法:
  • 读入你的图像。在你的例子中,<代码> IMG1 < /代码>是我们要翘曲的图像,而<代码> IMG2< /Cord>是空白的500×500图像。另外,定义2个坐标数组作为图像的关键点:
  • 最后,使用前面定义的
    warp
    函数来扭曲
    img1
    ,使其关键点与
    img2
    的关键点重叠,并显示结果图像。我将第二个坐标数组中的点绘制到生成的扭曲图像上,以使扭曲过程更易于可视化:

  • 三角形网格扭曲
    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()
    
    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()