| | from io import BytesIO |
| | import io |
| | import random |
| |
|
| | import requests |
| | import string |
| | import time |
| | from PIL import Image, ImageFilter |
| | import numpy as np |
| | import torch |
| | from dw_pose.main import dwpose |
| | from scipy.ndimage import binary_dilation |
| | from transformers import ViTFeatureExtractor, ViTForImageClassification |
| | import torch.nn.functional as F |
| | import transformers |
| | from diffusers import StableDiffusionControlNetInpaintPipeline, ControlNetModel, DDIMScheduler |
| | import os |
| | import pydash as _ |
| | import boto3 |
| |
|
| | is_production = True |
| |
|
| | age_detection_model = ViTForImageClassification.from_pretrained( |
| | 'nateraw/vit-age-classifier') |
| | age_detection_transforms = ViTFeatureExtractor.from_pretrained( |
| | 'nateraw/vit-age-classifier') |
| |
|
| | REPLICATE_API_KEY = "" |
| |
|
| | S3_REGION = "fra1" |
| | S3_ACCESS_ID = "0RN7BZXS59HYSBD3VB79" |
| | S3_ACCESS_SECRET = "hfSPgBlWl5jsGHa2xuByVkSpancgVeA2CVQf2EMp" |
| | S3_ENDPOINT_URL = "https://s3.solarcom.ch" |
| | S3_BUCKET_NAME = "pissnelke" |
| |
|
| | s3_session = boto3.session.Session() |
| | s3 = s3_session.client( |
| | service_name="s3", |
| | region_name=S3_REGION, |
| | aws_access_key_id=S3_ACCESS_ID, |
| | aws_secret_access_key=S3_ACCESS_SECRET, |
| | endpoint_url=S3_ENDPOINT_URL, |
| | ) |
| |
|
| | def find_bounding_box(pil_image): |
| | image_np = np.array(pil_image.convert('L')) |
| | white_pixels = np.argwhere(image_np == 255) |
| | x_min, y_min = np.min(white_pixels, axis=0) |
| | x_max, y_max = np.max(white_pixels, axis=0) |
| | return (y_min, x_min), (y_max, x_max) |
| |
|
| | def getSizeFromCoords(top_left, bottom_right): |
| | """ |
| | Calculate the width and height of a bounding box. |
| | |
| | Parameters: |
| | bounding_box (tuple): A tuple containing two tuples, |
| | the first is the top-left corner (x_min, y_min) |
| | and the second is the bottom-right corner (x_max, y_max). |
| | |
| | Returns: |
| | tuple: A tuple containing the width and height of the bounding box. |
| | """ |
| | (x_min, y_min), (x_max, y_max) = top_left, bottom_right |
| | width = x_max - x_min |
| | height = y_max - y_min |
| | return {"width": width, "height": height} |
| |
|
| |
|
| | def crop_to_coords(coords1, coords2, pil_image): |
| | top_left_x, top_left_y = coords1 |
| | bottom_right_x, bottom_right_y = coords2 |
| | cropped_image = pil_image.crop( |
| | (top_left_x, top_left_y, bottom_right_x, bottom_right_y)) |
| | return cropped_image |
| |
|
| |
|
| | def paste_image_at_coords(dest_image, src_image, coords): |
| | dest_image.paste(src_image, coords) |
| | return dest_image |
| |
|
| |
|
| | def resize(width, height, maxStretch): |
| | new_width = width * (maxStretch / max(width, height)) |
| | new_height = height * (maxStretch / max(width, height)) |
| |
|
| | return {"width": new_width, "height": new_height} |
| |
|
| |
|
| | def get_is_underage(input_pil): |
| | input_pil = input_pil.convert("RGB") |
| |
|
| | inputs = age_detection_transforms(input_pil, return_tensors='pt') |
| | output = age_detection_model(**inputs) |
| |
|
| | |
| | probabilities = F.softmax(output['logits'], dim=1) |
| |
|
| | |
| | predicted_class = probabilities.argmax().item() |
| |
|
| | map = { |
| | "0": "0-2", |
| | "1": "3-9", |
| | "2": "10-19", |
| | "3": "20-29", |
| | "4": "30-39", |
| | "5": "40-49", |
| | "6": "50-59", |
| | "7": "60-69", |
| | "8": "more than 70" |
| | } |
| |
|
| | print("Age:", map[str(predicted_class)], "years old") |
| |
|
| | if predicted_class < 3: |
| | return True |
| |
|
| | return False |
| |
|
| |
|
| | controlnet = ControlNetModel.from_pretrained( |
| | "lllyasviel/control_v11p_sd15_openpose", torch_dtype=torch.float16 |
| | ) |
| | base_pipe = StableDiffusionControlNetInpaintPipeline.from_pretrained( |
| | "redstonehero/epicrealism_pureevolutionv5-inpainting", controlnet=controlnet, torch_dtype=torch.float16 |
| | ) |
| | base_pipe.scheduler = DDIMScheduler.from_config(base_pipe.scheduler.config) |
| | base_pipe = base_pipe.to("cuda") |
| | |
| | base_pipe.safety_checker = None |
| | |
| |
|
| | pipe_with_tit_slider = _.clone_deep(base_pipe) |
| |
|
| | pipe_with_tit_slider.load_lora_weights(os.path.join("/repository" if is_production else ".", "models", "breastsizeslideroffset.safetensors"), weight_name="breastsizeslideroffset.safetensors", adapter_name="breastsizeslideroffset") |
| |
|
| | |
| | |
| |
|
| | |
| |
|
| | |
| | |
| |
|
| | def get_nude(original_pil, original_max_size=2000, generate_max_size=768, positive_prompt="nude girl, pussy, tits", negative_prompt="ugly", steps=20, cfg_scale=7, get_mask_function=None, with_small_tits=False, with_big_tits=False): |
| | try: |
| | exif_data = original_pil._getexif() |
| | orientation_tag = 274 |
| | if exif_data is not None and orientation_tag in exif_data: |
| | orientation = exif_data[orientation_tag] |
| | if orientation == 3: |
| | original_pil = original_pil.rotate(180, expand=True) |
| | elif orientation == 6: |
| | original_pil = original_pil.rotate(270, expand=True) |
| | elif orientation == 8: |
| | original_pil = original_pil.rotate(90, expand=True) |
| | except (AttributeError, KeyError, IndexError): |
| | |
| | pass |
| |
|
| | original_max_size = original_max_size or 2000 |
| | generate_max_size = generate_max_size or 768 |
| | positive_prompt = positive_prompt or "nude girl, pussy, tits" |
| | negative_prompt = negative_prompt or "ugly" |
| | steps = steps or 20 |
| | cfg_scale = cfg_scale or 7 |
| |
|
| | small_original_image = original_pil.copy() |
| |
|
| | small_original_image = small_original_image.convert("RGB") |
| |
|
| | small_original_image.thumbnail((original_max_size, original_max_size)) |
| |
|
| | start_time = time.time() |
| | is_underage = get_is_underage(small_original_image) |
| | print("get_is_underage", time.time() - start_time, "seconds") |
| |
|
| | if is_underage: |
| | raise Exception("Underage") |
| |
|
| | person_mask_pil_expanded = get_mask_function( |
| | small_original_image, "person", expand_by=20) |
| |
|
| | person_coords1, person_coords2 = find_bounding_box( |
| | person_mask_pil_expanded) |
| |
|
| | size = getSizeFromCoords(person_coords1, person_coords2) |
| |
|
| | there_height = size["height"] |
| | there_width = size["width"] |
| |
|
| | |
| | if there_height >= there_width: |
| | |
| | there_height_to_width = there_width / there_height |
| | then_height = 768 |
| | then_atleast_width = 768 * there_height_to_width |
| | else: |
| | |
| | there_width_to_height = there_height / there_width |
| | then_width = 768 |
| | then_atleast_height = 768 * there_width_to_height |
| |
|
| | |
| | if there_height >= there_width: |
| | then_width = then_atleast_width - (then_atleast_width % 8) + 8 |
| | crop_width = there_height * then_width / then_height |
| | crop_height = there_height |
| | else: |
| | then_height = then_atleast_height - (then_atleast_height % 8) + 8 |
| | crop_height = there_width * then_height / then_width |
| | crop_width = there_width |
| |
|
| | |
| | crop_coord_1 = ( |
| | person_coords1[0] - (crop_width - size["width"]), person_coords1[1]) |
| | crop_coord_2 = person_coords2 |
| |
|
| | if (crop_coord_1[0] < 0): |
| | crop_coord_1 = person_coords1 |
| | crop_coord_2 = ( |
| | person_coords2[0] + (crop_width - size["width"]), person_coords2[1]) |
| |
|
| | person_cropped_pil = crop_to_coords( |
| | crop_coord_1, crop_coord_2, small_original_image) |
| |
|
| | expanded_mask_image = get_mask_function( |
| | person_cropped_pil, "bra . blouse . skirt . dress", expand_by=10) |
| |
|
| | person_cropped_width, person_cropped_height = person_cropped_pil.size |
| | new_size = resize(crop_width, crop_height, generate_max_size) |
| |
|
| | dwpose_pil = dwpose(person_cropped_pil, 512) |
| |
|
| | expanded_mask_image_width, expanded_mask_image_height = expanded_mask_image.size |
| |
|
| | dwpose_pil_resized = dwpose_pil.resize( |
| | (int(expanded_mask_image_width), int(expanded_mask_image_height))) |
| |
|
| | end_result_images = pipe_with_tit_slider( |
| | positive_prompt, |
| | negative_prompt=negative_prompt, |
| | num_inference_steps=steps, |
| | guidance_scale=cfg_scale, |
| | eta=1.0, |
| | image=person_cropped_pil, |
| | mask_image=expanded_mask_image, |
| | control_image=dwpose_pil_resized, |
| | num_images_per_prompt=2, |
| | height=round(new_size["height"]), |
| | width=round(new_size["width"]), |
| | cross_attention_kwargs={"scale": -0.8} if with_small_tits else {"scale": 0.7} if with_big_tits else { "scale": 0 } |
| | ).images |
| |
|
| | |
| | def create_blurred_edge_mask(image, blur_radius): |
| | mask = Image.new("L", image.size, 0) |
| | mask.paste(255, [blur_radius, blur_radius, mask.width - |
| | blur_radius, mask.height - blur_radius]) |
| | return mask.filter(ImageFilter.GaussianBlur(blur_radius)) |
| |
|
| | output_pils = [] |
| |
|
| | |
| | for image in end_result_images: |
| | fit_into_group_image = image.resize( |
| | (person_cropped_width, person_cropped_height)) |
| |
|
| | |
| | blur_radius = 10 |
| | mask = create_blurred_edge_mask(fit_into_group_image, blur_radius) |
| |
|
| | |
| | small_original_image.paste( |
| | fit_into_group_image, (int(crop_coord_1[0]), crop_coord_1[1]), mask) |
| |
|
| | output_pils.append(small_original_image) |
| |
|
| | return output_pils |
| |
|
| | |
| |
|