File size: 5,046 Bytes
133a8d7
 
1e2d680
a7b1e41
1e2d680
a7b1e41
133a8d7
 
a7b1e41
 
133a8d7
 
a7b1e41
 
 
 
 
 
 
 
 
 
 
 
 
133a8d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7b1e41
133a8d7
 
 
 
 
 
 
 
 
 
 
a7b1e41
133a8d7
 
 
 
1e2d680
133a8d7
a7b1e41
133a8d7
 
a7b1e41
133a8d7
a7b1e41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133a8d7
a7b1e41
 
 
 
 
 
133a8d7
a7b1e41
 
133a8d7
a7b1e41
 
133a8d7
a7b1e41
 
37923f7
 
133a8d7
a7b1e41
 
133a8d7
a7b1e41
 
 
 
133a8d7
a7b1e41
 
133a8d7
a7b1e41
 
133a8d7
a7b1e41
133a8d7
a7b1e41
133a8d7
a7b1e41
 
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
import os
import cv2
import torch
import base64
import argparse
import numpy as np
import insightface
import onnxruntime
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

from face_swapper import Inswapper, paste_to_whole
from face_analyser import get_analysed_data
from face_parsing import init_parsing_model, get_parsed_mask


# Глобальные константы и переменные
USE_COLAB = user_args.colab
USE_CUDA = user_args.cuda
PROVIDER = ["CPUExecutionProvider"]
DETECT_SIZE = 640
DETECT_THRESH = 0.6
FACE_ANALYSER = None
FACE_SWAPPER = None
FACE_PARSER = None

## ------------------------------ USER ARGS ------------------------------

parser = argparse.ArgumentParser(description="Swap-Mukham Face Swapper")
parser.add_argument("--out_dir", help="Default Output directory", default=os.getcwd())
parser.add_argument("--batch_size", help="Gpu batch size", default=32)
parser.add_argument("--cuda", action="store_true", help="Enable cuda", default=False)
parser.add_argument(
    "--colab", action="store_true", help="Enable colab mode", default=False
)
user_args = parser.parse_args()

## ------------------------------ SET EXECUTION PROVIDER ------------------------------
# Note: Non CUDA users may change settings here

PROVIDER = ["CPUExecutionProvider"]

if USE_CUDA:
    available_providers = onnxruntime.get_available_providers()
    if "CUDAExecutionProvider" in available_providers:
        print("\n********** Running on CUDA **********\n")
        PROVIDER = ["CUDAExecutionProvider", "CPUExecutionProvider"]
    else:
        USE_CUDA = False
        print("\n********** CUDA unavailable running on CPU **********\n")
else:
    USE_CUDA = False
    print("\n********** Running on CPU **********\n")

device = "cuda" if USE_CUDA else "cpu"
EMPTY_CACHE = lambda: torch.cuda.empty_cache() if device == "cuda" else None


# Функции загрузки моделей
def load_face_analyser_model(name="buffalo_l"):
    global FACE_ANALYSER
    if FACE_ANALYSER is None:
        FACE_ANALYSER = insightface.app.FaceAnalysis(name=name, providers=PROVIDER)
        FACE_ANALYSER.prepare(
            ctx_id=0, det_size=(DETECT_SIZE, DETECT_SIZE), det_thresh=DETECT_THRESH
        )

def load_face_swapper_model(path="./assets/pretrained_models/inswapper_128.onnx"):
    global FACE_SWAPPER
    if FACE_SWAPPER is None:
        FACE_SWAPPER = Inswapper(model_file=path, batch_size=1, providers=PROVIDER)

def load_face_parser_model(path="./assets/pretrained_models/79999_iter.pth"):
    global FACE_PARSER
    if FACE_PARSER is None:
        FACE_PARSER = init_parsing_model(path, device=device)

# Загрузка всех моделей
load_face_analyser_model()
load_face_swapper_model()
load_face_parser_model()

def base64_to_image(base64_string):
    img_data = base64.b64decode(base64_string)
    nparr = np.frombuffer(img_data, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    return img

def image_to_base64(image):
    _, buffer = cv2.imencode('.png', image)
    return base64.b64encode(buffer).decode('utf-8')

def process_images(source_img_base64, target_img_base64):
    # Декодирование base64 в изображения
    source_img = base64_to_image(source_img_base64)
    target_img = base64_to_image(target_img_base64)
    
    # Анализ лиц
    analysed_targets, analysed_sources, _, _ = get_analysed_data(
        FACE_ANALYSER,
        [target_img],
        source_img,
        swap_condition="First",
        detect_condition="best detection"
    )

    # Замена лица
    preds = []
    matrs = []
    for batch_pred, batch_matr in FACE_SWAPPER.batch_forward([target_img], analysed_targets, analysed_sources):
        preds.extend(batch_pred)
        matrs.extend(batch_matr)

    # Парсинг лица и создание маски
    masks = get_parsed_mask(FACE_PARSER, preds, classes=["skin", "l_brow", "r_brow", "l_eye", "r_eye", "nose", "u_lip", "l_lip", "mouth"], device='cpu')

    # Наложение результата обратно на изображение
    result_img = paste_to_whole(preds[0], target_img, matrs[0], mask=masks[0])

    # Кодирование результата в base64
    result_base64 = image_to_base64(result_img)

    return result_base64

# Создание FastAPI приложения
app = FastAPI(title="Faceswap API", description="API для замены лица. Отправьте два изображения в формате base64.")

# Определение модели запроса
class SwapRequest(BaseModel):
    source_img: str
    target_img: str

@app.post("/swap_face")
async def swap_face(request: SwapRequest):
    try:
        result = process_images(request.source_img, request.target_img)
        return {"result": result}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

# Запуск сервера
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)