视角变换

变换的方法和正畸算法类似,但是正畸算法是将标准对象点变换到图像上,而透视变换是将一种视角的图像上的兴趣点,变换到目标视角图像上。通过这种变换我们可以更好的从图片中获取我们关注的信息。

进行线性变换,我们只需要在两张图片中各选取四个点,分别构建一个平面,然后计算变换矩阵,进行变换。

注意:有很多自动选点算法,比如利用边缘和端点等

  1. 基于源和目的图像的四个点,计算变换矩阵M
M = cv2.getPerspectiveTransform(src, dst)
  1. 计算逆矩阵(用于恢复)
Minv = cv2.getPerspectiveTransform(dst, src)
  1. 变换视角
warped = cv2.warpPerspective(img, M, img_size, flags=cv2.INTER_LINEAR)
_img = cv2.imread("./calibration_wide/dst.jpg")

nx = 8 # the number of inside corners in x
ny = 6 # the number of inside corners in y


def draw_poly(points,p_color,l_color,text_color,ax=None,fontsize=30):
    xx = []
    yy = []
    for index,v in enumerate(points):
        for x,y in v:
            if ax:
                ax.annotate("  p{0}({1},{2})".format(index,int(x),int(y)),(x,y),fontsize=fontsize,color=text_color)
                ax.plot(x,y,p_color,markersize="30")
            else:
                plt.annotate("  p{0}({1},{2})".format(index,int(x),int(y)),(x,y),fontsize=fontsize,color=text_color)
                plt.plot(x,y,p_color,markersize="30")
            xx.append(x)
            yy.append(y)
    
    xx.append(xx[0])
    yy.append(yy[0])
    if ax:
        ax.plot(xx,yy,l_color,lw=5)
    else:
        plt.plot(xx,yy,l_color,lw=5)


    
    
    
    
def corners_unwarp(img, nx, ny):
    # Pass in your image into this function
    # Write code to do the following steps
    # 1) Undistort using mtx and dist
    # 2) Convert to grayscale
    # 3) Find the chessboard corners
    # 4) If corners found: 
            # a) draw corners
            # b) define 4 source points src = np.float32([[,],[,],[,],[,]])
                 #Note: you could pick any four of the detected corners 
                 # as long as those four corners define a rectangle
                 #One especially smart way to do this would be to use four well-chosen
                 # corners that were automatically detected during the undistortion steps
                 #We recommend using the automatic detection of corners in your code
            # c) define 4 destination points dst = np.float32([[,],[,],[,],[,]])
            # d) use cv2.getPerspectiveTransform() to get M, the transform matrix
            # e) use cv2.warpPerspective() to warp your image to a top-down view
    #delete the next two lines
    _gray = cv2.cvtColor(_img,cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(_gray, (COL,ROW), None)
    #print(corners)
    dst_with_corner = cv2.drawChessboardCorners(_gray,(COL,ROW),corners,ret)
    
    src_point = np.float32([corners[0],corners[2],corners[10],corners[8]])
    plt.figure(figsize=(20,20))
    plt.imshow(dst_with_corner,cmap="gray")
    draw_poly(src_point,".g","-b","yellow")
    #print(src_point)
    
    #offset = 100
    #dst = np.float32([[offset, offset], [img_size[0]-offset, offset], [img_size[0]-offset, img_size[1]-offset], [offset, img_size[1]-offset]])
    dst_point = np.float32([[[94,214]],[[370,214]],[[370,365]],[[94,365]]])
    #dst_point = np.float32([[corners[0][0]],[[corners[0][1][0],214]],[[370,365]],[[94,365]]])
    #print(corners[0])
    #print(dst_point)
    draw_poly(dst_point,".r","--y","red")
    
    M = cv2.getPerspectiveTransform(src_point, dst_point)
    warped = cv2.warpPerspective(_gray, M, _gray.shape, flags=cv2.INTER_LINEAR)
 
    return warped, M,src_point,dst_point

top_down, perspective_M,src_point,dst_point= corners_unwarp(_img, nx, ny)
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()

draw_poly(src_point,".g","-b","yellow",ax1,fontsize=20)
ax1.imshow(_img,cmap="gray")
ax1.set_title('Original Image', fontsize=50)

draw_poly(dst_point,".r","--y","red",ax2,fontsize=20)
ax2.imshow(top_down,cmap="gray")
ax2.set_title('Undistorted and Warped Image', fontsize=50)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)

如果比例相差太大,会产生缩放的效果