mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-07-05 20:42:11 -07:00
core.imagelib: update
This commit is contained in:
parent
bcfc794a1b
commit
243f73fafc
5 changed files with 201 additions and 19 deletions
|
@ -24,4 +24,6 @@ from .filters import apply_random_rgb_levels, \
|
|||
apply_random_hsv_shift, \
|
||||
apply_random_motion_blur, \
|
||||
apply_random_gaussian_blur, \
|
||||
apply_random_bilinear_resize
|
||||
apply_random_nearest_resize, \
|
||||
apply_random_bilinear_resize, \
|
||||
apply_random_jpeg_compress
|
||||
|
|
|
@ -66,8 +66,7 @@ def apply_random_gaussian_blur( img, chance, kernel_max_size, mask=None, rnd_sta
|
|||
|
||||
return result
|
||||
|
||||
|
||||
def apply_random_bilinear_resize( img, chance, max_size_per, mask=None, rnd_state=None ):
|
||||
def apply_random_resize( img, chance, max_size_per, interpolation=cv2.INTER_LINEAR, mask=None, rnd_state=None ):
|
||||
if rnd_state is None:
|
||||
rnd_state = np.random
|
||||
|
||||
|
@ -79,9 +78,34 @@ def apply_random_bilinear_resize( img, chance, max_size_per, mask=None, rnd_stat
|
|||
rw = w - int( trg * int(w*(max_size_per/100.0)) )
|
||||
rh = h - int( trg * int(h*(max_size_per/100.0)) )
|
||||
|
||||
result = cv2.resize (result, (rw,rh), interpolation=cv2.INTER_LINEAR )
|
||||
result = cv2.resize (result, (w,h), interpolation=cv2.INTER_LINEAR )
|
||||
result = cv2.resize (result, (rw,rh), interpolation=interpolation )
|
||||
result = cv2.resize (result, (w,h), interpolation=interpolation )
|
||||
if mask is not None:
|
||||
result = img*(1-mask) + result*mask
|
||||
|
||||
return result
|
||||
|
||||
def apply_random_nearest_resize( img, chance, max_size_per, mask=None, rnd_state=None ):
|
||||
return apply_random_resize( img, chance, max_size_per, interpolation=cv2.INTER_NEAREST, mask=mask, rnd_state=rnd_state )
|
||||
|
||||
def apply_random_bilinear_resize( img, chance, max_size_per, mask=None, rnd_state=None ):
|
||||
return apply_random_resize( img, chance, max_size_per, interpolation=cv2.INTER_LINEAR, mask=mask, rnd_state=rnd_state )
|
||||
|
||||
def apply_random_jpeg_compress( img, chance, mask=None, rnd_state=None ):
|
||||
if rnd_state is None:
|
||||
rnd_state = np.random
|
||||
|
||||
result = img
|
||||
if rnd_state.randint(100) < np.clip(chance, 0, 100):
|
||||
h,w,c = result.shape
|
||||
|
||||
quality = rnd_state.randint(10,101)
|
||||
|
||||
ret, result = cv2.imencode('.jpg', np.clip(img*255, 0,255).astype(np.uint8), [int(cv2.IMWRITE_JPEG_QUALITY), quality] )
|
||||
if ret == True:
|
||||
result = cv2.imdecode(result, flags=cv2.IMREAD_UNCHANGED)
|
||||
result = result.astype(np.float32) / 255.0
|
||||
if mask is not None:
|
||||
result = img*(1-mask) + result*mask
|
||||
|
||||
return result
|
|
@ -1,2 +1,2 @@
|
|||
from .draw import *
|
||||
from .draw import circle_faded, random_circle_faded, bezier, random_bezier_split_faded, random_faded
|
||||
from .calc import *
|
|
@ -1,23 +1,36 @@
|
|||
"""
|
||||
Signed distance drawing functions using numpy.
|
||||
"""
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
from numpy import linalg as npla
|
||||
|
||||
def circle_faded( hw, center, fade_dists ):
|
||||
|
||||
def vector2_dot(a,b):
|
||||
return a[...,0]*b[...,0]+a[...,1]*b[...,1]
|
||||
|
||||
def vector2_dot2(a):
|
||||
return a[...,0]*a[...,0]+a[...,1]*a[...,1]
|
||||
|
||||
def vector2_cross(a,b):
|
||||
return a[...,0]*b[...,1]-a[...,1]*b[...,0]
|
||||
|
||||
|
||||
def circle_faded( wh, center, fade_dists ):
|
||||
"""
|
||||
returns drawn circle in [h,w,1] output range [0..1.0] float32
|
||||
|
||||
hw = [h,w] resolution
|
||||
center = [y,x] center of circle
|
||||
wh = [w,h] resolution
|
||||
center = [x,y] center of circle
|
||||
fade_dists = [fade_start, fade_end] fade values
|
||||
"""
|
||||
h,w = hw
|
||||
w,h = wh
|
||||
|
||||
pts = np.empty( (h,w,2), dtype=np.float32 )
|
||||
pts[...,1] = np.arange(h)[None,:]
|
||||
pts[...,0] = np.arange(w)[:,None]
|
||||
pts[...,1] = np.arange(h)[None,:]
|
||||
|
||||
pts = pts.reshape ( (h*w, -1) )
|
||||
|
||||
pts_dists = np.abs ( npla.norm(pts-center, axis=-1) )
|
||||
|
@ -30,15 +43,158 @@ def circle_faded( hw, center, fade_dists ):
|
|||
pts_dists = np.clip( 1-pts_dists, 0, 1)
|
||||
|
||||
return pts_dists.reshape ( (h,w,1) ).astype(np.float32)
|
||||
|
||||
|
||||
def bezier( wh, A, B, C ):
|
||||
"""
|
||||
returns drawn bezier in [h,w,1] output range float32,
|
||||
every pixel contains signed distance to bezier line
|
||||
|
||||
wh [w,h] resolution
|
||||
A,B,C points [x,y]
|
||||
"""
|
||||
|
||||
def random_circle_faded ( hw, rnd_state=None ):
|
||||
width,height = wh
|
||||
|
||||
A = np.float32(A)
|
||||
B = np.float32(B)
|
||||
C = np.float32(C)
|
||||
|
||||
|
||||
pos = np.empty( (height,width,2), dtype=np.float32 )
|
||||
pos[...,0] = np.arange(width)[:,None]
|
||||
pos[...,1] = np.arange(height)[None,:]
|
||||
|
||||
|
||||
a = B-A
|
||||
b = A - 2.0*B + C
|
||||
c = a * 2.0
|
||||
d = A - pos
|
||||
|
||||
b_dot = vector2_dot(b,b)
|
||||
if b_dot == 0.0:
|
||||
return np.zeros( (height,width), dtype=np.float32 )
|
||||
|
||||
kk = 1.0 / b_dot
|
||||
|
||||
kx = kk * vector2_dot(a,b)
|
||||
ky = kk * (2.0*vector2_dot(a,a)+vector2_dot(d,b))/3.0;
|
||||
kz = kk * vector2_dot(d,a);
|
||||
|
||||
res = 0.0;
|
||||
sgn = 0.0;
|
||||
|
||||
p = ky - kx*kx;
|
||||
|
||||
p3 = p*p*p;
|
||||
q = kx*(2.0*kx*kx - 3.0*ky) + kz;
|
||||
h = q*q + 4.0*p3;
|
||||
|
||||
hp_sel = h >= 0.0
|
||||
|
||||
hp_p = h[hp_sel]
|
||||
hp_p = np.sqrt(hp_p)
|
||||
|
||||
hp_x = ( np.stack( (hp_p,-hp_p), -1) -q[hp_sel,None] ) / 2.0
|
||||
hp_uv = np.sign(hp_x) * np.power( np.abs(hp_x), [1.0/3.0, 1.0/3.0] )
|
||||
hp_t = np.clip( hp_uv[...,0] + hp_uv[...,1] - kx, 0.0, 1.0 )
|
||||
|
||||
hp_t = hp_t[...,None]
|
||||
hp_q = d[hp_sel]+(c+b*hp_t)*hp_t
|
||||
hp_res = vector2_dot2(hp_q)
|
||||
hp_sgn = vector2_cross(c+2.0*b*hp_t,hp_q)
|
||||
|
||||
hl_sel = h < 0.0
|
||||
|
||||
hl_q = q[hl_sel]
|
||||
hl_p = p[hl_sel]
|
||||
hl_z = np.sqrt(-hl_p)
|
||||
hl_v = np.arccos( hl_q / (hl_p*hl_z*2.0)) / 3.0
|
||||
|
||||
hl_m = np.cos(hl_v)
|
||||
hl_n = np.sin(hl_v)*1.732050808;
|
||||
|
||||
hl_t = np.clip( np.stack( (hl_m+hl_m,-hl_n-hl_m,hl_n-hl_m), -1)*hl_z[...,None]-kx, 0.0, 1.0 );
|
||||
|
||||
hl_d = d[hl_sel]
|
||||
|
||||
hl_qx = hl_d+(c+b*hl_t[...,0:1])*hl_t[...,0:1]
|
||||
|
||||
hl_dx = vector2_dot2(hl_qx)
|
||||
hl_sx = vector2_cross(c+2.0*b*hl_t[...,0:1], hl_qx)
|
||||
|
||||
hl_qy = hl_d+(c+b*hl_t[...,1:2])*hl_t[...,1:2]
|
||||
hl_dy = vector2_dot2(hl_qy)
|
||||
hl_sy = vector2_cross(c+2.0*b*hl_t[...,1:2],hl_qy);
|
||||
|
||||
hl_dx_l_dy = hl_dx<hl_dy
|
||||
hl_dx_ge_dy = hl_dx>=hl_dy
|
||||
|
||||
hl_res = np.empty_like(hl_dx)
|
||||
hl_res[hl_dx_l_dy] = hl_dx[hl_dx_l_dy]
|
||||
hl_res[hl_dx_ge_dy] = hl_dy[hl_dx_ge_dy]
|
||||
|
||||
hl_sgn = np.empty_like(hl_sx)
|
||||
hl_sgn[hl_dx_l_dy] = hl_sx[hl_dx_l_dy]
|
||||
hl_sgn[hl_dx_ge_dy] = hl_sy[hl_dx_ge_dy]
|
||||
|
||||
res = np.empty( (height, width), np.float32 )
|
||||
res[hp_sel] = hp_res
|
||||
res[hl_sel] = hl_res
|
||||
|
||||
sgn = np.empty( (height, width), np.float32 )
|
||||
sgn[hp_sel] = hp_sgn
|
||||
sgn[hl_sel] = hl_sgn
|
||||
|
||||
sgn = np.sign(sgn)
|
||||
res = np.sqrt(res)*sgn
|
||||
|
||||
return res[...,None]
|
||||
|
||||
def random_faded(wh):
|
||||
"""
|
||||
apply one of them:
|
||||
random_circle_faded
|
||||
random_bezier_split_faded
|
||||
"""
|
||||
rnd = np.random.randint(2)
|
||||
if rnd == 0:
|
||||
return random_circle_faded(wh)
|
||||
elif rnd == 1:
|
||||
return random_bezier_split_faded(wh)
|
||||
|
||||
def random_circle_faded ( wh, rnd_state=None ):
|
||||
if rnd_state is None:
|
||||
rnd_state = np.random
|
||||
|
||||
h,w = hw
|
||||
hw_max = max(h,w)
|
||||
fade_start = rnd_state.randint(hw_max)
|
||||
fade_end = fade_start + rnd_state.randint(hw_max- fade_start)
|
||||
w,h = wh
|
||||
wh_max = max(w,h)
|
||||
fade_start = rnd_state.randint(wh_max)
|
||||
fade_end = fade_start + rnd_state.randint(wh_max- fade_start)
|
||||
|
||||
return circle_faded (hw, [ rnd_state.randint(h), rnd_state.randint(w) ],
|
||||
[fade_start, fade_end] )
|
||||
return circle_faded (wh, [ rnd_state.randint(h), rnd_state.randint(w) ],
|
||||
[fade_start, fade_end] )
|
||||
|
||||
def random_bezier_split_faded( wh ):
|
||||
width, height = wh
|
||||
|
||||
degA = np.random.randint(360)
|
||||
degB = np.random.randint(360)
|
||||
degC = np.random.randint(360)
|
||||
|
||||
deg_2_rad = math.pi / 180.0
|
||||
|
||||
center = np.float32([width / 2.0, height / 2.0])
|
||||
|
||||
radius = max(width, height)
|
||||
|
||||
A = center + radius*np.float32([ math.sin( degA * deg_2_rad), math.cos( degA * deg_2_rad) ] )
|
||||
B = center + np.random.randint(radius)*np.float32([ math.sin( degB * deg_2_rad), math.cos( degB * deg_2_rad) ] )
|
||||
C = center + radius*np.float32([ math.sin( degC * deg_2_rad), math.cos( degC * deg_2_rad) ] )
|
||||
|
||||
x = bezier( (width,height), A, B, C )
|
||||
|
||||
x = x / (1+np.random.randint(radius)) + 0.5
|
||||
|
||||
x = np.clip(x, 0, 1)
|
||||
return x
|
||||
|
|
|
@ -2,7 +2,7 @@ import numpy as np
|
|||
import cv2
|
||||
from core import randomex
|
||||
|
||||
def gen_warp_params (w, flip, rotation_range=[-10,10], scale_range=[-0.5, 0.5], tx_range=[-0.05, 0.05], ty_range=[-0.05, 0.05], rnd_state=None ):
|
||||
def gen_warp_params (w, flip=False, rotation_range=[-10,10], scale_range=[-0.5, 0.5], tx_range=[-0.05, 0.05], ty_range=[-0.05, 0.05], rnd_state=None ):
|
||||
if rnd_state is None:
|
||||
rnd_state = np.random
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue