示例#1
0
class ICPBase(object):
    """
    Base class for traditional ICP and paralleled ICP

    - Sketches the ICP algorithm skeleton
    - Define common attributes and functions
    """
    def __init__(self, src, dst, plot=True, reinit=False):
        """
        Initialize ICPBase class object

        :param src: source PointCloud object
        :param dst: destination PointCloud object
        :param plot: visualize the registration or not
        :param reinit: re-initialize the current PointCloud when local minima is encounted, or not
        """
        self.src = src
        self.dst = dst
        assert self.src.num == self.dst.num
        self.result = PointCloud(src)
        self.plot = plot
        self.reinit = reinit
        if self.plot: self.plotter = PointCloudPlotter(self.dst)



    def getPointCloudRegistration(self, target):
        """
        Compute the PointCloud registration with correspondence.
        It is same for both ICP and ICPParallel.

        :param target: the target PointCloud to register with
        :return: R: Rotation between PointCloud result and target
                T: Translation between PointCloud result and target
        """
        assert self.result and target
        assert self.result.num == target.num

        H = np.dot(self.result.normPoints.T, target.normPoints)
        U, S, Vt = np.linalg.svd(H)
        R = np.dot(Vt.T, U.T)
        # Consider reflection case
        if np.linalg.det(R) < 0:
            Vt[2,:] *= -1
            R = np.dot(Vt.T, U.T)
        # Raise a warning if the SVD is not correctly performed
        if abs(np.linalg.det(R) - 1.0) > 0.0001:
            Warning("Direct Point Cloud registration unstable!")
        T = target.center - self.result.center.dot(R.T)
        return R, T


    def computeCorrespondence(self):
        """
        Base function for finding correspondence.
        Assertion only. Detailed implementation varies.

        :return: total distance and updated PointCloud result
        """
        assert self.result and self.dst
        assert self.result.num == self.dst.num



    def solve(self):
        """
        Algorithmatic skeleton of ICP.
        It is common for both ICP and ICPParallel
        See PDF report or Besl's paper for more detials.

        :return: None
        """
        print 'Solve ICP with', self.__class__.__name__
        distanceThres, maxIteration, iteration = 0.001, 20, 0
        # Perform the initial computation of correspondence
        currentDistance, target = self.computeCorrespondence()
        print "Init ICP, distance: %f" % currentDistance
        # ICP loop
        while currentDistance > distanceThres and iteration < maxIteration:
            if self.plot: self.plotter.plotData(self.result)
            # Compute tranformation between self.result and self.target
            R, T = self.getPointCloudRegistration(target)

            # Appy transformation to self.result
            self.result.applyTransformation(R, T)

            # DEBUG
            if self.reinit:
                if np.amax(np.abs(R - np.identity(3))) < 0.000001 and np.amax(np.abs(T)) < 0.000001:
                    self.result.applyTransformation(getRandomRotation(), getRandomTranslation())

            # Compute point correspondence
            currentDistance, target = self.computeCorrespondence()

            # Update
            iteration += 1
            print "Iteration: %5d, with total distance: %f" % (iteration, currentDistance)
示例#2
0
    from optparse import OptionParser
    parser = OptionParser()
    parser.add_option('-n',
                      '--number',
                      dest='pointNum',
                      help='number of points in the point cloud',
                      type='int',
                      default=256)
    parser.add_option('-p',
                      '--plot',
                      dest='plot',
                      action='store_true',
                      help='visualize icp result',
                      default=False)
    parser.add_option('-c',
                      '--core',
                      dest='coreNum',
                      help='number of threads used in the cuda',
                      type='int',
                      default=0)
    (options, args) = parser.parse_args()
    pc1 = PointCloud()
    pc1.initFromRand(options.pointNum, 0, 1, 10, 20, 0, 1)
    pc2 = PointCloud(pc1)
    pc2.applyTransformation()
    icpSolver = ICPParallel(pc1,
                            pc2,
                            numCore=options.coreNum,
                            plot=options.plot)
    icpSolver.solve()
示例#3
0
                      '--number',
                      dest='pointNum',
                      help='number of points in the point cloud',
                      type='int',
                      default=256)
    parser.add_option('-p',
                      '--plot',
                      dest='plot',
                      action='store_true',
                      help='visualize icp result',
                      default=False)
    parser.add_option('-c',
                      '--core',
                      dest='coreNum',
                      help='number of threads used in the cuda',
                      type='int',
                      default=0)
    (options, args) = parser.parse_args()
    pc1 = PointCloud()
    pc1.initFromRand(options.pointNum, 0, 1, 10, 20, 0, 1)
    pc2 = PointCloud(pc1)
    pc2.applyTransformation(None, None)
    icpSolver = ICP(pc1, pc2, plot=options.plot)
    icpSolver.solve()
    print
    icpParallelSolver = ICPParallel(pc1,
                                    pc2,
                                    numCore=options.coreNum,
                                    plot=options.plot)
    icpParallelSolver.solve()