2019-12-27 01:27:10 +08:00
|
|
|
import multiprocessing
|
|
|
|
import shutil
|
|
|
|
|
|
|
|
from DFLIMG import *
|
2020-01-21 22:43:39 +08:00
|
|
|
from core.interact import interact as io
|
|
|
|
from core.joblib import Subprocessor
|
|
|
|
from core.leras import nn
|
|
|
|
from core import pathex
|
|
|
|
from core.cv2ex import *
|
2019-12-27 01:27:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
class FacesetEnhancerSubprocessor(Subprocessor):
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
2020-01-21 22:43:39 +08:00
|
|
|
def __init__(self, image_paths, output_dirpath, device_config):
|
2019-12-27 01:27:10 +08:00
|
|
|
self.image_paths = image_paths
|
|
|
|
self.output_dirpath = output_dirpath
|
|
|
|
self.result = []
|
2020-01-21 22:43:39 +08:00
|
|
|
self.nn_initialize_mp_lock = multiprocessing.Lock()
|
|
|
|
self.devices = FacesetEnhancerSubprocessor.get_devices_for_config(device_config)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
super().__init__('FacesetEnhancer', FacesetEnhancerSubprocessor.Cli, 600)
|
|
|
|
|
|
|
|
#override
|
|
|
|
def on_clients_initialized(self):
|
|
|
|
io.progress_bar (None, len (self.image_paths))
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
|
|
|
def on_clients_finalized(self):
|
|
|
|
io.progress_bar_close()
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
|
|
|
def process_info_generator(self):
|
2020-01-21 22:43:39 +08:00
|
|
|
base_dict = {'output_dirpath':self.output_dirpath,
|
|
|
|
'nn_initialize_mp_lock': self.nn_initialize_mp_lock,}
|
2019-12-27 01:27:10 +08:00
|
|
|
|
|
|
|
for (device_idx, device_type, device_name, device_total_vram_gb) in self.devices:
|
|
|
|
client_dict = base_dict.copy()
|
|
|
|
client_dict['device_idx'] = device_idx
|
|
|
|
client_dict['device_name'] = device_name
|
|
|
|
client_dict['device_type'] = device_type
|
|
|
|
yield client_dict['device_name'], {}, client_dict
|
|
|
|
|
|
|
|
#override
|
2020-01-26 01:58:19 +08:00
|
|
|
def get_data(self, host_dict):
|
2019-12-27 01:27:10 +08:00
|
|
|
if len (self.image_paths) > 0:
|
|
|
|
return self.image_paths.pop(0)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
|
|
|
def on_data_return (self, host_dict, data):
|
|
|
|
self.image_paths.insert(0, data)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
|
|
|
def on_result (self, host_dict, data, result):
|
|
|
|
io.progress_bar_inc(1)
|
|
|
|
if result[0] == 1:
|
|
|
|
self.result +=[ (result[1], result[2]) ]
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
#override
|
|
|
|
def get_result(self):
|
|
|
|
return self.result
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
@staticmethod
|
2020-01-26 01:58:19 +08:00
|
|
|
def get_devices_for_config (device_config):
|
2020-01-21 22:43:39 +08:00
|
|
|
devices = device_config.devices
|
|
|
|
cpu_only = len(devices) == 0
|
2020-01-26 01:58:19 +08:00
|
|
|
|
|
|
|
if not cpu_only:
|
2020-01-21 22:43:39 +08:00
|
|
|
return [ (device.index, 'GPU', device.name, device.total_mem_gb) for device in devices ]
|
|
|
|
else:
|
2019-12-27 01:27:10 +08:00
|
|
|
return [ (i, 'CPU', 'CPU%d' % (i), 0 ) for i in range( min(8, multiprocessing.cpu_count() // 2) ) ]
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
class Cli(Subprocessor.Cli):
|
|
|
|
|
|
|
|
#override
|
|
|
|
def on_initialize(self, client_dict):
|
|
|
|
device_idx = client_dict['device_idx']
|
|
|
|
cpu_only = client_dict['device_type'] == 'CPU'
|
|
|
|
self.output_dirpath = client_dict['output_dirpath']
|
2020-01-21 22:43:39 +08:00
|
|
|
nn_initialize_mp_lock = client_dict['nn_initialize_mp_lock']
|
|
|
|
|
|
|
|
if cpu_only:
|
|
|
|
device_config = nn.DeviceConfig.CPU()
|
|
|
|
device_vram = 99
|
|
|
|
else:
|
|
|
|
device_config = nn.DeviceConfig.GPUIndexes ([device_idx])
|
|
|
|
device_vram = device_config.devices[0].total_mem_gb
|
2020-01-26 01:58:19 +08:00
|
|
|
|
|
|
|
nn.initialize (device_config)
|
2019-12-27 01:27:10 +08:00
|
|
|
|
|
|
|
intro_str = 'Running on %s.' % (client_dict['device_name'])
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
self.log_info (intro_str)
|
|
|
|
|
2020-01-26 01:58:19 +08:00
|
|
|
from facelib import FaceEnhancer
|
2020-03-13 12:09:00 +08:00
|
|
|
self.fe = FaceEnhancer( place_model_on_cpu=(device_vram<=2 or cpu_only), run_on_cpu=cpu_only )
|
2019-12-27 01:27:10 +08:00
|
|
|
|
|
|
|
#override
|
|
|
|
def process_data(self, filepath):
|
|
|
|
try:
|
|
|
|
dflimg = DFLIMG.load (filepath)
|
2020-03-21 05:18:15 +08:00
|
|
|
if dflimg is None or not dflimg.has_data():
|
|
|
|
self.log_err (f"{filepath.name} is not a dfl image file")
|
2019-12-27 01:27:10 +08:00
|
|
|
else:
|
2020-03-21 05:18:15 +08:00
|
|
|
dfl_dict = dflimg.get_dict()
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2020-03-21 05:18:15 +08:00
|
|
|
img = cv2_imread(filepath).astype(np.float32) / 255.0
|
2019-12-27 01:27:10 +08:00
|
|
|
img = self.fe.enhance(img)
|
|
|
|
img = np.clip (img*255, 0, 255).astype(np.uint8)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
output_filepath = self.output_dirpath / filepath.name
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
cv2_imwrite ( str(output_filepath), img, [int(cv2.IMWRITE_JPEG_QUALITY), 100] )
|
2020-03-21 05:18:15 +08:00
|
|
|
|
|
|
|
dflimg = DFLIMG.load (output_filepath)
|
|
|
|
dflimg.set_dict(dfl_dict)
|
|
|
|
dflimg.save()
|
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
return (1, filepath, output_filepath)
|
|
|
|
except:
|
|
|
|
self.log_err (f"Exception occured while processing file {filepath}. Error: {traceback.format_exc()}")
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
return (0, filepath, None)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2020-01-21 22:43:39 +08:00
|
|
|
def process_folder ( dirpath, cpu_only=False, force_gpu_idxs=None ):
|
|
|
|
device_config = nn.DeviceConfig.GPUIndexes( force_gpu_idxs or nn.ask_choose_device_idxs(suggest_all_gpu=True) ) \
|
|
|
|
if not cpu_only else nn.DeviceConfig.CPU()
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
output_dirpath = dirpath.parent / (dirpath.name + '_enhanced')
|
|
|
|
output_dirpath.mkdir (exist_ok=True, parents=True)
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 01:27:10 +08:00
|
|
|
dirpath_parts = '/'.join( dirpath.parts[-2:])
|
|
|
|
output_dirpath_parts = '/'.join( output_dirpath.parts[-2:] )
|
2019-12-27 15:09:15 +08:00
|
|
|
io.log_info (f"Enhancing faceset in {dirpath_parts}")
|
|
|
|
io.log_info ( f"Processing to {output_dirpath_parts}")
|
2019-12-27 01:27:10 +08:00
|
|
|
|
2020-01-21 22:43:39 +08:00
|
|
|
output_images_paths = pathex.get_image_paths(output_dirpath)
|
2019-12-27 01:27:10 +08:00
|
|
|
if len(output_images_paths) > 0:
|
|
|
|
for filename in output_images_paths:
|
|
|
|
Path(filename).unlink()
|
2020-01-26 01:58:19 +08:00
|
|
|
|
|
|
|
image_paths = [Path(x) for x in pathex.get_image_paths( dirpath )]
|
2020-01-21 22:43:39 +08:00
|
|
|
result = FacesetEnhancerSubprocessor ( image_paths, output_dirpath, device_config=device_config).run()
|
2019-12-27 01:27:10 +08:00
|
|
|
|
2020-01-21 22:43:39 +08:00
|
|
|
is_merge = io.input_bool (f"\r\nMerge {output_dirpath_parts} to {dirpath_parts} ?", True)
|
2019-12-27 15:09:15 +08:00
|
|
|
if is_merge:
|
|
|
|
io.log_info (f"Copying processed files to {dirpath_parts}")
|
2020-01-26 01:58:19 +08:00
|
|
|
|
|
|
|
for (filepath, output_filepath) in result:
|
|
|
|
try:
|
2019-12-27 17:36:01 +08:00
|
|
|
shutil.copy (output_filepath, filepath)
|
|
|
|
except:
|
|
|
|
pass
|
2020-01-26 01:58:19 +08:00
|
|
|
|
2019-12-27 15:09:15 +08:00
|
|
|
io.log_info (f"Removing {output_dirpath_parts}")
|
|
|
|
shutil.rmtree(output_dirpath)
|