Spaces:
Runtime error
Runtime error
sugarknight commited on
Commit ·
1d7cf5a
1
Parent(s): 18d6271
Add application file
Browse files- app.py +49 -0
- launch.py +139 -0
- mozaikukun.py +208 -0
- package.txt +3 -0
- requirements.txt +0 -0
app.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from PIL import Image
|
| 4 |
+
|
| 5 |
+
import mozaikukun as moza
|
| 6 |
+
from ultralytics import YOLO
|
| 7 |
+
|
| 8 |
+
object_detector = YOLO("yolov8x.pt")
|
| 9 |
+
segmenter = YOLO("myseg3.pt")
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def mosaic_process(input_img, pussy, penis, sex, anus, nipple):
|
| 13 |
+
img = Image.fromarray(np.uint8(input_img))
|
| 14 |
+
img = img.convert("RGBA")
|
| 15 |
+
|
| 16 |
+
process_mode = {
|
| 17 |
+
"pussy": pussy,
|
| 18 |
+
"penis": penis,
|
| 19 |
+
"sex": sex,
|
| 20 |
+
"anus": anus,
|
| 21 |
+
"nipple": nipple,
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
result = moza.process_and_analyze_image(img, object_detector, segmenter)
|
| 25 |
+
for key in result.keys():
|
| 26 |
+
if key not in process_mode:
|
| 27 |
+
continue
|
| 28 |
+
|
| 29 |
+
if process_mode.get(key) == "mosaic":
|
| 30 |
+
for mosaic_img in result[key]:
|
| 31 |
+
mosaic_img = mosaic_img.convert("RGBA")
|
| 32 |
+
img = Image.alpha_composite(img, mosaic_img)
|
| 33 |
+
|
| 34 |
+
return img
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
demo = gr.Interface(
|
| 38 |
+
fn=mosaic_process,
|
| 39 |
+
inputs=[
|
| 40 |
+
gr.Image(),
|
| 41 |
+
gr.Radio(choices=['raw', 'mosaic'], value='mosaic'),
|
| 42 |
+
gr.Radio(choices=['raw', 'mosaic'], value='mosaic'),
|
| 43 |
+
gr.Radio(choices=['raw', 'mosaic'], value='mosaic'),
|
| 44 |
+
gr.Radio(choices=['raw', 'mosaic'], value='raw'),
|
| 45 |
+
gr.Radio(choices=['raw', 'mosaic'], value='raw'),
|
| 46 |
+
],
|
| 47 |
+
outputs=["image"])
|
| 48 |
+
|
| 49 |
+
demo.launch(server_name='0.0.0.0')
|
launch.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import importlib.util
|
| 2 |
+
import os
|
| 3 |
+
import shlex
|
| 4 |
+
import subprocess
|
| 5 |
+
import sys
|
| 6 |
+
|
| 7 |
+
commandline_args = os.environ.get("COMMANDLINE_ARGS", "")
|
| 8 |
+
sys.argv += shlex.split(commandline_args)
|
| 9 |
+
|
| 10 |
+
python = sys.executable
|
| 11 |
+
git = os.environ.get("GIT", "git")
|
| 12 |
+
index_url = os.environ.get("INDEX_URL", "")
|
| 13 |
+
stored_commit_hash = None
|
| 14 |
+
skip_install = False
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def run(command, desc=None, errdesc=None, custom_env=None):
|
| 18 |
+
if desc is not None:
|
| 19 |
+
print(desc)
|
| 20 |
+
|
| 21 |
+
result = subprocess.run(
|
| 22 |
+
command,
|
| 23 |
+
stdout=subprocess.PIPE,
|
| 24 |
+
stderr=subprocess.PIPE,
|
| 25 |
+
shell=True,
|
| 26 |
+
env=os.environ if custom_env is None else custom_env,
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
if result.returncode != 0:
|
| 30 |
+
message = f"""{errdesc or 'Error running command'}.
|
| 31 |
+
Command: {command}
|
| 32 |
+
Error code: {result.returncode}
|
| 33 |
+
stdout: {result.stdout.decode(encoding="utf8", errors="ignore") if len(result.stdout)>0 else '<empty>'}
|
| 34 |
+
stderr: {result.stderr.decode(encoding="utf8", errors="ignore") if len(result.stderr)>0 else '<empty>'}
|
| 35 |
+
"""
|
| 36 |
+
raise RuntimeError(message)
|
| 37 |
+
|
| 38 |
+
return result.stdout.decode(encoding="utf8", errors="ignore")
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def check_run(command):
|
| 42 |
+
result = subprocess.run(
|
| 43 |
+
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
|
| 44 |
+
)
|
| 45 |
+
return result.returncode == 0
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def is_installed(package):
|
| 49 |
+
try:
|
| 50 |
+
spec = importlib.util.find_spec(package)
|
| 51 |
+
except ModuleNotFoundError:
|
| 52 |
+
return False
|
| 53 |
+
|
| 54 |
+
return spec is not None
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def commit_hash():
|
| 58 |
+
global stored_commit_hash
|
| 59 |
+
|
| 60 |
+
if stored_commit_hash is not None:
|
| 61 |
+
return stored_commit_hash
|
| 62 |
+
|
| 63 |
+
try:
|
| 64 |
+
stored_commit_hash = run(f"{git} rev-parse HEAD").strip()
|
| 65 |
+
except Exception:
|
| 66 |
+
stored_commit_hash = "<none>"
|
| 67 |
+
|
| 68 |
+
return stored_commit_hash
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def run_pip(args, desc=None):
|
| 72 |
+
if skip_install:
|
| 73 |
+
return
|
| 74 |
+
|
| 75 |
+
index_url_line = f" --index-url {index_url}" if index_url != "" else ""
|
| 76 |
+
return run(
|
| 77 |
+
f'"{python}" -m pip {args} --prefer-binary{index_url_line}',
|
| 78 |
+
desc=f"Installing {desc}",
|
| 79 |
+
errdesc=f"Couldn't install {desc}",
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def run_python(code, desc=None, errdesc=None):
|
| 84 |
+
return run(f'"{python}" -c "{code}"', desc, errdesc)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def extract_arg(args, name):
|
| 88 |
+
return [x for x in args if x != name], name in args
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def prepare_environment():
|
| 92 |
+
commit = commit_hash()
|
| 93 |
+
|
| 94 |
+
print(f"Python {sys.version}")
|
| 95 |
+
print(f"Commit hash: {commit}")
|
| 96 |
+
|
| 97 |
+
torch_command = os.environ.get(
|
| 98 |
+
"TORCH_COMMAND",
|
| 99 |
+
"pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118",
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
sys.argv, skip_install = extract_arg(sys.argv, "--skip-install")
|
| 103 |
+
if skip_install:
|
| 104 |
+
return
|
| 105 |
+
|
| 106 |
+
sys.argv, reinstall_torch = extract_arg(sys.argv, "--reinstall-torch")
|
| 107 |
+
ngrok = "--ngrok" in sys.argv
|
| 108 |
+
|
| 109 |
+
if reinstall_torch or not is_installed("torch") or not is_installed("torchaudio"):
|
| 110 |
+
run(
|
| 111 |
+
f'"{python}" -m {torch_command}',
|
| 112 |
+
"Installing torch and torchaudio",
|
| 113 |
+
"Couldn't install torch",
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
if not is_installed("pyngrok") and ngrok:
|
| 117 |
+
run_pip("install pyngrok", "ngrok")
|
| 118 |
+
|
| 119 |
+
run(
|
| 120 |
+
f'"{python}" -m pip install -r requirements.txt',
|
| 121 |
+
desc=f"Installing requirements",
|
| 122 |
+
errdesc=f"Couldn't install requirements",
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def start():
|
| 127 |
+
os.environ["PATH"] = (
|
| 128 |
+
os.path.join(os.path.dirname(__file__), "bin")
|
| 129 |
+
+ os.pathsep
|
| 130 |
+
+ os.environ.get("PATH", "")
|
| 131 |
+
)
|
| 132 |
+
subprocess.run(
|
| 133 |
+
[python, "webui.py", *sys.argv[1:]],
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
if __name__ == "__main__":
|
| 138 |
+
prepare_environment()
|
| 139 |
+
start()
|
mozaikukun.py
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import os
|
| 3 |
+
from glob import glob
|
| 4 |
+
import threading
|
| 5 |
+
from multiprocessing import Process, Queue
|
| 6 |
+
import json
|
| 7 |
+
import time
|
| 8 |
+
|
| 9 |
+
from PIL.Image import Image
|
| 10 |
+
from ultralytics import YOLO
|
| 11 |
+
from PIL import Image, ImageDraw
|
| 12 |
+
from typing import Dict, Tuple
|
| 13 |
+
|
| 14 |
+
BLOCK_SIZE_RATIO = 100
|
| 15 |
+
MARGIN_FACTOR = 3
|
| 16 |
+
MARGIN_EXTRA = 20
|
| 17 |
+
DEVICE='cpu' # Specify the device number when using CUDA. Example: DEVICE='0'
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def calculate_pixel_block_and_margin(image: Image.Image) -> Tuple[int, int]:
|
| 21 |
+
"""
|
| 22 |
+
Calculate the pixel block size and margin based on image dimension.
|
| 23 |
+
"""
|
| 24 |
+
block_size = math.ceil(max(image.width, image.height) / BLOCK_SIZE_RATIO)
|
| 25 |
+
margin = block_size * MARGIN_FACTOR + MARGIN_EXTRA
|
| 26 |
+
return block_size, margin
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def resize_bounding_box(bounding_box: Dict[str, int], margin: int, block_size: int) -> Dict[str, int]:
|
| 30 |
+
"""
|
| 31 |
+
Resize the bounding box by adding the margin.
|
| 32 |
+
"""
|
| 33 |
+
bounding_box["x1"] = int((bounding_box["x1"] - margin) / block_size) * block_size
|
| 34 |
+
bounding_box["x2"] = int(math.ceil((bounding_box["x2"] + margin) / block_size) * block_size)
|
| 35 |
+
|
| 36 |
+
bounding_box["y1"] = int((bounding_box["y1"] - margin) / block_size) * block_size
|
| 37 |
+
bounding_box["y2"] = int(math.ceil((bounding_box["y2"] + margin) / block_size) * block_size)
|
| 38 |
+
|
| 39 |
+
return bounding_box
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def create_transparent_mask(segment_box: Dict[str, int], segments: Dict[str, list]) -> tuple[Image, Image]:
|
| 43 |
+
"""
|
| 44 |
+
Create a transparent mask for image segmentation.
|
| 45 |
+
"""
|
| 46 |
+
empty_mask = Image.new("RGBA", (
|
| 47 |
+
int(segment_box["x2"] - segment_box["x1"]), int(segment_box["y2"] - segment_box["y1"])), (0, 0, 0, 0))
|
| 48 |
+
mask = Image.new('RGBA', (
|
| 49 |
+
int(segment_box["x2"] - segment_box["x1"]), int(segment_box["y2"] - segment_box["y1"])), (0, 0, 0, 0))
|
| 50 |
+
mask_draw = ImageDraw.Draw(mask)
|
| 51 |
+
|
| 52 |
+
adjusted_x_segments = [math.ceil(segment_x) - segment_box["x1"] for segment_x in segments['x']]
|
| 53 |
+
adjusted_y_segments = [math.ceil(segment_y) - segment_box["y1"] for segment_y in segments['y']]
|
| 54 |
+
|
| 55 |
+
polygon_points = list(zip(adjusted_x_segments, adjusted_y_segments))
|
| 56 |
+
mask_draw.polygon(polygon_points, fill=(255, 255, 255, 255))
|
| 57 |
+
|
| 58 |
+
for i in range(len(polygon_points) - 1):
|
| 59 |
+
mask_draw.line([polygon_points[i], polygon_points[i + 1]], fill=(255, 255, 255, 255), width=5)
|
| 60 |
+
|
| 61 |
+
return mask, empty_mask
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def apply_mask_on_image(cropped_region: Image.Image, segment_box: Dict[str, int], mask: Image.Image,
|
| 65 |
+
empty_mask: Image.Image) -> Image.Image:
|
| 66 |
+
"""
|
| 67 |
+
Apply the created mask on the image.
|
| 68 |
+
"""
|
| 69 |
+
segment_region = cropped_region.crop(
|
| 70 |
+
(segment_box["x1"], segment_box["y1"], segment_box["x2"], segment_box["y2"]))
|
| 71 |
+
empty_mask.paste(segment_region)
|
| 72 |
+
|
| 73 |
+
masked_image = Image.new("RGBA", empty_mask.size)
|
| 74 |
+
masked_image.paste(empty_mask, mask=mask)
|
| 75 |
+
return masked_image
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def generate_mosaic(masked_image: Image.Image, block_size: int) -> Image.Image:
|
| 79 |
+
"""
|
| 80 |
+
Generate a mosaic image from the masked image and block size.
|
| 81 |
+
"""
|
| 82 |
+
small_masked_image = masked_image.resize(
|
| 83 |
+
(int(masked_image.size[0] // block_size), int(masked_image.size[1] // block_size)), Image.BILINEAR)
|
| 84 |
+
mosaic_masked_image = small_masked_image.resize(masked_image.size, Image.NEAREST)
|
| 85 |
+
return mosaic_masked_image
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def image_detection_worker(process_id: int, input_queue: Queue, result_queue: Queue):
|
| 89 |
+
print(f"start subprocess {process_id}")
|
| 90 |
+
object_detector = YOLO("yolov8x.pt")
|
| 91 |
+
segmenter = YOLO("myseg3.pt")
|
| 92 |
+
while True:
|
| 93 |
+
img, name = input_queue.get()
|
| 94 |
+
print(f"{process_id}: get {name}")
|
| 95 |
+
start_time = time.time()
|
| 96 |
+
result_queue.put((process_and_analyze_image(img, object_detector, segmenter), name))
|
| 97 |
+
end_time = time.time()
|
| 98 |
+
elapsed_time = end_time - start_time
|
| 99 |
+
print(f"{process_id}: put ({elapsed_time} sec) {name}")
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def process_and_analyze_image(image: Image.Image, object_detector: YOLO, segmenter: YOLO) -> Dict:
|
| 103 |
+
"""
|
| 104 |
+
Process a single image, analyze it and save the result.
|
| 105 |
+
"""
|
| 106 |
+
original_image = image.convert("RGBA")
|
| 107 |
+
|
| 108 |
+
block_size, margin = calculate_pixel_block_and_margin(original_image)
|
| 109 |
+
|
| 110 |
+
detection_results = object_detector(original_image, save=False, device=DEVICE, project="yolov8x", name="pname1",
|
| 111 |
+
verbose=False)
|
| 112 |
+
|
| 113 |
+
result = {}
|
| 114 |
+
sensitive_areas = ["pussy", "penis", "sex"]
|
| 115 |
+
|
| 116 |
+
for detection in detection_results:
|
| 117 |
+
for detected_object in json.loads(detection.tojson()):
|
| 118 |
+
if detected_object["name"] != "person":
|
| 119 |
+
continue
|
| 120 |
+
bounding_box = resize_bounding_box(detected_object["box"], margin, block_size)
|
| 121 |
+
|
| 122 |
+
cropped_region = original_image.crop(
|
| 123 |
+
(bounding_box["x1"], bounding_box["y1"], bounding_box["x2"], bounding_box["y2"]))
|
| 124 |
+
|
| 125 |
+
segmentation_results = segmenter(cropped_region, save=False, device=DEVICE, project="myseg2", name="pname2",
|
| 126 |
+
verbose=False)
|
| 127 |
+
for segmentation in segmentation_results:
|
| 128 |
+
for segmented_object in json.loads(segmentation.tojson()):
|
| 129 |
+
name = segmented_object["name"]
|
| 130 |
+
#if name not in sensitive_areas:
|
| 131 |
+
# continue
|
| 132 |
+
segments = segmented_object["segments"]
|
| 133 |
+
segment_box = resize_bounding_box(segmented_object["box"], margin, block_size)
|
| 134 |
+
|
| 135 |
+
if len(segments.get("x", [])) <= 2:
|
| 136 |
+
continue
|
| 137 |
+
if len(segments.get("y", [])) <= 2:
|
| 138 |
+
continue
|
| 139 |
+
|
| 140 |
+
mask, empty_mask = create_transparent_mask(segment_box, segments)
|
| 141 |
+
masked_image = apply_mask_on_image(cropped_region, segment_box, mask, empty_mask)
|
| 142 |
+
mosaic_masked_image = generate_mosaic(masked_image, block_size)
|
| 143 |
+
|
| 144 |
+
final_image = Image.new('RGBA', original_image.size)
|
| 145 |
+
mosaic_position = (
|
| 146 |
+
int(bounding_box["x1"] + segment_box["x1"]), int(bounding_box["y1"] + segment_box["y1"]))
|
| 147 |
+
final_image.paste(mosaic_masked_image, mosaic_position)
|
| 148 |
+
if name not in result:
|
| 149 |
+
result[name] = []
|
| 150 |
+
result[name].append(increase_image_opacity(final_image))
|
| 151 |
+
|
| 152 |
+
return result
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def increase_image_opacity(img: Image.Image, rate: int = 10) -> Image.Image:
|
| 156 |
+
img = img.convert("RGBA") # ensure image has alpha channel
|
| 157 |
+
|
| 158 |
+
datas = img.getdata()
|
| 159 |
+
new_data = []
|
| 160 |
+
for item in datas:
|
| 161 |
+
if item[3] != 0:
|
| 162 |
+
new_data.append((item[0], item[1], item[2], min(255, int(item[3] * rate))))
|
| 163 |
+
else:
|
| 164 |
+
new_data.append(item) # leave fully transparent pixel as it is
|
| 165 |
+
img.putdata(new_data)
|
| 166 |
+
return img
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def main():
|
| 170 |
+
print("Start processing...")
|
| 171 |
+
worker_count = 3
|
| 172 |
+
|
| 173 |
+
worker_processes = []
|
| 174 |
+
worker_queue = {}
|
| 175 |
+
task_queue = Queue()
|
| 176 |
+
result_queue = Queue()
|
| 177 |
+
|
| 178 |
+
for worker_number in range(worker_count):
|
| 179 |
+
worker_queue[worker_number] = Queue()
|
| 180 |
+
p = Process(
|
| 181 |
+
target=image_detection_worker,
|
| 182 |
+
args=(worker_number, task_queue, result_queue, worker_queue[worker_number]))
|
| 183 |
+
p.start()
|
| 184 |
+
worker_processes.append(p)
|
| 185 |
+
|
| 186 |
+
output_dir = "output"
|
| 187 |
+
|
| 188 |
+
os.makedirs(output_dir, exist_ok=True)
|
| 189 |
+
|
| 190 |
+
for image_path in glob("input/*.jpg"):
|
| 191 |
+
task_queue.put((Image.open(image_path), image_path, {}))
|
| 192 |
+
|
| 193 |
+
sensitive_areas = ["pussy", "penis", "sex"]
|
| 194 |
+
|
| 195 |
+
while True:
|
| 196 |
+
result_data, image_name = result_queue.get()
|
| 197 |
+
for sensitive_area in sensitive_areas:
|
| 198 |
+
image_number = 0
|
| 199 |
+
for result_image in result_data[sensitive_area]:
|
| 200 |
+
new_image_filename = (f"{os.path.splitext(os.path.basename(image_name))[0]}_"
|
| 201 |
+
f"{sensitive_area}_{image_number}.png")
|
| 202 |
+
image_save_path = os.path.join(output_dir, new_image_filename)
|
| 203 |
+
result_image.save(image_save_path)
|
| 204 |
+
image_number += 1
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
if __name__ == '__main__':
|
| 208 |
+
main()
|
package.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
libgl1-mesa-glx
|
| 2 |
+
libgl1-mesa-dri
|
| 3 |
+
|
requirements.txt
ADDED
|
Binary file (108 Bytes). View file
|
|
|