Exemple #1
0
    def smoothBorder(self, img, points = None):
        if points is None:
            points = self.facePointsStasm(img)

        mask = blender.mask_from_points(img.shape[:2], points)
        inner_points = self.expandConvex(points, ratio=0.9)
        inner_mask = blender.mask_from_points(img.shape[:2], inner_points)

        mask = mask-inner_mask

        return cv2.textureFlattening(img, mask, low_threshold=30 , high_threshold=45)
Exemple #2
0
def test_local():
    from functools import partial
    import scipy.ndimage
    import scipy.misc
    from facemorpher import locator
    from facemorpher import aligner

    # Load source image
    face_points_func = partial(locator.face_points, '../data')
    base_path = '../females/Screenshot 2015-03-04 17.11.12.png'
    src_path = '../females/BlDmB5QCYAAY8iw.jpg'
    src_img = scipy.ndimage.imread(src_path)[:, :, :3]

    # Define control points for warps
    src_points = face_points_func(src_path)
    base_img = scipy.ndimage.imread(base_path)[:, :, :3]
    base_points = face_points_func(base_path)

    size = (600, 500)
    src_img, src_points = aligner.resize_align(src_img, src_points, size)
    base_img, base_points = aligner.resize_align(base_img, base_points, size)
    result_points = locator.weighted_average_points(src_points, base_points,
                                                    0.2)

    # Perform transform
    dst_img1 = warp_image(src_img, src_points, result_points, size)
    dst_img2 = warp_image(base_img, base_points, result_points, size)

    from facemorpher import blender
    ave = blender.weighted_average(dst_img1, dst_img2, 0.6)
    mask = blender.mask_from_points(size, result_points)
    blended_img = blender.poisson_blend(dst_img1, dst_img2, mask)
Exemple #3
0
def averager(imgpaths,
             dest_filename=None,
             width=500,
             height=600,
             background='black',
             blur_edges=False,
             out_filename='result.png',
             plot=False):

    size = (height, width)

    images = []
    point_set = []
    for path in imgpaths:
        img, points = load_image_points(path, size)
        if img is not None:
            images.append(img)
            point_set.append(points)

    if len(images) == 0:
        raise FileNotFoundError('Could not find any valid images.' +
                                ' Supported formats are .jpg, .png, .jpeg')

    if dest_filename is not None:
        dest_img, dest_points = load_image_points(dest_filename, size)
        if dest_img is None or dest_points is None:
            raise Exception('No face or detected face points in dest img: ' +
                            dest_filename)
    else:
        dest_img = np.zeros(images[0].shape, np.uint8)
        dest_points = locator.average_points(point_set)

    num_images = len(images)
    result_images = np.zeros(images[0].shape, np.float32)
    for i in range(num_images):
        result_images += warper.warp_image(images[i], point_set[i],
                                           dest_points, size, np.float32)

    result_image = np.uint8(result_images / num_images)
    face_indexes = np.nonzero(result_image)
    dest_img[face_indexes] = result_image[face_indexes]

    mask = blender.mask_from_points(size, dest_points)
    if blur_edges:
        blur_radius = 10
        mask = cv2.blur(mask, (blur_radius, blur_radius))

    if background in ('transparent', 'average'):
        dest_img = np.dstack((dest_img, mask))

        if background == 'average':
            average_background = locator.average_points(images)
            dest_img = blender.overlay_image(dest_img, mask,
                                             average_background)

    print('Averaged {} images'.format(num_images))
    plt = plotter.Plotter(plot, num_images=1, out_filename=out_filename)
    plt.save(dest_img)
    plt.plot_one(dest_img)
    plt.show()
def morph(src_img,
          src_points,
          dest_img,
          dest_points,
          video,
          width=500,
          height=600,
          num_frames=20,
          fps=10,
          out_frames=None,
          out_video=None,
          plot=False,
          background='black'):
    """
  Create a morph sequence from source to destination image

  :param src_img: ndarray source image
  :param src_points: source image array of x,y face points
  :param dest_img: ndarray destination image
  :param dest_points: destination image array of x,y face points
  :param video: facemorpher.videoer.Video object
  """
    size = (height, width)
    stall_frames = np.clip(int(fps * 0.15), 1, fps)  # Show first & last longer
    plt = plotter.Plotter(plot, num_images=num_frames, out_folder=out_frames)
    num_frames -= (stall_frames * 2)  # No need to process src and dest image

    plt.plot_one(src_img)
    video.write(src_img, 1)

    # Produce morph frames!
    for percent in np.linspace(1, 0, num=num_frames):
        points = locator.weighted_average_points(src_points, dest_points,
                                                 percent)
        src_face = warper.warp_image(src_img, src_points, points, size)
        end_face = warper.warp_image(dest_img, dest_points, points, size)
        average_face = blender.weighted_average(src_face, end_face, percent)

        if background in ('transparent', 'average'):
            mask = blender.mask_from_points(average_face.shape[:2], points)
            average_face = np.dstack((average_face, mask))

            if background == 'average':
                average_background = blender.weighted_average(
                    src_img, dest_img, percent)
                average_face = blender.overlay_image(average_face, mask,
                                                     average_background)

        plt.plot_one(average_face)
        plt.save(average_face)
        video.write(average_face)

    plt.plot_one(dest_img)
    video.write(dest_img, stall_frames)
    plt.show()
Exemple #5
0
def averager(imgpaths,
             dest_filename=None,
             width=500,
             height=600,
             alpha=False,
             blur_edges=False,
             out_filename='result.png',
             plot=False):

    size = (height, width)

    images = []
    point_set = []
    for path in imgpaths:
        img, points = load_image_points(path, size)
        if img is not None:
            images.append(img)
            point_set.append(points)

    if len(images) == 0:
        raise FileNotFoundError('Could not find any valid images.' +
                                ' Supported formats are .jpg, .png, .jpeg')

    if dest_filename is not None:
        dest_img, dest_points = load_image_points(dest_filename, size)
        if dest_img is None or dest_points is None:
            raise Exception('No face or detected face points in dest img: ' +
                            dest_filename)
    else:
        dest_img = np.zeros(images[0].shape, np.uint8)
        dest_points = locator.average_points(point_set)

    num_images = len(images)
    result_images = np.zeros(images[0].shape, np.float32)
    for i in range(num_images):
        result_images += warper.warp_image(images[i], point_set[i],
                                           dest_points, size, np.float32)

    result_image = np.uint8(result_images / num_images)
    face_indexes = np.nonzero(result_image)
    dest_img[face_indexes] = result_image[face_indexes]

    mask = blender.mask_from_points(size, dest_points)
    if blur_edges:
        blur_radius = 10
        mask = cv2.blur(mask, (blur_radius, blur_radius))
    if alpha:
        dest_img = np.dstack((dest_img, mask))
    mpimg.imsave(out_filename, dest_img)

    if plot:
        plt.axis('off')
        plt.imshow(dest_img)
        plt.show()
def average_face(imgpaths,
                 width=500,
                 height=500,
                 background='black',
                 blur_edges=False,
                 out_filename='result.jpg'):
    size = (height, width)

    images = []
    point_set = []
    for path in imgpaths:
        img, points = load_image_points(path, size)
        if img is not None:
            images.append(img)
            point_set.append(points)

    if len(images) == 0:
        raise FileNotFoundError(
            'Could not find any valid images. Supported formats are .jpg, .png, .jpeg'
        )

    dest_img, dest_points = load_image_points(REFERENCE_IMG_PATH, size)

    num_images = len(images)
    result_images = np.zeros(images[0].shape, np.float32)
    for i in range(num_images):
        result_images += warper.warp_image(images[i], point_set[i],
                                           dest_points, size, np.float32)

    result_image = np.uint8(result_images / num_images)
    face_indexes = np.nonzero(result_image)
    dest_img[face_indexes] = result_image[face_indexes]

    mask = blender.mask_from_points(size, dest_points)
    if blur_edges:
        blur_radius = 10
        mask = cv2.blur(mask, (blur_radius, blur_radius))

    if background in ('transparent', 'average'):
        dest_img = np.dstack((dest_img, mask))

        if background == 'average':
            # average_background = np.uint8(locator.average_points(images))
            avg_background = perlin_background(images)
            avg_background[np.where(
                (avg_background == [0, 0, 0]).all(axis=2))] = [
                    128, 128, 128
                ]  # black -> gray pixels in background
            dest_img = blender.overlay_image(dest_img, mask, avg_background)

    print('Averaged {} images'.format(num_images))
    plt = plotter.Plotter(False, num_images=1, out_filename=out_filename)
    plt.save(dest_img)
Exemple #7
0
def morph_ani(
    src_imgpaths,
    des_imgpath,
    num_pics,
    width=500,
    height=600,
    fps_in=24,
    slow_rate=5,
    out_frames=None,
    out_video=None,
    plot=False,
):
    num_frames = num_pics * slow_rate
    fps = fps_in * slow_rate

    video = videoer.Video(out_video, fps, width, height)
    plt = plotter.Plotter(plot, num_images=num_frames, out_folder=out_frames)

    dest_img, dest_points = load_image_points(des_imgpath, (height, width))
    images_points_gen = load_valid_image_points(src_imgpaths, (height, width))

    frameCount = 0
    for src_img, src_points in images_points_gen:
        if frameCount == 0:
            p_face = src_img
            p_points = src_points

        avg_face0, avg_points0 = morph_one(
            src_img, src_points, dest_img, dest_points,
            1 - float(frameCount) / (num_frames - 1), width, height)
        for i in range(0, slow_rate):
            avg_face, avg_points = morph_one(avg_face0, avg_points0, p_face,
                                             p_points,
                                             i / float(slow_rate - 1), width,
                                             height)
            mask = blender.mask_from_points(avg_face.shape[:2], avg_points)
            avg_face = np.dstack((avg_face, mask))
            plt.plot_one(avg_face)
            plt.save(avg_face)
            video.write(avg_face)
            frameCount = frameCount + 1
        p_face = avg_face0
        p_points = avg_points0

    video.end()
    plt.show()
Exemple #8
0
def alpha_image(img, points):
    mask = blender.mask_from_points(img.shape[:2], points)
    return np.dstack((img, mask))
Exemple #9
0
def warp_image(src_img,
               src_points,
               dest_points,
               dest_shape,
               dtype=np.uint8,
               result_type="zero",
               bk_img=None,
               smoothing=False):
    # Resultant image will not have an alpha channel
    num_chans = 3

    src_img = src_img[:, :, :3]

    rows, cols = dest_shape[:2]

    try:
        if result_type == "white":
            # New attempt: fill with WHITE
            result_img = np.full((rows, cols, num_chans), 255, dtype)
        elif result_type == "image":
            # Take the background image, but make sure the destination points are empty
            # result_img = bk_img
            # Step 1: fill the background with zeroes
            result_img = np.zeros((rows, cols, num_chans), dtype)
        else:
            # Default (original) = fill with black = zero
            result_img = np.zeros((rows, cols, num_chans), dtype)

        # Calculate a set of triangles within [dest_points]
        delaunay = spatial.Delaunay(dest_points)
        tri_affines = np.asarray(
            list(
                triangular_affine_matrices(delaunay.simplices, src_points,
                                           dest_points)))

        process_warp(src_img, result_img, tri_affines, dest_points, delaunay)

        if result_type == "image":
            # Step 2: re-combine the background image and the face

            # Step 2.a: get a mask based on [dest_points] (filled with 255)
            mask = blender.mask_from_points((rows, cols), dest_points)

            # Step 2.b: combine two images based on the mask
            result_img[np.where(mask != 255)] = bk_img[np.where(mask != 255)]

            # Step 2.c: get the edge of the mask
            contour = cv2.Canny(mask, 100, 200)

            # Possibly add smoothing in a larger area
            if smoothing:
                kernel = np.ones((3, 3), np.uint8)
                contour = cv2.dilate(contour, kernel, iterations=1)
                # Create an image with the smoothing
                # TODO: work this out in a better way
                avg_img = cv2.addWeighted(bk_img, 0.5, src_img, 0.5, 0)
            else:
                # Step 2.d: Just take the average of two images
                avg_img = cv2.addWeighted(bk_img, 0.5, src_img, 0.5, 0)

            # Step 2.e: replace the contour with the averaged
            result_img[np.where(contour == 255)] = avg_img[np.where(
                contour == 255)]

            if bUseGrayScale:
                result_img = cv2.cvtColor(result_img, cv2.COLOR_RGB2GRAY)
                # cv2.COLOR_RGB2GRAY

        return result_img
    except:
        utils.DoError("warp_image: ")
        return np.zeros((rows, cols, num_chans), dtype)