Example #1
0
    def onInitializeOptions(self, is_first_run, ask_override):
        yn_str = {True: 'y', False: 'n'}

        default_resolution = 128
        default_archi = 'df'
        default_face_type = 'f'

        if is_first_run:
            resolution = io.input_int(
                "Resolution ( 64-256 ?:help skip:128) : ",
                default_resolution,
                help_message=
                "More resolution requires more VRAM and time to train. Value will be adjusted to multiple of 16."
            )
            resolution = np.clip(resolution, 64, 256)
            while np.modf(resolution / 16)[0] != 0.0:
                resolution -= 1
            self.options['resolution'] = resolution

            self.options['face_type'] = io.input_str(
                "Half or Full face? (h/f, ?:help skip:f) : ",
                default_face_type, ['h', 'f'],
                help_message=
                "Half face has better resolution, but covers less area of cheeks."
            ).lower()
            self.options['learn_mask'] = io.input_bool(
                "Learn mask? (y/n, ?:help skip:y) : ",
                True,
                help_message=
                "Learning mask can help model to recognize face directions. Learn without mask can reduce model size, in this case converter forced to use 'not predicted mask' that is not smooth as predicted. Model with style values can be learned without mask and produce same quality result."
            )
        else:
            self.options['resolution'] = self.options.get(
                'resolution', default_resolution)
            self.options['face_type'] = self.options.get(
                'face_type', default_face_type)
            self.options['learn_mask'] = self.options.get('learn_mask', True)

        if is_first_run and 'tensorflow' in self.device_config.backend:
            def_optimizer_mode = self.options.get('optimizer_mode', 1)
            self.options['optimizer_mode'] = io.input_int(
                "Optimizer mode? ( 1,2,3 ?:help skip:%d) : " %
                (def_optimizer_mode),
                def_optimizer_mode,
                help_message=
                "1 - no changes. 2 - allows you to train x2 bigger network consuming RAM. 3 - allows you to train x3 bigger network consuming huge amount of RAM and slower, depends on CPU power."
            )
        else:
            self.options['optimizer_mode'] = self.options.get(
                'optimizer_mode', 1)

        if is_first_run:
            self.options['archi'] = io.input_str(
                "AE architecture (df, liae, vg ?:help skip:%s) : " %
                (default_archi),
                default_archi, ['df', 'liae', 'vg'],
                help_message=
                "'df' keeps faces more natural. 'liae' can fix overly different face shapes. 'vg' - currently testing."
            ).lower()
        else:
            self.options['archi'] = self.options.get('archi', default_archi)

        default_ae_dims = 256 if self.options['archi'] == 'liae' else 512
        default_ed_ch_dims = 42
        def_ca_weights = False
        if is_first_run:
            self.options['ae_dims'] = np.clip(
                io.input_int(
                    "AutoEncoder dims (32-1024 ?:help skip:%d) : " %
                    (default_ae_dims),
                    default_ae_dims,
                    help_message=
                    "More dims are better, but requires more VRAM. You can fine-tune model size to fit your GPU."
                ), 32, 1024)
            self.options['ed_ch_dims'] = np.clip(
                io.input_int(
                    "Encoder/Decoder dims per channel (21-85 ?:help skip:%d) : "
                    % (default_ed_ch_dims),
                    default_ed_ch_dims,
                    help_message=
                    "More dims are better, but requires more VRAM. You can fine-tune model size to fit your GPU."
                ), 21, 85)
            self.options['ca_weights'] = io.input_bool(
                "Use CA weights? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_ca_weights]),
                def_ca_weights,
                help_message=
                "Initialize network with 'Convolution Aware' weights. This may help to achieve a higher accuracy model, but consumes time at first run."
            )
        else:
            self.options['ae_dims'] = self.options.get('ae_dims',
                                                       default_ae_dims)
            self.options['ed_ch_dims'] = self.options.get(
                'ed_ch_dims', default_ed_ch_dims)
            self.options['ca_weights'] = self.options.get(
                'ca_weights', def_ca_weights)

        if is_first_run:
            self.options['lighter_encoder'] = io.input_bool(
                "Use lightweight encoder? (y/n, ?:help skip:n) : ",
                False,
                help_message=
                "Lightweight encoder is 35% faster, requires less VRAM, but sacrificing overall quality."
            )

            if self.options['archi'] != 'vg':
                self.options['multiscale_decoder'] = io.input_bool(
                    "Use multiscale decoder? (y/n, ?:help skip:n) : ",
                    False,
                    help_message=
                    "Multiscale decoder helps to get better details.")
        else:
            self.options['lighter_encoder'] = self.options.get(
                'lighter_encoder', False)

            if self.options['archi'] != 'vg':
                self.options['multiscale_decoder'] = self.options.get(
                    'multiscale_decoder', False)

        default_face_style_power = 0.0
        default_bg_style_power = 0.0
        if is_first_run or ask_override:
            def_pixel_loss = self.options.get('pixel_loss', False)
            self.options['pixel_loss'] = io.input_bool(
                "Use pixel loss? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_pixel_loss]),
                def_pixel_loss,
                help_message=
                "Default DSSIM loss good for initial understanding structure of faces. Use pixel loss after 15-25k iters to enhance fine details and decrease face jitter."
            )

            default_face_style_power = default_face_style_power if is_first_run else self.options.get(
                'face_style_power', default_face_style_power)
            self.options['face_style_power'] = np.clip(
                io.input_number(
                    "Face style power ( 0.0 .. 100.0 ?:help skip:%.2f) : " %
                    (default_face_style_power),
                    default_face_style_power,
                    help_message=
                    "Learn to transfer face style details such as light and color conditions. Warning: Enable it only after 10k iters, when predicted face is clear enough to start learn style. Start from 0.1 value and check history changes."
                ), 0.0, 100.0)

            default_bg_style_power = default_bg_style_power if is_first_run else self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['bg_style_power'] = np.clip(
                io.input_number(
                    "Background style power ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_bg_style_power),
                    default_bg_style_power,
                    help_message=
                    "Learn to transfer image around face. This can make face more like dst."
                ), 0.0, 100.0)
        else:
            self.options['pixel_loss'] = self.options.get('pixel_loss', False)
            self.options['face_style_power'] = self.options.get(
                'face_style_power', default_face_style_power)
            self.options['bg_style_power'] = self.options.get(
                'bg_style_power', default_bg_style_power)
Example #2
0
    def onInitializeOptions(self, is_first_run, ask_override):
        yn_str = {True: 'y', False: 'n'}

        default_resolution = 128
        default_archi = 'df'
        default_face_type = 'f'

        if is_first_run:
            resolution = io.input_int(
                "Resolution ( 64-256 ?:help skip:128) : ",
                default_resolution,
                help_message=
                "More resolution requires more VRAM and time to train. Value will be adjusted to multiple of 16."
            )
            resolution = np.clip(resolution, 64, 256)
            while np.modf(resolution / 16)[0] != 0.0:
                resolution -= 1
            self.options['resolution'] = resolution
            self.options['face_type'] = io.input_str(
                "Half, mid full, or full face? (h/mf/f, ?:help skip:f) : ",
                default_face_type, ['h', 'mf', 'f'],
                help_message=
                "Half face has better resolution, but covers less area of cheeks. Mid face is 30% wider than half face."
            ).lower()
        else:
            self.options['resolution'] = self.options.get(
                'resolution', default_resolution)
            self.options['face_type'] = self.options.get(
                'face_type', default_face_type)

        default_learn_mask = self.options.get('learn_mask', True)
        if is_first_run or ask_override:
            self.options['learn_mask'] = io.input_bool(
                f"Learn mask? (y/n, ?:help skip:{yn_str[default_learn_mask]} ) : ",
                default_learn_mask,
                help_message=
                "Learning mask can help model to recognize face directions. Learn without mask can reduce model size, in this case converter forced to use 'not predicted mask' that is not smooth as predicted."
            )
        else:
            self.options['learn_mask'] = self.options.get(
                'learn_mask', default_learn_mask)

        if (is_first_run or
                ask_override) and 'tensorflow' in self.device_config.backend:
            def_optimizer_mode = self.options.get('optimizer_mode', 1)
            self.options['optimizer_mode'] = io.input_int(
                "Optimizer mode? ( 1,2,3 ?:help skip:%d) : " %
                (def_optimizer_mode),
                def_optimizer_mode,
                help_message=
                "1 - no changes. 2 - allows you to train x2 bigger network consuming RAM. 3 - allows you to train x3 bigger network consuming huge amount of RAM and slower, depends on CPU power."
            )
        else:
            self.options['optimizer_mode'] = self.options.get(
                'optimizer_mode', 1)

        if is_first_run:
            self.options['archi'] = io.input_str(
                "AE architecture (df, liae ?:help skip:%s) : " %
                (default_archi),
                default_archi, ['df', 'liae'],
                help_message=
                "'df' keeps faces more natural. 'liae' can fix overly different face shapes."
            ).lower(
            )  #-s version is slower, but has decreased change to collapse.
        else:
            self.options['archi'] = self.options.get('archi', default_archi)

        default_ae_dims = 256
        default_ed_ch_dims = 21

        if is_first_run:
            self.options['ae_dims'] = np.clip(
                io.input_int(
                    "AutoEncoder dims (32-1024 ?:help skip:%d) : " %
                    (default_ae_dims),
                    default_ae_dims,
                    help_message=
                    "All face information will packed to AE dims. If amount of AE dims are not enough, then for example closed eyes will not be recognized. More dims are better, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 32, 1024)
            self.options['ed_ch_dims'] = np.clip(
                io.input_int(
                    "Encoder/Decoder dims per channel (10-85 ?:help skip:%d) : "
                    % (default_ed_ch_dims),
                    default_ed_ch_dims,
                    help_message=
                    "More dims help to recognize more facial features and achieve sharper result, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 10, 85)
        else:
            self.options['ae_dims'] = self.options.get('ae_dims',
                                                       default_ae_dims)
            self.options['ed_ch_dims'] = self.options.get(
                'ed_ch_dims', default_ed_ch_dims)

        default_true_face_training = self.options.get('true_face_training',
                                                      False)
        default_face_style_power = self.options.get('face_style_power', 0.0)
        default_bg_style_power = self.options.get('bg_style_power', 0.0)

        if is_first_run or ask_override:
            default_random_warp = self.options.get('random_warp', True)
            self.options['random_warp'] = io.input_bool(
                f"Enable random warp of samples? ( y/n, ?:help skip:{yn_str[default_random_warp]}) : ",
                default_random_warp,
                help_message=
                "Random warp is required to generalize facial expressions of both faces. When the face is trained enough, you can disable it to get extra sharpness for less amount of iterations."
            )

            self.options['true_face_training'] = io.input_bool(
                f"Enable 'true face' training? (y/n, ?:help skip:{yn_str[default_true_face_training]}) : ",
                default_true_face_training,
                help_message=
                "The result face will be more like src and will get extra sharpness. Enable it for last 10-20k iterations before conversion."
            )

            self.options['face_style_power'] = np.clip(
                io.input_number(
                    "Face style power ( 0.0 .. 100.0 ?:help skip:%.2f) : " %
                    (default_face_style_power),
                    default_face_style_power,
                    help_message=
                    "Learn to transfer face style details such as light and color conditions. Warning: Enable it only after 10k iters, when predicted face is clear enough to start learn style. Start from 0.1 value and check history changes. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            self.options['bg_style_power'] = np.clip(
                io.input_number(
                    "Background style power ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_bg_style_power),
                    default_bg_style_power,
                    help_message=
                    "Learn to transfer image around face. This can make face more like dst. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            default_ct_mode = self.options.get('ct_mode', 'none')
            self.options['ct_mode'] = io.input_str(
                f"Color transfer mode apply to src faceset. ( none/rct/lct/mkl/idt, ?:help skip:{default_ct_mode}) : ",
                default_ct_mode, ['none', 'rct', 'lct', 'mkl', 'idt'],
                help_message=
                "Change color distribution of src samples close to dst samples. Try all modes to find the best."
            )

            if nnlib.device.backend != 'plaidML':  # todo https://github.com/plaidml/plaidml/issues/301
                default_clipgrad = False if is_first_run else self.options.get(
                    'clipgrad', False)
                self.options['clipgrad'] = io.input_bool(
                    f"Enable gradient clipping? (y/n, ?:help skip:{yn_str[default_clipgrad]}) : ",
                    default_clipgrad,
                    help_message=
                    "Gradient clipping reduces chance of model collapse, sacrificing speed of training."
                )
            else:
                self.options['clipgrad'] = False

        else:
            self.options['random_warp'] = self.options.get('random_warp', True)
            self.options['true_face_training'] = self.options.get(
                'true_face_training', default_true_face_training)
            self.options['face_style_power'] = self.options.get(
                'face_style_power', default_face_style_power)
            self.options['bg_style_power'] = self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['ct_mode'] = self.options.get('ct_mode', 'none')
            self.options['clipgrad'] = self.options.get('clipgrad', False)

        if is_first_run:
            self.options['pretrain'] = io.input_bool(
                "Pretrain the model? (y/n, ?:help skip:n) : ",
                False,
                help_message=
                "Pretrain the model with large amount of various faces. This technique may help to train the fake with overly different face shapes and light conditions of src/dst data. Face will be look more like a morphed. To reduce the morph effect, some model files will be initialized but not be updated after pretrain: LIAE: inter_AB.h5 DF: encoder.h5. The longer you pretrain the model the more morphed face will look. After that, save and run the training again."
            )
        else:
            self.options['pretrain'] = False
Example #3
0
    def onInitializeOptions(self, is_first_run, ask_override):
        yn_str = {True: 'y', False: 'n'}

        default_resolution = 128
        default_archi = 'df'
        default_face_type = 'f'

        if is_first_run:
            resolution = io.input_int(
                "Resolution ( 16-1024 ?:help skip:128) : ",
                default_resolution,
                help_message=
                "More resolution requires more VRAM and time to train. Value will be adjusted to multiple of 16."
            )
            resolution = np.clip(resolution, 16, 1024)
            while np.modf(resolution / 16)[0] != 0.0:
                resolution -= 1
            self.options['resolution'] = resolution

            self.options['face_type'] = io.input_str(
                "Half or Full face? (h/f, ?:help skip:f) : ",
                default_face_type, ['h', 'f'],
                help_message=
                "Half face has better resolution, but covers less area of cheeks."
            ).lower()
        else:
            self.options['resolution'] = self.options.get(
                'resolution', default_resolution)
            self.options['face_type'] = self.options.get(
                'face_type', default_face_type)

        if is_first_run or ask_override:
            default_learn_mask = self.options.get('learn_mask', True)
            self.options['learn_mask'] = io.input_bool(
                f'Learn mask? (y/n, ?:help skip:{yn_str[default_learn_mask]}) : ',
                default_learn_mask,
                help_message=
                "Learning mask can help model to recognize face directions. Learn without mask can reduce "
                "model size, in this case converter forced to use 'not predicted mask' that is not smooth "
                "as predicted. Model with style values can be learned without mask and produce same "
                "quality result.")

        if (is_first_run or
                ask_override) and 'tensorflow' in self.device_config.backend:
            def_optimizer_mode = self.options.get('optimizer_mode', 1)
            self.options['optimizer_mode'] = io.input_int(
                "Optimizer mode? ( 1,2,3 ?:help skip:%d) : " %
                (def_optimizer_mode),
                def_optimizer_mode,
                help_message=
                "1 - no changes. 2 - allows you to train x2 bigger network consuming RAM. 3 - allows you to train x3 bigger network consuming huge amount of RAM and slower, depends on CPU power."
            )
        else:
            self.options['optimizer_mode'] = self.options.get(
                'optimizer_mode', 1)

        if is_first_run:
            self.options['archi'] = io.input_str(
                "AE architecture (df, liae ?:help skip:%s) : " %
                (default_archi),
                default_archi, ['df', 'liae'],
                help_message=
                "'df' keeps faces more natural. 'liae' can fix overly different face shapes."
            ).lower(
            )  # -s version is slower, but has decreased change to collapse.
        else:
            self.options['archi'] = self.options.get('archi', default_archi)

        default_ae_dims = 256 if 'liae' in self.options['archi'] else 512
        default_e_ch_dims = 42
        default_d_ch_dims = default_e_ch_dims // 2
        def_ca_weights = False

        if is_first_run:
            self.options['ae_dims'] = np.clip(
                io.input_int(
                    "AutoEncoder dims (1-2048 ?:help skip:%d) : " %
                    (default_ae_dims),
                    default_ae_dims,
                    help_message=
                    "All face information will packed to AE dims. If amount of AE dims are not enough, then for example closed eyes will not be recognized. More dims are better, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 1, 2048)
            self.options['e_ch_dims'] = np.clip(
                io.input_int(
                    "Encoder dims per channel (1-128 ?:help skip:%d) : " %
                    (default_e_ch_dims),
                    default_e_ch_dims,
                    help_message=
                    "More encoder dims help to recognize more facial features, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 1, 128)
            default_d_ch_dims = self.options['e_ch_dims'] // 2
            self.options['d_ch_dims'] = np.clip(
                io.input_int(
                    "Decoder dims per channel (1-128 ?:help skip:%d) : " %
                    (default_d_ch_dims),
                    default_d_ch_dims,
                    help_message=
                    "More decoder dims help to get better details, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 1, 128)
            self.options['multiscale_decoder'] = io.input_bool(
                "Use multiscale decoder? (y/n, ?:help skip:n) : ",
                False,
                help_message="Multiscale decoder helps to get better details.")
            self.options['ca_weights'] = io.input_bool(
                "Use CA weights? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_ca_weights]),
                def_ca_weights,
                help_message=
                "Initialize network with 'Convolution Aware' weights. This may help to achieve a higher accuracy model, but consumes a time at first run."
            )
        else:
            self.options['ae_dims'] = self.options.get('ae_dims',
                                                       default_ae_dims)
            self.options['e_ch_dims'] = self.options.get(
                'e_ch_dims', default_e_ch_dims)
            self.options['d_ch_dims'] = self.options.get(
                'd_ch_dims', default_d_ch_dims)
            self.options['multiscale_decoder'] = self.options.get(
                'multiscale_decoder', False)
            self.options['ca_weights'] = self.options.get(
                'ca_weights', def_ca_weights)

        default_face_style_power = 0.0
        default_bg_style_power = 0.0
        if is_first_run or ask_override:
            def_pixel_loss = self.options.get('pixel_loss', False)
            self.options['pixel_loss'] = io.input_bool(
                "Use pixel loss? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_pixel_loss]),
                def_pixel_loss,
                help_message=
                "Pixel loss may help to enhance fine details and stabilize face color. Use it only if quality does not improve over time. Enabling this option too early increases the chance of model collapse."
            )

            default_face_style_power = default_face_style_power if is_first_run else self.options.get(
                'face_style_power', default_face_style_power)
            self.options['face_style_power'] = np.clip(
                io.input_number(
                    "Face style power ( 0.0 .. 100.0 ?:help skip:%.2f) : " %
                    (default_face_style_power),
                    default_face_style_power,
                    help_message=
                    "Learn to transfer face style details such as light and color conditions. Warning: Enable it only after 10k iters, when predicted face is clear enough to start learn style. Start from 0.1 value and check history changes. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            default_bg_style_power = default_bg_style_power if is_first_run else self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['bg_style_power'] = np.clip(
                io.input_number(
                    "Background style power ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_bg_style_power),
                    default_bg_style_power,
                    help_message=
                    "Learn to transfer image around face. This can make face more like dst. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            default_apply_random_ct = ColorTransferMode.NONE if is_first_run else self.options.get(
                'apply_random_ct', ColorTransferMode.NONE)
            self.options['apply_random_ct'] = np.clip(
                io.input_int(
                    "Apply random color transfer to src faceset? (0) None, (1) LCT, (2) RCT, (3) RCT-c, (4) RCT-p, "
                    "(5) RCT-pc, (6) mRTC, (7) mRTC-c, (8) mRTC-p, (9) mRTC-pc ?:help skip:%s) : "
                    % default_apply_random_ct,
                    default_apply_random_ct,
                    help_message=
                    "Increase variativity of src samples by apply LCT color transfer from random dst "
                    "samples. It is like 'face_style' learning, but more precise color transfer and without "
                    "risk of model collapse, also it does not require additional GPU resources, "
                    "but the training time may be longer, due to the src faceset is becoming more diverse."
                ), ColorTransferMode.NONE,
                ColorTransferMode.MASKED_RCT_PAPER_CLIP)

            default_random_color_change = False if is_first_run else self.options.get(
                'random_color_change', False)
            self.options['random_color_change'] = io.input_bool(
                "Enable random color change? (y/n, ?:help skip:%s) : " %
                (yn_str[default_random_color_change]),
                default_random_color_change,
                help_message="")

            if nnlib.device.backend != 'plaidML':  # todo https://github.com/plaidml/plaidml/issues/301
                default_clipgrad = False if is_first_run else self.options.get(
                    'clipgrad', False)
                self.options['clipgrad'] = io.input_bool(
                    "Enable gradient clipping? (y/n, ?:help skip:%s) : " %
                    (yn_str[default_clipgrad]),
                    default_clipgrad,
                    help_message=
                    "Gradient clipping reduces chance of model collapse, sacrificing speed of training."
                )
            else:
                self.options['clipgrad'] = False

            self.options['pretrain'] = io.input_bool(
                "Pretrain the model? (y/n, ?:help skip:n) : ",
                False,
                help_message="Pretrain the model with large amount of various "
                "faces. This technique may help to train the fake "
                "with overly different face shapes and light "
                "conditions of src/dst data. Face will be look more "
                "like a morphed. To reduce the morph effect, "
                "some model files will be initialized but not be "
                "updated after pretrain: LIAE: inter_AB.h5 DF: "
                "encoder.h5. The longer you pretrain the model the "
                "more morphed face will look. After that, "
                "save and run the training again.")

        else:
            self.options['pixel_loss'] = self.options.get('pixel_loss', False)
            self.options['face_style_power'] = self.options.get(
                'face_style_power', default_face_style_power)
            self.options['bg_style_power'] = self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['apply_random_ct'] = self.options.get(
                'apply_random_ct', ColorTransferMode.NONE)
            self.options['clipgrad'] = self.options.get('clipgrad', False)
            self.options['random_color_change'] = self.options.get(
                'random_color_change', False)
            self.options['pretrain'] = self.options.get('pretrain', False)
Example #4
0
    def onInitializeOptions(self, is_first_run, ask_override):
        yn_str = {True: 'y', False: 'n'}

        default_resolution = 128
        default_archi = 'df'
        default_face_type = 'f'

        if is_first_run:
            resolution = io.input_int(
                "Resolution ( 64-256 ?:help skip:128) : ",
                default_resolution,
                help_message=
                "More resolution requires more VRAM and time to train. Value will be adjusted to multiple of 16."
            )
            resolution = np.clip(resolution, 64, 256)
            while np.modf(resolution / 16)[0] != 0.0:
                resolution -= 1
            self.options['resolution'] = resolution

            self.options['face_type'] = io.input_str(
                "Half or Full face? (h/f, ?:help skip:f) : ",
                default_face_type, ['h', 'f'],
                help_message=
                "Half face has better resolution, but covers less area of cheeks."
            ).lower()
            self.options['learn_mask'] = io.input_bool(
                "Learn mask? (y/n, ?:help skip:y) : ",
                True,
                help_message=
                "Learning mask can help model to recognize face directions. Learn without mask can reduce model size, in this case converter forced to use 'not predicted mask' that is not smooth as predicted. Model with style values can be learned without mask and produce same quality result."
            )
        else:
            self.options['resolution'] = self.options.get(
                'resolution', default_resolution)
            self.options['face_type'] = self.options.get(
                'face_type', default_face_type)
            self.options['learn_mask'] = self.options.get('learn_mask', True)

        if (is_first_run or
                ask_override) and 'tensorflow' in self.device_config.backend:
            def_optimizer_mode = self.options.get('optimizer_mode', 1)
            self.options['optimizer_mode'] = io.input_int(
                "Optimizer mode? ( 1,2,3 ?:help skip:%d) : " %
                (def_optimizer_mode),
                def_optimizer_mode,
                help_message=
                "1 - no changes. 2 - allows you to train x2 bigger network consuming RAM. 3 - allows you to train x3 bigger network consuming huge amount of RAM and slower, depends on CPU power."
            )
        else:
            self.options['optimizer_mode'] = self.options.get(
                'optimizer_mode', 1)

        if is_first_run:
            self.options['archi'] = io.input_str(
                "AE architecture (df, liae ?:help skip:%s) : " %
                (default_archi),
                default_archi, ['df', 'liae'],
                help_message=
                "'df' keeps faces more natural. 'liae' can fix overly different face shapes."
            ).lower()
        else:
            self.options['archi'] = self.options.get('archi', default_archi)

        default_ae_dims = 256 if self.options['archi'] == 'liae' else 512
        default_e_ch_dims = 42
        default_d_ch_dims = default_e_ch_dims // 2

        if is_first_run:
            self.options['ae_dims'] = np.clip(
                io.input_int(
                    "AutoEncoder dims (32-1024 ?:help skip:%d) : " %
                    (default_ae_dims),
                    default_ae_dims,
                    help_message=
                    "All face information will packed to AE dims. If amount of AE dims are not enough, then for example closed eyes will not be recognized. More dims are better, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 32, 1024)
            self.options['e_ch_dims'] = np.clip(
                io.input_int(
                    "Encoder dims per channel (21-85 ?:help skip:%d) : " %
                    (default_e_ch_dims),
                    default_e_ch_dims,
                    help_message=
                    "More encoder dims help to recognize more facial features, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 21, 85)
            default_d_ch_dims = self.options['e_ch_dims'] // 2
            self.options['d_ch_dims'] = np.clip(
                io.input_int(
                    "Decoder dims per channel (10-85 ?:help skip:%d) : " %
                    (default_d_ch_dims),
                    default_d_ch_dims,
                    help_message=
                    "More decoder dims help to get better details, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 10, 85)
            self.options['remove_gray_border'] = io.input_bool(
                "Remove gray border? (y/n, ?:help skip:n) : ",
                False,
                help_message=
                "Removes gray border of predicted face, but requires more computing resources."
            )
        else:
            self.options['ae_dims'] = self.options.get('ae_dims',
                                                       default_ae_dims)
            self.options['e_ch_dims'] = self.options.get(
                'e_ch_dims', default_e_ch_dims)
            self.options['d_ch_dims'] = self.options.get(
                'd_ch_dims', default_d_ch_dims)
            self.options['remove_gray_border'] = self.options.get(
                'remove_gray_border', False)

        if is_first_run:
            self.options['multiscale_decoder'] = io.input_bool(
                "Use multiscale decoder? (y/n, ?:help skip:n) : ",
                False,
                help_message="Multiscale decoder helps to get better details.")
        else:
            self.options['multiscale_decoder'] = self.options.get(
                'multiscale_decoder', False)

        default_face_style_power = 0.0
        default_bg_style_power = 0.0
        if is_first_run or ask_override:
            def_pixel_loss = self.options.get('pixel_loss', False)
            self.options['pixel_loss'] = io.input_bool(
                "Use pixel loss? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_pixel_loss]),
                def_pixel_loss,
                help_message=
                "Pixel loss may help to enhance fine details and stabilize face color. Use it only if quality does not improve over time."
            )

            default_face_style_power = default_face_style_power if is_first_run else self.options.get(
                'face_style_power', default_face_style_power)
            self.options['face_style_power'] = np.clip(
                io.input_number(
                    "Face style power ( 0.0 .. 100.0 ?:help skip:%.2f) : " %
                    (default_face_style_power),
                    default_face_style_power,
                    help_message=
                    "Learn to transfer face style details such as light and color conditions. Warning: Enable it only after 10k iters, when predicted face is clear enough to start learn style. Start from 0.1 value and check history changes."
                ), 0.0, 100.0)

            default_bg_style_power = default_bg_style_power if is_first_run else self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['bg_style_power'] = np.clip(
                io.input_number(
                    "Background style power ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_bg_style_power),
                    default_bg_style_power,
                    help_message=
                    "Learn to transfer image around face. This can make face more like dst."
                ), 0.0, 100.0)
        else:
            self.options['pixel_loss'] = self.options.get('pixel_loss', False)
            self.options['face_style_power'] = self.options.get(
                'face_style_power', default_face_style_power)
            self.options['bg_style_power'] = self.options.get(
                'bg_style_power', default_bg_style_power)
Example #5
0
    def onInitializeOptions(self, is_first_run, ask_override):
        yn_str = {True: 'y', False: 'n'}

        default_resolution = 128
        default_archi = 'df'
        default_face_type = 'f'

        if is_first_run:
            resolution = io.input_int(
                "像素[Resolution=]( 64-256 ?:help skip:128) : ",
                default_resolution,
                help_message="更高的分辨率需要更多的VRAM和训练时间。取值为16的倍数.")
            resolution = np.clip(resolution, 64, 256)
            while np.modf(resolution / 16)[0] != 0.0:
                resolution -= 1
            self.options['resolution'] = resolution

            self.options['face_type'] = io.input_str(
                "全脸还是半脸[Half or Full face]? (h/f, ?:help skip:f) : ",
                default_face_type, ['h', 'f'],
                help_message=
                "Half face has better resolution, but covers less area of cheeks."
            ).lower()
            self.options['learn_mask'] = io.input_bool(
                "Learn mask? (y/n, ?:help skip:y) : ",
                True,
                help_message=
                "Learning mask can help model to recognize face directions. Learn without mask can reduce model size, in this case converter forced to use 'not predicted mask' that is not smooth as predicted. Model with style values can be learned without mask and produce same quality result."
            )
        else:
            self.options['resolution'] = self.options.get(
                'resolution', default_resolution)
            self.options['face_type'] = self.options.get(
                'face_type', default_face_type)
            self.options['learn_mask'] = self.options.get('learn_mask', True)

        if (is_first_run or
                ask_override) and 'tensorflow' in self.device_config.backend:
            def_optimizer_mode = self.options.get('optimizer_mode', 1)
            self.options['optimizer_mode'] = io.input_int(
                "优化模式[Optimizer mode]? ( 1,2,3 ?:help skip:%d) : " %
                (def_optimizer_mode),
                def_optimizer_mode,
                help_message=
                "1 - no changes. 2 - allows you to train x2 bigger network consuming RAM. 3 - allows you to train x3 bigger network consuming huge amount of RAM and slower, depends on CPU power."
            )
        else:
            self.options['optimizer_mode'] = self.options.get(
                'optimizer_mode', 1)

        if is_first_run:
            self.options['archi'] = io.input_str(
                "模型结构[AE architecture] (df, liae ?:help skip:%s) : " %
                (default_archi),
                default_archi, ['df', 'liae'],
                help_message=
                "'df' keeps faces more natural. 'liae' can fix overly different face shapes."
            ).lower(
            )  #-s version is slower, but has decreased change to collapse.
        else:
            self.options['archi'] = self.options.get('archi', default_archi)

        default_ae_dims = 256 if 'liae' in self.options['archi'] else 512
        default_e_ch_dims = 42
        default_d_ch_dims = default_e_ch_dims // 2
        def_ca_weights = False

        if is_first_run:
            self.options['ae_dims'] = np.clip(
                io.input_int(
                    "自动编码器维度[AutoEncoder dims] (32-1024 ?:help skip:%d) : " %
                    (default_ae_dims),
                    default_ae_dims,
                    help_message=
                    "All face information will packed to AE dims. If amount of AE dims are not enough, then for example closed eyes will not be recognized. More dims are better, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 32, 1024)
            self.options['e_ch_dims'] = np.clip(
                io.input_int(
                    "每个通道编码器维度 [Encoder dims per channel] (21-85 ?:help skip:%d) : "
                    % (default_e_ch_dims),
                    default_e_ch_dims,
                    help_message=
                    "More encoder dims help to recognize more facial features, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 21, 85)
            default_d_ch_dims = self.options['e_ch_dims'] // 2
            self.options['d_ch_dims'] = np.clip(
                io.input_int(
                    "每个通道解码器维度 [Decoder dims per channel] (10-85 ?:help skip:%d) : "
                    % (default_d_ch_dims),
                    default_d_ch_dims,
                    help_message=
                    "More decoder dims help to get better details, but require more VRAM. You can fine-tune model size to fit your GPU."
                ), 10, 85)
            self.options['multiscale_decoder'] = io.input_bool(
                "使用多尺度解码器 [Use multiscale decoder]? (y/n, ?:help skip:n) : ",
                False,
                help_message="Multiscale decoder helps to get better details.")
            self.options['ca_weights'] = io.input_bool(
                "使用CA权重[Use CA weights]? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_ca_weights]),
                def_ca_weights,
                help_message=
                "Initialize network with 'Convolution Aware' weights. This may help to achieve a higher accuracy model, but consumes a time at first run."
            )
        else:
            self.options['ae_dims'] = self.options.get('ae_dims',
                                                       default_ae_dims)
            self.options['e_ch_dims'] = self.options.get(
                'e_ch_dims', default_e_ch_dims)
            self.options['d_ch_dims'] = self.options.get(
                'd_ch_dims', default_d_ch_dims)
            self.options['multiscale_decoder'] = self.options.get(
                'multiscale_decoder', False)
            self.options['ca_weights'] = self.options.get(
                'ca_weights', def_ca_weights)

        default_face_style_power = 0.0
        default_bg_style_power = 0.0
        if is_first_run or ask_override:
            def_pixel_loss = self.options.get('pixel_loss', False)
            self.options['pixel_loss'] = io.input_bool(
                "使用像素丢失[pixel loss]? (y/n, ?:help skip: %s ) : " %
                (yn_str[def_pixel_loss]),
                def_pixel_loss,
                help_message="像素丢失可能有助于增强细节和稳定面部颜色。 仅在质量不随时间改善时使用。")

            default_face_style_power = default_face_style_power if is_first_run else self.options.get(
                'face_style_power', default_face_style_power)
            self.options['face_style_power'] = np.clip(
                io.input_number(
                    "脸部风格强度[Face style power] ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_face_style_power),
                    default_face_style_power,
                    help_message=
                    "Learn to transfer face style details such as light and color conditions. Warning: Enable it only after 10k iters, when predicted face is clear enough to start learn style. Start from 0.1 value and check history changes. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            default_bg_style_power = default_bg_style_power if is_first_run else self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['bg_style_power'] = np.clip(
                io.input_number(
                    "背景风格强度[Background style power] ( 0.0 .. 100.0 ?:help skip:%.2f) : "
                    % (default_bg_style_power),
                    default_bg_style_power,
                    help_message=
                    "Learn to transfer image around face. This can make face more like dst. Enabling this option increases the chance of model collapse."
                ), 0.0, 100.0)

            default_apply_random_ct = False if is_first_run else self.options.get(
                'apply_random_ct', False)
            self.options['apply_random_ct'] = io.input_bool(
                "随机颜色[Apply random color transfer to src faceset]? (y/n, ?:help skip:%s) : "
                % (yn_str[default_apply_random_ct]),
                default_apply_random_ct,
                help_message=
                "Increase variativity of src samples by apply LCT color transfer from random dst samples. It is like 'face_style' learning, but more precise color transfer and without risk of model collapse, also it does not require additional GPU resources, but the training time may be longer, due to the src faceset is becoming more diverse."
            )

            if nnlib.device.backend != 'plaidML':  # todo https://github.com/plaidml/plaidml/issues/301
                default_clipgrad = False if is_first_run else self.options.get(
                    'clipgrad', False)
                self.options['clipgrad'] = io.input_bool(
                    "启用渐变剪裁[Enable gradient clipping]? (y/n, ?:help skip:%s) : "
                    % (yn_str[default_clipgrad]),
                    default_clipgrad,
                    help_message=
                    "Gradient clipping reduces chance of model collapse, sacrificing speed of training."
                )
            else:
                self.options['clipgrad'] = False

        else:
            self.options['pixel_loss'] = self.options.get('pixel_loss', False)
            self.options['face_style_power'] = self.options.get(
                'face_style_power', default_face_style_power)
            self.options['bg_style_power'] = self.options.get(
                'bg_style_power', default_bg_style_power)
            self.options['apply_random_ct'] = self.options.get(
                'apply_random_ct', False)
            self.options['clipgrad'] = self.options.get('clipgrad', False)

        if is_first_run:
            self.options['pretrain'] = io.input_bool(
                "模型预训练[Pretrain the model]? (y/n, ?:help skip:n) : ",
                False,
                help_message=
                "Pretrain the model with large amount of various faces. This technique may help to train the fake with overly different face shapes and light conditions of src/dst data. Face will be look more like a morphed. To reduce the morph effect, some model files will be initialized but not be updated after pretrain: LIAE: inter_AB.h5 DF: encoder.h5. The longer you pretrain the model the more morphed face will look. After that, save and run the training again."
            )
        else:
            self.options['pretrain'] = False