Advertisement
ZeroCool22

merge_faces_masked

Jan 2nd, 2018
15,259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.86 KB | None | 0 0
  1. import argparse
  2. import cv2
  3. import json
  4. import numpy
  5. from pathlib import Path
  6. from tqdm import tqdm
  7. from scipy import ndimage
  8. from model import autoencoder_A
  9. from model import autoencoder_B
  10. from model import encoder, decoder_A, decoder_B
  11.  
  12. encoder  .load_weights( "models/encoder.h5"   )
  13. decoder_A.load_weights( "models/decoder_A.h5" )
  14. decoder_B.load_weights( "models/decoder_B.h5" )
  15.  
  16.  
  17. def convert_one_image( autoencoder, image, mat,facepoints,erosion_kernel,blurSize,seamlessClone,maskType ):
  18.     size = 64
  19.     image_size = image.shape[1], image.shape[0]
  20.  
  21.     face = cv2.warpAffine( image, mat * size, (size,size) )
  22.     face = numpy.expand_dims( face, 0 )
  23.     new_face = autoencoder.predict( face / 255.0 )[0]
  24.  
  25.     new_face = numpy.clip( new_face * 255, 0, 255 ).astype( image.dtype )
  26.  
  27.     face_mask = numpy.zeros(image.shape,dtype=float)
  28.     if 'Rect' in maskType:
  29.       face_src = numpy.ones(new_face.shape,dtype=float)
  30.       cv2.warpAffine( face_src, mat * size, image_size, face_mask, cv2.WARP_INVERSE_MAP, cv2.BORDER_TRANSPARENT )
  31.  
  32.     hull_mask = numpy.zeros(image.shape,dtype=float)
  33.     if 'Hull' in maskType:
  34.       hull = cv2.convexHull( numpy.array( facepoints ).reshape((-1,2)).astype(int) ).flatten().reshape( (-1,2) )
  35.       cv2.fillConvexPoly( hull_mask,hull,(1,1,1) )
  36.  
  37.     if maskType == 'FaceHull':
  38.       image_mask = hull_mask
  39.     elif maskType == 'Rect':
  40.       image_mask = face_mask
  41.     else:
  42.       image_mask = ((face_mask*hull_mask))
  43.  
  44.  
  45.     if erosion_kernel is not None:
  46.       image_mask = cv2.erode(image_mask,erosion_kernel,iterations = 1)
  47.  
  48.     if blurSize!=0:
  49.       image_mask = cv2.blur(image_mask,(blurSize,blurSize))
  50.  
  51.     base_image = numpy.copy( image )
  52.     new_image = numpy.copy( image )
  53.  
  54.     cv2.warpAffine( new_face, mat * size, image_size, new_image, cv2.WARP_INVERSE_MAP, cv2.BORDER_TRANSPARENT )
  55.  
  56.     outImage = None
  57.     if seamlessClone:
  58.       masky,maskx = cv2.transform( numpy.array([ size/2,size/2 ]).reshape(1,1,2) ,cv2.invertAffineTransform(mat*size) ).reshape(2).astype(int)
  59.       outimage = cv2.seamlessClone(new_image.astype(numpy.uint8),base_image.astype(numpy.uint8),(image_mask*255).astype(numpy.uint8),(masky,maskx) , cv2.NORMAL_CLONE )
  60.     else:
  61.       foreground = cv2.multiply(image_mask, new_image.astype(float))
  62.       background = cv2.multiply(1.0 - image_mask, base_image.astype(float))
  63.       outimage = cv2.add(foreground, background)
  64.  
  65.     return outimage
  66.  
  67. def main( args ):
  68.  
  69.  
  70.  
  71.  
  72.     input_dir = Path( args.input_dir )
  73.     assert input_dir.is_dir()
  74.  
  75.     alignments = input_dir / args.alignments
  76.     with alignments.open() as f:
  77.         alignments = json.load(f)
  78.  
  79.     output_dir = input_dir / args.output_dir
  80.     output_dir.mkdir( parents=True, exist_ok=True )
  81.  
  82.     if args.direction == 'AtoB': autoencoder = autoencoder_B
  83.     if args.direction == 'BtoA': autoencoder = autoencoder_A
  84.    
  85.     if args.erosionKernelSize>0:
  86.       erosion_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(args.erosionKernelSize,args.erosionKernelSize))
  87.     else:
  88.       erosion_kernel = None
  89.  
  90.     for e in alignments:    
  91.       if len(e)<4:
  92.         raise LookupError('This script expects new format json files with face points included.')
  93.  
  94.  
  95.     for image_file, face_file, mat,facepoints in tqdm( alignments ):
  96.         image = cv2.imread( str( input_dir / image_file ) )
  97.         face  = cv2.imread( str( input_dir / face_file  ) )
  98.  
  99.  
  100.         mat = numpy.array(mat).reshape(2,3)
  101.  
  102.         if image is None: continue
  103.         if face  is None: continue
  104.  
  105.  
  106.         new_image = convert_one_image( autoencoder, image, mat, facepoints, erosion_kernel, args.blurSize, args.seamlessClone, args.maskType)
  107.  
  108.         output_file = output_dir / Path(image_file).name
  109.         cv2.imwrite( str(output_file), new_image )
  110.  
  111. def str2bool(v):
  112.   if v.lower() in ('yes', 'true', 't', 'y', '1'):
  113.     return True
  114.   elif v.lower() in ('no', 'false', 'f', 'n', '0'):
  115.     return False
  116.   else:
  117.     raise argparse.ArgumentTypeError('Boolean value expected.')
  118.  
  119. if __name__ == '__main__':
  120.     parser = argparse.ArgumentParser()
  121.     parser.add_argument( "input_dir", type=str )
  122.     parser.add_argument( "alignments", type=str, nargs='?', default='alignments.json' )
  123.     parser.add_argument( "output_dir", type=str, nargs='?', default='merged' )
  124.  
  125.     parser.add_argument("--seamlessClone", type=str2bool, nargs='?', const=False, default='False', help="Attempt to use opencv seamlessClone.")
  126.  
  127.     parser.add_argument('--maskType', type=str, default='FaceHullAndRect' ,choices=['FaceHullAndRect','FaceHull','Rect'], help="The type of masking to use around the face.")
  128.  
  129.     parser.add_argument( "--blurSize",          type=int, default='2' )
  130.     parser.add_argument( "--erosionKernelSize", type=int, default='0' )
  131.     parser.add_argument( "--direction",         type=str, default="AtoB", choices=["AtoB", "BtoA"])
  132.     main( parser.parse_args() )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement