diff --git a/framesEvaluation.py b/framesEvaluation.py new file mode 100644 index 0000000..2d8abe6 --- /dev/null +++ b/framesEvaluation.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# coding: utf-8 + +# In[1]: + + +from DFLIMG import DFLJPG +import glob +import numpy as np +import matplotlib.pyplot as plt +import os, sys, math +import csv +import cv2 + + +# In[2]: + + +def normalize_vector(data): + return (data - np.min(data)) / (np.max(data) - np.min(data)) + +def normalize_landmarks(lm): + c0 = normalize_vector(lm[:,0]) + c1 = normalize_vector(lm[:,1]) + return np.transpose(np.vstack([[c0], [c1]])) + + +# In[3]: + + +landmarks = [] +src_filename = glob.glob('DeepFaceLab_Linux/workspace/data_src/aligned/*.jpg') +for f in src_filename: + img = DFLJPG.load(f) + landmarks.append(img.get_landmarks()) +np.save("src_landmarks.npy", landmarks) + + +# In[4]: + + + +print(len(src_filename)) +print(len(landmarks)) + + +# In[5]: + + + +norm_landmarks = [normalize_landmarks(lm) for lm in landmarks] +#np.column_stack((NormalizeData(landmarks[0][:,0]), NormalizeData(landmarks[0][:,1]))) +print(len(norm_landmarks)) + + +# In[6]: + + +all_src_landmarks = norm_landmarks +dst_landmarks = [] + +dists = [] +# This method computes the distance between two images +# by comparing their landmarks. +# It calculates the distance between two correspondig landmark's dots +# (one of the src image, and the other belonging to the dst img) +# It then sums up all the distances of a pair of images. This sum will be +# the score assigned to the face swap frame. +for ii, f in enumerate(glob.glob('DeepFaceLab_Linux/workspace/data_dst/aligned/*.jpg')): + img = DFLJPG.load(f) + dst_landmarks = normalize_landmarks(img.get_landmarks()) + dists_local = [] + for f_src, src_landmarks in enumerate(all_src_landmarks): + dist = np.sum(np.linalg.norm(src_landmarks - dst_landmarks, ord=2, axis=1)) + dists_local.append((dist, f, src_filename[f_src], dst_landmarks, src_landmarks)) + # get the distance between the dst and the best src image + dists.append((sorted(dists_local, key=lambda d: d[0]))[0]) + +# The Euclidean distance between all the landmarks of two images is +# considered as the quality metric used to jugde the resulting frame + +# In[7]: + + +# sort all samples from the best to the worst landmark pairing +dists = list(sorted(dists, key=lambda d: d[0])) +print("Primo metodo: ", dists[0][0]) +dist_scores = list(zip(*dists))[0] + + +# In[8]: + +rangeMax = np.quantile(dist_scores, 0.95) +fig = plt.figure() # Create matplotlib figure +plt.hist(dist_scores, bins=500) +plt.xlabel('Score') +plt.ylabel('Number of imgs') +plt.ylim(0, 50) +plt.axvline(rangeMax, color='red') +plt.show() + + +# In[9]: + + +print(np.quantile(dist_scores, q=0.95)) + +# In[10]: + +img_index = 0#len(dists)-1 +dst_frame_name = dists[img_index][1] +dst_frame_num = str(dists[img_index][1])[-10:-6] +src_frame_name = dists[img_index][2] +print(dst_frame_name, dst_frame_num, src_frame_name) + + +# In[11]: + + +plt.axis('equal') +plt.scatter(list(dists[img_index])[4][:, 0], -list(dists[img_index])[4][:, 1], label='src_img') + + +# In[12]: + + +plt.scatter(list(dists[img_index])[3][:, 0], -list(dists[img_index])[3][:, 1]) +plt.plot(list(dists[img_index])[3][:, 0], -list(dists[img_index])[3][:, 1]) +plt.axis('equal') + + +# In[13]: + + +fig = plt.figure() +ax1 = fig.add_subplot(111) +ax1.set_aspect('equal') + +ax1.scatter(list(dists[img_index])[4][:, 0], -list(dists[img_index])[4][:, 1], label='src_img') +ax1.scatter(list(dists[img_index])[3][:, 0], -list(dists[img_index])[3][:, 1], c='r', label='dst_img') +plt.legend(loc='lower left'); +plt.show() + + +# In[14]: + + +# This block computes the exact same evaluation of the beginning block. +# It's just for debug and check. +def point_dist(p1, p2): + dx, dy = p2[0] - p1[0], p2[1] - p1[1] + return math.sqrt(dx*dx + dy*dy) +src_lm = dists[img_index][3] +dst_lm = dists[img_index][4] +plt.axis('equal') +plt.scatter(src_lm[:,0], -src_lm[:,1], label='src') +plt.scatter(dst_lm[:,0], -dst_lm[:,1], label='dst') +sum_dd = 0 +for x1, y1, x2, y2 in zip(src_lm[:,0], -src_lm[:,1], dst_lm[:,0], -dst_lm[:,1]): + plt.plot([x1, x2], [y1, y2], c='r') + dd = point_dist([x1, y1], [x2, y2]) + sum_dd += dd +plt.legend(loc='lower left'); +print(sum_dd, dists[img_index][0], np.sum(np.linalg.norm(src_lm - dst_lm, ord=2, axis=1))) + +print("Second metodo: ",sum_dd) + + +# In[15]: + + +def get_frame(fname, frame_number): + cmd = f"ffmpeg -i {fname} -vf select='eq(n\,{frame_number})' -vsync 0 frame_{frame_number}.jpg" + os.system(cmd) + +video_fname = '../workspace/result.mp4' +get_frame(video_fname, dst_frame_num) + + +# In[16]: + + +cmd = 'xdg-open '+dst_frame_name+'&' +os.system(cmd) +cmd = 'xdg-open frame_'+dst_frame_num+'.jpg &' +os.system(cmd) +print(cmd) +debug_name = str(dst_frame_name)[0:-12]+"_debug/"+str(dst_frame_name)[-11:-6]+'.jpg' +print(debug_name) +cmd = 'xdg-open '+debug_name+'&' +os.system(cmd) +cmd = 'xdg-open '+src_frame_name+' &' +os.system(cmd) + + +# In[31]: + + +dists_w_result = [] +for i, d in enumerate(dists): + dists_w_result.append([int(os.path.basename(dists[i][1]).split('_')[0]), d[0] < rangeMax, d[0], d[1], d[2], "frame_"+str(dists[i][1])[-10:-6]+".jpg", d[3], d[4]]) +print((dists_w_result)[0]) + +# In[52]: + +headers = ["dst_index", "valid_face" , "landmark_distance_sum", "dst_frame_name", "src_frame_name", "result_frame_name", "landmarks"] +with open('dists.csv', 'w') as v: + write = csv.writer(v) + write.writerow(headers) + write.writerows(dists_w_result) +v.close() +