Gourieff / sd-webui-reactor

Fast and Simple Face Swap Extension for StableDiffusion WebUI (A1111 SD WebUI, SD WebUI Forge, SD.Next, Cagliostro)
GNU Affero General Public License v3.0
2.46k stars 263 forks source link

X/Y/Z Plot keeps wrong model in shared.opt.data in sd-forge #444

Open CrunchyBanana1 opened 4 months ago

CrunchyBanana1 commented 4 months ago

First, confirm

What happened?

It seems like using X/Y/Z plot is writing the last model name into opt.data and never clears it after closing the X/Y/Z Script. So when generating without X/Y/Z Plot afterwards, it always picks your last used face model from your last run with X/Y/Z Plot.

I'm sorry, but my Python is extremely bad and I had no idea how to clear it automatically, but I hope you see my point when looking at my trashy code. I temporarily helped myself by adding another AxisOption that simply deletes the 'Face_Model' value from opt.data

xyz_grid.AxisOption("[ReActor] No XYZ", str, str_deleter("face_model"), choices=choices_face_models),

with

def str_deleter(value_name:str):
    def remove_str(p, x, xs):
        del opts.data[value_name]
    return remove_str

and changed the reactor_faceswap.py to

if 'face_model' in shared.opts.data.keys():
                if shared.state.job_count > 0:
                    # logger.debug(f"Job count: {shared.state.job_count}")
                    self.face_restorer_visibility = shared.opts.data['restorer_visibility'] if 'restorer_visibility' in shared.opts.data.keys() else face_restorer_visibility
                    self.codeformer_weight = shared.opts.data['codeformer_weight'] if 'codeformer_weight' in shared.opts.data.keys() else codeformer_weight
                    self.mask_face = shared.opts.data['mask_face'] if 'mask_face' in shared.opts.data.keys() else mask_face
                    self.face_model = shared.opts.data['face_model'] if 'face_model' in shared.opts.data.keys() else face_model

                logger.debug("*** Set Device")
                set_Device(self.device)
            else:
                if shared.state.job_count > 0:
                    # logger.debug(f"Job count: {shared.state.job_count}")
                    self.face_restorer_visibility = face_restorer_visibility
                    self.codeformer_weight = codeformer_weight
                    self.mask_face = mask_face
                    self.face_model = face_model

                logger.debug("*** Set Device")
                set_Device(self.device)

I know this is dirty, but it works for now (with one extra step). I'm sorry, I never really used git and I'm pretty sure there's a way more elegant way to do it than this.

The same problem persists for the other values stored by the X/Y/Z Script (codeformer_weight, restorer_visibility and mask_face), too.

If I'm missing something obvious, at least it was a nice little trip into python for me :)

Steps to reproduce the problem

  1. Run with X/Y/Z Plot and a face model selected on one axis
  2. Run without X/Y/Z Plot with another face model selected in ReActor
  3. ReActor picks the model from step 1

Relevant console log

X/Y/Z plot will create 1 images on 1 1x1 grid. (Total steps to process: 10)████████████| 10/10 [00:02<00:00, 26.55it/s]
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 24.20it/s]
Total progress:  90%|████████████████████████████████████████████████████████████▎      | 9/10 [00:00<00:00, 24.76it/s]
0: 640x640 1 face, 7.0ms
Speed: 3.0ms preprocess, 7.0ms inference, 1.0ms postprocess per image at shape (1, 3, 640, 640)
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 24.73it/s]
00:15:25 - ReActor - STATUS - Working: source face index [0], target face index [0]
00:15:25 - ReActor - STATUS - Using Loaded Source Face Model: test1.safetensors
00:15:25 - ReActor - STATUS - Analyzing Target Image...
00:15:26 - ReActor - STATUS - Detecting Source Face, Index = 0
00:15:26 - ReActor - STATUS - Detected: -38- y.o. Male
00:15:26 - ReActor - STATUS - Detecting Target Face, Index = 0
00:15:26 - ReActor - STATUS - Detected: -33- y.o. Male
00:15:26 - ReActor - STATUS - Swapping Source into Target
00:15:26 - ReActor - STATUS - Restoring the face with CodeFormer (weight: 0.5)
Cleanup minimal inference memory.
Total progress: 100%|██████████████████████████████████████████████████████████████████| 10/10 [00:02<00:00,  4.24it/s]
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 23.76it/s]
Total progress:  80%|█████████████████████████████████████████████████████▌             | 8/10 [00:00<00:00, 26.25it/s]
0: 640x640 1 face, 5.0ms
Speed: 2.0ms preprocess, 5.0ms inference, 1.0ms postprocess per image at shape (1, 3, 640, 640)
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 24.34it/s]
00:15:38 - ReActor - STATUS - Working: source face index [0], target face index [0]
00:15:38 - ReActor - STATUS - Using Loaded Source Face Model: test1.safetensors
00:15:38 - ReActor - STATUS - Analyzing Target Image...
00:15:39 - ReActor - STATUS - Detecting Source Face, Index = 0
00:15:39 - ReActor - STATUS - Detected: -38- y.o. Male
00:15:39 - ReActor - STATUS - Detecting Target Face, Index = 0
00:15:39 - ReActor - STATUS - Detected: -33- y.o. Male
00:15:39 - ReActor - STATUS - Swapping Source into Target
00:15:39 - ReActor - STATUS - Restoring the face with CodeFormer (weight: 0.5)
Cleanup minimal inference memory.
Total progress: 100%|██████████████████████████████████████████████████████████████████| 10/10 [00:02<00:00,  4.45it/s]
Total progress: 100%|██████████████████████████████████████████████████████████████████| 10/10 [00:02<00:00, 26.25it/s]

Additional information

No response

Gourieff commented 4 months ago

I've just tested and cannot reproduce your bug, ReActor works fine

image

All the faces swapped according to the loaded models

CrunchyBanana1 commented 4 months ago

Ok thats weird. But I see you're using A1111 and not forge. So maybe it's a problem with their implementation of the XYZ Script?

The last used model is even kept (and used) from opt.data after a restart.

stargatemaster commented 3 months ago

I am having the same issue. The issue doesn't appear when using txt2img or img2img. It only appears when I'm using the mov2mov extension as far as I'm aware.

CrunchyBanana1 commented 3 months ago

The user in #454 seemed to have a similar problem, but this time in A1111

Can I do anything to help you narrow it down further?