From 24f5bbe6296309341c740a2aee9f090b97f8080d Mon Sep 17 00:00:00 2001 From: Andrew Tonko Date: Mon, 25 Mar 2019 13:38:05 +0300 Subject: [PATCH] Updated to run on Python 3.5.2 ( tensorflow-gpu==1.13.1 ) --- .gitignore | 5 + README.md | 4 +- ResNet/ThreeDMM_expr.py | 6 +- ResNet/ThreeDMM_shape.py | 6 +- kaffe/tensorflow/network_expr.py | 6 +- kaffe/tensorflow/network_shape.py | 8 +- kaffe/tensorflow/transformer.py | 2 +- main_ExpShapePoseNet.py | 21 +- pose_utils.py | 93 ++++--- utils.py | 428 +++++++++++++++--------------- 10 files changed, 295 insertions(+), 284 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79b60a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Expression_Model/ +__pycache__/ +Shape_Model/ +fpn_new_model/ +output_preproc.csv diff --git a/README.md b/README.md index b6b5940..e3191bc 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ The code provided here bundles all three components for holistic 3D face modelin * [TensorFlow](https://www.tensorflow.org/) * [OpenCV Python Wrapper](http://opencv.org/) * [Numpy](http://www.numpy.org/) -* [Python2.7](https://www.python.org/download/releases/2.7/) +* [Python3.5](https://www.python.org/downloads/release/python-352/) -The code has been tested on Linux with Python 2.7.12. On Linux you can rely on the default version of python, installing all the packages needed from the package manager or on Anaconda Python and install required packages through `conda`. +The code has been tested on Linux with Python 3.5.2. On Linux you can rely on the default version of python, installing all the packages needed from the package manager or on Anaconda Python and install required packages through `conda`. ## Usage diff --git a/ResNet/ThreeDMM_expr.py b/ResNet/ThreeDMM_expr.py index 15e68f2..2f7658a 100644 --- a/ResNet/ThreeDMM_expr.py +++ b/ResNet/ThreeDMM_expr.py @@ -1,6 +1,8 @@ import sys -#sys.path.append('../kaffe') -sys.path.append('/home/usc/Desktop/Research/FG18/ExpNet_Code_Release/kaffe/tensorflow') +from os.path import dirname, join + +sys.path.append(join(dirname(dirname(__file__)), 'kaffe', 'tensorflow')) + from network_expr import Network_Expr diff --git a/ResNet/ThreeDMM_shape.py b/ResNet/ThreeDMM_shape.py index 9835fa3..1078249 100644 --- a/ResNet/ThreeDMM_shape.py +++ b/ResNet/ThreeDMM_shape.py @@ -1,6 +1,8 @@ import sys -#sys.path.append('../kaffe') -sys.path.append('/home/usc/Desktop/Research/FG18/ExpNet_Code_Release/kaffe/tensorflow') +from os.path import dirname, join + +sys.path.append(join(dirname(dirname(__file__)), 'kaffe', 'tensorflow')) + from network_shape import Network_Shape diff --git a/kaffe/tensorflow/network_expr.py b/kaffe/tensorflow/network_expr.py index 058a98b..9081e45 100644 --- a/kaffe/tensorflow/network_expr.py +++ b/kaffe/tensorflow/network_expr.py @@ -137,7 +137,7 @@ def feed(self, *args): assert len(args) != 0 self.terminals = [] for fed_layer in args: - if isinstance(fed_layer, basestring): + if isinstance(fed_layer, (str, bytes)): try: fed_layer = self.layers[fed_layer] except KeyError: @@ -197,9 +197,9 @@ def conv(self, with tf.variable_scope(name) as scope: if name == 'res5c_branch2c' or name == 'res5c_branch2b' or name == 'res5c_branch2a' or \ name == 'res5b_branch2c' or name == 'res5b_branch2b' or name == 'res5b_branch2a': - kernel = self.make_var('weights', shape=[k_h, k_w, c_i / group, c_o]) + kernel = self.make_var('weights', shape=[k_h, k_w, int(c_i) / group, c_o]) else: - kernel = self.make_var_fixed('weights', shape=[k_h, k_w, c_i / group, c_o]) + kernel = self.make_var_fixed('weights', shape=[k_h, k_w, int(c_i) / group, c_o]) if group == 1: # This is the common-case. Convolve the input without any further complications. diff --git a/kaffe/tensorflow/network_shape.py b/kaffe/tensorflow/network_shape.py index d9c2a89..7cf000b 100644 --- a/kaffe/tensorflow/network_shape.py +++ b/kaffe/tensorflow/network_shape.py @@ -59,7 +59,7 @@ def load(self, data_path, prefix_name, session, ignore_missing=False): ignore_missing: If true, serialized weights for missing layers are ignored. ''' data_dict = np.load(data_path).item() - print len(data_dict) #data_dict['res2b_branch2a'] + print(len(data_dict)) #data_dict['res2b_branch2a'] for op_name in data_dict: #print op_name #if op_name == "res2b_branch2a": @@ -137,7 +137,7 @@ def feed(self, *args): assert len(args) != 0 self.terminals = [] for fed_layer in args: - if isinstance(fed_layer, basestring): + if isinstance(fed_layer, (str, bytes)): try: fed_layer = self.layers[fed_layer] except KeyError: @@ -197,9 +197,9 @@ def conv(self, with tf.variable_scope(name) as scope: if name == 'res5c_branch2c' or name == 'res5c_branch2b' or name == 'res5c_branch2a' or \ name == 'res5b_branch2c' or name == 'res5b_branch2b' or name == 'res5b_branch2a': - kernel = self.make_var('weights', shape=[k_h, k_w, c_i / group, c_o]) + kernel = self.make_var('weights', shape=[k_h, k_w, int(c_i) / group, c_o]) else: - kernel = self.make_var_fixed('weights', shape=[k_h, k_w, c_i / group, c_o]) + kernel = self.make_var_fixed('weights', shape=[k_h, k_w, int(c_i) / group, c_o]) if group == 1: # This is the common-case. Convolve the input without any further complications. diff --git a/kaffe/tensorflow/transformer.py b/kaffe/tensorflow/transformer.py index 34bfc9a..6ee48ed 100644 --- a/kaffe/tensorflow/transformer.py +++ b/kaffe/tensorflow/transformer.py @@ -44,7 +44,7 @@ def __init__(self, op, *args, **kwargs): def format(self, arg): '''Returns a string representation for the given value.''' - return "'%s'" % arg if isinstance(arg, basestring) else str(arg) + return "'%s'" % arg if isinstance(arg, (str, bytes)) else str(arg) def pair(self, key, value): '''Returns key=formatted(value).''' diff --git a/main_ExpShapePoseNet.py b/main_ExpShapePoseNet.py index 967dbc9..1dacebe 100644 --- a/main_ExpShapePoseNet.py +++ b/main_ExpShapePoseNet.py @@ -32,7 +32,7 @@ # Global parameters _tmpdir = './tmp/'#save intermediate images needed to fed into ExpNet, ShapeNet, and PoseNet -print '> make dir' +print('> make dir') if not os.path.exists( _tmpdir): os.makedirs( _tmpdir ) output_proc = 'output_preproc.csv' # save intermediate image list @@ -71,9 +71,9 @@ def extract_PSE_feats(): # Prepare data data_dict = myparse.parse_input(inputlist) # please see input.csv for the input format - print len(data_dict) + print(len(data_dict)) ## Pre-processing the images - print '> preproc' + print('> preproc') pu.preProcessImage(_tmpdir, data_dict, './', factor, _alexNetSize, output_proc) @@ -86,7 +86,7 @@ def extract_PSE_feats(): ################### # Face Pose-Net ################### - net_data = np.load("./fpn_new_model/PAM_frontal_ALexNet.npy").item() + net_data = np.load("./fpn_new_model/PAM_frontal_ALexNet_py3.npy").item() pose_labels = np.zeros([FLAGS.batch_size,6]) x1 = tf.image.resize_bilinear(x, tf.constant([227,227], dtype=tf.int32)) @@ -195,19 +195,19 @@ def extract_PSE_feats(): model = scipy.io.loadmat(BFM_path,squeeze_me=True,struct_as_record=False) model = model["BFM"] faces = model.faces-1 - print '> Loaded the Basel Face Model to write the 3D output!' + print('> Loaded the Basel Face Model to write the 3D output!') - print '> Start to estimate Expression, Shape, and Pose!' - with open(output_proc, 'rb') as csvfile: + print('> Start to estimate Expression, Shape, and Pose!') + with open(output_proc, 'r') as csvfile: csvreader = csv.reader(csvfile, delimiter=',') for row in csvreader: - image_key = row[0] image_file_path = row[1] - print '> Process ' + image_file_path + start = time.time() + print('> Process ' + image_file_path) image = cv2.imread(image_file_path,1) # BGR @@ -251,6 +251,9 @@ def extract_PSE_feats(): # Shape + Expression + Pose SEP,TEP = utils.projectBackBFM_withEP(model, Shape_Texture, Expr, Pose) utils.write_ply_textureless(outFile + '_Shape_Expr_Pose.ply', SEP, faces) + end = time.time() + + print(end - start) diff --git a/pose_utils.py b/pose_utils.py index fe68b28..4999419 100644 --- a/pose_utils.py +++ b/pose_utils.py @@ -6,29 +6,31 @@ import fileinput import shutil + def increaseBbox(bbox, factor): - tlx = bbox[0] - tly = bbox[1] - brx = bbox[2] - bry = bbox[3] + tlx = bbox[0] + tly = bbox[1] + brx = bbox[2] + bry = bbox[3] dx = factor dy = factor dw = 1 + factor dh = 1 + factor - #Getting bbox height and width - w = brx-tlx; - h = bry-tly; + # Getting bbox height and width + w = brx - tlx + h = bry - tly tlx2 = tlx - w * dx tly2 = tly - h * dy brx2 = tlx + w * dw bry2 = tly + h * dh - nbbox = np.zeros( (4,1), dtype=np.float32 ) + nbbox = np.zeros((4, 1), dtype=np.float32) nbbox[0] = tlx2 nbbox[1] = tly2 nbbox[2] = brx2 - nbbox[3] = bry2 + nbbox[3] = bry2 return nbbox + def image_bbox_processing_v2(img, bbox): img_h, img_w, img_c = img.shape lt_x = bbox[0] @@ -36,16 +38,16 @@ def image_bbox_processing_v2(img, bbox): rb_x = bbox[2] rb_y = bbox[3] - fillings = np.zeros( (4,1), dtype=np.int32) - if lt_x < 0: ## 0 for python + fillings = np.zeros((4, 1), dtype=np.int32) + if lt_x < 0: # 0 for python fillings[0] = math.ceil(-lt_x) if lt_y < 0: fillings[1] = math.ceil(-lt_y) - if rb_x > img_w-1: + if rb_x > img_w - 1: fillings[2] = math.ceil(rb_x - img_w + 1) - if rb_y > img_h-1: + if rb_y > img_h - 1: fillings[3] = math.ceil(rb_y - img_h + 1) - new_bbox = np.zeros( (4,1), dtype=np.float32 ) + new_bbox = np.zeros((4, 1), dtype=np.float32) # img = [zeros(size(img,1),fillings(1),img_c), img] # img = [zeros(fillings(2), size(img,2),img_c); img] # img = [img, zeros(size(img,1), fillings(3),img_c)] @@ -54,20 +56,18 @@ def image_bbox_processing_v2(img, bbox): imgc = img.copy() if fillings[0] > 0: img_h, img_w, img_c = imgc.shape - imgc = np.hstack( [np.zeros( (img_h, fillings[0][0], img_c), dtype=np.uint8 ), imgc] ) + imgc = np.hstack([np.zeros((img_h, fillings[0][0], img_c), dtype=np.uint8), imgc]) if fillings[1] > 0: img_h, img_w, img_c = imgc.shape - imgc = np.vstack( [np.zeros( (fillings[1][0], img_w, img_c), dtype=np.uint8 ), imgc] ) + imgc = np.vstack([np.zeros((fillings[1][0], img_w, img_c), dtype=np.uint8), imgc]) if fillings[2] > 0: - img_h, img_w, img_c = imgc.shape - imgc = np.hstack( [ imgc, np.zeros( (img_h, fillings[2][0], img_c), dtype=np.uint8 ) ] ) + imgc = np.hstack([imgc, np.zeros((img_h, fillings[2][0], img_c), dtype=np.uint8)]) if fillings[3] > 0: img_h, img_w, img_c = imgc.shape - imgc = np.vstack( [ imgc, np.zeros( (fillings[3][0], img_w, img_c), dtype=np.uint8) ] ) - + imgc = np.vstack([imgc, np.zeros((fillings[3][0], img_w, img_c), dtype=np.uint8)]) new_bbox[0] = lt_x + fillings[0] new_bbox[1] = lt_y + fillings[1] @@ -75,16 +75,17 @@ def image_bbox_processing_v2(img, bbox): new_bbox[3] = rb_y + fillings[1] return imgc, new_bbox + def preProcessImage(_savingDir, data_dict, data_root, factor, _alexNetSize, _listFile): - #### Formatting the images as needed + # Formatting the images as needed file_output = _listFile count = 1 - fileIn = open(file_output , 'w' ) - for key in data_dict.keys(): + fileIn = open(file_output, 'w') + for key in data_dict.keys(): filename = data_dict[key]['file'] - im = cv2.imread(data_root + filename) + im = cv2.imread(data_root + filename) if im is not None: - print 'Processing ' + filename + ' '+ str(count) + print('Processing ' + filename + ' ' + str(count)) sys.stdout.flush() lt_x = data_dict[key]['x'] lt_y = data_dict[key]['y'] @@ -92,13 +93,13 @@ def preProcessImage(_savingDir, data_dict, data_root, factor, _alexNetSize, _lis rb_y = lt_y + data_dict[key]['height'] w = data_dict[key]['width'] h = data_dict[key]['height'] - center = ( (lt_x+rb_x)/2, (lt_y+rb_y)/2 ) - side_length = max(w,h); - bbox = np.zeros( (4,1), dtype=np.float32 ) - bbox[0] = center[0] - side_length/2 - bbox[1] = center[1] - side_length/2 - bbox[2] = center[0] + side_length/2 - bbox[3] = center[1] + side_length/2 + center = ((lt_x + rb_x) / 2, (lt_y + rb_y) / 2) + side_length = max(w, h) + bbox = np.zeros((4, 1), dtype=np.float32) + bbox[0] = center[0] - side_length / 2 + bbox[1] = center[1] - side_length / 2 + bbox[2] = center[0] + side_length / 2 + bbox[3] = center[1] + side_length / 2 #img_2, bbox_green = image_bbox_processing_v2(im, bbox) #%% Get the expanded square bbox bbox_red = increaseBbox(bbox, factor) @@ -106,31 +107,29 @@ def preProcessImage(_savingDir, data_dict, data_root, factor, _alexNetSize, _lis img_3, bbox_new = image_bbox_processing_v2(im, bbox_red) #%% Crop and resized #bbox_red = ceil(bbox_red); - bbox_new = np.ceil( bbox_new ) + bbox_new = np.ceil(bbox_new) #side_length = max(bbox_new(3) - bbox_new(1), bbox_new(4) - bbox_new(2)); - side_length = max( bbox_new[2] - bbox_new[0], bbox_new[3] - bbox_new[1] ) + side_length = max(bbox_new[2] - bbox_new[0], bbox_new[3] - bbox_new[1]) bbox_new[2:4] = bbox_new[0:2] + side_length - #crop_img = img(bbox_red(2):bbox_red(4), bbox_red(1):bbox_red(3), :); - #resized_crop_img = imresize(crop_img, [227, 227]);# % re-scaling to 227 x 227 + # crop_img = img(bbox_red(2):bbox_red(4), bbox_red(1):bbox_red(3), :); + # resized_crop_img = imresize(crop_img, [227, 227]);# % re-scaling to 227 x 227 bbox_new = bbox_new.astype(int) crop_img = img_3[bbox_new[1][0]:bbox_new[3][0], bbox_new[0][0]:bbox_new[2][0], :]; - resized_crop_img = cv2.resize(crop_img, ( _alexNetSize, _alexNetSize ), interpolation = cv2.INTER_CUBIC) - cv2.imwrite(_savingDir + key + '.jpg', resized_crop_img ) - - + resized_crop_img = cv2.resize(crop_img, (_alexNetSize, _alexNetSize), interpolation=cv2.INTER_CUBIC) + cv2.imwrite(_savingDir + key + '.jpg', resized_crop_img) - ## Tracking pose image + # Tracking pose image fileIn.write(key + ',') fileIn.write(_savingDir + key + '.jpg\n') - + else: - print ' '.join(['Skipping image:', filename, 'Image is None', str(count)]) - count+=1 - #if count == 101: + print(' '.join(['Skipping image:', filename, 'Image is None', str(count)])) + count += 1 + # if count == 101: # break fileIn.close() + def replaceInFile(filep, before, after): for line in fileinput.input(filep, inplace=True): - print line.replace(before,after), - + print(line.replace(before, after),) diff --git a/utils.py b/utils.py index 70b6ddb..5f62030 100644 --- a/utils.py +++ b/utils.py @@ -1,14 +1,14 @@ ############################################################################# -#Copyright 2016-2017, Anh Tuan Tran, Tal Hassner, Iacopo Masi, and Gerard Medioni -#The SOFTWARE provided in this page is provided "as is", without any guarantee -#made as to its suitability or fitness for any particular use. It may contain -#bugs, so use of this tool is at your own risk. We take no responsibility for -#any damage of any sort that may unintentionally be caused through its use. +# Copyright 2016-2017, Anh Tuan Tran, Tal Hassner, Iacopo Masi, and Gerard Medioni +# The SOFTWARE provided in this page is provided "as is", without any guarantee +# made as to its suitability or fitness for any particular use. It may contain +# bugs, so use of this tool is at your own risk. We take no responsibility for +# any damage of any sort that may unintentionally be caused through its use. # Please, cite the paper: # @article{tran16_3dmm_cnn, # title={Regressing Robust and Discriminative {3D} Morphable Models with a very Deep Neural Network}, -# author={Anh Tran -# and Tal Hassner +# author={Anh Tran +# and Tal Hassner # and Iacopo Masi # and G\'{e}rard Medioni} # journal={arXiv preprint}, @@ -25,229 +25,229 @@ def get_mean_shape(model): - S = model.shapeMU - numVert = S.shape[0]/3 - ## Final Saving for visualization - S = np.reshape(S,(numVert,3)) - return S - -def projectBackBFM(model,features): - alpha = model.shapeEV * 0 - for it in range(0, 99): - alpha[it] = model.shapeEV[it] * features[it] - S = np.matmul(model.shapePC, alpha) - ## Adding back average shape - S = model.shapeMU + S - numVert = S.shape[0]/3 - # (Texture) - beta = model.texEV * 0 - for it in range(0, 99): - beta[it] = model.texEV[it] * features[it+99] - T = np.matmul(model.texPC, beta) - ## Adding back average texture - T = model.texMU + T - ## Some filtering - T = [truncateUint8(value) for value in T] - ## Final Saving for visualization - S = np.reshape(S,(numVert,3)) - T = np.reshape(T,(numVert, 3)) - return S,T + S = model.shapeMU + numVert = int(S.shape[0] / 3) + # Final Saving for visualization + S = np.reshape(S, (numVert, 3)) + return S + + +def projectBackBFM(model, features): + alpha = model.shapeEV * 0 + for it in range(0, 99): + alpha[it] = model.shapeEV[it] * features[it] + S = np.matmul(model.shapePC, alpha) + # Adding back average shape + S = model.shapeMU + S + numVert = int(S.shape[0] / 3) + # (Texture) + beta = model.texEV * 0 + for it in range(0, 99): + beta[it] = model.texEV[it] * features[it + 99] + T = np.matmul(model.texPC, beta) + # Adding back average texture + T = model.texMU + T + # Some filtering + T = [truncateUint8(value) for value in T] + # Final Saving for visualization + S = np.reshape(S, (numVert, 3)) + T = np.reshape(T, (numVert, 3)) + return S, T def projectBackBFM_withExpr(model, features, expr_paras): - alpha = model.shapeEV * 0 - for it in range(0, 99): - alpha[it] = model.shapeEV[it] * features[it] - S = np.matmul(model.shapePC, alpha) - - expr = model.expEV * 0 - for it in range(0, 29): - expr[it] = model.expEV[it] * expr_paras[it] - E = np.matmul(model.expPC, expr) - - ## Adding back average shape - S = model.shapeMU + S + model.expMU + E - numVert = S.shape[0]/3 - - # (Texture) - beta = model.texEV * 0 - for it in range(0, 99): - beta[it] = model.texEV[it] * features[it+99] - T = np.matmul(model.texPC, beta) - ## Adding back average texture - T = model.texMU + T - ## Some filtering - T = [truncateUint8(value) for value in T] - ## Final Saving for visualization - S = np.reshape(S,(numVert,3)) - T = np.reshape(T,(numVert, 3)) - return S,T + alpha = model.shapeEV * 0 + for it in range(0, 99): + alpha[it] = model.shapeEV[it] * features[it] + S = np.matmul(model.shapePC, alpha) + + expr = model.expEV * 0 + for it in range(0, 29): + expr[it] = model.expEV[it] * expr_paras[it] + E = np.matmul(model.expPC, expr) + + # Adding back average shape + S = model.shapeMU + S + model.expMU + E + numVert = int(S.shape[0] / 3) + + # (Texture) + beta = model.texEV * 0 + for it in range(0, 99): + beta[it] = model.texEV[it] * features[it + 99] + T = np.matmul(model.texPC, beta) + # Adding back average texture + T = model.texMU + T + # Some filtering + T = [truncateUint8(value) for value in T] + # Final Saving for visualization + S = np.reshape(S, (numVert, 3)) + T = np.reshape(T, (numVert, 3)) + return S, T def projectBackBFM_withEP(model, features, expr_paras, pose_paras): - alpha = model.shapeEV * 0 - for it in range(0, 99): - alpha[it] = model.shapeEV[it] * features[it] - S = np.matmul(model.shapePC, alpha) - - # Expression - expr = model.expEV * 0 - for it in range(0, 29): - expr[it] = model.expEV[it] * expr_paras[it] - E = np.matmul(model.expPC, expr) - - ## Adding back average shape - S = model.shapeMU + S + model.expMU + E - numVert = S.shape[0]/3 - - # Pose - #PI = np.array([[ 2.88000000e+03, 0.00000000e+00, 1.12000000e+02], [0.00000000e+00, 2.88000000e+03, 1.12000000e+02], [0, 0, 1]]); - r = pose_paras[0:3] - r[1] = -r[1] - r[2] = -r[2] - t = pose_paras[3:6] - t[0] = -t[0] - #print r.shape, t.shape - R, jacobian = cv2.Rodrigues(r, None) - #print R - - S = np.reshape(S,(numVert,3)) - #print S.shape - S_RT = np.matmul(R, np.transpose(S)) + np.reshape(t, [3,1]) - #S_RT = np.matmul(PI, S_RT) - S_RT = np.transpose(S_RT) - - - - # (Texture) - beta = model.texEV * 0 - for it in range(0, 99): - beta[it] = model.texEV[it] * features[it+99] - T = np.matmul(model.texPC, beta) - ## Adding back average texture - T = model.texMU + T - ## Some filtering - T = [truncateUint8(value) for value in T] - ## Final Saving for visualization - S = np.reshape(S_RT,(numVert,3)) - T = np.reshape(T,(numVert, 3)) - - - return S,T + alpha = model.shapeEV * 0 + for it in range(0, 99): + alpha[it] = model.shapeEV[it] * features[it] + S = np.matmul(model.shapePC, alpha) + + # Expression + expr = model.expEV * 0 + for it in range(0, 29): + expr[it] = model.expEV[it] * expr_paras[it] + E = np.matmul(model.expPC, expr) + + # Adding back average shape + S = model.shapeMU + S + model.expMU + E + numVert = int(S.shape[0] / 3) + + # Pose + #PI = np.array([[ 2.88000000e+03, 0.00000000e+00, 1.12000000e+02], [0.00000000e+00, 2.88000000e+03, 1.12000000e+02], [0, 0, 1]]); + r = pose_paras[0:3] + r[1] = -r[1] + r[2] = -r[2] + t = pose_paras[3:6] + t[0] = -t[0] + # print r.shape, t.shape + R, jacobian = cv2.Rodrigues(r, None) + # print R + + S = np.reshape(S, (numVert, 3)) + # print S.shape + S_RT = np.matmul(R, np.transpose(S)) + np.reshape(t, [3, 1]) + #S_RT = np.matmul(PI, S_RT) + S_RT = np.transpose(S_RT) + + # (Texture) + beta = model.texEV * 0 + for it in range(0, 99): + beta[it] = model.texEV[it] * features[it + 99] + T = np.matmul(model.texPC, beta) + # Adding back average texture + T = model.texMU + T + # Some filtering + T = [truncateUint8(value) for value in T] + # Final Saving for visualization + S = np.reshape(S_RT, (numVert, 3)) + T = np.reshape(T, (numVert, 3)) + + return S, T + def truncateUint8(val): - if val < 0: - return 0 - elif val > 255: - return 255 - else: - return val + if val < 0: + return 0 + elif val > 255: + return 255 + else: + return val -def write_ply(fname, S, T, faces): - nV = S.shape[0] - nF = faces.shape[0] - f = open(fname,'w') - f.write('ply\n') - f.write('format ascii 1.0\n') - f.write('element vertex ' + str(nV) + '\n') - f.write('property float x\n') - f.write('property float y\n') - f.write('property float z\n') - f.write('property uchar red\n') - f.write('property uchar green\n') - f.write('property uchar blue\n') - f.write('element face ' + str(nF) + '\n') - f.write('property list uchar int vertex_indices\n') - f.write('end_header\n') - for i in range(0,nV): - f.write('%0.4f %0.4f %0.4f %d %d %d\n' % (S[i,0],S[i,1],S[i,2],T[i,0],T[i,1],T[i,2])) - - for i in range(0,nF): - f.write('3 %d %d %d\n' % (faces[i,0],faces[i,1],faces[i,2])) - f.close() +def write_ply(fname, S, T, faces): + nV = S.shape[0] + nF = faces.shape[0] + f = open(fname, 'w') + f.write('ply\n') + f.write('format ascii 1.0\n') + f.write('element vertex ' + str(nV) + '\n') + f.write('property float x\n') + f.write('property float y\n') + f.write('property float z\n') + f.write('property uchar red\n') + f.write('property uchar green\n') + f.write('property uchar blue\n') + f.write('element face ' + str(nF) + '\n') + f.write('property list uchar int vertex_indices\n') + f.write('end_header\n') + for i in range(0, nV): + f.write('%0.4f %0.4f %0.4f %d %d %d\n' % (S[i, 0], S[i, 1], S[i, 2], T[i, 0], T[i, 1], T[i, 2])) + + for i in range(0, nF): + f.write('3 %d %d %d\n' % (faces[i, 0], faces[i, 1], faces[i, 2])) + f.close() def write_ply_textureless(fname, S, faces): - nV = S.shape[0] - nF = faces.shape[0] - f = open(fname,'w') - f.write('ply\n') - f.write('format ascii 1.0\n') - f.write('element vertex ' + str(nV) + '\n') - f.write('property float x\n') - f.write('property float y\n') - f.write('property float z\n') - f.write('element face ' + str(nF) + '\n') - f.write('property list uchar int vertex_indices\n') - f.write('end_header\n') - - for i in range(0,nV): - f.write('%0.4f %0.4f %0.4f\n' % (S[i,0],S[i,1],S[i,2])) - - - for i in range(0,nF): - f.write('3 %d %d %d\n' % (faces[i,0],faces[i,1],faces[i,2])) - - f.close() - - -def cropImg(img,tlx,tly,brx,bry, img2, rescale): - l = float( tlx ) - t = float ( tly ) - ww = float ( brx - l ) - hh = float( bry - t ) - # Approximate LM tight BB - h = img.shape[0] - w = img.shape[1] - cv2.rectangle(img2, (int(l),int(t)), (int(brx), int(bry)), (0,255,255),2) - cx = l + ww/2 - cy = t + hh/2 - tsize = max(ww,hh)/2 - l = cx - tsize - t = cy - tsize - - # Approximate expanded bounding box - bl = int(round(cx - rescale[0]*tsize)) - bt = int(round(cy - rescale[1]*tsize)) - br = int(round(cx + rescale[2]*tsize)) - bb = int(round(cy + rescale[3]*tsize)) - nw = int(br-bl) - nh = int(bb-bt) - imcrop = np.zeros((nh,nw,3), dtype = "uint8") - - ll = 0 - if bl < 0: - ll = -bl - bl = 0 - rr = nw - if br > w: - rr = w+nw - br - br = w - tt = 0 - if bt < 0: - tt = -bt - bt = 0 - bbb = nh - if bb > h: - bbb = h+nh - bb - bb = h - imcrop[tt:bbb,ll:rr,:] = img[bt:bb,bl:br,:] - return imcrop + nV = S.shape[0] + nF = faces.shape[0] + f = open(fname, 'w') + f.write('ply\n') + f.write('format ascii 1.0\n') + f.write('element vertex ' + str(nV) + '\n') + f.write('property float x\n') + f.write('property float y\n') + f.write('property float z\n') + f.write('element face ' + str(nF) + '\n') + f.write('property list uchar int vertex_indices\n') + f.write('end_header\n') + + for i in range(0, nV): + f.write('%0.4f %0.4f %0.4f\n' % (S[i, 0], S[i, 1], S[i, 2])) + + for i in range(0, nF): + f.write('3 %d %d %d\n' % (faces[i, 0], faces[i, 1], faces[i, 2])) + + f.close() + + +def cropImg(img, tlx, tly, brx, bry, img2, rescale): + l = float(tlx) + t = float(tly) + ww = float(brx - l) + hh = float(bry - t) + # Approximate LM tight BB + h = img.shape[0] + w = img.shape[1] + cv2.rectangle(img2, (int(l), int(t)), (int(brx), int(bry)), (0, 255, 255), 2) + cx = l + int(ww / 2) + cy = t + int(hh / 2) + tsize = int(max(ww, hh) / 2) + l = cx - tsize + t = cy - tsize + + # Approximate expanded bounding box + bl = int(round(cx - rescale[0] * tsize)) + bt = int(round(cy - rescale[1] * tsize)) + br = int(round(cx + rescale[2] * tsize)) + bb = int(round(cy + rescale[3] * tsize)) + nw = int(br - bl) + nh = int(bb - bt) + imcrop = np.zeros((nh, nw, 3), dtype="uint8") + + ll = 0 + if bl < 0: + ll = -bl + bl = 0 + rr = nw + if br > w: + rr = w + nw - br + br = w + tt = 0 + if bt < 0: + tt = -bt + bt = 0 + bbb = nh + if bb > h: + bbb = h + nh - bb + bb = h + imcrop[tt:bbb, ll:rr, :] = img[bt:bb, bl:br, :] + return imcrop + def cropByInputLM(img, lms, img2): - nLM = lms.shape[0] - lms_x = [lms[i,0] for i in range(0,nLM)]; - lms_y = [lms[i,1] for i in range(0,nLM)]; - return cropImg(img,min(lms_x),min(lms_y),max(lms_x),max(lms_y), img2, rescaleCASIA) + nLM = lms.shape[0] + lms_x = [lms[i, 0] for i in range(0, nLM)] + lms_y = [lms[i, 1] for i in range(0, nLM)] + return cropImg(img, min(lms_x), min(lms_y), max(lms_x), max(lms_y), img2, rescaleCASIA) + def cropByFaceDet(img, detected_face, img2): - return cropImg(img,detected_face.left(),detected_face.top(),\ - detected_face.right(),detected_face.bottom(), img2, rescaleBB) + return cropImg(img, detected_face.left(), detected_face.top(), + detected_face.right(), detected_face.bottom(), img2, rescaleBB) -def cropByLM(img, shape, img2): - nLM = shape.num_parts - lms_x = [shape.part(i).x for i in range(0,nLM)] - lms_y = [shape.part(i).y for i in range(0,nLM)] - return cropImg(img,min(lms_x),min(lms_y),max(lms_x),max(lms_y), img2, rescaleCASIA) +def cropByLM(img, shape, img2): + nLM = shape.num_parts + lms_x = [shape.part(i).x for i in range(0, nLM)] + lms_y = [shape.part(i).y for i in range(0, nLM)] + return cropImg(img, min(lms_x), min(lms_y), max(lms_x), max(lms_y), img2, rescaleCASIA)