diff --git a/Nodes/Inputs.py b/Nodes/Inputs.py index 012970e..a0149bf 100644 --- a/Nodes/Inputs.py +++ b/Nodes/Inputs.py @@ -394,7 +394,7 @@ class PrimereMetaHandler: return { "required": { "data_source": ("BOOLEAN", {"default": False, "label_on": "Use image meta", "label_off": "Use workflow settings"}), - "prompt_surce": ("BOOLEAN", {"default": True, "label_on": "Meta prompt", "label_off": "Workflow prompt"}), + "prompt_surce": ("BOOLEAN", {"default": True, "label_on": "Meta or workflow", "label_off": "Pic2story model"}), "prompt_state": ("BOOLEAN", {"default": False, "label_on": "Use decoded prompt", "label_off": "Use dynamic prompt"}), "model": ("BOOLEAN", {"default": True, "label_on": "Meta model", "label_off": "Workflow model"}), "model_hash_check": ("BOOLEAN", {"default": False, "label_on": "Check model hash", "label_off": "Use model name"}), @@ -723,18 +723,37 @@ class PrimereMetaHandler: else: return len(utility.WORKFLOW_SORT_LIST) + image_file = Path(image_path) + if 'image' in kwargs and image_file.is_file() == True: + img = nodes.LoadImage.load_image(self, kwargs['image'])[0] + + if kwargs['prompt_surce'] == False and workflow_tuple is None: + workflow_tuple = {} + workflow_tuple['exif_status'] = 'FAILED' + + if kwargs['prompt_surce'] != False and workflow_tuple is not None: + workflow_tuple['pic2story'] = 'OFF' + + if kwargs['prompt_surce'] == False and workflow_tuple is not None: + repo_id = "abhijit2111/Pic2Story" + prompts = ['Image of', 'Image creation style is', 'Colours on the picture'] + + story_out = utility.Pic2Story(repo_id, img, prompts, True, True) + if type(story_out) == str: + workflow_tuple['pic2story'] = 'SUCCEED' + workflow_tuple['pic2story_positive'] = story_out + else: + workflow_tuple['pic2story'] = 'FAILED' + + else: + img = None + if workflow_tuple is not None and len(workflow_tuple) >= 1: workflow_tuple = dict(sorted(workflow_tuple.items(), key=lambda pair: DictSort(pair[0]))) workflow_tuple['setup_states'] = kwargs if 'workflow_tuple' in workflow_tuple['setup_states']: del workflow_tuple['setup_states']['workflow_tuple'] - image_file = Path(image_path) - if 'image' in kwargs and image_file.is_file() == True: - img = nodes.LoadImage.load_image(self, kwargs['image'])[0] - else: - img = None - return (workflow_tuple, original_exif, img,) class PrimereMetaDistributor: @@ -752,7 +771,7 @@ class PrimereMetaDistributor: } def expand_meta(self, workflow_tuple): - PROCESSED_KEYS = ['positive', 'negative', 'positive_l', 'negative_l', 'positive_r', 'negative_r', + PROCESSED_KEYS = ['pic2story', 'positive', 'negative', 'positive_l', 'negative_l', 'positive_r', 'negative_r', 'model', 'model_version', 'model_concept', 'concept_data', 'vae', 'sampler', 'scheduler', 'steps', 'cfg', 'seed', 'width', 'height'] @@ -761,10 +780,27 @@ class PrimereMetaDistributor: if workflow_tuple is not None and type(workflow_tuple).__name__ == 'dict': for outputkeys in PROCESSED_KEYS: if outputkeys in workflow_tuple: - output_value = workflow_tuple[outputkeys] - if output_value == "": - output_value = None - OUTPUT_TUPLE.append(output_value) + match outputkeys: + case "pic2story": + if workflow_tuple[outputkeys] == 'SUCCEED' and 'pic2story_positive' in workflow_tuple: + workflow_tuple['positive'] = workflow_tuple['pic2story_positive'] + workflow_tuple['prompt_state'] = 'Dynamic' + workflow_tuple['exif_status'] = 'OFF' + if 'decoded_positive' in workflow_tuple: + del workflow_tuple['decoded_positive'] + if 'decoded_negative' in workflow_tuple: + del workflow_tuple['decoded_negative'] + if 'pic2story_positive' in workflow_tuple: + del workflow_tuple['pic2story_positive'] + if 'exif_data_count' in workflow_tuple: + del workflow_tuple['exif_data_count'] + if 'meta_source' in workflow_tuple: + del workflow_tuple['meta_source'] + case _: + output_value = workflow_tuple[outputkeys] + if output_value == "": + output_value = None + OUTPUT_TUPLE.append(output_value) else: MISSING_VALUES = None match outputkeys: diff --git a/README.md b/README.md index cff03b9..bd6e96e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Git link: https://github.com/CosmicLaca/ComfyUI_Primere_Nodes - Multiply original resolution by integer, but can be define the final resolution by target megapixels from any image sizes. Image resolution multiplier can solve low memory error problem if using Ultimate SD Upscaler - Remove previously included networks from the content of prompts (Embedding, Lora, Lycoris and Hypernetwork), use network remover if the selected model incompatible with them or if you want to try your prompt without included networks or want to change to different, or using SDXL checkpoint and SD Loras have to be changed to SDXL compatible version - Use more than one prompt or style input nodes for testing and developing prompts, select any by 1 click at the 'Prompt Switch' node -- Special image META/EXIF/PNGINFO reader, which handle model name and samplers from A1111 and ComfyUI .png or .jpg. Never was easier to recycle your older A1111 and ComfyUI images and re-using them with same or different workflow settings. With switches you can change or keep the original meta seed/model/size/etc... to workflow settings. Test workflow: **civitai-image-recycler.json** +- Special image META/EXIF/PNGINFO/PIC2PROMPT reader, which handle model name and samplers from A1111 and ComfyUI .png or .jpg. Never was easier to recycle your older A1111 and ComfyUI images and re-using them with same or different workflow settings. With switches you can change or keep the original meta seed/model/size/etc... to workflow settings. Test workflow: **civitai-image-recycler.json** - Workflow and nodes support Lycoris in dedicated node, no need to copy Lycoris files to Loras path - Adjustable detailers and refiners for face, eye, hands, mouth, fashion wear, etc..., separated prompt input for detailers can be mixed to original for better result, included test workflow: **civitai-all-refiner.json** - Visual (select element by preview image instead of long list) loaders available for Checkpoints, Loras, Lycoris, Embedding, Hypernetworks and .csv prompts. You only have to create preview images to right name and path, see readme details under "Visual", or use 1 click preview creator @@ -55,6 +55,7 @@ Git link: https://github.com/CosmicLaca/ComfyUI_Primere_Nodes ## Last changes: #### Usually after node changes have to reload/re-wire nodes within existing workflow, or open the latest workflows from the nodepack's **Workflow** folder. +- Image recycler node read images without meta, using Pic2Story model to generate prompt from picture only - Some nodes moved to **deprecated** subtree. Nodes can be used but not developed in the future. - **Segmented refiners** will mesure the aesthetic score of results, and if the original segment is better, changes will be ignored. Only in **Primere_full_workflow.json** workflow. Feature can switch off. - Friendly response icons in **segment refiners** if the detailer off or not found segment in the source image. @@ -293,6 +294,7 @@ Follow the file schema for your own prompts but don't forget to rename the attac ### Primere image recycler: - This node read prompt-exif (called meta) from loaded image. Compatible with A1111 .jpg and .png, and usually with ComfyUI, but not with results of all other custom workflows. +- The **prompt_source** input can be switch to **Pic2Story** mode, what creating prompt from the loaded image without reading metdata. diff --git a/Workflow/civitai-image-recycler.json b/Workflow/civitai-image-recycler.json index 864a87a..3ad4cc9 100644 --- a/Workflow/civitai-image-recycler.json +++ b/Workflow/civitai-image-recycler.json @@ -1,6 +1,6 @@ { - "last_node_id": 14, - "last_link_id": 56, + "last_node_id": 18, + "last_link_id": 90, "nodes": [ { "id": 1, @@ -53,7 +53,7 @@ "widgets_values": [ true, true, - false, + true, true, false, true, @@ -63,12 +63,12 @@ true, true, false, - false, true, - false, - false, - false, - "civitai-recycler02.jpg", + true, + true, + true, + true, + "00005-20230520175222-382989844.jpg", "image" ] }, @@ -98,7 +98,8 @@ "name": "PROMPT+", "type": "STRING", "links": [ - 41 + 83, + 87 ], "shape": 3, "slot_index": 0 @@ -107,7 +108,7 @@ "name": "PROMPT-", "type": "STRING", "links": [ - 42 + 88 ], "shape": 3, "slot_index": 1 @@ -149,7 +150,8 @@ "name": "MODEL_VERSION", "type": "STRING", "links": [ - 40 + 84, + 85 ], "shape": 3, "slot_index": 7 @@ -159,8 +161,9 @@ "type": "STRING", "links": [ 10, - 38, - 43 + 61, + 72, + 86 ], "shape": 3, "slot_index": 8 @@ -187,7 +190,7 @@ "name": "SAMPLER", "type": "COMBO", "links": [ - 51 + 64 ], "shape": 3, "slot_index": 11 @@ -196,7 +199,7 @@ "name": "SCHEDULER", "type": "COMBO", "links": [ - 54 + 65 ], "shape": 3, "slot_index": 12 @@ -205,7 +208,7 @@ "name": "STEPS", "type": "INT", "links": [ - 55 + 66 ], "shape": 3, "slot_index": 13 @@ -214,7 +217,7 @@ "name": "CFG", "type": "FLOAT", "links": [ - 56 + 67 ], "shape": 3, "slot_index": 14 @@ -224,7 +227,7 @@ "type": "INT", "links": [ 52, - 53 + 63 ], "shape": 3, "slot_index": 15 @@ -234,7 +237,7 @@ "type": "INT", "links": [ 18, - 44 + 73 ], "shape": 3, "slot_index": 16 @@ -244,7 +247,7 @@ "type": "INT", "links": [ 21, - 45 + 74 ], "shape": 3, "slot_index": 17 @@ -261,10 +264,10 @@ 901, 515 ], - "size": { - "0": 840, - "1": 863 - }, + "size": [ + 759.6296813964843, + 953.7951538085938 + ], "flags": {}, "order": 2, "mode": 0, @@ -279,7 +282,91 @@ "Node name for S&R": "PrimereAnyOutput" }, "widgets_values": [ - "{\n \"exif_status\": \"SUCCEED\",\n \"exif_data_count\": 15,\n \"positive\": \"Golden Yellow luxury slow European big modern futuristic spaceship in the highway of small city, racing, professional car photography\",\n \"model\": \"BestAll\\\\photon_v1.safetensors\",\n \"model_version\": \"BaseModel_768\",\n \"is_sdxl\": 0,\n \"model_hash\": \"ec41bd2a82\",\n \"vae\": \"Baked VAE\",\n \"sampler\": \"dpmpp_sde\",\n \"scheduler\": \"karras\",\n \"steps\": 30,\n \"cfg\": 9.0,\n \"seed\": 1255477315,\n \"width\": 768,\n \"height\": 512,\n \"size_string\": \"768x512\",\n \"face_restoration\": \"GFPGAN\",\n \"cfg_rescale\": 0.0,\n \"npw_weight\": 1.2,\n \"antiburn\": 5,\n \"version\": \"v1.3.1-1-gcbe17997\",\n \"meta_source\": \"Automatic1111\",\n \"setup_states\": {\n \"data_source\": true,\n \"prompt_surce\": true,\n \"prompt_state\": false,\n \"model\": true,\n \"model_hash_check\": false,\n \"sampler\": true,\n \"scheduler\": true,\n \"cfg\": true,\n \"steps\": true,\n \"seed\": true,\n \"image_size\": true,\n \"recount_image\": false,\n \"vae\": false,\n \"force_vae\": true,\n \"model_concept\": false,\n \"preferred\": false,\n \"use_preferred\": false,\n \"image\": \"civitai-recycler02.jpg\"\n }\n}" + "{\n \"exif_status\": \"SUCCEED\",\n \"exif_data_count\": 19,\n \"meta_source\": \"Automatic1111\",\n \"pic2story\": \"SUCCEED\",\n \"positive\": \"human scientist operate brain within the head of platina robot, medical room, operating table, computers, Photorealistic, Hyperrealistic, Hyperdetailed, analog style, hip cocked, demure, low cut, black lace, detailed skin, matte skin, soft lighting, subsurface scattering, realistic, heavy shadow, masterpiece, best quality, ultra realistic, 8k, golden ratio, Intricate, High Detail, film photography, soft focus\",\n \"negative\": \"draw, text, kid, nsfw, nude, tits, porn, nudity, gold\",\n \"pic2story_positive\": \"image of two people with glowing faces a robot head in the background, full moon sky, creation style digital art work woman eyes red light, colours on picture blue, robot's eyes\",\n \"model\": \"BestSci-fi\\\\rinamix3.safetensors\",\n \"model_version\": \"BaseModel_768\",\n \"is_sdxl\": 0,\n \"model_hash\": \"dedf1e6c80\",\n \"vae\": \"Baked VAE\",\n \"sampler\": \"euler_ancestral\",\n \"scheduler\": \"normal\",\n \"steps\": 30,\n \"cfg\": 12.0,\n \"seed\": 382989844,\n \"width\": 1024,\n \"height\": 768,\n \"size_string\": \"1024x768\",\n \"face_restoration\": \"CodeFormer\",\n \"variation_seed\": 3550237358,\n \"variation_seed_strength\": 1,\n \"version\": \"v1.2.1\",\n \"npw_weight\": 1.2,\n \"antiburn\": 5,\n \"template\": \"human scientist operate brain within the head of platina robot, medical room, operating table, computers, Photorealistic, Hyperrealistic, Hyperdetailed, analog style, hip cocked, demure, low cut, black lace, detailed skin, matte skin, soft lighting, subsurface scattering, realistic, heavy shadow, masterpiece, best quality, ultra realistic, 8k, golden ratio, Intricate, High Detail, film photography, soft focus\",\n \"negative_template\": \"draw, text, kid, nsfw, nude, tits, porn, nudity, gold\",\n \"setup_states\": {\n \"data_source\": true,\n \"prompt_surce\": false,\n \"prompt_state\": true,\n \"model\": true,\n \"model_hash_check\": false,\n \"sampler\": true,\n \"scheduler\": true,\n \"cfg\": true,\n \"steps\": true,\n \"seed\": true,\n \"image_size\": true,\n \"recount_image\": false,\n \"vae\": true,\n \"force_vae\": true,\n \"model_concept\": true,\n \"preferred\": true,\n \"use_preferred\": true,\n \"image\": \"00005-20230520175222-382989844.jpg\"\n }\n}" + ] + }, + { + "id": 18, + "type": "PrimereClearPrompt", + "pos": [ + 1722, + 652 + ], + "size": [ + 324.00089111328134, + 238 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "model_version", + "type": "STRING", + "link": 85, + "widget": { + "name": "model_version" + } + }, + { + "name": "positive_prompt", + "type": "STRING", + "link": 87, + "widget": { + "name": "positive_prompt" + } + }, + { + "name": "negative_prompt", + "type": "STRING", + "link": 88, + "widget": { + "name": "negative_prompt" + } + }, + { + "name": "model_concept", + "type": "STRING", + "link": 86, + "widget": { + "name": "model_concept" + } + } + ], + "outputs": [ + { + "name": "PROMPT+", + "type": "STRING", + "links": [ + 89 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "PROMPT-", + "type": "STRING", + "links": [ + 90 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "PrimereClearPrompt" + }, + "widgets_values": [ + "BaseModel_1024", + "", + "", + false, + false, + true, + true, + true, + true, + "Normal" ] }, { @@ -294,7 +381,7 @@ "1": 206 }, "flags": {}, - "order": 3, + "order": 4, "mode": 0, "inputs": [ { @@ -336,7 +423,7 @@ "name": "MODEL", "type": "MODEL", "links": [ - 34 + 79 ], "shape": 3, "slot_index": 0 @@ -345,7 +432,7 @@ "name": "CLIP", "type": "CLIP", "links": [ - 39 + 81 ], "shape": 3, "slot_index": 1 @@ -379,24 +466,258 @@ ] }, { - "id": 12, - "type": "PrimereCLIPEncoder", + "id": 17, + "type": "PrimereNetworkTagLoader", "pos": [ - 1769, - 700 + 1716, + 988 + ], + "size": [ + 315, + 586 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 79 + }, + { + "name": "clip", + "type": "CLIP", + "link": 81 + }, + { + "name": "positive_prompt", + "type": "STRING", + "link": 83, + "widget": { + "name": "positive_prompt" + } + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 80 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 82 + ], + "shape": 3, + "slot_index": 1 + }, + { + "name": "LORA_STACK", + "type": "LORA_STACK", + "links": null, + "shape": 3 + }, + { + "name": "LYCORIS_STACK", + "type": "LYCORIS_STACK", + "links": null, + "shape": 3 + }, + { + "name": "HYPERNETWORK_STACK", + "type": "HYPERNETWORK_STACK", + "links": null, + "shape": 3 + }, + { + "name": "LORA_KEYWORD", + "type": "MODEL_KEYWORD", + "links": null, + "shape": 3 + }, + { + "name": "LYCORIS_KEYWORD", + "type": "MODEL_KEYWORD", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "PrimereNetworkTagLoader" + }, + "widgets_values": [ + "", + true, + true, + true, + false, + false, + 1, + 1, + true, + "Last", + "Select in order", + 1, + 1, + true, + "Last", + "Select in order", + 1, + 1 + ] + }, + { + "id": 5, + "type": "PrimereVAELoader", + "pos": [ + 1824, + 88 ], "size": { - "0": 359.3300476074219, - "1": 782 + "0": 210, + "1": 46 }, "flags": {}, - "order": 4, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "vae_name", + "type": "VAE_NAME", + "link": 13 + }, + { + "name": "baked_vae", + "type": "VAE", + "link": 12 + } + ], + "outputs": [ + { + "name": "VAE", + "type": "VAE", + "links": [ + 14 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "PrimereVAELoader" + } + }, + { + "id": 9, + "type": "PrimereLatentNoise", + "pos": [ + 1755, + 187 + ], + "size": [ + 329.02227172851553, + 406 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "optional_vae", + "type": "VAE", + "link": 17 + }, + { + "name": "width", + "type": "INT", + "link": 18, + "widget": { + "name": "width" + } + }, + { + "name": "height", + "type": "INT", + "link": 21, + "widget": { + "name": "height" + } + }, + { + "name": "noise_seed", + "type": "INT", + "link": 52, + "widget": { + "name": "noise_seed" + } + } + ], + "outputs": [ + { + "name": "LATENTS", + "type": "LATENT", + "links": [ + 60 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "PREVIEWS", + "type": "IMAGE", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "PrimereLatentNoise" + }, + "widgets_values": [ + 512, + 512, + true, + "white", + true, + 1, + 0.5, + 1.5, + true, + 1, + 0.8, + 1.4, + 140930013015817, + "randomize", + true, + "cpu", + false + ] + }, + { + "id": 16, + "type": "PrimereCLIPEncoder", + "pos": [ + 2099, + 640 + ], + "size": [ + 378.8222717285157, + 806 + ], + "flags": {}, + "order": 8, "mode": 0, "inputs": [ { "name": "clip", "type": "CLIP", - "link": 39 + "link": 82 }, { "name": "model_keywords", @@ -426,7 +747,7 @@ { "name": "model_version", "type": "STRING", - "link": 40, + "link": 84, "widget": { "name": "model_version" } @@ -434,7 +755,7 @@ { "name": "positive_prompt", "type": "STRING", - "link": 41, + "link": 89, "widget": { "name": "positive_prompt" } @@ -442,7 +763,7 @@ { "name": "negative_prompt", "type": "STRING", - "link": 42, + "link": 90, "widget": { "name": "negative_prompt" } @@ -450,7 +771,7 @@ { "name": "model_concept", "type": "STRING", - "link": 43, + "link": 72, "widget": { "name": "model_concept" } @@ -506,7 +827,7 @@ { "name": "width", "type": "INT", - "link": 44, + "link": 73, "widget": { "name": "width" } @@ -514,7 +835,7 @@ { "name": "height", "type": "INT", - "link": 45, + "link": 74, "widget": { "name": "height" } @@ -525,7 +846,7 @@ "name": "COND+", "type": "CONDITIONING", "links": [ - 47 + 75 ], "shape": 3, "slot_index": 0 @@ -534,7 +855,7 @@ "name": "COND-", "type": "CONDITIONING", "links": [ - 48 + 76 ], "shape": 3, "slot_index": 1 @@ -543,17 +864,19 @@ "name": "PROMPT+", "type": "STRING", "links": [ - 49 + 77 ], - "shape": 3 + "shape": 3, + "slot_index": 2 }, { "name": "PROMPT-", "type": "STRING", "links": [ - 50 + 78 ], - "shape": 3 + "shape": 3, + "slot_index": 3 }, { "name": "PROMPT L+", @@ -575,16 +898,17 @@ "BaseModel_1024", "", "", + true, 0, - 1, + 1.2, false, "None", 1, "None", 1, true, - "none", - "comfy", + "mean", + "comfy++", "Normal", "", 1, @@ -604,207 +928,15 @@ ] }, { - "id": 5, - "type": "PrimereVAELoader", - "pos": [ - 1824, - 88 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [ - { - "name": "vae_name", - "type": "VAE_NAME", - "link": 13 - }, - { - "name": "baked_vae", - "type": "VAE", - "link": 12 - } - ], - "outputs": [ - { - "name": "VAE", - "type": "VAE", - "links": [ - 14 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "PrimereVAELoader" - } - }, - { - "id": 9, - "type": "PrimereLatentNoise", - "pos": [ - 1766, - 198 - ], - "size": { - "0": 314, - "1": 454 - }, - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "name": "optional_vae", - "type": "VAE", - "link": 17 - }, - { - "name": "width", - "type": "INT", - "link": 18, - "widget": { - "name": "width" - } - }, - { - "name": "height", - "type": "INT", - "link": 21, - "widget": { - "name": "height" - } - }, - { - "name": "noise_seed", - "type": "INT", - "link": 52, - "widget": { - "name": "noise_seed" - } - } - ], - "outputs": [ - { - "name": "LATENTS", - "type": "LATENT", - "links": [ - 37 - ], - "shape": 3, - "slot_index": 0 - }, - { - "name": "PREVIEWS", - "type": "IMAGE", - "links": null, - "shape": 3 - } - ], - "properties": { - "Node name for S&R": "PrimereLatentNoise" - }, - "widgets_values": [ - 512, - 512, - true, - "white", - true, - 1, - 0.5, - 1.5, - true, - 1, - 0.8, - 1.4, - 933167228365428, - "randomize", - true, - "cpu", - false - ] - }, - { - "id": 13, - "type": "PrimereTextOutput", - "pos": [ - 2162, - 1065 - ], - "size": { - "0": 557.7000122070312, - "1": 408.1000061035156 - }, - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "name": "text", - "type": "STRING", - "link": 49, - "widget": { - "name": "text" - }, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "PrimereTextOutput" - }, - "widgets_values": [ - "", - "Golden Yellow luxury slow European big modern futuristic spaceship in the highway of small city, racing, professional car photography" - ] - }, - { - "id": 14, - "type": "PrimereTextOutput", - "pos": [ - 2763, - 1060 - ], - "size": { - "0": 566.3809814453125, - "1": 413.2881774902344 - }, - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "name": "text", - "type": "STRING", - "link": 50, - "widget": { - "name": "text" - }, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "PrimereTextOutput" - }, - "widgets_values": [ - "", - "" - ] - }, - { - "id": 11, + "id": 15, "type": "PrimereKSampler", "pos": [ - 2136, - 198 + 2141, + 188 ], "size": [ - 333.8629180908197, - 286 + 323.2222717285158, + 310 ], "flags": {}, "order": 9, @@ -813,27 +945,27 @@ { "name": "model", "type": "MODEL", - "link": 34 + "link": 80 }, { "name": "positive", "type": "CONDITIONING", - "link": 47 + "link": 75 }, { "name": "negative", "type": "CONDITIONING", - "link": 48 + "link": 76 }, { "name": "latent_image", "type": "LATENT", - "link": 37 + "link": 60 }, { "name": "model_concept", "type": "STRING", - "link": 38, + "link": 61, "widget": { "name": "model_concept" } @@ -841,31 +973,15 @@ { "name": "seed", "type": "INT", - "link": 53, + "link": 63, "widget": { "name": "seed" } }, - { - "name": "sampler_name", - "type": "COMBO", - "link": 51, - "widget": { - "name": "sampler_name" - } - }, - { - "name": "scheduler_name", - "type": "COMBO", - "link": 54, - "widget": { - "name": "scheduler_name" - } - }, { "name": "steps", "type": "INT", - "link": 55, + "link": 66, "widget": { "name": "steps" } @@ -873,10 +989,26 @@ { "name": "cfg", "type": "FLOAT", - "link": 56, + "link": 67, "widget": { "name": "cfg" } + }, + { + "name": "sampler_name", + "type": "COMBO", + "link": 64, + "widget": { + "name": "sampler_name" + } + }, + { + "name": "scheduler_name", + "type": "COMBO", + "link": 65, + "widget": { + "name": "scheduler_name" + } } ], "outputs": [ @@ -884,7 +1016,7 @@ "name": "LATENT", "type": "LATENT", "links": [ - 46 + 62 ], "shape": 3, "slot_index": 0 @@ -894,18 +1026,85 @@ "Node name for S&R": "PrimereKSampler" }, "widgets_values": [ - 735053506994241, + 70620202405593, "randomize", 20, 8, "euler", "normal", 1, - 0.22, + 0, + 0, "DEFAULT", "Normal" ] }, + { + "id": 13, + "type": "PrimereTextOutput", + "pos": [ + 3362, + 86 + ], + "size": { + "0": 557.7000122070312, + "1": 408.1000061035156 + }, + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 77, + "widget": { + "name": "text" + }, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "PrimereTextOutput" + }, + "widgets_values": [ + "", + "image of two people with glowing faces a robot head in the background, full moon sky, creation style digital art work woman eyes red light, colours on picture blue, robot's eyes" + ] + }, + { + "id": 14, + "type": "PrimereTextOutput", + "pos": [ + 3353, + 603 + ], + "size": { + "0": 566.3809814453125, + "1": 413.2881774902344 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 78, + "widget": { + "name": "text" + }, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "PrimereTextOutput" + }, + "widgets_values": [ + "", + "(draw, text, kid, nsfw, nude, tits, porn, nudity, gold:1.20)" + ] + }, { "id": 8, "type": "VAEDecode", @@ -918,13 +1117,13 @@ "1": 46 }, "flags": {}, - "order": 10, + "order": 12, "mode": 0, "inputs": [ { "name": "samples", "type": "LATENT", - "link": 46 + "link": 62 }, { "name": "vae", @@ -959,7 +1158,7 @@ "1": 915 }, "flags": {}, - "order": 11, + "order": 13, "mode": 0, "inputs": [ { @@ -1070,134 +1269,6 @@ 0, "IMAGE" ], - [ - 34, - 3, - 0, - 11, - 0, - "MODEL" - ], - [ - 37, - 9, - 0, - 11, - 3, - "LATENT" - ], - [ - 38, - 2, - 8, - 11, - 4, - "STRING" - ], - [ - 39, - 3, - 1, - 12, - 0, - "CLIP" - ], - [ - 40, - 2, - 7, - 12, - 6, - "STRING" - ], - [ - 41, - 2, - 0, - 12, - 7, - "STRING" - ], - [ - 42, - 2, - 1, - 12, - 8, - "STRING" - ], - [ - 43, - 2, - 8, - 12, - 9, - "STRING" - ], - [ - 44, - 2, - 16, - 12, - 16, - "INT" - ], - [ - 45, - 2, - 17, - 12, - 17, - "INT" - ], - [ - 46, - 11, - 0, - 8, - 0, - "LATENT" - ], - [ - 47, - 12, - 0, - 11, - 1, - "CONDITIONING" - ], - [ - 48, - 12, - 1, - 11, - 2, - "CONDITIONING" - ], - [ - 49, - 12, - 2, - 13, - 0, - "STRING" - ], - [ - 50, - 12, - 3, - 14, - 0, - "STRING" - ], - [ - 51, - 2, - 11, - 11, - 6, - "COMBO" - ], [ 52, 2, @@ -1207,36 +1278,220 @@ "INT" ], [ - 53, + 60, + 9, + 0, + 15, + 3, + "LATENT" + ], + [ + 61, + 2, + 8, + 15, + 4, + "STRING" + ], + [ + 62, + 15, + 0, + 8, + 0, + "LATENT" + ], + [ + 63, 2, 15, - 11, + 15, 5, "INT" ], [ - 54, + 64, 2, - 12, 11, - 7, + 15, + 8, "COMBO" ], [ - 55, + 65, + 2, + 12, + 15, + 9, + "COMBO" + ], + [ + 66, 2, 13, - 11, - 8, + 15, + 6, "INT" ], [ - 56, + 67, 2, 14, - 11, - 9, + 15, + 7, "FLOAT" + ], + [ + 72, + 2, + 8, + 16, + 9, + "STRING" + ], + [ + 73, + 2, + 16, + 16, + 16, + "INT" + ], + [ + 74, + 2, + 17, + 16, + 17, + "INT" + ], + [ + 75, + 16, + 0, + 15, + 1, + "CONDITIONING" + ], + [ + 76, + 16, + 1, + 15, + 2, + "CONDITIONING" + ], + [ + 77, + 16, + 2, + 13, + 0, + "STRING" + ], + [ + 78, + 16, + 3, + 14, + 0, + "STRING" + ], + [ + 79, + 3, + 0, + 17, + 0, + "MODEL" + ], + [ + 80, + 17, + 0, + 15, + 0, + "MODEL" + ], + [ + 81, + 3, + 1, + 17, + 1, + "CLIP" + ], + [ + 82, + 17, + 1, + 16, + 0, + "CLIP" + ], + [ + 83, + 2, + 0, + 17, + 2, + "STRING" + ], + [ + 84, + 2, + 7, + 16, + 6, + "STRING" + ], + [ + 85, + 2, + 7, + 18, + 0, + "STRING" + ], + [ + 86, + 2, + 8, + 18, + 3, + "STRING" + ], + [ + 87, + 2, + 0, + 18, + 1, + "STRING" + ], + [ + 88, + 2, + 1, + 18, + 2, + "STRING" + ], + [ + 89, + 18, + 0, + 16, + 7, + "STRING" + ], + [ + 90, + 18, + 1, + 16, + 8, + "STRING" ] ], "groups": [], diff --git a/Workflow/readme_images/pimgrecycler.jpg b/Workflow/readme_images/pimgrecycler.jpg index 5a782a9..aa21d5f 100644 Binary files a/Workflow/readme_images/pimgrecycler.jpg and b/Workflow/readme_images/pimgrecycler.jpg differ diff --git a/components/utility.py b/components/utility.py index fb410cd..5d4477f 100644 --- a/components/utility.py +++ b/components/utility.py @@ -41,10 +41,10 @@ PREVIEW_PATH_BY_TYPE = { "Embedding": os.path.join(PREVIEW_ROOT, "embeddings"), } -WORKFLOW_SORT_LIST = ['exif_status', 'exif_data_count', 'positive', 'positive_l', 'positive_r', 'negative', 'negative_l', 'negative_r', 'prompt_state', 'decoded_positive', 'decoded_negative', 'model', - 'model_concept', 'concept_data', 'model_version', 'is_sdxl', 'model_hash', 'vae', 'vae_hash', 'vae_name_sd', 'vae_name_sdxl', 'sampler', 'scheduler', 'steps', - 'cfg', 'seed', 'width', 'height', 'size_string', 'preferred', 'saved_image_width', 'saved_image_heigth', 'upscaler_ratio', - 'vae_name_sd', 'vae_name_sdxl'] +WORKFLOW_SORT_LIST = ['exif_status', 'exif_data_count', 'meta_source', 'pic2story', 'positive', 'positive_l', 'positive_r', 'negative', 'negative_l', 'negative_r', 'prompt_state', 'decoded_positive', 'decoded_negative', 'pic2story_positive', + 'model', 'model_concept', 'concept_data', 'model_version', 'is_sdxl', 'model_hash', 'vae', 'vae_hash', 'vae_name_sd', 'vae_name_sdxl', 'sampler', 'scheduler', 'steps', + 'cfg', 'seed', 'width', 'height', 'size_string', 'preferred', 'saved_image_width', 'saved_image_heigth', 'upscaler_ratio', + 'vae_name_sd', 'vae_name_sdxl'] def merge_str_to_tuple(item1, item2): if not isinstance(item1, tuple): @@ -641,6 +641,12 @@ def downloader(from_url, to_path): print('ERROR: Cannot download ' + TargetFilename) return False +def hf_downloader(repo_id, model_local_dir): + from huggingface_hub import snapshot_download + model_path = f"{model_local_dir}/{repo_id.split('/')[-1]}" + snapshot_download(repo_id=repo_id, local_dir=model_path, local_dir_use_symlinks=True, max_workers=1) + return model_path + def ModelConceptNames(ckpt_name, model_concept, lightning_selector, lightning_model_step): lora_name = None unet_name = None @@ -840,4 +846,88 @@ def ImageLoaderFromPath(ImgPath, new_width = None, new_height = None): # print('[Primere Error]: error loading image from path: ' + ImgPath) # output_image = None - return output_image \ No newline at end of file + return output_image + +def tensor_to_image(tensor): + tensor = tensor.cpu() + image_np = tensor.squeeze().mul(255).clamp(0, 255).byte().numpy() + image = Image.fromarray(image_np, mode='RGB') + return image + +def Pic2Story(repo_id, img, prompts, special_tokens_skip = True, clean_same_result = True): + story_out = None + from transformers import BlipProcessor, BlipForConditionalGeneration + import torch + + os.environ['TRANSFORMERS_OFFLINE'] = "1" + processor = BlipProcessor.from_pretrained(repo_id) + pil_image = tensor_to_image(img) + + try: + model = BlipForConditionalGeneration.from_pretrained(repo_id, torch_dtype=torch.float16).to("cuda") + if type(prompts) == str: + inputs = processor(pil_image, prompts, return_tensors="pt").to("cuda", torch.float16) + out = model.generate(**inputs) + story_out = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + + elif type(prompts).__name__ == 'list': + for prompt in prompts: + inputs = processor(pil_image, prompt, return_tensors="pt").to("cuda", torch.float16) + out = model.generate(**inputs) + Processed = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + ', ' + if story_out is not None: + story_out = story_out + Processed + else: + story_out = Processed + + except Exception: + print('Pic2Story Float 16 failed') + + if type(story_out) != str: + try: + model = BlipForConditionalGeneration.from_pretrained(repo_id).to("cuda") + if type(prompts) == str: + inputs = processor(pil_image, prompts, return_tensors="pt").to("cuda") + out = model.generate(**inputs) + story_out = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + + elif type(prompts).__name__ == 'list': + for prompt in prompts: + inputs = processor(pil_image, prompt, return_tensors="pt").to("cuda") + out = model.generate(**inputs) + Processed = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + ', ' + if story_out is not None: + story_out = story_out + Processed + else: + story_out = Processed + + except Exception: + print('Pic2Story GPU failed') + + if type(story_out) != str: + try: + model = BlipForConditionalGeneration.from_pretrained(repo_id) + if type(prompts) == str: + inputs = processor(pil_image, prompts, return_tensors="pt") + out = model.generate(**inputs) + story_out = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + + elif type(prompts).__name__ == 'list': + for prompt in prompts: + inputs = processor(pil_image, prompt, return_tensors="pt") + out = model.generate(**inputs) + Processed = processor.decode(out[0], skip_special_tokens=special_tokens_skip) + ', ' + if story_out is not None: + story_out = story_out + Processed + else: + story_out = Processed + + except Exception: + print('Pic2Story CPU failed') + + if type(story_out) == str: + if clean_same_result == True: + story_out = ' '.join(dict.fromkeys(story_out.split())) + return story_out.rstrip(', ').replace(' and ', ' ').replace(' an ', ' ').replace(' is ', ' ').replace(' are ', ' ') + else: + return story_out \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b0a86ae..f1264d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,4 +32,5 @@ tqdm transformers ultralytics yapf -openai-clip \ No newline at end of file +openai-clip +huggingface_hub \ No newline at end of file