diff --git a/README.md b/README.md index df8b848..cb37f07 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Roop-GE* 0.2.4b for StableDiffusion -### NSFW (uncensored) version (use it on your own responsibility) of [original sd-webui-roop](https://github.com/s0md3v/sd-webui-roop) with a lot of improvements +# ReActor 0.3.0 for StableDiffusion +### The Fast and Simple "[roop-based](https://github.com/s0md3v/sd-webui-roop)" FaceSwap Extension with a lot of improvements and without NSFW filter (uncensored, use it on your own responsibility) -> *Will be renamed soon! Stay tuned! (GE - Gourieff Edition, aka "NSFW-Roop") +> Ex "Roop-GE" (GE - Gourieff Edition, aka "NSFW-Roop"), the extension was renamed with the version 0.3.0 --- -[**Disclaimer**](#disclaimer) | [**Installation**](#installation) | [**Usage**](#usage) | [**Troubleshooting**](#troubleshooting) | [**Updating**](#updating) +[**Disclaimer**](#disclaimer) | [**Installation**](#installation) | [**Usage**](#usage) | [**Troubleshooting**](#troubleshooting) | [**Updating**](#updating) | [**ComfyUI**](#comfyui) --- @@ -35,8 +35,8 @@ Users of this software are expected to use this software responsibly while abidi 2. In web-ui, go to the "Extensions" tab and use this URL `https://github.com/Gourieff/sd-webui-roop-nsfw` in the "Install from URL" tab and click "Install" 3. Please, wait for several minutes until the installation process will be finished 4. Check the last message in your SD-WebUI Console: -* If you see the message "--- PLEASE, RESTART the Server! ---" - so, do it, stop the Server (CTRL+C) and start it again. -* If you see the message "Done!", just go to the "Installed" tab (*if you have any other Roop extension enabled - disable it, otherwise this extension won't work*), click "Apply and restart UI" +* If you see the message "--- PLEASE, RESTART the Server! ---" - so, do it, stop the Server (CTRL+C or CMD+C) and start it again - or just go to the "Installed" tab (*if you have any other Roop-based extension enabled - disable it, otherwise this extension won't work*), click "Apply and restart UI" +* If you see the message "Done!", just go to the "Installed" tab (*if you have any other Roop-based extension enabled - disable it, otherwise this extension won't work*), click "Apply and restart UI" - or you can just simply reload the UI 5. Enjoy! If you use [SD.Next](https://github.com/vladmandic/automatic): @@ -47,28 +47,29 @@ Users of this software are expected to use this software responsibly while abidi 4. Run SD.Next, go to the "Extensions" tab and use this URL `https://github.com/Gourieff/sd-webui-roop-nsfw` in the "Install from URL" tab and click "Install" 5. Please, wait for several minutes until the installation process will be finished 6. Check the last message in your SD.Next Console: -* If you see the message "--- PLEASE, RESTART the Server! ---" - so, do it, stop the Server (CTRL+C) and start it again. -* If you see the message "Done!", just go to the "Installed" tab (*if you have any other Roop extension enabled - disable it, otherwise this extension won't work*), click "Restart the UI" +* If you see the message "--- PLEASE, RESTART the Server! ---" - so, do it, stop the Server (CTRL+C or CMD+C) and start it again - or just go to the "Installed" tab (*if you have any other Roop-based extension enabled - disable it, otherwise this extension won't work*), click "Restart the UI" 7. Stop SD.Next, go to the `automatic\extensions\sd-webui-roop-nsfw` directory - if you see there `models\roop` folder with the file `inswapper_128.onnx`, just move the file to the `automatic\models\roop` folder 8. Run your SD.Next WebUI and enjoy! If you use [Cagliostro Colab UI](https://github.com/Linaqruf/sd-notebook-collection): -1. In active web-ui, go to the "Extensions" tab and use this URL `https://github.com/Gourieff/sd-webui-roop-nsfw` in the "Install from URL" tab and click "Install" +1. In active WebUI, go to the "Extensions" tab and use this URL `https://github.com/Gourieff/sd-webui-roop-nsfw` in the "Install from URL" tab and click "Install" 2. Please, wait for several minutes until the installation process will be finished -3. When you see the message "--- PLEASE, RESTART the Server! ---" in your Colab Notebook Start UI section ("Start Cagliostro Colab UI") - just go to the "Installed" tab and click "Apply and restart UI" (*if you have any other Roop extension enabled - disable it before restart, otherwise this extension won't work*) +3. When you see the message "--- PLEASE, RESTART the Server! ---" (in your Colab Notebook Start UI section "Start Cagliostro Colab UI") - just go to the "Installed" tab and click "Apply and restart UI" (*if you have any other Roop-based extension enabled - disable it before restart, otherwise this extension won't work*) 4. Enjoy! ## Usage -1. Under "Roop-GE" drop-down menu, import an image containing a face; +1. Under "ReActor" drop-down menu, import an image containing a face; 2. Turn on the "Enable" checkbox; 3. That's it, now the generated result will have the face you selected. -**You can use Roop-GE with Webui API:** +example + +**You can use ReActor with Webui API:** 1. Check the [SD Web API Wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/API) for how to use API; -2. Call `requests.get(url=f'{address}/sdapi/v1/script-info')` to find the args that Roop-GE needs; -3. Define Roop-GE script args and add like this `"alwayson_scripts": {"roop-ge":{"args":args}}` in the payload; +2. Call `requests.get(url=f'{address}/sdapi/v1/script-info')` to find the args that ReActor needs; +3. Define ReActor script args and add like this `"alwayson_scripts": {"reactor":{"args":args}}` in the payload; 4. Call the API, there's an [full usage example](./example/api_example.py) in example folder. ### The result face is blurry @@ -116,12 +117,12 @@ Please, check the path where "inswapper_128.onnx" model is stored. It must be in - `pip install onnxruntime==1.15.0` - `pip install opencv-python==4.7.0.72` - `pip install tqdm` -7. Type `deactivate`, you can close your Terminal or Console and start your sd-webui, Roop should start OK - if not, welcome to Issues section. +7. Type `deactivate`, you can close your Terminal or Console and start your sd-webui, ReActor should start OK - if not, welcome to Issues section. **III. "TypeError: UpscaleOptions.init() got an unexpected keyword argument 'do_restore_first'"** -First of all - you need to disable any other Roop extensions: -- Go to 'Extensions -> Installed' tab and uncheck any Roop except this one +First of all - you need to disable any other Roop-based extensions: +- Go to 'Extensions -> Installed' tab and uncheck any Roop-based extensions except this one uncompatible-with-other-roop - Click 'Apply and restart UI' @@ -140,8 +141,8 @@ and put it to the `stable-diffusion-webui\models\roop` replacing existing one **VI. "ValueError: This ORT build has ['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider'] enabled"** -1. Go to the `G:\stable-diffusion-webui\venv\lib\site-packages` and see if there are any folders with names start from "~" (for example "~rotobuf"), delete them -2. Go to the `G:\stable-diffusion-webui\venv\Scripts` run CMD there and type `activate` in your Console +1. Go to the `stable-diffusion-webui\venv\lib\site-packages` and see if there are any folders with names start from "~" (for example "~rotobuf"), delete them +2. Go to the `stable-diffusion-webui\venv\Scripts` run CMD there and type `activate` in your Console 3. Then: - `python -m pip install -U pip` - `pip uninstall -y onnx onnxruntime onnxruntime-gpu onnxruntime-silicon` @@ -149,14 +150,14 @@ and put it to the `stable-diffusion-webui\models\roop` replacing existing one **VII. "ImportError: cannot import name 'builder' from 'google.protobuf.internal'"** -1. Go to the `G:\stable-diffusion-webui\venv\lib\site-packages` and see if there are any folders with names start from "~" (for example "~rotobuf"), delete them -2. Go to the `G:\stable-diffusion-webui\venv\Scripts` run CMD there and type `activate` in your Console +1. Go to the `stable-diffusion-webui\venv\lib\site-packages` and see if there are any folders with names start from "~" (for example "~rotobuf"), delete them +2. Go to the `stable-diffusion-webui\venv\Scripts` run CMD there and type `activate` in your Console 3. Then: - `python -m pip install -U pip` - `pip uninstall protobuf` - `pip install protobuf==3.20.3` -If this method doesn't help - there is some other extension that has a higher version of protobuf dependence and sd-webui installs it on startup requirements check +If this method doesn't help - there is some other extension that has a higher version of protobuf dependence and SD WebUI installs it on startup requirements check **VIII. (For Windows users) If you still cannot build Insightface for some reasons or just don't want to install Visual Studio or VS C++ Build Tools - do the following:** @@ -169,3 +170,8 @@ If this method doesn't help - there is some other extension that has a higher ve ## Updating A good and quick way to check for Extensions updates: https://github.com/Gourieff/sd-webui-extensions-updater + +## ComfyUI + +You can use ReActor with ComfyUI +For the installation instruction follow the [ReActor Node repo](https://github.com/Gourieff/comfyui-reactor-node) diff --git a/example/api_example.py b/example/api_example.py index 0b3eac1..8d202e5 100644 --- a/example/api_example.py +++ b/example/api_example.py @@ -20,17 +20,17 @@ img_bytes = io.BytesIO() im.save(img_bytes, format='PNG') img_base64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8') -# Roop-GE arguments: +# ReActor arguments: args=[ img_base64, #0 - True, #1 Enable Roop-GE + True, #1 Enable ReActor '0', #2 Comma separated face number(s) from swap-source image '0', #3 Comma separated face number(s) for target image (result) 'C:\stable-diffusion-webui\models/roop\inswapper_128.onnx', #4 model path 'CodeFormer', #4 Restore Face: None; CodeFormer; GFPGAN 1, #5 Restore visibility value True, #7 Restore face -> Upscale - '4x_NMKD-Superscale-SP_178000_G', #8 Upscaler (type 'None' if doesn't need), see full list here: http://127.0.0.1:7860/sdapi/v1/script-info -> roop-ge -> sec.8 + '4x_NMKD-Superscale-SP_178000_G', #8 Upscaler (type 'None' if doesn't need), see full list here: http://127.0.0.1:7860/sdapi/v1/script-info -> reactor -> sec.8 2, #9 Upscaler scale value 1, #10 Upscaler visibility (if scale = 1) False, #11 Swap in source image @@ -38,7 +38,7 @@ args=[ 1, #13 Console Log Level (0 - min, 1 - med or 2 - max) ] -# The args for roop-ge can be found by +# The args for ReActor can be found by # requests.get(url=f'{address}/sdapi/v1/script-info') prompt = "(8k, best quality, masterpiece, highly detailed:1.1),realistic photo of fantastic happy woman,hairstyle of blonde and red short bob hair,modern clothing,cinematic lightning,film grain,dynamic pose,bokeh,dof" @@ -55,7 +55,7 @@ payload = { "width": 512, "height": 768, "restore_faces": False, - "alwayson_scripts": {"roop-ge":{"args":args}} + "alwayson_scripts": {"reactor":{"args":args}} } try: diff --git a/example/demo_crop.jpg b/example/demo_crop.jpg index 9ba6630..a76dd62 100644 Binary files a/example/demo_crop.jpg and b/example/demo_crop.jpg differ diff --git a/install.py b/install.py index c60b3f0..8f9f599 100644 --- a/install.py +++ b/install.py @@ -35,7 +35,7 @@ def is_installed ( def download(url, path): request = urllib.request.urlopen(url) total = int(request.headers.get('Content-Length', 0)) - with tqdm(total=total, desc='Downloading', unit='B', unit_scale=True, unit_divisor=1024) as progress: + with tqdm(total=total, desc='Downloading...', unit='B', unit_scale=True, unit_divisor=1024) as progress: urllib.request.urlretrieve(url, path, reporthook=lambda count, block_size, total_size: progress.update(block_size)) if not os.path.exists(models_dir): @@ -44,7 +44,7 @@ if not os.path.exists(models_dir): if not os.path.exists(model_path): download(model_url, model_path) -print("Checking Roop-GE requirements...") +print("Checking ReActor (ex Roop-GE) requirements...", end=' ') with open(req_file) as file: install_count = 0 for package in file: @@ -58,9 +58,9 @@ with open(req_file) as file: run_pip(package) except Exception as e: print(e) - print(f"Warning: Failed to install {package}, Roop-GE will not work.") + print(f"\nERROR: Failed to install {package} - ReActor won't start") raise e if install_count > 0: print(f'\n--- PLEASE, RESTART the Server! ---\n') else: - print('Done!') + print('Ok') diff --git a/scripts/faceswap.py b/scripts/faceswap.py index 32e300c..025be5f 100644 --- a/scripts/faceswap.py +++ b/scripts/faceswap.py @@ -13,7 +13,7 @@ from modules.face_restoration import FaceRestoration from scripts.logger import logger from scripts.swapper import UpscaleOptions, swap_face -from scripts.version import version_flag +from scripts.version import version_flag, app_title from scripts.console_log_patch import apply_logging_patch import os @@ -36,16 +36,16 @@ def get_models(): class FaceSwapScript(scripts.Script): def title(self): - return f"Roop-GE" + return f"{app_title}" def show(self, is_img2img): return scripts.AlwaysVisible def ui(self, is_img2img): - with gr.Accordion(f"Roop-GE {version_flag}", open=False): + with gr.Accordion(f"{app_title} (ex Roop-GE)", open=False): with gr.Column(): img = gr.inputs.Image(type="pil") - enable = gr.Checkbox(False, label="Enable", info="The Extension will be renamed to a cool new name in a future update! Stay tuned!") + enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple \"roop-based\" FaceSwap Extension - {version_flag}") with gr.Row(): source_faces_index = gr.Textbox( value="0", @@ -201,10 +201,10 @@ class FaceSwapScript(scripts.Script): if self.source is not None: apply_logging_patch(console_logging_level) if isinstance(p, StableDiffusionProcessingImg2Img) and swap_in_source: - logger.info(f"Roop-GE is enabled, face index %s", self.faces_index) + logger.info(f"Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index) for i in range(len(p.init_images)): - logger.info(f"Swap in source %s", i) + logger.info(f"Swap in %s", i) result = swap_face( self.source, p.init_images[i], @@ -224,6 +224,7 @@ class FaceSwapScript(scripts.Script): def postprocess_image(self, p, script_pp: scripts.PostprocessImageArgs, *args): if self.enable and self.swap_in_generated: if self.source is not None: + logger.info(f"Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index) image: Image.Image = script_pp.image result = swap_face( self.source, diff --git a/scripts/globals.py b/scripts/globals.py new file mode 100644 index 0000000..d41b27e --- /dev/null +++ b/scripts/globals.py @@ -0,0 +1 @@ +IS_RUN: bool = False diff --git a/scripts/logger.py b/scripts/logger.py index 55529c3..7bd8922 100644 --- a/scripts/logger.py +++ b/scripts/logger.py @@ -3,11 +3,13 @@ import copy import sys from modules import shared +from scripts.globals import IS_RUN class ColoredFormatter(logging.Formatter): COLORS = { "DEBUG": "\033[0;36m", # CYAN + "STATUS": "\033[38;5;137m", # Calm ORANGE "INFO": "\033[0;32m", # GREEN "WARNING": "\033[0;33m", # YELLOW "ERROR": "\033[0;31m", # RED @@ -24,18 +26,29 @@ class ColoredFormatter(logging.Formatter): # Create a new logger -logger = logging.getLogger("Roop-GE") +logger = logging.getLogger("ReActor") logger.propagate = False +# Custom Level name +logging.addLevelName(logging.INFO, "STATUS") + # Add handler if we don't have one. if not logger.handlers: handler = logging.StreamHandler(sys.stdout) handler.setFormatter( - ColoredFormatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + ColoredFormatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s","%H:%M:%S") ) logger.addHandler(handler) # Configure logger -loglevel_string = getattr(shared.cmd_opts, "roop_loglevel", "INFO") +loglevel_string = getattr(shared.cmd_opts, "reactor_loglevel", "INFO") loglevel = getattr(logging, loglevel_string.upper(), "info") logger.setLevel(loglevel) + +def set_Run(value): + global IS_RUN + IS_RUN = value + +def get_Run(): + global IS_RUN + return IS_RUN diff --git a/scripts/swapper.py b/scripts/swapper.py index 9a3481e..9b0ed3e 100644 --- a/scripts/swapper.py +++ b/scripts/swapper.py @@ -77,7 +77,7 @@ def upscale_image(image: Image, upscale_options: UpscaleOptions): if upscale_options.do_restore_first: if upscale_options.face_restorer is not None: original_image = result_image.copy() - logger.info("Restore face with %s", upscale_options.face_restorer.name()) + logger.info("Restoring the face with %s", upscale_options.face_restorer.name()) numpy_image = np.array(result_image) numpy_image = upscale_options.face_restorer.restore(numpy_image) restored_image = Image.fromarray(numpy_image) @@ -87,7 +87,7 @@ def upscale_image(image: Image, upscale_options: UpscaleOptions): if upscale_options.upscaler is not None and upscale_options.upscaler.name != "None": original_image = result_image.copy() logger.info( - "Upscale with %s scale = %s", + "Upscaling with %s scale = %s", upscale_options.upscaler.name, upscale_options.scale, ) @@ -102,7 +102,7 @@ def upscale_image(image: Image, upscale_options: UpscaleOptions): if upscale_options.upscaler is not None and upscale_options.upscaler.name != "None": original_image = result_image.copy() logger.info( - "Upscale with %s scale = %s", + "Upscaling with %s scale = %s", upscale_options.upscaler.name, upscale_options.scale, ) @@ -115,7 +115,7 @@ def upscale_image(image: Image, upscale_options: UpscaleOptions): ) if upscale_options.face_restorer is not None: original_image = result_image.copy() - logger.info("Restore face with %s", upscale_options.face_restorer.name()) + logger.info("Restoring the face with %s", upscale_options.face_restorer.name()) numpy_image = np.array(result_image) numpy_image = upscale_options.face_restorer.restore(numpy_image) restored_image = Image.fromarray(numpy_image) @@ -192,7 +192,7 @@ def swap_face( logger.info(f"No source face found for face number {source_face_idx}.") result_image = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)) - if upscale_options is not None: + if upscale_options is not None and target_face is not None: result_image = upscale_image(result_image, upscale_options) else: diff --git a/scripts/version.py b/scripts/version.py index 4ebc359..5ad1e16 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -1,5 +1,10 @@ -version_flag = "v0.2.4b" +app_title = "ReActor" +version_flag = "v0.3.0" -from scripts.logger import logger +from scripts.logger import logger, get_Run, set_Run -logger.info(f"Roop-GE {version_flag}") +is_run = get_Run() + +if not is_run: + logger.info(f"Running {version_flag}") + set_Run(True)