def best_into_mapping(domain, H, codomain):
    """
    Associates each point in *domain* with the point in *codomain* nearest its image
    under homography *H*. Returns an ordered list of images corresponding to points
    in *domain*, along with some indication of how good or bad the match is.
    """
    RANGE = []
    total_error = 0
    
    for preimage in domain:
        modeled = H * preimage
        
        min_error = None
        image = None
        for point in codomain:
            error = sqdist(htoc(modeled), htoc(point))
            if min_error == None or error < min_error:
                min_error = error
                image = point
        
        total_error += min_error
        RANGE.append(image)
    
    return RANGE, total_error
def _reshape(points2, HOM_OUT=None):
    """
    Returns a matrix containing two-dimensional representations of corner points in
    *points2*, in a shape which hopefully corresponds to that of the calibration
    board on which the corners are located. The associated homography is constrained
    to map the corners of a pre-image board to the observed corners, and the
    board dimensions must be co-divisors of len(*points2*). If requested,
    np.savetxt()'s this homography to *HOM_OUT*.
    """
    corners = cl.corners(points2)
    npts = len(points2)
    
    min_error = None
    H = None
    height = None
    width = None
    ordered = None
    for (rows, cols) in [ (div, npts/div)
                          for div in range(2, npts/2 + 1)
                          if npts % div == 0 ]:
        h = hm.homography(_box(rows, cols), [ ctoh(p) for p in corners ])
        ordering, error = hm.best_into_mapping(_board(rows, cols),
                                               h,
                                               [ ctoh(p) for p in points2 ])
        
        if min_error == None or error < min_error:
            min_error = error
            H = h
            height = rows
            width = cols
            ordered = ordering
    
    print "    sum of squared error:", min_error
    
    if HOM_OUT != None:
        np.savetxt(HOM_OUT, H)
    # return the homography and a matrix of the points in the shape of the board
    return np.reshape(np.asarray([ htoc(p)
                                   for p in ordered ]),
                      (height, width, -1))