first commit
This commit is contained in:
39
Dockerfile
Normal file
39
Dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Change CUDA and cuDNN version here
|
||||||
|
FROM nvidia/cuda:12.4.1-base-ubuntu22.04
|
||||||
|
ARG PYTHON_VERSION=3.11
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
software-properties-common \
|
||||||
|
wget \
|
||||||
|
&& add-apt-repository ppa:deadsnakes/ppa \
|
||||||
|
&& apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python$PYTHON_VERSION \
|
||||||
|
python$PYTHON_VERSION-dev \
|
||||||
|
python$PYTHON_VERSION-venv \
|
||||||
|
&& wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||||
|
&& python$PYTHON_VERSION get-pip.py \
|
||||||
|
&& rm get-pip.py \
|
||||||
|
&& ln -sf /usr/bin/python$PYTHON_VERSION /usr/bin/python \
|
||||||
|
&& ln -sf /usr/local/bin/pip$PYTHON_VERSION /usr/local/bin/pip \
|
||||||
|
&& python --version \
|
||||||
|
&& pip --version \
|
||||||
|
&& apt-get purge -y --auto-remove software-properties-common \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
####### Add your own installation commands here #######
|
||||||
|
# RUN pip install some-package
|
||||||
|
# RUN wget https://path/to/some/data/or/weights
|
||||||
|
RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 -y \
|
||||||
|
&& apt install -y build-essential g++
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
# Install litserve and requirements
|
||||||
|
RUN pip install --no-cache-dir litserve==0.2.16
|
||||||
|
RUN pip install -r requirements-GPU.txt
|
||||||
|
RUN pip install opencv-python
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["python", "/app/litserver_main.py"]
|
||||||
8
README-AIDA-LC.md
Normal file
8
README-AIDA-LC.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
创建Docker file:
|
||||||
|
litserve dockerize server.py --port 8000 --gpu
|
||||||
|
|
||||||
|
构建镜像:
|
||||||
|
docker build -t litserve-model .
|
||||||
|
|
||||||
|
运行容器:
|
||||||
|
docker run -p 8000:8000 litserve-model
|
||||||
7
client.py
Normal file
7
client.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is auto-generated by LitServe.
|
||||||
|
# Disable auto-generation by setting `generate_client_file=False` in `LitServer.run()`.
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
response = requests.post("http://127.0.0.1:8080/predict", json={"input": 4.0})
|
||||||
|
print(f"Status: {response.status_code}\nResponse:\n {response.text}")
|
||||||
93
codeformer_wrapper_no_path.py
Normal file
93
codeformer_wrapper_no_path.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import os
|
||||||
|
import torch
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from pathlib import Path
|
||||||
|
from torchvision.transforms.functional import normalize
|
||||||
|
from basicsr.utils import img2tensor, tensor2img
|
||||||
|
from basicsr.utils.download_util import load_file_from_url
|
||||||
|
from facelib.utils.face_restoration_helper import FaceRestoreHelper
|
||||||
|
from basicsr.utils.registry import ARCH_REGISTRY
|
||||||
|
|
||||||
|
# Cross-platform device selection: CUDA > MPS > CPU
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
device = torch.device("cuda")
|
||||||
|
elif torch.backends.mps.is_available():
|
||||||
|
device = torch.device("mps")
|
||||||
|
else:
|
||||||
|
device = torch.device("cpu")
|
||||||
|
|
||||||
|
# Download and load model
|
||||||
|
pretrain_model_url = {
|
||||||
|
'restoration': 'https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth',
|
||||||
|
}
|
||||||
|
|
||||||
|
net = ARCH_REGISTRY.get('CodeFormer')(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9,
|
||||||
|
connect_list=['32', '64', '128', '256']).to(device)
|
||||||
|
|
||||||
|
ckpt_path = load_file_from_url(url=pretrain_model_url['restoration'],
|
||||||
|
model_dir='weights/CodeFormer', progress=True, file_name=None)
|
||||||
|
checkpoint = torch.load(ckpt_path, map_location=device)['params_ema']
|
||||||
|
net.load_state_dict(checkpoint)
|
||||||
|
net.eval()
|
||||||
|
|
||||||
|
face_helper = FaceRestoreHelper(
|
||||||
|
upscale_factor=1,
|
||||||
|
face_size=512,
|
||||||
|
crop_ratio=(1, 1),
|
||||||
|
det_model='retinaface_resnet50',
|
||||||
|
save_ext='jpg',
|
||||||
|
use_parse=True,
|
||||||
|
device=device
|
||||||
|
)
|
||||||
|
|
||||||
|
def _enhance_img(img: np.ndarray, w: float = 0.5) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Internal helper to enhance a numpy image with CodeFormer.
|
||||||
|
"""
|
||||||
|
face_helper.clean_all()
|
||||||
|
face_helper.read_image(img)
|
||||||
|
num_faces = face_helper.get_face_landmarks_5(only_center_face=False, resize=640, eye_dist_threshold=5)
|
||||||
|
if num_faces == 0:
|
||||||
|
return img # Return original if no faces detected
|
||||||
|
|
||||||
|
face_helper.align_warp_face()
|
||||||
|
|
||||||
|
for cropped_face in face_helper.cropped_faces:
|
||||||
|
cropped_face_t = img2tensor(cropped_face / 255., bgr2rgb=True, float32=True).to(device)
|
||||||
|
normalize(cropped_face_t, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True)
|
||||||
|
cropped_face_t = cropped_face_t.unsqueeze(0) # (1, 3, H, W), already on correct device
|
||||||
|
|
||||||
|
with torch.no_grad():
|
||||||
|
output = net(cropped_face_t, w=w, adain=True)[0]
|
||||||
|
restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1))
|
||||||
|
|
||||||
|
restored_face = restored_face.astype('uint8')
|
||||||
|
face_helper.add_restored_face(restored_face)
|
||||||
|
|
||||||
|
face_helper.get_inverse_affine(None)
|
||||||
|
restored_img = face_helper.paste_faces_to_input_image()
|
||||||
|
return restored_img
|
||||||
|
|
||||||
|
def enhance_image(img: str, w: float = 0.5) -> str:
|
||||||
|
"""
|
||||||
|
Enhances an input image using CodeFormer and saves it with a '.enhanced.jpg' suffix.
|
||||||
|
"""
|
||||||
|
# input_path = Path(input_image_path)
|
||||||
|
# output_path = input_path.with_name(f"{input_path.stem}.enhanced.jpg")
|
||||||
|
# img = cv2.imread(str(input_path), cv2.IMREAD_COLOR)
|
||||||
|
if img is None:
|
||||||
|
raise ValueError(f"Cannot read image")
|
||||||
|
|
||||||
|
restored_img = _enhance_img(img, w=w)
|
||||||
|
|
||||||
|
# os.makedirs(output_path.parent, exist_ok=True)
|
||||||
|
# cv2.imwrite(str(output_path), restored_img)
|
||||||
|
# print(f"Enhanced image saved to: {output_path}")
|
||||||
|
return restored_img
|
||||||
|
|
||||||
|
def enhance_image_memory(img: np.ndarray, w: float = 0.5) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Enhances an input image entirely in memory and returns the enhanced image.
|
||||||
|
"""
|
||||||
|
return _enhance_img(img, w=w)
|
||||||
70
litserver_main.py
Normal file
70
litserver_main.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import litserve as ls
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from refacer_no_path import Refacer as NoPathRefacer
|
||||||
|
from utils.minio_client import oss_get_image, minio_client, oss_upload_image
|
||||||
|
|
||||||
|
|
||||||
|
class PredictRequest(BaseModel):
|
||||||
|
input_image_list: list[str] # 待换脸图片
|
||||||
|
input_face: str # 目标脸图片
|
||||||
|
threshold: float = 0.2 # 相似度 max:0.5
|
||||||
|
|
||||||
|
|
||||||
|
class InferencePipeline(ls.LitAPI):
|
||||||
|
def setup(self, device):
|
||||||
|
force_cpu = False
|
||||||
|
colab_performance = False
|
||||||
|
self.supported_exts = {'jpg', 'jpeg', 'png', 'bmp', 'webp'}
|
||||||
|
self.refacer = NoPathRefacer(force_cpu=force_cpu, colab_performance=colab_performance)
|
||||||
|
|
||||||
|
def decode_request(self, request: PredictRequest):
|
||||||
|
self.input_image_list = []
|
||||||
|
for path in request.input_image_list:
|
||||||
|
self.input_image_list.append({
|
||||||
|
'img_obj': oss_get_image(oss_client=minio_client, path=path, data_type="cv2"),
|
||||||
|
'img_path': path
|
||||||
|
})
|
||||||
|
dest_img = oss_get_image(oss_client=minio_client, path=request.input_face, data_type="cv2")
|
||||||
|
faces_config = [
|
||||||
|
{
|
||||||
|
'origin': None,
|
||||||
|
'destination': dest_img,
|
||||||
|
'destination_path': request.input_face,
|
||||||
|
'threshold': request.threshold,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
self.refacer.prepare_faces(faces_config)
|
||||||
|
return faces_config
|
||||||
|
|
||||||
|
def predict(self, faces_config):
|
||||||
|
refaced_images_url = []
|
||||||
|
for i, image in enumerate(self.input_image_list):
|
||||||
|
ext = image['img_path'].rsplit(".", 1)[1].lower()
|
||||||
|
|
||||||
|
if ext not in self.supported_exts:
|
||||||
|
print(f"Skipping non-image file: {image['img_path']}")
|
||||||
|
continue
|
||||||
|
print(f"Refacing: {image['img_path']}")
|
||||||
|
try:
|
||||||
|
refaced_image = self.refacer.reface_image(image['img_obj'], faces_config, disable_similarity=True)
|
||||||
|
refaced_image_rgb = cv2.cvtColor(refaced_image, cv2.COLOR_RGB2BGR)
|
||||||
|
image_bytes = cv2.imencode('.jpg', refaced_image_rgb)[1].tobytes()
|
||||||
|
req = oss_upload_image(oss_client=minio_client, bucket="lanecarford", object_name=f"refaced_image/refaced{time.time()}.{ext}", image_bytes=image_bytes)
|
||||||
|
refaced_images_url.append(f"{req.bucket_name}/{req.object_name}")
|
||||||
|
print(f"Saved -> {req.bucket_name}/{req.object_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to process {image['img_path']}: {e}")
|
||||||
|
return refaced_images_url
|
||||||
|
|
||||||
|
def encode_response(self, output):
|
||||||
|
return {"output": output}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
api = InferencePipeline()
|
||||||
|
server = ls.LitServer(api, accelerator="gpu")
|
||||||
|
server.run(port=8080)
|
||||||
30
refacer.py
30
refacer.py
@@ -1,6 +1,9 @@
|
|||||||
import cv2
|
import cv2
|
||||||
import onnxruntime as rt
|
import onnxruntime as rt
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from utils.minio_client import oss_get_image, minio_client
|
||||||
|
|
||||||
sys.path.insert(1, './recognition')
|
sys.path.insert(1, './recognition')
|
||||||
from scrfd import SCRFD
|
from scrfd import SCRFD
|
||||||
from arcface_onnx import ArcFaceONNX
|
from arcface_onnx import ArcFaceONNX
|
||||||
@@ -40,9 +43,11 @@ if sys.platform in ("win32", "win64"):
|
|||||||
if hasattr(rt, "preload_dlls"):
|
if hasattr(rt, "preload_dlls"):
|
||||||
rt.preload_dlls()
|
rt.preload_dlls()
|
||||||
|
|
||||||
|
|
||||||
class RefacerMode(Enum):
|
class RefacerMode(Enum):
|
||||||
CPU, CUDA, COREML, TENSORRT = range(1, 5)
|
CPU, CUDA, COREML, TENSORRT = range(1, 5)
|
||||||
|
|
||||||
|
|
||||||
class Refacer:
|
class Refacer:
|
||||||
def __init__(self, force_cpu=False, colab_performance=False):
|
def __init__(self, force_cpu=False, colab_performance=False):
|
||||||
self.disable_similarity = False
|
self.disable_similarity = False
|
||||||
@@ -60,8 +65,8 @@ class Refacer:
|
|||||||
h_frame, w_frame = original_frame.shape[:2]
|
h_frame, w_frame = original_frame.shape[:2]
|
||||||
|
|
||||||
x1, y1, x2, y2 = map(int, face.bbox)
|
x1, y1, x2, y2 = map(int, face.bbox)
|
||||||
x1 = max(0, min(x1, w_frame-1))
|
x1 = max(0, min(x1, w_frame - 1))
|
||||||
y1 = max(0, min(y1, h_frame-1))
|
y1 = max(0, min(y1, h_frame - 1))
|
||||||
x2 = max(0, min(x2, w_frame))
|
x2 = max(0, min(x2, w_frame))
|
||||||
y2 = max(0, min(y2, h_frame))
|
y2 = max(0, min(y2, h_frame))
|
||||||
|
|
||||||
@@ -95,7 +100,6 @@ class Refacer:
|
|||||||
|
|
||||||
return blended_frame
|
return blended_frame
|
||||||
|
|
||||||
|
|
||||||
def __download_with_progress(self, url, output_path):
|
def __download_with_progress(self, url, output_path):
|
||||||
response = requests.get(url, stream=True)
|
response = requests.get(url, stream=True)
|
||||||
total_size = int(response.headers.get('content-length', 0))
|
total_size = int(response.headers.get('content-length', 0))
|
||||||
@@ -368,10 +372,6 @@ class Refacer:
|
|||||||
|
|
||||||
return converted_path, None
|
return converted_path, None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __generate_gif(self, video_path, gif_output_path):
|
def __generate_gif(self, video_path, gif_output_path):
|
||||||
os.makedirs(os.path.dirname(gif_output_path), exist_ok=True)
|
os.makedirs(os.path.dirname(gif_output_path), exist_ok=True)
|
||||||
print(f"Generating GIF at {gif_output_path}")
|
print(f"Generating GIF at {gif_output_path}")
|
||||||
@@ -400,13 +400,16 @@ class Refacer:
|
|||||||
self.first_face = False if multiple_faces_mode else (faces[0].get("origin") is None or disable_similarity)
|
self.first_face = False if multiple_faces_mode else (faces[0].get("origin") is None or disable_similarity)
|
||||||
self.partial_reface_ratio = partial_reface_ratio
|
self.partial_reface_ratio = partial_reface_ratio
|
||||||
|
|
||||||
ext = osp.splitext(image_path)[1].lower()
|
ext = osp.splitext(image_path)[1].lower() #
|
||||||
os.makedirs("output", exist_ok=True)
|
# ext = image_path.rsplit('.',1)[1].lower()
|
||||||
|
os.makedirs("output", exist_ok=True) #
|
||||||
|
|
||||||
original_name = osp.splitext(osp.basename(image_path))[0]
|
original_name = osp.splitext(osp.basename(image_path))[0]
|
||||||
timestamp = str(int(time.time()))
|
timestamp = str(int(time.time()))
|
||||||
|
|
||||||
if ext in ['.tif', '.tiff']:
|
if ext in ['.tif', '.tiff']:
|
||||||
pil_img = Image.open(image_path)
|
pil_img = Image.open(image_path) #
|
||||||
|
# pil_img = oss_get_image(oss_client=minio_client, path=image_path, data_type="PIL")
|
||||||
frames = []
|
frames = []
|
||||||
|
|
||||||
page_count = 0
|
page_count = 0
|
||||||
@@ -417,7 +420,8 @@ class Refacer:
|
|||||||
except EOFError:
|
except EOFError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
pil_img = Image.open(image_path)
|
pil_img = Image.open(image_path) #
|
||||||
|
# pil_img = oss_get_image(oss_client=minio_client, path=image_path, data_type="PIL")
|
||||||
|
|
||||||
with tqdm(total=page_count, desc="Processing TIFF pages") as pbar:
|
with tqdm(total=page_count, desc="Processing TIFF pages") as pbar:
|
||||||
for page in range(page_count):
|
for page in range(page_count):
|
||||||
@@ -436,7 +440,8 @@ class Refacer:
|
|||||||
return output_path
|
return output_path
|
||||||
|
|
||||||
else:
|
else:
|
||||||
bgr_image = cv2.imread(image_path)
|
bgr_image = cv2.imread(image_path) #
|
||||||
|
# bgr_image = oss_get_image(oss_client=minio_client, path=image_path, data_type="cv2")
|
||||||
if bgr_image is None:
|
if bgr_image is None:
|
||||||
raise ValueError("Failed to read input image")
|
raise ValueError("Failed to read input image")
|
||||||
|
|
||||||
@@ -450,7 +455,6 @@ class Refacer:
|
|||||||
print(f"Saved refaced image to {output_path}")
|
print(f"Saved refaced image to {output_path}")
|
||||||
return output_path
|
return output_path
|
||||||
|
|
||||||
|
|
||||||
def extract_faces_from_image(self, image_path, max_faces=5):
|
def extract_faces_from_image(self, image_path, max_faces=5):
|
||||||
frame = cv2.imread(image_path)
|
frame = cv2.imread(image_path)
|
||||||
if frame is None:
|
if frame is None:
|
||||||
|
|||||||
82
refacer_bulk_no_path.py
Normal file
82
refacer_bulk_no_path.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# refacer_bulk.py
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# python refacer_bulk.py --input_path ./input --dest_face myface.jpg --facetoreplace face1.jpg --threshold 0.3
|
||||||
|
#
|
||||||
|
# Or, to disable similarity check (i.e., just apply the destination face to all detected faces):
|
||||||
|
# python refacer_bulk.py --input_path ./input --dest_face myface.jpg
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from refacer_no_path import Refacer as NoPathRefacer
|
||||||
|
import pyfiglet
|
||||||
|
|
||||||
|
from utils.minio_client import oss_get_image, minio_client, oss_upload_image
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
input_path = [
|
||||||
|
"lanecarford/original_image/7450d6e8-bc54-4c85-940c-4a31c879e02f-0-89.png",
|
||||||
|
"lanecarford-outfits/outfits/outfit_6420.jpg",
|
||||||
|
"lanecarford-outfits/outfits/outfit_7579.jpg"
|
||||||
|
]
|
||||||
|
dest_face = "lanecarford/input_face/leijun.jpg"
|
||||||
|
facetoreplace = ""
|
||||||
|
threshold = 0.2
|
||||||
|
force_cpu = False
|
||||||
|
colab_performance = False
|
||||||
|
input_dir = input_path
|
||||||
|
|
||||||
|
refacer = NoPathRefacer(force_cpu=force_cpu, colab_performance=colab_performance)
|
||||||
|
|
||||||
|
# Load destination and origin face
|
||||||
|
dest_img = oss_get_image(oss_client=minio_client, path=dest_face, data_type="cv2")
|
||||||
|
if dest_img is None:
|
||||||
|
raise ValueError(f"Destination face image not found: {dest_face}")
|
||||||
|
|
||||||
|
origin_img = None
|
||||||
|
if facetoreplace:
|
||||||
|
origin_img = oss_get_image(oss_client=minio_client, path=facetoreplace, data_type="cv2")
|
||||||
|
if origin_img is None:
|
||||||
|
raise ValueError(f"Face to replace image not found: {facetoreplace}")
|
||||||
|
|
||||||
|
disable_similarity = origin_img is None
|
||||||
|
|
||||||
|
faces_config = [{
|
||||||
|
'origin': origin_img,
|
||||||
|
'destination': dest_img,
|
||||||
|
'threshold': threshold
|
||||||
|
}]
|
||||||
|
|
||||||
|
refacer.prepare_faces(faces_config, disable_similarity=disable_similarity)
|
||||||
|
|
||||||
|
print(f"Processing images from: {input_dir}")
|
||||||
|
image_files = list(input_dir)
|
||||||
|
supported_exts = {'jpg', 'jpeg', 'png', 'bmp', 'webp'}
|
||||||
|
|
||||||
|
refaced_images_url = []
|
||||||
|
for i, image_path in enumerate(image_files):
|
||||||
|
ext = image_path.rsplit(".", 1)[1].lower()
|
||||||
|
if ext not in supported_exts:
|
||||||
|
print(f"Skipping non-image file: {image_path}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"Refacing: {image_path}")
|
||||||
|
try:
|
||||||
|
refaced_image = refacer.reface_image(str(image_path), faces_config, disable_similarity=disable_similarity)
|
||||||
|
refaced_image_rgb = cv2.cvtColor(refaced_image, cv2.COLOR_RGB2BGR)
|
||||||
|
image_bytes = cv2.imencode('.jpg', refaced_image_rgb)[1].tobytes()
|
||||||
|
req = oss_upload_image(oss_client=minio_client, bucket="lanecarford", object_name=f"refaced_image/refaced{time.time()}.{ext}", image_bytes=image_bytes)
|
||||||
|
refaced_images_url.append(f"{req.bucket_name}/{req.object_name}")
|
||||||
|
print(f"Saved -> {req.bucket_name}/{req.object_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to process {image_path}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
31
refacer_server.py
Normal file
31
refacer_server.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from refacer import Refacer
|
||||||
|
from utils.minio_client import oss_get_image, minio_client
|
||||||
|
|
||||||
|
|
||||||
|
class ReFaceServer:
|
||||||
|
def __init__(self):
|
||||||
|
self.force_cpu = False
|
||||||
|
self.threshold = 0.2
|
||||||
|
self.colab_performance = False
|
||||||
|
self.refacer = Refacer(force_cpu=self.force_cpu, colab_performance=self.colab_performance)
|
||||||
|
|
||||||
|
def run(self, input_list, dest_face, facetoreplace):
|
||||||
|
dest_img = oss_get_image(oss_client=minio_client, path=dest_face, data_type="cv2")
|
||||||
|
if dest_img is None:
|
||||||
|
raise ValueError(f"Destination face image not found: {dest_face}")
|
||||||
|
|
||||||
|
origin_img = None
|
||||||
|
if facetoreplace:
|
||||||
|
origin_img = oss_get_image(oss_client=minio_client, path=facetoreplace, data_type="cv2")
|
||||||
|
if origin_img is None:
|
||||||
|
raise ValueError(f"Face to replace image not found: {facetoreplace}")
|
||||||
|
|
||||||
|
disable_similarity = origin_img is None
|
||||||
|
|
||||||
|
faces_config = [{
|
||||||
|
'origin': origin_img,
|
||||||
|
'destination': dest_img,
|
||||||
|
'threshold': self.threshold
|
||||||
|
}]
|
||||||
|
self.refacer.prepare_faces(faces_config, disable_similarity=disable_similarity)
|
||||||
|
print(f"Processing images from: {input_dir}")
|
||||||
@@ -18,3 +18,5 @@ pyfiglet==1.0.2
|
|||||||
# torchvision==0.21.0
|
# torchvision==0.21.0
|
||||||
gdown==5.2.0
|
gdown==5.2.0
|
||||||
lpips==0.1.4
|
lpips==0.1.4
|
||||||
|
opencv-python
|
||||||
|
minio
|
||||||
81
utils/minio_client.py
Normal file
81
utils/minio_client.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import io
|
||||||
|
import logging
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import urllib3
|
||||||
|
from PIL import Image
|
||||||
|
from minio import Minio
|
||||||
|
|
||||||
|
from utils.minio_config import MINIO_URL, MINIO_ACCESS, MINIO_SECRET, MINIO_SECURE
|
||||||
|
|
||||||
|
minio_client = Minio(MINIO_URL, access_key=MINIO_ACCESS, secret_key=MINIO_SECRET, secure=MINIO_SECURE)
|
||||||
|
|
||||||
|
|
||||||
|
# 自定义 Retry 类
|
||||||
|
class CustomRetry(urllib3.Retry):
|
||||||
|
def increment(self, method=None, url=None, response=None, error=None, **kwargs):
|
||||||
|
# 调用父类的 increment 方法
|
||||||
|
new_retry = super(CustomRetry, self).increment(method, url, response, error, **kwargs)
|
||||||
|
# 打印重试信息
|
||||||
|
logger.info(f"重试连接: {method} {url},错误: {error},重试次数: {self.total - new_retry.total}")
|
||||||
|
return new_retry
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
timeout = urllib3.Timeout(connect=1, read=10.0) # 连接超时 5 秒,读取超时 10 秒
|
||||||
|
http_client = urllib3.PoolManager(
|
||||||
|
num_pools=10, # 设置连接池大小
|
||||||
|
maxsize=10,
|
||||||
|
timeout=timeout,
|
||||||
|
cert_reqs='CERT_REQUIRED', # 需要证书验证
|
||||||
|
retries=CustomRetry(
|
||||||
|
total=5,
|
||||||
|
backoff_factor=0.2,
|
||||||
|
status_forcelist=[500, 502, 503, 504],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# 获取图片
|
||||||
|
def oss_get_image(oss_client, path, data_type):
|
||||||
|
# cv2 默认全通道读取
|
||||||
|
bucket = path.split("/", 1)[0]
|
||||||
|
object_name = path.split("/", 1)[1]
|
||||||
|
image_object = None
|
||||||
|
try:
|
||||||
|
image_data = oss_client.get_object(bucket_name=bucket, object_name=object_name)
|
||||||
|
if data_type == "cv2":
|
||||||
|
image_bytes = image_data.read()
|
||||||
|
image_array = np.frombuffer(image_bytes, np.uint8) # 转成8位无符号整型
|
||||||
|
image_object = cv2.imdecode(image_array, cv2.IMREAD_UNCHANGED)
|
||||||
|
if image_object.dtype == np.uint16:
|
||||||
|
image_object = (image_object / 256).astype('uint8')
|
||||||
|
else:
|
||||||
|
data_bytes = BytesIO(image_data.read())
|
||||||
|
image_object = Image.open(data_bytes)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"获取图片出现异常 ######: {e}")
|
||||||
|
return image_object
|
||||||
|
|
||||||
|
|
||||||
|
def oss_upload_image(oss_client, bucket, object_name, image_bytes):
|
||||||
|
req = None
|
||||||
|
try:
|
||||||
|
req = oss_client.put_object(bucket_name=bucket, object_name=object_name, data=io.BytesIO(image_bytes), length=len(image_bytes), content_type='image/png')
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"上传图片出现异常 ######: {e}")
|
||||||
|
return req
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
url = "lanecarford/refaced_image/refaced1760687023.736802.png"
|
||||||
|
read_type = "1"
|
||||||
|
img = oss_get_image(oss_client=minio_client, path=url, data_type=read_type)
|
||||||
|
if read_type == "cv2":
|
||||||
|
cv2.imshow("", img)
|
||||||
|
cv2.waitKey(0)
|
||||||
|
else:
|
||||||
|
img.show()
|
||||||
|
img.save("result.png")
|
||||||
5
utils/minio_config.py
Normal file
5
utils/minio_config.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# minio 配置
|
||||||
|
MINIO_URL = "www.minio-api.aida.com.hk"
|
||||||
|
MINIO_ACCESS = 'vXKFLSJkYeEq2DrSZvkB'
|
||||||
|
MINIO_SECRET = 'uKTZT3x7C43WvPN9QTc99DiRkwddWZrG9Uh3JVlR'
|
||||||
|
MINIO_SECURE = True
|
||||||
Reference in New Issue
Block a user