pythonnumpyopencvhomographyimage-stitching

OpenCV findHomography should return an identity matrix. Why is it instead returning these unexpected homography matrices?


I use findHomography to stitch images together. But as I was testing it with already perfectly overlapping pictures I got some unexpected results. I was expecting that the homography would always be an identity matrix and most of the time that was true, but one time it returned a completely different matrix.

I made a simple example with the points that returned this unexpected matrix and I got a different result but again not an identity matrix.

import numpy as np
import cv2

image1_points = np.array([[56., 96.], [56., 219.], [56., 219.], [37., 667.], [56., 720.], [56., 780.], [56., 837.]])
image2_points = np.array([[56., 96.], [56., 219.], [56., 219.], [37., 667.], [56., 720.], [56., 780.], [56., 837.]])

homography, mask = cv2.findHomography(image2_points, image1_points, cv2.RANSAC)
# In stitching.py I get:
#  -23.58183,  -0.00000,  547.67250
# -176.30191, -13.80196, 9872.90692
#   -0.26432,  -0.00000,    1.00000

# Here I get:
#   -2.95431,  -0.00000,   88.10041
#  -28.36051,  -1.38109, 1588.18848
#   -0.04252,  -0.00000,    1.00000

So, can somebody explain what is happening here? Is this a bug or some special case that can be worked around?

Any help is appreciated!


Solution

  • So now I tested the suggestions by @ZWang and @Micka. Here is an updated version of the code provided in my question with added comments for explanation. I hope this will help some people!

        import numpy as np
        import cv2
        
        # Original arrays were the problem occurs. There are enough points, but they lack the property to span a plane, wich is needed for finding a homography
        image1_points = np.array([[56., 96.], [56., 219.], [56., 219.], [37., 667.], [56., 720.], [56., 780.], [56., 837.]])
        image2_points = np.array([[56., 96.], [56., 219.], [56., 219.], [37., 667.], [56., 720.], [56., 780.], [56., 837.]])
        
        homography, mask = cv2.findHomography(image2_points, image1_points, cv2.RANSAC)
        print(homography)
        # In stitching.py I get:
        #  -23.58183,  -0.00000,  547.67250
        # -176.30191, -13.80196, 9872.90692
        #   -0.26432,  -0.00000,    1.00000
        
        # Here I get:
        #   -2.95431,  -0.00000,   88.10041
        #  -28.36051,  -1.38109, 1588.18848
        #   -0.04252,  -0.00000,    1.00000
    
        # No problems as long as there are at least 4 corresponding points and they span a plane!
        image1_points = np.array([[40., 96.], [56., 219.], [37., 667.], [56., 720.]])
        image2_points = np.array([[40., 96.], [56., 219.], [37., 667.], [56., 720.]])
    
        homography, mask = cv2.findHomography(image2_points, image1_points, cv2.RANSAC)
        print(homography)
        # Now I get the identity matrix that is to be expected:
        # 1.00000, 0.00000, 0.00000
        # 0.00000, 1.00000, 0.00000
        # 0.00000, 0.00000, 1.00000