Inverting a real-valued index grid

前端 未结 7 927
南笙
南笙 2020-12-24 15:37

OpenCV\'s remap() uses a real-valued index grid to sample a grid of values from an image using bilinear interpolation, and returns the grid of samples as a new image.

<
7条回答
  •  梦毁少年i
    2020-12-24 15:57

    If you map is derived from a homography H you could invert H and directly create the inverse maps with cv::initUndistortRectifyMap().

    e.g. in Python:

    import numpy as np.
    map_size = () # fill in your map size
    H_inv = np.linalg.inv(H)
    map1, map2 = cv2.initUndistortRectifyMap(cameraMatrix=np.eye(3), distCoeffs=np.zeros(5), R=H_inv, newCameraMatrix=np.eye(3), size=map_size, m1type=cv2.CV_32FC1)
    

    The OpenCV documentation states about initUndistortRectifyMap():

    The function actually builds the maps for the inverse mapping algorithm that is used by remap(). That is, for each pixel (u, v) in the destination image, the function computes the corresponding coordinates in the source image.

    In the case you have just given the maps, you have to do it by yourself. Hoewever, interpolation of the new maps' coordinates is not trivial, because the support region for one pixel could be very large.

    Here is a simple Python solution which inverts the maps by doing point-to-point mapping. This will probably leave some coordinates unassigned, while others will be updated several times. So there may be holes in the map.

    Here is a small Python program demonstrating both approaches:

    import cv2
    import numpy as np
    
    
    def invert_maps(map_x, map_y):
        assert(map_x.shape == map_y.shape)
        rows = map_x.shape[0]
        cols = map_x.shape[1]
        m_x = np.ones(map_x.shape, dtype=map_x.dtype) * -1
        m_y = np.ones(map_y.shape, dtype=map_y.dtype) * -1
        for i in range(rows):
            for j in range(cols):
                i_ = round(map_y[i, j])
                j_ = round(map_x[i, j])
                if 0 <= i_ < rows and 0 <= j_ < cols:
                    m_x[i_, j_] = j
                    m_y[i_, j_] = i
        return m_x, m_y
    
    
    def main():
        img = cv2.imread("pigeon.png", cv2.IMREAD_GRAYSCALE)
    
        # a simply rotation by 45 degrees
        H = np.array([np.sin(np.pi/4), -np.cos(np.pi/4), 0, np.cos(np.pi/4), np.sin(np.pi/4), 0, 0, 0, 1]).reshape((3,3))
        H_inv = np.linalg.inv(H)
        map_size = (img.shape[1], img.shape[0])
    
        map1, map2 = cv2.initUndistortRectifyMap(cameraMatrix=np.eye(3), distCoeffs=np.zeros(5), R=H, newCameraMatrix=np.eye(3), size=map_size, m1type=cv2.CV_32FC1)
        map1_inv, map2_inv = cv2.initUndistortRectifyMap(cameraMatrix=np.eye(3), distCoeffs=np.zeros(5), R=H_inv, newCameraMatrix=np.eye(3), size=map_size, m1type=cv2.CV_32FC1)
        map1_simple_inv, map2_simple_inv = invert_maps(map1, map2)
    
        img1 = cv2.remap(src=img, map1=map1, map2=map2, interpolation=cv2.INTER_LINEAR)
        img2 = cv2.remap(src=img1, map1=map1_inv, map2=map2_inv, interpolation=cv2.INTER_LINEAR)
        img3 = cv2.remap(src=img1, map1=map1_simple_inv, map2=map2_simple_inv,
                                   interpolation=cv2.INTER_LINEAR)
    
        cv2.imshow("Original image", img)
        cv2.imshow("Mapped image", img1)
        cv2.imshow("Mapping forth and back with H_inv", img2)
        cv2.imshow("Mapping forth and back with invert_maps()", img3)
        cv2.waitKey(0)
    
    
    if __name__ == '__main__':
        main()
    

提交回复
热议问题