【问题标题】:Warp Perspective transform of sub sections of image do not align图像子部分的翘曲透视变换不对齐
【发布时间】:2019-09-16 06:44:04
【问题描述】:

我想扭曲图像的子部分以将其投影到不均匀的表面上。最终我想扭曲图像HERE,有点像在HERE 中从THIS 项目中完成的。

我的问题是,当我将转换应用于图像的每个子部分时,事情就是不对齐

这是我实现转换然后缝合的过程(将它们裁剪并粘贴到最终图像上。

  1. 获取所有点的列表
  2. 从一组 4 个点创建一个四边形的感兴趣区域 (ROI)
  3. 这 4 个点用于将图像与对应的原始 4 个点进行变换。这是使用我的名为 perspective_transform() 的函数完成的

    一个。我取 2 组 4 个点并将它们传递给 M = cv2.getPerspectiveTransform(corners, newCorners)

    b.然后我调用:warped = cv2.warpPerspective(roi, M, (width, height))

  4. 在获得新的扭曲图像后,我使用蒙版根据关联的 ROI 将所有内容拼接在一起:

    一个。这是由函数 quadr_croped()

    完成的

    初始化屏幕以从屏幕获取原始像素,并将其保存到 Numpy 数组中

    img0 = np.array(sct.grab(monitor))
    clone = img0.copy()
    total_height, total_width, channels = img0.shape
    
    xSub =int (input("How many columns would you like to divide the screen in to? (integers only)"))
    ySub =int (input("How many rows would you like to divide the screen in to? (integers only)"))
    roi_width = float(total_width/xSub)
    roi_height = float(total_height/ySub)
    
    point_list = []
    

    第三:使用2组4个点来扭曲图像的透视

    def perspective_transform(image, roi, corners, newCorners, i = -1 ):

    corners = list (corners)
    newCorners = list (newCorners)
    height, width, pixType = image.shape
    corners = np.array([[corners[0][0],corners[0][1],corners[0][2],corners[0][3]]],np.float32)
    newCorners = np.array([[newCorners[0][0],newCorners[0][1],newCorners[0][2],newCorners[0][3]]],np.float32)
    
    
    M = cv2.getPerspectiveTransform(corners, newCorners)
    
    #warped = cv2.warpPerspective(roi, M, (width, height), flags=cv2.INTER_LINEAR)
    warped = cv2.warpPerspective(roi, M, (width, height))
    
    return warped
    

    第二个:将四边形剪切并粘贴到主图像中

    def quadr_croped (mainImg,image, pts, i): #example

    # mask defaulting to black for 3-channel and transparent for 4-channel
    # (of course replace corners with yours)
    mask = np.zeros(image.shape, dtype=np.uint8)
    roi_corners = pts #np.array([[(10,10), (300,300), (10,300)]], dtype=np.int32)
    # fill the ROI so it doesn't get wiped out when the mask is applied
    channel_count = image.shape[2]  # i.e. 3 or 4 depending on your image
    ignore_mask_color = (255,)*channel_count
    cv2.fillConvexPoly(mask, roi_corners, ignore_mask_color)
    
    
    # apply the mask
    masked_image = cv2.bitwise_and(image, mask)
    
    mainImg = cv2.bitwise_or(mainImg, mask)
    
    mainImg = mainImg + masked_image
    
    # cv2.imshow("debug: image, mainImg: " +str(i), mainImg)
    
    return mainImg
    

    首先:启动函数

    def draw_quadr(img1):

    #set up list for ROIquadrilateral == polygon with 4 sides
    numb_ROI = xSub * ySub
    skips =int((numb_ROI-1)/xSub)
    numb_ROI = skips + numb_ROI
    quadrilateral_list.clear()
    
    for i in range(numb_ROI):
        if not point_list[i][0] <= point_list[(i+xSub+2)][0]:
            continue
        vert_poly = np.array([[
            point_list[i],
            point_list[i+1],
            point_list[i+xSub+2], 
            point_list[i+xSub+1]
              ]], dtype=np.int32)  
    
    
        verticesPoly_old = np.array([[
            H_points_list[i],
            H_points_list[i+1],
            H_points_list[i+xSub+2], 
            H_points_list[i+xSub+1]
              ]], dtype=np.int32) 
    
        roi = img0.copy()
        # cv2.imshow("debug: roi"+str(i), roi)
        overlay = perspective_transform(
            img1,
            roi, 
            verticesPoly_old,
            vert_poly, 
            i)
    
        img1 = quadr_croped(img1,overlay,vert_poly,i)
    
    
        cv2.polylines(img1,vert_poly,True,(255,255,0))
        quadrilateral_list.append(vert_poly)
    
        pt1 = point_list[i]
        pt2 = point_list[i+xSub+2]
        cntPt = (int( (pt1[0]+pt2[0])/2),int((pt1[1]+pt2[1])/2) )
        cv2.putText(img1,str(len(quadrilateral_list)-1),cntPt,cv2.FONT_HERSHEY_SIMPLEX, 1,(0,255,0),2,cv2.LINE_AA)
        #cv2.imshow(str(i), img1) 
    return img1
    

图片结果链接

请看这些,因为它们很好地说明了问题。

原图无失真


此图像与中心有一个左偏移(没有 y 方向移动)

x方向畸变图像的结果


此图像从中心向上偏移(没有 x 方向移动)

y 方向失真图像的结果


这张图片从中心向上和向左偏移

x 和 y 方向失真图像的结果


我是计算机视觉和 stackoverflow 的新手,我希望我已经包含了所有内容来帮助描述问题,如果您需要其他帮助,请告诉我

【问题讨论】:

    标签: opencv python-3.7 camera-projection


    【解决方案1】:

    代码中肯定存在一些错误,因为输出图像看起来不应该(或可能不是)。但是由于透视变换的数学性质,你永远不会得到你想要的东西。也就是说,因为它们是非线性的。可以使矩形的角重合,但是在角之间图像的缩放不均匀,并且不能使这些不均匀在分割线的两侧都相同。

    但是您可以使用仿射变换来统一缩放图像。这保证了如果一条线上的两个点重合,那么所有其他点也重合。这里唯一的问题是使用三角形确定仿射变换,因此您需要将四边形拆分为三角形。例如。在下面的代码中,每个四边形被分成 4 个三角形,使用四边形的中心作为附加顶点。

    import numpy as np
    import matplotlib.pyplot as plt
    import cv2
    
    # generate a test image
    im = np.full((400,600), 255, 'u1')
    h, w = im.shape
    for i in range(1, w//20):
        im = cv2.line(im, (i*20, 0), (i*20, h), i*8)
    for i in range(1, h//20):
        im = cv2.line(im, (0, i*20), (w, i*20), i*10)
    plt.figure(figsize=(w/30, h/30))
    plt.imshow(im, 'gray')
    plt.show()
    
    # Number of grid cells
    nx, ny = 3, 2
    p0 = np.meshgrid(np.linspace(0, w-1, nx+1, dtype='f'), np.linspace(0, h-1, ny+1, dtype='f'))
    print(np.vstack(p0))
    p1 = [v.copy() for v in p0]
    
    # Move the central points
    p1[0][1,1] -= 30; p1[1][1,1] -= 40
    p1[0][1,2] += 20; p1[1][1,2] += 10
    print(np.vstack(p1))
    
    # Set perspective = True to see what happens if we use perspective transform
    perspective = False
    im1 = np.zeros_like(im)
    for i in range(nx):
        for j in range(ny):
            x0, y0 = p0[0][j,i], p0[1][j,i]
            c0 = np.stack((p0[0][j:(j+2),i:(i+2)].ravel() - x0, p0[1][j:(j+2),i:(i+2)].ravel() - y0))
            c1 = np.stack((p1[0][j:(j+2),i:(i+2)].ravel(), p1[1][j:(j+2),i:(i+2)].ravel()))
    
            if perspective:
                ic0 = np.round(c0).astype('i')
                ic1 = np.round(c1).astype('i')
                M = cv2.getPerspectiveTransform(c0.T, c1.T)
                imw = cv2.warpPerspective(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
                im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,[0,1,3,2]].T, 255) & imw
            else:
                c0 = np.append(c0, np.mean(c0, axis=1, keepdims=True), 1)
                c1 = np.append(c1, np.mean(c1, axis=1, keepdims=True), 1)
                ic0 = np.round(c0).astype('i')
                ic1 = np.round(c1).astype('i')
                for ind in ([0,1,4], [1,3,4], [3,2,4], [2,0,4]):
                    M = cv2.getAffineTransform(c0[:,ind].T, c1[:,ind].T)
                    imw = cv2.warpAffine(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
                    im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,ind].T, 255) & imw
    plt.figure(figsize=(w/30, h/30))
    plt.imshow(im1, 'gray')
    plt.show()
    

    【讨论】:

    • 谢谢,我会试一试,告诉你进展如何
    • 这就是问题所在,我需要使用仿射变换来让所有内容对齐,现在我需要加快整个过程。当我获得声誉时,我会投票赞成。感谢您的所有帮助和示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 2021-02-19
    • 2013-07-01
    • 2012-10-13
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    相关资源
    最近更新 更多