示例#1
0
 def scale_and_rotate(self, subject, s, theta, inverse=False):
     '''Rotate over theta and scale by s'''
     rotation_matrix = np.array(
         [[s * math.cos(theta), -1 * s * math.sin(theta)],
          [s * math.sin(theta), s * math.cos(theta)]])
     if inverse:
         return Shape(np.dot(rotation_matrix.T, subject.matrix))
     else:
         return Shape(np.dot(rotation_matrix, subject.matrix))
示例#2
0
    def normalize(self, shape):
        '''
        Perform isomorphic scaling in order to normalize shapes
        See Amy Ross on GPA p.5

        in: target Shape
        out: scaled Shape object
        '''
        return Shape([shape.vector / np.linalg.norm(shape.vector)])
示例#3
0
    def __init__(self, eigenvalues, eigenvectors, mean):
        self.dimension = eigenvalues.size
        self.eigenvalues = eigenvalues
        self.eigenvectors = eigenvectors
        self.mean = Shape(mean)

        # create a set of scaled eigenvectors
        self.scaled_eigenvectors = np.dot(self.eigenvectors,
                                          np.diag(self.eigenvalues))
示例#4
0
    def deform(self, shape_param):
        '''
        Reconstruct a shape based on principal components and a set of
        parameters that define a deformable model (see Cootes p. 6 eq. 2)

        in: Tx1 vector deformable model b
        out: 1xC deformed image
        '''
        return Shape(self.mean.vector +
                     self.scaled_eigenvectors.dot(shape_param))
示例#5
0
    def examine(self, model_points, t=0, pyramid_level=0):
        '''
        Examines points normal to model points and compare its grey-levels
        with the grey-level model.

        in: matrix of pixels image
            array of model points (x1, x2, ..., xN, y1, ..., yN)
            int t amount of pixels examined either side of the normal (t > k)
        out: Shape with adjustments (dx, dy) to better approximate target
        '''
        if not isinstance(model_points, Shape):
            model_points = Shape(model_points)
        new_points = model_points.matrix
        # keep track of large movements
        movement = np.zeros((model_points.length, 1))
        # get greylevel model for requested pyramid level
        glmodel = self.glmodel_pyramid[pyramid_level]
        # determine reduction based on pyramid level
        reduction = 2**pyramid_level

        i = 0
        for m in range(model_points.length):
            i += 1
            # set model index (for mean/cov)
            glmodel.set_evaluation_index(m - 1)
            # choose model points according to pyramid level
            prev, curr, nex = m - 2, m - 1, m
            reduced_points = model_points / reduction
            # get current, previous and next
            points = np.array([
                reduced_points.get(prev),
                reduced_points.get(curr),
                reduced_points.get(nex)
            ])
            # get point that best matches gray levels
            new_points[:, curr], movement[curr] = self.get_best_match(glmodel,
                                                                      points,
                                                                      t=t)
        print 'Number of points examined:', str(i)

        return Shape(new_points) * reduction, movement
示例#6
0
    def fit(self, prev_shape, new_shape, pyramid_level=0, n=None):
        '''
        Algorithm that finds the best shape parameters that match identified
        image points.

        In: PointDistributionModel instance pdm,
            array of new image points (x1, x2, ..., xN, y1, y2,..., yN)
        Out: the pose params (Tx, Ty, s, theta) and shape parameter (c) to
            fit the model to the image
        '''
        if not isinstance(new_shape, Shape):
            new_shape = Shape(new_shape)
        if not isinstance(prev_shape, Shape):
            prev_shape = Shape(prev_shape)
        if not self.start_pose:
            raise ValueError('No inital pose parameters found.')

        # find pose parameters to align with new image points
        Tx, Ty, s, theta = self.start_pose
        dx, dy, ds, dTheta = self.aligner.get_pose_parameters(
            prev_shape, new_shape)
        changed_pose = (Tx + dx, Ty + dy, s * (1 + ds), theta + dTheta)

        # align image with model
        y = self.aligner.invert_transform(new_shape, changed_pose)

        # SVD on scaled eigenvectors of the model
        u, w, v = np.linalg.svd(self.pdmodel.scaled_eigenvectors,
                                full_matrices=False)
        W = np.zeros_like(w)

        # define weight vector n
        if n is None:
            last_eigenvalue = self.pdmodel.eigenvalues[-1]
            n = last_eigenvalue**2 if last_eigenvalue**2 >= 0 else 0

        # calculate the shape vector
        W = np.diag(w / ((w**2) + n))
        c = (v.T).dot(W).dot(u.T).dot(y.vector)

        return changed_pose, c
示例#7
0
    def _parse(self, path):
        '''
        Parse the data from path directory and return arrays of x and y coordinates
        Data should be in the form (x1, y1)

        in: String pathdirectory with list of landmarks (x1, y1, ..., xN, yN)
        out: 1xc array (x1, ..., xN, y1, ..., yN)
        '''
        data = np.loadtxt(path)
        x = np.absolute(data[::2, ])
        y = data[1::2, ]
        return Shape(np.hstack((x, y)))
示例#8
0
def render_shape_to_image(img, shape, color=(255, 0, 0), title='Image'):
    '''
    Draw shape over image
    '''
    if not isinstance(shape, Shape):
        shape = Shape(shape)

    for i in range(shape.length - 1):
        cv2.line(img, (int(shape.x[i]), int(shape.y[i])),
            (int(shape.x[i + 1]), int(shape.y[i + 1])), color, 5)

    render(img)
示例#9
0
 def align(self, shape):
     '''
     Align shape with the mean shape and return the aligned shape.
     All arrays in form (x1, ..., xC, ..., y1, ..., yC)
     In: 1xC array shape
     Out: 1xC aligned shape
     '''
     # perform aligning
     translated = self.translate_to_origin(Shape(shape))
     scaled = self.normalize(translated)
     aligned = self.rotate_to_target(scaled, self.mean_shape)
     return aligned.vector
示例#10
0
    def translate_to_origin(self, shape):
        '''
        Move all shapes to a common center, most likely the origin (0,0)

        In: array x
            array y
        Out = array, array
        '''
        # compute centroid
        centr_x, centr_y = shape.centroid()
        # translate w.r.t. centroid
        return Shape([shape.x - centr_x, shape.y - centr_y])
示例#11
0
    def rotate_to_target(self, subject, target):
        '''
        Rotate shape such that it aligns with the target shape

        in: Shapes
        out: rotated Rx2 matrix of subject
        '''
        # perform singular value decomposition (svd) to get U, S, V'
        u, s, v = np.linalg.svd(target.matrix.dot(np.transpose(
            subject.matrix)))
        # multiply VU' with subject to get the rotated matrix
        vu = np.transpose(v).dot(np.transpose(u))
        return Shape(vu.dot(subject.matrix))
def slice_images(images, landmarks_per_image):
    '''
    Slice the landmarks from the images
    '''
    imagecount, shapecount, landmarkcount = landmarks_per_image.shape
    for i in range(imagecount):
        image = images[i]
        for s in range(shapecount):
            landmark = Shape(landmarks_per_image[i, s, :])
            # slice the landmarks from the images
            landmark_image = image[min(landmark.y) - 5:max(landmark.y) + 5,
                                   min(landmark.x) - 5:max(landmark.x) + 5]
            cv2.imwrite(
                '../Project Data/_Data/Slicings2/' + str(i) + '-' + str(s) +
                '.png', landmark_image)
示例#13
0
    def multiresolution_search(self,
                               image,
                               region,
                               t=0,
                               max_level=0,
                               max_iter=5,
                               n=None):
        '''
        Perform Multi-resolution Search ASM algorithm.

        in: np array of training image
            np array region; array of coordinates that gives a rough
                estimation of the target in form (x1, ..., xN, y1, ..., yN)
            int t; amount of pixels to be examined on each side of the
                normal of each point during an iteration (t>k)
            int max_levels; max amount of levels to be searched
            int max_iter; amount to stop iterations at each level
            int n; fitting parameter
        out: Shape region; approximation of the target
        '''
        if not isinstance(region, Shape):
            region = Shape(region)

        # create Gaussian pyramid of input image
        image_pyramid = gaussian_pyramid(image,
                                         levels=len(self.glmodel_pyramid))

        # allow examiner to render the largest image (for testing)
        self.examiner.bigImage = image_pyramid[0]

        level = max_level
        max_level = True
        while level >= 0:
            # get image at level resolution
            image = image_pyramid[level]
            # search in the image
            region = self.search(image,
                                 region,
                                 t=t,
                                 level=level,
                                 max_level=max_level,
                                 max_iter=max_iter,
                                 n=n)
            # descend the pyramid
            level -= 1
            max_level = False

        return region
示例#14
0
    def scan_region(self, landmarks, diff=0, searchStep=30):
        '''
        Scan landmark centroids to find a good search region for the feature
        detector.

        in: np array of landmarks Shapes
            int diff; narrows down the search space
            int seachStep; a larger search step fastens search, but also
                increases the risk of missing matches.
        '''
        centroids = np.zeros((landmarks.shape[0], 2))
        for l in range(landmarks.shape[0]):
            centroids[l] = Shape(landmarks[l]).centroid()

        x = (int(min(centroids[:, 0])) + diff,
             int(max(centroids[:, 0])) - diff)
        y = (int(min(centroids[:, 1])) + diff,
             int(max(centroids[:, 1])) - diff)

        return (y, x, searchStep)
示例#15
0
 def translate(self, shape, Tx, Ty):
     '''
     Translate a shape according to translation parameters
     '''
     return Shape([shape.x + Tx, shape.y + Ty])
示例#16
0
def render_shape(shape):
    if not isinstance(shape, Shape):
        shape = Shape(shape)
    plt.plot(shape.x, shape.y, marker='o')
    plt.show()
示例#17
0
 def _ellipse(self, center, amount_of_points=LANDMARK_AMOUNT):
     '''
     Returns points along the ellipse around a center.
     '''
     ellipse = cv2.ellipse2Poly(tuple(center), (80, 210), 90, 0, 360, 4)
     return Shape(np.hstack(ellipse[:amount_of_points, :].T))
示例#18
0
 def set_mean_shape(self, shape):
     self.mean_shape = Shape(shape)