mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-08-20 13:33:24 -07:00
Upgraded to TF version 1.13.2
Removed the wait at first launch for most graphics cards. Increased speed of training by 10-20%, but you have to retrain all models from scratch. SAEHD: added option 'use float16' Experimental option. Reduces the model size by half. Increases the speed of training. Decreases the accuracy of the model. The model may collapse or not train. Model may not learn the mask in large resolutions. true_face_training option is replaced by "True face power". 0.0000 .. 1.0 Experimental option. Discriminates the result face to be more like the src face. Higher value - stronger discrimination. Comparison - https://i.imgur.com/czScS9q.png
This commit is contained in:
parent
a3dfcb91b9
commit
76ca79216e
49 changed files with 1320 additions and 1297 deletions
|
@ -54,7 +54,7 @@ class IEPolys:
|
|||
self.n = max(0, self.n-1)
|
||||
self.dirty = True
|
||||
return self.n
|
||||
|
||||
|
||||
def n_inc(self):
|
||||
self.n = min(len(self.list), self.n+1)
|
||||
self.dirty = True
|
||||
|
|
|
@ -9,7 +9,7 @@ from scipy.sparse.linalg import spsolve
|
|||
def color_transfer_sot(src,trg, steps=10, batch_size=5, reg_sigmaXY=16.0, reg_sigmaV=5.0):
|
||||
"""
|
||||
Color Transform via Sliced Optimal Transfer
|
||||
ported by @iperov from https://github.com/dcoeurjo/OTColorTransfer
|
||||
ported by @iperov from https://github.com/dcoeurjo/OTColorTransfer
|
||||
|
||||
src - any float range any channel image
|
||||
dst - any float range any channel image, same shape as src
|
||||
|
@ -17,7 +17,7 @@ def color_transfer_sot(src,trg, steps=10, batch_size=5, reg_sigmaXY=16.0, reg_si
|
|||
batch_size - solver batch size
|
||||
reg_sigmaXY - apply regularization and sigmaXY of filter, otherwise set to 0.0
|
||||
reg_sigmaV - sigmaV of filter
|
||||
|
||||
|
||||
return value - clip it manually
|
||||
"""
|
||||
if not np.issubdtype(src.dtype, np.floating):
|
||||
|
@ -27,11 +27,11 @@ def color_transfer_sot(src,trg, steps=10, batch_size=5, reg_sigmaXY=16.0, reg_si
|
|||
|
||||
if len(src.shape) != 3:
|
||||
raise ValueError("src shape must have rank 3 (h,w,c)")
|
||||
|
||||
if src.shape != trg.shape:
|
||||
raise ValueError("src and trg shapes must be equal")
|
||||
|
||||
src_dtype = src.dtype
|
||||
if src.shape != trg.shape:
|
||||
raise ValueError("src and trg shapes must be equal")
|
||||
|
||||
src_dtype = src.dtype
|
||||
h,w,c = src.shape
|
||||
new_src = src.copy()
|
||||
|
||||
|
@ -59,63 +59,63 @@ def color_transfer_sot(src,trg, steps=10, batch_size=5, reg_sigmaXY=16.0, reg_si
|
|||
src_diff_filt = src_diff_filt[...,None]
|
||||
new_src = src + src_diff_filt
|
||||
return new_src
|
||||
|
||||
|
||||
def color_transfer_mkl(x0, x1):
|
||||
eps = np.finfo(float).eps
|
||||
|
||||
|
||||
h,w,c = x0.shape
|
||||
h1,w1,c1 = x1.shape
|
||||
|
||||
|
||||
x0 = x0.reshape ( (h*w,c) )
|
||||
x1 = x1.reshape ( (h1*w1,c1) )
|
||||
|
||||
|
||||
a = np.cov(x0.T)
|
||||
b = np.cov(x1.T)
|
||||
|
||||
Da2, Ua = np.linalg.eig(a)
|
||||
Da = np.diag(np.sqrt(Da2.clip(eps, None)))
|
||||
Da = np.diag(np.sqrt(Da2.clip(eps, None)))
|
||||
|
||||
C = np.dot(np.dot(np.dot(np.dot(Da, Ua.T), b), Ua), Da)
|
||||
|
||||
Dc2, Uc = np.linalg.eig(C)
|
||||
Dc = np.diag(np.sqrt(Dc2.clip(eps, None)))
|
||||
Dc = np.diag(np.sqrt(Dc2.clip(eps, None)))
|
||||
|
||||
Da_inv = np.diag(1./(np.diag(Da)))
|
||||
|
||||
t = np.dot(np.dot(np.dot(np.dot(np.dot(np.dot(Ua, Da_inv), Uc), Dc), Uc.T), Da_inv), Ua.T)
|
||||
t = np.dot(np.dot(np.dot(np.dot(np.dot(np.dot(Ua, Da_inv), Uc), Dc), Uc.T), Da_inv), Ua.T)
|
||||
|
||||
mx0 = np.mean(x0, axis=0)
|
||||
mx1 = np.mean(x1, axis=0)
|
||||
|
||||
result = np.dot(x0-mx0, t) + mx1
|
||||
return np.clip ( result.reshape ( (h,w,c) ).astype(x0.dtype), 0, 1)
|
||||
|
||||
|
||||
def color_transfer_idt(i0, i1, bins=256, n_rot=20):
|
||||
relaxation = 1 / n_rot
|
||||
h,w,c = i0.shape
|
||||
h1,w1,c1 = i1.shape
|
||||
|
||||
|
||||
i0 = i0.reshape ( (h*w,c) )
|
||||
i1 = i1.reshape ( (h1*w1,c1) )
|
||||
|
||||
|
||||
n_dims = c
|
||||
|
||||
|
||||
d0 = i0.T
|
||||
d1 = i1.T
|
||||
|
||||
|
||||
for i in range(n_rot):
|
||||
|
||||
|
||||
r = sp.stats.special_ortho_group.rvs(n_dims).astype(np.float32)
|
||||
|
||||
|
||||
d0r = np.dot(r, d0)
|
||||
d1r = np.dot(r, d1)
|
||||
d_r = np.empty_like(d0)
|
||||
|
||||
|
||||
for j in range(n_dims):
|
||||
|
||||
|
||||
lo = min(d0r[j].min(), d1r[j].min())
|
||||
hi = max(d0r[j].max(), d1r[j].max())
|
||||
|
||||
|
||||
p0r, edges = np.histogram(d0r[j], bins=bins, range=[lo, hi])
|
||||
p1r, _ = np.histogram(d1r[j], bins=bins, range=[lo, hi])
|
||||
|
||||
|
@ -124,11 +124,11 @@ def color_transfer_idt(i0, i1, bins=256, n_rot=20):
|
|||
|
||||
cp1r = p1r.cumsum().astype(np.float32)
|
||||
cp1r /= cp1r[-1]
|
||||
|
||||
|
||||
f = np.interp(cp0r, cp1r, edges[1:])
|
||||
|
||||
|
||||
d_r[j] = np.interp(d0r[j], edges[1:], f, left=0, right=bins)
|
||||
|
||||
|
||||
d0 = relaxation * np.linalg.solve(r, (d_r - d0r)) + d0
|
||||
|
||||
return np.clip ( d0.T.reshape ( (h,w,c) ).astype(i0.dtype) , 0, 1)
|
||||
|
@ -137,16 +137,16 @@ def laplacian_matrix(n, m):
|
|||
mat_D = scipy.sparse.lil_matrix((m, m))
|
||||
mat_D.setdiag(-1, -1)
|
||||
mat_D.setdiag(4)
|
||||
mat_D.setdiag(-1, 1)
|
||||
mat_A = scipy.sparse.block_diag([mat_D] * n).tolil()
|
||||
mat_D.setdiag(-1, 1)
|
||||
mat_A = scipy.sparse.block_diag([mat_D] * n).tolil()
|
||||
mat_A.setdiag(-1, 1*m)
|
||||
mat_A.setdiag(-1, -1*m)
|
||||
mat_A.setdiag(-1, -1*m)
|
||||
return mat_A
|
||||
|
||||
def seamless_clone(source, target, mask):
|
||||
h, w,c = target.shape
|
||||
result = []
|
||||
|
||||
|
||||
mat_A = laplacian_matrix(h, w)
|
||||
laplacian = mat_A.tocsc()
|
||||
|
||||
|
@ -155,7 +155,7 @@ def seamless_clone(source, target, mask):
|
|||
mask[:,0] = 1
|
||||
mask[:,-1] = 1
|
||||
q = np.argwhere(mask==0)
|
||||
|
||||
|
||||
k = q[:,1]+q[:,0]*w
|
||||
mat_A[k, k] = 1
|
||||
mat_A[k, k + 1] = 0
|
||||
|
@ -163,22 +163,22 @@ def seamless_clone(source, target, mask):
|
|||
mat_A[k, k + w] = 0
|
||||
mat_A[k, k - w] = 0
|
||||
|
||||
mat_A = mat_A.tocsc()
|
||||
mat_A = mat_A.tocsc()
|
||||
mask_flat = mask.flatten()
|
||||
for channel in range(c):
|
||||
|
||||
|
||||
source_flat = source[:, :, channel].flatten()
|
||||
target_flat = target[:, :, channel].flatten()
|
||||
target_flat = target[:, :, channel].flatten()
|
||||
|
||||
mat_b = laplacian.dot(source_flat)*0.75
|
||||
mat_b[mask_flat==0] = target_flat[mask_flat==0]
|
||||
|
||||
|
||||
x = spsolve(mat_A, mat_b).reshape((h, w))
|
||||
result.append (x)
|
||||
|
||||
|
||||
|
||||
return np.clip( np.dstack(result), 0, 1 )
|
||||
|
||||
|
||||
def reinhard_color_transfer(target, source, clip=False, preserve_paper=False, source_mask=None, target_mask=None):
|
||||
"""
|
||||
Transfers the color distribution from the source to the target
|
||||
|
@ -368,26 +368,26 @@ def color_hist_match(src_im, tar_im, hist_match_threshold=255):
|
|||
def color_transfer_mix(img_src,img_trg):
|
||||
img_src = (img_src*255.0).astype(np.uint8)
|
||||
img_trg = (img_trg*255.0).astype(np.uint8)
|
||||
|
||||
|
||||
img_src_lab = cv2.cvtColor(img_src, cv2.COLOR_BGR2LAB)
|
||||
img_trg_lab = cv2.cvtColor(img_trg, cv2.COLOR_BGR2LAB)
|
||||
|
||||
rct_light = np.clip ( linear_color_transfer(img_src_lab[...,0:1].astype(np.float32)/255.0,
|
||||
|
||||
rct_light = np.clip ( linear_color_transfer(img_src_lab[...,0:1].astype(np.float32)/255.0,
|
||||
img_trg_lab[...,0:1].astype(np.float32)/255.0 )[...,0]*255.0,
|
||||
0, 255).astype(np.uint8)
|
||||
0, 255).astype(np.uint8)
|
||||
|
||||
img_src_lab[...,0] = (np.ones_like (rct_light)*100).astype(np.uint8)
|
||||
img_src_lab = cv2.cvtColor(img_src_lab, cv2.COLOR_LAB2BGR)
|
||||
img_src_lab = cv2.cvtColor(img_src_lab, cv2.COLOR_LAB2BGR)
|
||||
|
||||
img_trg_lab[...,0] = (np.ones_like (rct_light)*100).astype(np.uint8)
|
||||
img_trg_lab = cv2.cvtColor(img_trg_lab, cv2.COLOR_LAB2BGR)
|
||||
|
||||
|
||||
img_rct = color_transfer_sot( img_src_lab.astype(np.float32), img_trg_lab.astype(np.float32) )
|
||||
img_rct = np.clip(img_rct, 0, 255).astype(np.uint8)
|
||||
|
||||
img_rct = cv2.cvtColor(img_rct, cv2.COLOR_BGR2LAB)
|
||||
|
||||
img_rct = cv2.cvtColor(img_rct, cv2.COLOR_BGR2LAB)
|
||||
img_rct[...,0] = rct_light
|
||||
img_rct = cv2.cvtColor(img_rct, cv2.COLOR_LAB2BGR)
|
||||
|
||||
|
||||
|
||||
|
||||
return (img_rct / 255.0).astype(np.float32)
|
|
@ -13,24 +13,24 @@ def normalize_channels(img, target_channels):
|
|||
if c == 0 and target_channels > 0:
|
||||
img = img[...,np.newaxis]
|
||||
c = 1
|
||||
|
||||
|
||||
if c == 1 and target_channels > 1:
|
||||
img = np.repeat (img, target_channels, -1)
|
||||
c = target_channels
|
||||
|
||||
|
||||
if c > target_channels:
|
||||
img = img[...,0:target_channels]
|
||||
c = target_channels
|
||||
|
||||
return img
|
||||
|
||||
|
||||
def cut_odd_image(img):
|
||||
h, w, c = img.shape
|
||||
wm, hm = w % 2, h % 2
|
||||
if wm + hm != 0:
|
||||
if wm + hm != 0:
|
||||
img = img[0:h-hm,0:w-wm,:]
|
||||
return img
|
||||
|
||||
|
||||
def overlay_alpha_image(img_target, img_source, xy_offset=(0,0) ):
|
||||
(h,w,c) = img_source.shape
|
||||
if c != 4:
|
||||
|
|
|
@ -16,7 +16,7 @@ def _get_pil_font (font, size):
|
|||
|
||||
def get_text_image( shape, text, color=(1,1,1), border=0.2, font=None):
|
||||
h,w,c = shape
|
||||
try:
|
||||
try:
|
||||
pil_font = _get_pil_font( localization.get_default_ttf_font_name() , h-2)
|
||||
|
||||
canvas = Image.new('RGB', (w,h) , (0,0,0) )
|
||||
|
@ -25,7 +25,7 @@ def get_text_image( shape, text, color=(1,1,1), border=0.2, font=None):
|
|||
draw.text(offset, text, font=pil_font, fill=tuple((np.array(color)*255).astype(np.int)) )
|
||||
|
||||
result = np.asarray(canvas) / 255
|
||||
|
||||
|
||||
if c > 3:
|
||||
result = np.concatenate ( (result, np.ones ((h,w,c-3)) ), axis=-1 )
|
||||
elif c < 3:
|
||||
|
|
|
@ -6,7 +6,7 @@ def gen_warp_params (source, flip, rotation_range=[-10,10], scale_range=[-0.5, 0
|
|||
h,w,c = source.shape
|
||||
if (h != w):
|
||||
raise ValueError ('gen_warp_params accepts only square images.')
|
||||
|
||||
|
||||
if rnd_seed != None:
|
||||
rnd_state = np.random.RandomState (rnd_seed)
|
||||
else:
|
||||
|
@ -15,9 +15,9 @@ def gen_warp_params (source, flip, rotation_range=[-10,10], scale_range=[-0.5, 0
|
|||
rotation = rnd_state.uniform( rotation_range[0], rotation_range[1] )
|
||||
scale = rnd_state.uniform(1 +scale_range[0], 1 +scale_range[1])
|
||||
tx = rnd_state.uniform( tx_range[0], tx_range[1] )
|
||||
ty = rnd_state.uniform( ty_range[0], ty_range[1] )
|
||||
ty = rnd_state.uniform( ty_range[0], ty_range[1] )
|
||||
p_flip = flip and rnd_state.randint(10) < 4
|
||||
|
||||
|
||||
#random warp by grid
|
||||
cell_size = [ w // (2**i) for i in range(1,4) ] [ rnd_state.randint(3) ]
|
||||
cell_count = w // cell_size + 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue