1. はじめに

Real-ESRGAN は、実写画像の劣化を考慮した超解像モデルです。公式リポジトリと論文が公開されており、写真の拡大を試す OSS として扱いやすいです。サービス選定の全体像は AI 超解像サービス比較:Replicate・Real-ESRGAN・セルフホストの選び方【2026年版】 も参考になります。

この記事では、写真向けモデルを使い、Gradio で最小のサンプルアプリを作る手順に絞って説明します。

2. Real-ESRGAN を選ぶ理由

2.1 写真向けの OSS として始めやすい

Real-ESRGAN の公式実装は BSD-3-Clause です。商用検討時も比較的扱いやすく、Python から組み込みやすいです。

2.2 モデルの選び分けが明確

モデル向いている画像メモ
RealESRGAN_x4plus写真・一般画像まずはこれで検証しやすい
RealESRGAN_x4plus_anime_6Bアニメ・イラスト写真用途には通常は使わない

2.3 実運用で使う注意点が公式にそろっている

  • VRAM が厳しい場合は --tile が有効です
  • 顔補正は GFPGAN と組み合わせられます
  • 公式コードでは GPU が使えない場合に CPU 実行へ切り替える流れがあります

3. 環境構築

最小構成では Python 仮想環境を作り、公式リポジトリ準拠の依存関係を入れます。

なお、本構成は Python 3.11 を前提とします。Real-ESRGAN / basicsr / gfpgan などの依存ライブラリは 3.11 で安定して動作するため、仮想環境も 3.11 で作成します。複数の Python バージョンが混在する環境でも確実に 3.11 を指定できるよう、下記では python3.11 -m venv .venv と明示しています。

bash
python3.11 -m venv .venv
source .venv/bin/activate
git clone https://github.com/xinntao/Real-ESRGAN.git
cd Real-ESRGAN
# オプショナル: pip のアップグレード
pip install -U pip
pip install torch torchvision basicsr facexlib gfpgan pillow opencv-python gradio
pip install -e .

注意: Python 3.14 などの新しいバージョンで実行すると、上記の pip install(torch / basicsr など)の段階で、torchbasicsr などの依存パッケージが対応ホイールを提供しておらず、インストールに失敗しやすいです。このため本構成では前述のとおり Python 3.11 を使います。

次に、公式リリースから重みを取得して weights/ に置きます。

  • RealESRGAN_x4plus.pth
  • 必要なら RealESRGAN_x4plus_anime_6B.pth

4. サンプルアプリの最小構成

4.1 ディレクトリ構成

text
Real-ESRGAN/
├ app.py
└ weights/
   ├ RealESRGAN_x4plus.pth
   └ RealESRGAN_x4plus_anime_6B.pth

4.2 Gradio アプリのコード

python
# Compatibility shim: basicsr imports `torchvision.transforms.functional_tensor`,
# which was removed in newer torchvision. Recreate it before importing basicsr.
import sys
import types
import torchvision.transforms.functional as _tv_functional

if "torchvision.transforms.functional_tensor" not in sys.modules:
    _ft = types.ModuleType("torchvision.transforms.functional_tensor")
    _ft.rgb_to_grayscale = _tv_functional.rgb_to_grayscale
    sys.modules["torchvision.transforms.functional_tensor"] = _ft

import gradio as gr
import numpy as np
import torch
from functools import lru_cache
from basicsr.archs.rrdbnet_arch import RRDBNet
from gfpgan import GFPGANer
from PIL import Image
from realesrgan import RealESRGANer


DEVICE = "cuda" if torch.cuda.is_available() else "cpu"


@lru_cache(maxsize=8)
def build_upsampler(model_name: str, tile: int):
    if model_name == "RealESRGAN_x4plus_anime_6B":
        model = RRDBNet(
            num_in_ch=3, num_out_ch=3, num_feat=64,
            num_block=6, num_grow_ch=32, scale=4
        )
    else:
        model = RRDBNet(
            num_in_ch=3, num_out_ch=3, num_feat=64,
            num_block=23, num_grow_ch=32, scale=4
        )

    return RealESRGANer(
        scale=4,
        model_path=f"weights/{model_name}.pth",
        model=model,
        tile=tile,
        pre_pad=0,
        half=(DEVICE == "cuda"),
        gpu_id=0 if DEVICE == "cuda" else None,
    )


@lru_cache(maxsize=8)
def build_face_enhancer(model_name: str, tile: int):
    return GFPGANer(
        model_path="https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth",
        upscale=4,
        arch="clean",
        channel_multiplier=2,
        bg_upsampler=build_upsampler(model_name, tile),
    )


def upscale(image: Image.Image, model_name: str, face_enhance: bool, tile: int):
    upsampler = build_upsampler(model_name, tile)
    img = np.array(image.convert("RGB"))[:, :, ::-1]

    if face_enhance:
        face_enhancer = build_face_enhancer(model_name, tile)
        _, _, output = face_enhancer.enhance(
            img, has_aligned=False, only_center_face=False, paste_back=True
        )
    else:
        output, _ = upsampler.enhance(img, outscale=4)

    return Image.fromarray(output[:, :, ::-1])


demo = gr.Interface(
    fn=upscale,
    inputs=[
        gr.Image(type="pil", label="入力画像"),
        gr.Dropdown(
            ["RealESRGAN_x4plus", "RealESRGAN_x4plus_anime_6B"],
            value="RealESRGAN_x4plus",
            label="モデル",
        ),
        gr.Checkbox(label="顔補正を有効化 (GFPGAN)", value=False),
        gr.Slider(0, 512, value=0, step=32, label="tile"),
    ],
    outputs=gr.Image(type="pil", label="出力画像"),
    title="Real-ESRGAN Sample App",
)

demo.launch()

冒頭の互換性 shim は必須です。basicsrtorchvision.transforms.functional_tensor を import しますが、このモジュールは新しい torchvision で削除されています。shim を削除すると basicsr の import 時に ModuleNotFoundError が発生するため、functional_tensor を再作成するこのコードは必ず basicsr / realesrgan を import する前に置いてください。

この例では lru_cache を使い、起動後のプロセス内でモデル生成を再利用します。Gradio のリクエストごとに重みを再読込しないため、初回以降の待ち時間を減らしやすいです。また、PIL は RGB、Real-ESRGAN / GFPGAN は OpenCV 系の BGR 配列を前提にするため、推論の前後でチャンネル順を明示的に変換します。

5. 実行方法

bash
python app.py

ブラウザで表示された Gradio UI から画像を選びます。写真なら RealESRGAN_x4plus を選び、顔が主題なら GFPGAN を有効化します。メモリ不足が気になる場合は tile を 128 や 256 から試します。

6. 実行結果

実際に RealESRGAN_x4plus を適用した例を示します。まず、入力に使ったオリジナル写真です。これはアプリにアップロードした .jpg 形式の画像です。

Real-ESRGAN 適用前のオリジナル写真

次に、同じ画像を Real-ESRGAN で 4 倍に高解像度化した出力です。4.2 のコードは Image.fromarray(...) を返すだけですが、Gradio が出力画像をデフォルトで .webp として書き出すため、ここでは .webp 形式になっています。拡大後の解像度に対してファイルサイズを抑えやすい形式です。

Real-ESRGAN で 4 倍に高解像度化した写真

入力(.jpg)と出力(.webp)はサイズも形式も異なるため、ブラウザの拡大表示や原寸比較で見比べると差分を確認しやすいです。仕上がりは元画像の状態に依存するため、用途に合うかは手元の画像で実際に試して判断することをおすすめします。

7. ハマりやすいポイント

7.1 写真にアニメ向けモデルを使わない

RealESRGAN_x4plus_anime_6B はアニメ向けです。写真では RealESRGAN_x4plus を優先します。

7.2 GPU がなくても動くが遅くなりやすい

公式実装は GPU 前提で使われることが多いですが、CUDA が使えない環境では CPU 実行に切り替える構成を取りやすいです。検証用途では便利ですが、処理時間は環境依存で伸びやすいです。

7.3 OOM 対策は tile が基本

大きな画像でメモリ不足が出る場合は、まず tile を使って分割推論を試します。画質と速度のバランスを見ながら調整します。

7.4 顔補正は万能ではない

GFPGAN は Apache-2.0 で公開されており、人物写真では有効です。ただし、顔以外の細部改善が主目的なら、常時有効にせず比較して使う方が安全です。

7.5 ライセンス確認は先に行う

Real-ESRGAN は BSD-3-Clause、GFPGAN は Apache-2.0 で、いずれも寛容型 OSS です。ただし顔補正のモデルや opencv-python の同梱物など、商用提供で個別に確認しておきたい点があります。配布形態や同梱物が増える前に整理しておくと後戻りが少なくなります。詳しくは「8. ライセンスと商用利用の注意点」で扱います。

7.6 Python は 3.11 を使う

本構成の依存ライブラリ(Real-ESRGAN / basicsr / gfpgan など)は Python 3.11 への対応を前提に組み合わせています。3.11 より新しい、または古い Python では依存解決やビルドで失敗しやすく、環境構築の段階でつまずきがちです。特に Python 3.14 などの新しいバージョンでは、torchbasicsr が対応ホイールを用意していないため pip install の段階でエラーになりやすいです。環境を作る前に、使用する Python が 3.11 かどうかを確認しておくと後戻りが少なくなります。

7.7 互換性 shim を消さない

app.py 冒頭の互換性 shim は削除しないでください。basicsr が参照する torchvision.transforms.functional_tensor は新しい torchvision で削除されているため、shim で再作成してから basicsr / realesrgan を import しないと ImportErrorModuleNotFoundError)になります。配置順が重要で、必ず basicsr 系の import より前に置く必要があります。

8. ライセンスと商用利用の注意点

ここからは、サンプルアプリを商用サービスへ組み込む前提でライセンスを整理します。以下は公開された一次情報(各 OSS の LICENSE / README)に基づく一般的な整理であり、法的助言ではありません。最終判断は最新のライセンス原文の確認と、必要に応じた法務レビューに基づいてください。

8.1 依存コンポーネント別ライセンス一覧

本構成の主な依存は、いずれも寛容型 OSS(BSD-3-Clause / Apache-2.0 / MIT 系)です。強いコピーレフト(GPL/AGPL)はコア依存に含まれません。

コンポーネントライセンス商用利用主な義務 / 注意
Real-ESRGAN(本体)BSD-3-Clause著作権表示・ライセンス文・免責の保持
BasicSRApache-2.0著作権・NOTICE の保持、変更明示、特許条項
facexlibMIT著作権・ライセンス表示
GFPGAN(本体・clean 版モデル)Apache-2.0Apache の表示義務(論文モデルは後述の制約あり)
PyTorch / torchvision / NumPyBSD-3-Clause著作権表示の保持
PillowMIT-CMU(HPND 系)著作権表示の保持
GradioApache-2.0Apache の表示義務
opencv-pythonスクリプト=MIT / OpenCV 本体=Apache-2.0○(条件付き)wheel 同梱バイナリに注意(後述)

8.2 商用サービスへ組み込めるか

結論は 条件付きで可能 です。コア依存に GPL/AGPL はなく、各 OSS の 著作権表示とライセンス全文の同梱(帰属表示) を満たせば、SaaS / API として商用提供できます。Apache-2.0 のコンポーネント(BasicSR / GFPGAN / Gradio / OpenCV 本体)は NOTICE があれば同梱し、改変したファイルには変更を明示します。

ただし、次の 2 点は個別に確認しておく必要があります。

8.3 注意点1: GFPGAN 顔補正の制約

GFPGAN の本体コードと clean 版モデル(v1.2 / v1.3 / v1.4)は Apache-2.0 です。一方で 論文モデル(PaperModel) は、StyleGAN2(NVIDIA Source Code License = 非商用)と DFDNet(CC BY-NC-SA 4.0 = 非商用)に依存します。さらに学習データの FFHQ は CC BY-NC-SA 4.0(非商用)です。

  • 顔補正を商用提供する場合は、論文モデルを使わず clean 版モデルを使用し、念のため法務確認を行うのが安全です。
  • なお、clean 版でも FFHQ(非商用)学習・StyleGAN2 prior 由来の重みに非商用条項が波及するかはリポジトリ上で明示的に解決されておらず、「確実に商用可」とは断言できません。
  • 顔補正機能を使わなければ(Real-ESRGAN の超解像のみ)、この論点は回避できます。Real-ESRGAN 本体は BSD-3-Clause で、学習は「pure synthetic data」と説明されています。重みには個別のライセンス文が付与されていないため、本体の BSD-3-Clause に従うと解釈できます。

8.4 注意点2: opencv-python の wheel 同梱物

opencv-python の配布 wheel には FFmpeg(LGPL-2.1)が、非 headless の Linux wheel には Qt5(LGPL-3.0)が同梱されます。

  • SaaS(サーバ側で実行し、バイナリを配布しない) 場合、LGPL の主要義務は通常発生せず、ライセンス文の表記で足りる運用が一般的です。
  • wheel やコンテナイメージ、オンプレ製品として再配布する 場合は、同梱バイナリについて LGPL 義務(ライセンス文同梱・ライブラリ差し替え可能性の確保)が発生し得ます。
  • GUI が不要なサーバ用途では、opencv-python-headless を採用 すると Qt5(LGPL-3.0)を回避できます(FFmpeg は headless でも同梱される点に注意)。

8.5 出力物(高解像度化した画像)の取り扱い

  • ここで使う OSS ライセンス(BSD / Apache / MIT 系)は ソフトウェアのライセンス であり、生成した出力画像そのものに権利を主張する条項は含まれません。
  • ただし 入力画像の著作権・肖像権・パブリシティ権は別問題として残ります。第三者の写真や人物が写った写真を扱う場合は、権利者の許諾や本人同意が別途必要になり得ます。
  • 「学習データのライセンスが学習済みモデルの出力にまで及ぶか」は 法的に未確定 で、確立した判例も乏しいのが現状です。本記事の範囲では「商用可/不可」を断定できる一次情報は確認できませんでした。グレーな点として正直に共有します。

8.6 実務チェックリスト

  • 各 OSS の 著作権表示とライセンス全文 を製品の「ライセンス表記」または配布物に同梱した
  • Apache-2.0 の NOTICE があれば同梱し、改変ファイルに変更を明示した
  • 使用する .pth が配布元と一致し、GFPGAN の 論文モデルを使っていない ことを確認した
  • 顔補正を商用提供する場合は 法務確認を実施、または顔補正機能を外した
  • サーバ用途では opencv-python-headless を採用し、再配布時は FFmpeg(LGPL-2.1) の義務を満たした
  • 入力画像の 著作権・肖像権 について、利用規約・同意取得・権利者許諾のフローを整備した
  • 追加依存に GPL/AGPL が紛れ込んでいないか定期的にスキャンした

本セクションはライセンスの一般的な整理であり、法的助言ではありません。最終的な商用判断は最新のライセンス原文の確認と、必要に応じた弁護士・法務のレビューに基づいてください。

9. まとめ

Real-ESRGAN を使ったサンプルアプリは、公式実装に近い Python 構成と Gradio を組み合わせると、少ないコードで試せます。まずは写真向けの RealESRGAN_x4plus で始め、必要に応じて tile、CPU フォールバック、GFPGAN を追加する流れが実践的です。次の一歩としては、複数画像の一括処理、保存先の外部化、API 化を進めるとアプリらしさが増します。

10. 参考リンク


この記事の執筆にあたり、AI の支援を受けています。