import sys import os # 依存関係のインストール(basicsrを明示的にインストール) os.system("git clone https://github.com/sczhou/CodeFormer.git") os.system("pip install basicsr facexlib gfpgan") # 主要な依存関係を先にインストール os.system("cd CodeFormer && pip install -r requirements.txt") os.system("pip install -e ./CodeFormer") os.system("pip install -e ./CodeFormer/basicsr") # パスを追加(CodeFormerとそのサブディレクトリ) sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('CodeFormer')) sys.path.insert(0, os.path.abspath('CodeFormer/CodeFormer')) sys.path.insert(0, os.path.abspath('CodeFormer/basicsr')) os.makedirs("/home/user/app/CodeFormer/basicsr", exist_ok=True) with open("/home/user/app/CodeFormer/basicsr/version.py", "w") as f: f.write("__version__ = '1.0.0'\n__gitsha__ = 'unknown'\n") # ウェイトファイルをダウンロード weights = { 'realesr-general-x4v3.pth': 'https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth', 'GFPGANv1.2.pth': 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.2.pth', 'GFPGANv1.3.pth': 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth', 'GFPGANv1.4.pth': 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth', 'RestoreFormer.pth': 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/RestoreFormer.pth', 'CodeFormer.pth': 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/CodeFormer.pth' } for filename, url in weights.items(): if not os.path.exists(filename): os.system(f"wget {url} -O {filename}") import cv2 import torch from flask import Flask, request, jsonify, send_file from basicsr.archs.srvgg_arch import SRVGGNetCompact from gfpgan.utils import GFPGANer from realesrgan.utils import RealESRGANer import uuid import tempfile from torchvision.transforms.functional import normalize from torchvision import transforms from PIL import Image from basicsr.utils import img2tensor, tensor2img from facexlib.utils.face_restoration_helper import FaceRestoreHelper from CodeFormer.codeformer_arch import CodeFormer app = Flask(__name__) # モデルの初期化 model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu') model_path = 'realesr-general-x4v3.pth' half = True if torch.cuda.is_available() else False upsampler = RealESRGANer(scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half) os.makedirs('output', exist_ok=True) def restore_with_codeformer(img, scale=2, weight=0.5): device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') net = CodeFormer(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9, connect_list=['32', '64', '128', '256']).to(device) net.load_state_dict(torch.load('CodeFormer.pth')['params_ema']) net.eval() img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = Image.fromarray(img) face_helper = FaceRestoreHelper( upscale_factor=scale, face_size=512, crop_ratio=(1, 1), use_parse=True, device=device) face_helper.clean_all() face_helper.read_image(img) face_helper.get_face_landmarks_5(only_center_face=False, resize=640) face_helper.align_warp_face() for idx, cropped_face in enumerate(face_helper.cropped_faces): cropped_face_t = img2tensor(cropped_face / 255.0, bgr2rgb=False, float32=True) normalize(cropped_face_t, [0.5], [0.5], inplace=True) cropped_face_t = cropped_face_t.unsqueeze(0).to(device) with torch.no_grad(): output = net(cropped_face_t, w=weight, adain=True)[0] restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1)) face_helper.add_restored_face(restored_face) restored_img = face_helper.paste_faces_to_input_image() return cv2.cvtColor(restored_img, cv2.COLOR_RGB2BGR) @app.route('/api/restore', methods=['POST']) def restore_image(): try: if 'file' not in request.files: return jsonify({'error': 'No file uploaded'}), 400 file = request.files['file'] version = request.form.get('version', 'v1.4') scale = float(request.form.get('scale', 2)) weight = float(request.form.get('weight', 0.5)) temp_dir = tempfile.mkdtemp() input_path = os.path.join(temp_dir, file.filename) file.save(input_path) extension = os.path.splitext(os.path.basename(str(input_path)))[1] img = cv2.imread(input_path, cv2.IMREAD_UNCHANGED) if len(img.shape) == 3 and img.shape[2] == 4: img_mode = 'RGBA' elif len(img.shape) == 2: img_mode = None img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) else: img_mode = None h, w = img.shape[0:2] if h < 300: img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4) if version == 'v1.2': face_enhancer = GFPGANer( model_path='GFPGANv1.2.pth', upscale=2, arch='clean', channel_multiplier=2, bg_upsampler=upsampler) _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True) elif version == 'v1.3': face_enhancer = GFPGANer( model_path='GFPGANv1.3.pth', upscale=2, arch='clean', channel_multiplier=2, bg_upsampler=upsampler) _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True) elif version == 'v1.4': face_enhancer = GFPGANer( model_path='GFPGANv1.4.pth', upscale=2, arch='clean', channel_multiplier=2, bg_upsampler=upsampler) _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True) elif version == 'RestoreFormer': face_enhancer = GFPGANer( model_path='RestoreFormer.pth', upscale=2, arch='RestoreFormer', channel_multiplier=2, bg_upsampler=upsampler) _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True) elif version == 'CodeFormer': output = restore_with_codeformer(img, scale=scale, weight=weight) elif version == 'RealESR-General-x4v3': face_enhancer = GFPGANer( model_path='realesr-general-x4v3.pth', upscale=2, arch='realesr-general', channel_multiplier=2, bg_upsampler=upsampler) _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True) if scale != 2: interpolation = cv2.INTER_AREA if scale < 2 else cv2.INTER_LANCZOS4 h, w = img.shape[0:2] output = cv2.resize(output, (int(w * scale / 2), int(h * scale / 2)), interpolation=interpolation) output_filename = f'output_{uuid.uuid4().hex}' if img_mode == 'RGBA': output_path = os.path.join('output', f'{output_filename}.png') cv2.imwrite(output_path, output) mimetype = 'image/png' else: output_path = os.path.join('output', f'{output_filename}.jpg') cv2.imwrite(output_path, output) mimetype = 'image/jpeg' return send_file(output_path, mimetype=mimetype, as_attachment=True, download_name=os.path.basename(output_path)) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/') def index(): return """ Image Upscaling & Restoration API

Image Upscaling & Restoration API

Result:

API Usage:

// JavaScript fetch code will appear here
""" if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, debug=True)