File size: 13,040 Bytes
cee5404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ac7f47
 
 
 
 
 
 
 
 
 
cee5404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ac7f47
 
cee5404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
import torch
import random
import comfy
from comfy.sd import load_checkpoint_guess_config
import nodes
from nodes import NODE_CLASS_MAPPINGS
from comfy_extras import nodes_post_processing, nodes_differential_diffusion, nodes_upscale_model
import numpy as np
from PIL import Image
import asyncio
import execution
import server
from nodes import load_custom_node
from math import ceil, floor

import os, json, requests, runpod

discord_token = os.getenv('com_camenduru_discord_token')
web_uri = os.getenv('com_camenduru_web_uri')
web_token = os.getenv('com_camenduru_web_token')

def download_file(url, save_dir='/content/ComfyUI/input'):
    os.makedirs(save_dir, exist_ok=True)
    file_name = url.split('/')[-1]
    file_path = os.path.join(save_dir, file_name)
    response = requests.get(url)
    response.raise_for_status()
    with open(file_path, 'wb') as file:
        file.write(response.content)
    return file_path

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
server_instance = server.PromptServer(loop)
execution.PromptQueue(server_instance)

load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-AutomaticCFG")
load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-Custom-Scripts")
load_custom_node("/content/ComfyUI/custom_nodes/Derfuu_ComfyUI_ModdedNodes")
load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-Impact-Pack")
load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-Inspire-Pack")
load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-KJNodes")
load_custom_node("/content/ComfyUI/custom_nodes/comfyui_controlnet_aux")
load_custom_node("/content/ComfyUI/custom_nodes/ComfyUI-TiledDiffusion")
load_custom_node("/content/ComfyUI/custom_nodes/was-node-suite-comfyui")

Automatic_CFG = NODE_CLASS_MAPPINGS["Automatic CFG"]()
ImageScaleToTotalPixels = nodes_post_processing.NODE_CLASS_MAPPINGS["ImageScaleToTotalPixels"]()
GetImageSizeAndCount = NODE_CLASS_MAPPINGS["GetImageSizeAndCount"]()
TTPlanet_TileSimple = NODE_CLASS_MAPPINGS["TTPlanet_TileSimple_Preprocessor"]()
TiledDiffusion = NODE_CLASS_MAPPINGS["TiledDiffusion"]()
KSampler_inspire = NODE_CLASS_MAPPINGS["KSampler //Inspire"]()
ControlNetApplyAdvanced = NODE_CLASS_MAPPINGS["ControlNetApplyAdvanced"]()
UltralyticsDetectorProvider = NODE_CLASS_MAPPINGS["UltralyticsDetectorProvider"]()
SegmDetectorSEGS = NODE_CLASS_MAPPINGS["SegmDetectorSEGS"]()
DifferentialDiffusion = nodes_differential_diffusion.NODE_CLASS_MAPPINGS["DifferentialDiffusion"]()
DetailerForEach = NODE_CLASS_MAPPINGS["DetailerForEach"]()
VAEDecodeTiled = NODE_CLASS_MAPPINGS["VAEDecodeTiled"]()
ColorMatch = NODE_CLASS_MAPPINGS["ColorMatch"]()
ImageBlend = nodes_post_processing.NODE_CLASS_MAPPINGS["ImageBlend"]()
WAS_Image_Blending_Mode = NODE_CLASS_MAPPINGS["Image Blending Mode"]()
ImageScale = NODE_CLASS_MAPPINGS["ImageScale"]()
ImageScaleBy = NODE_CLASS_MAPPINGS["ImageScaleBy"]()
UpscaleModelLoader = nodes_upscale_model.NODE_CLASS_MAPPINGS["UpscaleModelLoader"]()
ImageUpscaleWithModel = nodes_upscale_model.NODE_CLASS_MAPPINGS["ImageUpscaleWithModel"]()

with torch.inference_mode():
    model_patcher, clip, vae, clipvision = load_checkpoint_guess_config("/content/ComfyUI/models/checkpoints/dreamshaperXL_lightningDPMSDE.safetensors", output_vae=True, output_clip=True, embedding_directory=None)
    tile_control_net = comfy.controlnet.load_controlnet("/content/ComfyUI/models/controlnet/xinsir-controlnet-tile-sdxl-1.0.safetensors")
    segm_detector = UltralyticsDetectorProvider.doit(model_name="segm/PitEyeDetailer-v2-seg.pt")
    upscale_model = UpscaleModelLoader.load_model(model_name="4xRealWebPhoto_v4_dat2.safetensors")[0]
    model_patcher = Automatic_CFG.patch(model=model_patcher, hard_mode=True, boost=True)[0]

@torch.inference_mode()
def generate(input):
    values = input["input"]

    input_image = values['input_image_check']
    input_image = download_file(input_image)
    positive_prompt = values['positive_prompt']
    negative_prompt = values['negative_prompt']
    inspire_seed = values['inspire_seed']
    inspire_steps = values['inspire_steps']
    inspire_cfg = values['inspire_cfg']
    inspire_sampler_name = values['inspire_sampler_name']
    inspire_scheduler = values['inspire_scheduler']
    inspire_denoise = values['inspire_denoise']
    inspire_noise_mode = values['inspire_noise_mode']
    inspire_batch_seed_mode = values['inspire_batch_seed_mode']
    inspire_variation_seed = values['inspire_variation_seed']
    inspire_variation_strength = values['inspire_variation_strength']
    inspire_variation_method = values['inspire_variation_method']
    scale_factor = values['scale_factor']
    blur_strength = values['blur_strength']
    strength = values['strength']
    start_percent = values['start_percent']
    end_percent = values['end_percent']
    tile_method = values['tile_method']
    tile_overlap = values['tile_overlap']
    tile_size = values['tile_size']
    threshold = values['threshold']
    dilation = values['dilation']
    crop_factor = values['crop_factor']
    drop_size = values['drop_size']
    labels = values['labels']
    detailer_guide_size = values['detailer_guide_size']
    detailer_guide_size_for_bbox = values['detailer_guide_size_for_bbox']
    detailer_max_size = values['detailer_max_size']
    detailer_seed = values['detailer_seed']
    detailer_steps = values['detailer_steps']
    detailer_cfg = values['detailer_cfg']
    detailer_sampler_name = values['detailer_sampler_name']
    detailer_scheduler = values['detailer_scheduler']
    detailer_denoise = values['detailer_denoise']
    detailer_feather = values['detailer_feather']
    detailer_noise_mask = values['detailer_noise_mask']
    detailer_force_inpaint = values['detailer_force_inpaint']
    detailer_cycle = values['detailer_cycle']
    detailer_inpaint_model = values['detailer_inpaint_model']
    detailer_noise_mask_feather = values['detailer_noise_mask_feather']
    color_method = values['color_method']
    blend_factor = values['blend_factor']
    blend_mode = values['blend_mode']
    blending_mode = values['blending_mode']
    blending_blend_percentage = values['blending_blend_percentage']

    output_image, output_mask = nodes.LoadImage().load_image(input_image)
    output_image_s = ImageScaleToTotalPixels.upscale(image=output_image, upscale_method="nearest-exact", megapixels=1.0)[0]
    image_width = GetImageSizeAndCount.getsize(output_image_s)["result"][1]
    image_height = GetImageSizeAndCount.getsize(output_image_s)["result"][2]
    upscale_mp = 4
    w_math = ceil((image_width * upscale_mp) / 8) * 8
    h_math = ceil((image_height * upscale_mp) / 8) * 8
    w_tiles = 4
    tile_width = ceil((w_math / w_tiles) / 8) * 8
    h_tiles = 4
    tile_height = ceil((h_math / h_tiles) / 8) * 8
    vram = 8
    tile_batch_size = floor((vram-3) / ((tile_width*tile_height) / 1000000))
    upscale_image = ImageScaleBy.upscale(image=output_image, upscale_method="bilinear", scale_by=1.0)[0]
    upscaled_image = ImageUpscaleWithModel.upscale(upscale_model=upscale_model, image=upscale_image)[0]
    output_image = ImageScale.upscale(image=upscaled_image, upscale_method="bilinear", width=w_math, height=h_math, crop="disabled")[0]

    cond, pooled = clip.encode_from_tokens(clip.tokenize(positive_prompt), return_pooled=True)
    cond = [[cond, {"pooled_output": pooled}]]
    n_cond, n_pooled = clip.encode_from_tokens(clip.tokenize(negative_prompt), return_pooled=True)
    n_cond = [[n_cond, {"pooled_output": n_pooled}]]
    output_image_t = TTPlanet_TileSimple.execute(output_image, scale_factor=scale_factor, blur_strength=blur_strength)[0]
    positive, negative = ControlNetApplyAdvanced.apply_controlnet(positive=cond, negative=n_cond, control_net=tile_control_net, image=output_image_t, strength=strength, start_percent=start_percent, end_percent=end_percent)
    tile_model = TiledDiffusion.apply(model=model_patcher, method=tile_method, tile_width=tile_width, tile_height=tile_height, tile_overlap=tile_overlap, tile_batch_size=tile_batch_size)[0]
    latent_image = nodes.VAEEncode().encode(vae, output_image)[0]
    inspire_sample = KSampler_inspire.doit(model=tile_model, 
                                            seed=inspire_seed, 
                                            steps=inspire_steps, 
                                            cfg=inspire_cfg, 
                                            sampler_name=inspire_sampler_name, 
                                            scheduler=inspire_scheduler, 
                                            positive=positive, 
                                            negative=negative,
                                            latent_image=latent_image, 
                                            denoise=inspire_denoise,
                                            noise_mode=inspire_noise_mode,
                                            batch_seed_mode=inspire_batch_seed_mode,
                                            variation_seed=inspire_variation_seed,
                                            variation_strength=inspire_variation_strength,
                                            variation_method=inspire_variation_method)[0]
    tiled_decoded = VAEDecodeTiled.decode(vae=vae, samples=inspire_sample, tile_size=tile_size)[0]
    segs = SegmDetectorSEGS.doit(segm_detector=segm_detector[1], image=output_image, threshold=threshold, dilation=dilation, crop_factor=crop_factor, drop_size=drop_size, labels=labels)[0]
    dd_model_patcher = DifferentialDiffusion.apply(model_patcher)[0]
    detailer_image = DetailerForEach.do_detail(image=tiled_decoded, 
                                        segs=segs, 
                                        model=dd_model_patcher, 
                                        clip=clip, 
                                        vae=vae, 
                                        guide_size=detailer_guide_size, 
                                        guide_size_for_bbox=detailer_guide_size_for_bbox, 
                                        max_size=detailer_max_size, 
                                        seed=detailer_seed, 
                                        steps=detailer_steps, 
                                        cfg=detailer_cfg, 
                                        sampler_name=detailer_sampler_name, 
                                        scheduler=detailer_scheduler,
                                        positive=cond, 
                                        negative=n_cond, 
                                        denoise=detailer_denoise, 
                                        feather=detailer_feather, 
                                        noise_mask=detailer_noise_mask, 
                                        force_inpaint=detailer_force_inpaint,
                                        cycle=detailer_cycle,
                                        inpaint_model=detailer_inpaint_model,
                                        noise_mask_feather=detailer_noise_mask_feather)[0]
    color_image = ColorMatch.colormatch(image_ref=output_image, image_target=detailer_image, method=color_method)[0]
    blend_image = ImageBlend.blend_images(image1=color_image, image2=detailer_image, blend_factor=blend_factor, blend_mode=blend_mode)[0]
    blending_image = WAS_Image_Blending_Mode.image_blending_mode(image_a=blend_image, image_b=output_image, mode=blending_mode, blend_percentage=blending_blend_percentage)[0]
    Image.fromarray(np.array(blending_image*255, dtype=np.uint8)[0]).save("/content/ultralytics.png")

    result = "/content/ultralytics.png"
    response = None
    try:
        source_id = values['source_id']
        del values['source_id']
        source_channel = values['source_channel']     
        del values['source_channel']
        job_id = values['job_id']
        del values['job_id']
        default_filename = os.path.basename(result)
        files = {default_filename: open(result, "rb").read()}
        payload = {"content": f"{json.dumps(values)} <@{source_id}>"}
        response = requests.post(
            f"https://discord.com/api/v9/channels/{source_channel}/messages",
            data=payload,
            headers={"authorization": f"Bot {discord_token}"},
            files=files
        )
        response.raise_for_status()
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        if os.path.exists(result):
            os.remove(result)

    if response and response.status_code == 200:
        try:
            payload = {"jobId": job_id, "result": response.json()['attachments'][0]['url']}
            requests.post(f"{web_uri}/api/notify", data=json.dumps(payload), headers={'Content-Type': 'application/json', "authorization": f"{web_token}"})
        except Exception as e:
            print(f"An unexpected error occurred: {e}")
        finally:
            return {"result": response.json()['attachments'][0]['url']}
    else:
        return {"result": "ERROR"}

runpod.serverless.start({"handler": generate})