0

I am trying to run the code suggested here by Harry R. (first solution to the question) and I get an error saying cv2 does not have transform method:

Traceback (most recent call last):
  File "/Users/kkk/PycharmProjects/TestICPPython3.7/ICPTest.py", line 64, in <module>
    M2 = icp(a, b, [0.1, 0.33, np.pi / 2.2], 30)
  File "/Users/kkk/PycharmProjects/TestICPPython3.7/ICPTest.py", line 32, in icp
    src = cv2.transform(src, Tr[0:2])
AttributeError: module 'cv2' has no attribute 'transform'

Did anyone get this? What could be wrong? Thanks

user2167741
  • 277
  • 1
  • 10
  • I think you are calling transform not as a method. did you type transform()? – NoSkillMan May 30 '20 at 14:04
  • Yes, I did. And it says `NameError: name 'transform' is not defined`. It is actually defined through cv2 - https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html – user2167741 May 30 '20 at 14:44
  • Do you perhaps have a script of your own named `cv2.py`, that is being imported instead of the actual module? – jasonharper May 30 '20 at 15:39
  • No, actually it appears that it is not available for Python 3.7. It works in Python 3.0. – user2167741 May 30 '20 at 18:01

1 Answers1

0

OK, I finally got this to work in Python 3.0 (I think the original version was Python 2.7) and not in Python 3.7. Note that there cv2.estimateRigidTransform is changed into cv2.estimateAffinePartial2D and we have two return variables instead of one in the original code since cv2.estimateRigidTransform is now eliminated.

import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import NearestNeighbors

def icp(a, b, init_pose=(0, 0, 0), no_iterations=13):

    """
    The Iterative Closest Point estimator.
    Takes two cloudpoints a[x,y], b[x,y], an initial estimation of
    their relative pose and the number of iterations
    Returns the affine transform that transforms
    the cloudpoint a to the cloudpoint b.
    Note:
        (1) This method works for cloudpoints with minor
        transformations. Thus, the result depents greatly on
        the initial pose estimation.
        (2) A large number of iterations does not necessarily
        ensure convergence. Contrarily, most of the time it
        produces worse results.
    """

    src = np.array([a.T], copy=True).astype(np.float32)
    dst = np.array([b.T], copy=True).astype(np.float32)

    # Initialise with the initial pose estimation
    Tr = np.array([[np.cos(init_pose[2]), -np.sin(init_pose[2]), init_pose[0]],
                   [np.sin(init_pose[2]), np.cos(init_pose[2]), init_pose[1]],
                   [0, 0, 1]])

    src = cv2.transform(src, Tr[0:2])

    for i in range(no_iterations):

        # Find the nearest neighbours between the current source and the
        # destination cloudpoint

        nbrs = NearestNeighbors(n_neighbors=1, algorithm='auto').fit(dst[0])
        distances, indices = nbrs.kneighbors(src[0])

        # Compute the transformation between the current source
        # and destination cloudpoint
        T, tmp = cv2.estimateAffinePartial2D(src, dst[0, indices.T], False)
        # Transform the previous source and update the
        # current source cloudpoint
        src = cv2.transform(src, T)
        # Save the transformation from the actual source cloudpoint
        # to the destination
        Tr = np.dot(Tr, np.vstack((T, [0, 0, 1])))

    return Tr[0:2]


# Create the datasets
ang = np.linspace(-np.pi / 2, np.pi / 2, 320)
a = np.array([ang, np.sin(ang)])
th = np.pi / 2
rot = np.array([[np.cos(th), -np.sin(th)], [np.sin(th), np.cos(th)]])
b = np.dot(rot, a) + np.array([[0.2], [0.3]])

# Run the icp
M2 = icp(a, b, [0.1, 0.33, np.pi / 2.2], 30)
#
# # Plot the result
src = np.array([a.T]).astype(np.float32)
res = cv2.transform(src, M2)
plt.figure()
plt.plot(b[0], b[1])
plt.plot(res[0].T[0], res[0].T[1], 'r.')
plt.plot(a[0], a[1])
plt.show()
user2167741
  • 277
  • 1
  • 10