高精度・高解像度・境界を綺麗 に背景を透過できるBiRefNet
BiRefNetとは
BiRefNet(Bilateral Reference Network) は、
高解像度の二値画像セグメンテーション(前景/背景の切り分け)に特化した最新モデル です。
用途は主に:
- 背景除去(人物・物体の切り抜き)
- 顕著物体検出(SOD)
- 高解像度画像のマスク生成
- マッティング(髪の毛などの細かい境界)
- カモフラージュ物体検出(COD)
- 医療画像などの二値セグメンテーション
とにかく 高精度・高解像度・境界が綺麗 というのが特徴。
インストール方法(公式推奨)
BiRefNet のコードを取得
git clone https://github.com/ZhengPeng7/BiRefNet
cd BiRefNet
必要ライブラリをインストール
(GitHub の requirements.txt を使用)
pip install -r requirements.txt
4. モデル(weights)をダウンロード
GitHub Releases(v1)または Google Drive から取得https://github.com/ZhengPeng7/BiRefNet/releases
BiRefNet のモデル種類と用途(重要)
BiRefNet は用途別に 複数のモデル が公開されています。
1. BiRefNet-general(General 用)
用途:人物・物体の背景除去、一般的な切り抜き
- 最も汎用的
- 人物・動物・物体など幅広く対応
- 実用アプリ(背景除去サービスなど)でよく使われる
人物切り抜きならまずこれ
2. BiRefNet_HR(高解像度用)
用途:高解像度写真(2048×2048 以上)で高品質なマスク
- 髪の毛・細かい境界が綺麗
- 写真・商品画像の切り抜きに最適
高画質写真の人物切り抜きに最適
3. BiRefNet_HR-matting(マッティング用)
用途:髪の毛・透明物・細かい境界のマッティング
- トリマップ不要
- 透明感のある境界が必要な場合に最強
髪の毛の自然な切り抜きが必要ならこれ
4. BiRefNet_dynamic(解像度可変モデル)
用途:解像度がバラバラの大量画像を処理したい場合
- 256?2304px の幅広い解像度に対応
- 実務向けの安定モデル
大量バッチ処理に向く
5. BiRefNet-lite / SwinT バージョン
用途:軽量・高速推論
- モバイル・低スペックGPU向け
- 精度はやや下がるが高速
速度重視ならこれ
6. BiRefNet-HRSOD / DIS / COD(研究用)
用途:特定データセット向け(研究・比較用)
- HRSOD:高解像度顕著物体検出
- DIS:高精細境界のセグメンテーション
- COD:カモフラージュ物体検出
一般ユーザーは不要
人物切り抜きに最適なモデルは?
あなたの用途(人物切り抜き)なら:
1位:BiRefNet-general(General)
- 最も汎用的で人物に強い
- ONNX 版もあり高速
2位:BiRefNet_HR
- 高解像度写真ならこちらが最強
3位:BiRefNet_HR-matting
- 髪の毛の自然さを重視するならこれ
ONNX推論コード
1つ上の場所に移す
"D:\WinPython\content\BiRefNet\birefnet.py"モデルのダウンロードと設置
- “D:\WinPython\content\BiRefNet\models\BiRefNet-general-epoch_244.onnx"
import os
import cv2
import argparse
import numpy as np
import onnxruntime
from PIL import Image
# ---------------------------------------------------------
# 1. デフォルトパス(指定が無い場合に使用)
# ---------------------------------------------------------
DEFAULT_MODEL_PATH = r"D:\WinPython\content\BiRefNet\models\BiRefNet-general-epoch_244.onnx"
DEFAULT_INPUT_DIR = r"D:\WinPython\content\BiRefNet\input_images"
DEFAULT_OUTPUT_DIR = r"D:\WinPython\content\BiRefNet\output_images"
# ---------------------------------------------------------
# 2. Sigmoid
# ---------------------------------------------------------
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# ---------------------------------------------------------
# 3. GPU があれば使うセッション生成
# ---------------------------------------------------------
def create_session(model_path):
available = onnxruntime.get_available_providers()
print("Available providers:", available)
providers = []
if "CUDAExecutionProvider" in available:
providers.append("CUDAExecutionProvider")
if "CPUExecutionProvider" in available:
providers.append("CPUExecutionProvider")
print("Using providers:", providers)
return onnxruntime.InferenceSession(model_path, providers=providers)
# ---------------------------------------------------------
# 4. ONNX 推論(色補正済み)
# ---------------------------------------------------------
def run_inference(onnx_session, bgr_image):
input_size = onnx_session.get_inputs()[0].shape
input_width = input_size[3]
input_height = input_size[2]
# ---- 前処理 ----
img = cv2.resize(bgr_image, (input_width, input_height))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # ★ RGB に変換(青み対策)
img = img.astype(np.float32) / 255.0 # ★ 正規化なし(ResNet-general)
img = img.transpose(2, 0, 1)
img = np.expand_dims(img, axis=0)
# ---- 推論 ----
input_name = onnx_session.get_inputs()[0].name
result = onnx_session.run(None, {input_name: img})
# ---- 後処理 ----
mask = np.squeeze(result[-1])
mask = sigmoid(mask)
mask = (mask * 255).astype(np.uint8)
return mask
# ---------------------------------------------------------
# 5. メイン処理
# ---------------------------------------------------------
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"-i", "--input",
type=str,
default=DEFAULT_INPUT_DIR,
help="入力フォルダー(省略時はデフォルト)"
)
parser.add_argument(
"-o", "--output",
type=str,
default=DEFAULT_OUTPUT_DIR,
help="出力フォルダー(省略時はデフォルト)"
)
parser.add_argument(
"-m", "--model",
type=str,
default=DEFAULT_MODEL_PATH,
help="ONNX モデルパス(省略時はデフォルト)"
)
args = parser.parse_args()
input_dir = args.input
output_dir = args.output
model_path = args.model
os.makedirs(output_dir, exist_ok=True)
print("Input folder :", input_dir)
print("Output folder:", output_dir)
print("Model path :", model_path)
print("\nLoading ONNX model...")
onnx_session = create_session(model_path)
print("Model loaded.\n")
valid_ext = [".jpg", ".jpeg", ".png", ".bmp", ".webp"]
print("Start processing images...\n")
for filename in os.listdir(input_dir):
if not any(filename.lower().endswith(ext) for ext in valid_ext):
continue
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(
output_dir, os.path.splitext(filename)[0] + ".png"
)
print("Processing:", filename)
bgr = cv2.imread(input_path)
if bgr is None:
print("Failed to read:", input_path)
continue
mask = run_inference(onnx_session, bgr)
mask = cv2.resize(mask, (bgr.shape[1], bgr.shape[0]))
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
rgba = np.dstack([rgb, mask])
Image.fromarray(rgba).save(output_path)
print("\nAll images processed successfully.")
if __name__ == "__main__":
main()
インストールと実行用バッチファイル
インストールが終わったら"D:\WinPython\content\BiRefNet\process_images_onnx.py"作ってください
@echo off
call %~dp0\scripts\env_for_icons.bat %*
SET PATH=%PATH%;%WINPYDIRBASE%\PortableGit;%WINPYDIRBASE%\PortableGit\bin
SET PATH=%PATH%;%WINPYDIRBASE%\ffmpeg\bin
If not exist %WINPYDIRBASE%\content mkdir %WINPYDIRBASE%\content
set APP_NAME=BiRefNet
set APP_DIR=%WINPYDIRBASE%\content\%APP_NAME%
cd %WINPYDIRBASE%\content\
If not exist %APP_DIR% git clone https://github.com/ZhengPeng7/BiRefNet
echo %APP_DIR%
cd %APP_DIR%
if not defined VENV_DIR (set "VENV_DIR=%APP_DIR%\venv")
if EXIST %VENV_DIR% goto :activate_venv
::python.exe -m venv "%VENV_DIR%"
python.exe -m venv "%VENV_DIR%" --system-site-packages
if %ERRORLEVEL% == 0 goto :activate_venv
echo Unable to create venv
goto :skip_venv
:activate_venv
call "%VENV_DIR%\Scripts\activate"
If exist %APP_DIR%\process_images_onnx.py goto :skip_cmd
::
pip install -r requirements.txt
::pip uninstall -y onnxruntime
pip install onnxruntime-gpu
cmd.exe /k
goto :skip_venv
:skip_cmd
If not exist Y:\input mkdir Y:\input
python process_images_onnx.py -i Y:\input -o Y:\output
::python process_images_onnx.py -t 80 -i Y:\input -o Y:\output
:skip_venv
timeout /t 55
::
cmd.exe /k
モデル切り替え
"--close マスクの穴埋め(closing)ピクセル数
"--model-type 使用するモデルタイプ(general / portrait)
"--threshold マスクしきい値(0〜255)
"--dilate マスク膨張ピクセル数(甘めにしたい場合)例
- 汎用(general)そのまま
python script.py --model-type general - 人物特化 portrait + 少し甘め
python script.py --model-type portrait -t 110 -d 4 - HR-matting で欠け対策強め
python script.py --model-type hrmatting --close 6 -d 3 -t 120
import os
import cv2
import argparse
import numpy as np
import onnxruntime
from PIL import Image
# ---------------------------------------------------------
# 1. デフォルトパス
# ---------------------------------------------------------
DEFAULT_MODEL_GENERAL = r"D:\WinPython\content\BiRefNet\models\BiRefNet-general-epoch_244.onnx"
DEFAULT_MODEL_PORTRAIT = r"D:\WinPython\content\BiRefNet\models\BiRefNet-portrait-epoch_150.onnx"
DEFAULT_MODEL_HRMATTING = r"D:\WinPython\content\BiRefNet\models\BiRefNet_HR-matting-epoch_135.onnx"
DEFAULT_INPUT_DIR = r"D:\WinPython\content\BiRefNet\input_images"
DEFAULT_OUTPUT_DIR = r"D:\WinPython\content\BiRefNet\output_images"
DEFAULT_THRESHOLD = 128
# ---------------------------------------------------------
# 2. Sigmoid
# ---------------------------------------------------------
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# ---------------------------------------------------------
# 3. GPU があれば使うセッション生成
# ---------------------------------------------------------
def create_session(model_path):
available = onnxruntime.get_available_providers()
print("Available providers:", available)
providers = []
if "CUDAExecutionProvider" in available:
providers.append("CUDAExecutionProvider")
if "CPUExecutionProvider" in available:
providers.append("CPUExecutionProvider")
print("Using providers:", providers)
return onnxruntime.InferenceSession(model_path, providers=providers)
# ---------------------------------------------------------
# 4. ONNX 推論
# ---------------------------------------------------------
def run_inference(onnx_session, bgr_image):
input_size = onnx_session.get_inputs()[0].shape
# (N, C, H, W)
input_height = input_size[2]
input_width = input_size[3]
img = cv2.resize(bgr_image, (input_width, input_height))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32) / 255.0
img = img.transpose(2, 0, 1) # (H, W, C) -> (C, H, W)
img = np.expand_dims(img, axis=0) # (1, C, H, W)
input_name = onnx_session.get_inputs()[0].name
result = onnx_session.run(None, {input_name: img})
# BiRefNet 系は最後の出力がマスク
mask = np.squeeze(result[-1])
mask = sigmoid(mask)
mask = (mask * 255).astype(np.uint8)
return mask
# ---------------------------------------------------------
# 5. メイン処理
# ---------------------------------------------------------
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"-i", "--input",
type=str,
default=DEFAULT_INPUT_DIR,
help="入力フォルダー"
)
parser.add_argument(
"-o", "--output",
type=str,
default=DEFAULT_OUTPUT_DIR,
help="出力フォルダー"
)
parser.add_argument(
"--model-type",
type=str,
default="general",
choices=["general", "portrait", "hrmatting"],
help="使用するモデルタイプ(general / portrait / hrmatting)"
)
parser.add_argument(
"-t", "--threshold",
type=int,
default=DEFAULT_THRESHOLD,
help="マスクしきい値(0?255、低いほど甘め)"
)
parser.add_argument(
"-d", "--dilate",
type=int,
default=0,
help="マスク膨張ピクセル数(甘めにしたい場合)"
)
parser.add_argument(
"--close",
type=int,
default=0,
help="マスク穴埋め(closing)ピクセル数(欠け対策など)"
)
args = parser.parse_args()
# モデルパス切り替え
if args.model_type == "general":
model_path = DEFAULT_MODEL_GENERAL
elif args.model_type == "portrait":
model_path = DEFAULT_MODEL_PORTRAIT
elif args.model_type == "hrmatting":
model_path = DEFAULT_MODEL_HRMATTING
else:
model_path = DEFAULT_MODEL_GENERAL
input_dir = args.input
output_dir = args.output
threshold = args.threshold
os.makedirs(output_dir, exist_ok=True)
print("Input folder :", input_dir)
print("Output folder:", output_dir)
print("Model type :", args.model_type)
print("Model path :", model_path)
print("Threshold :", threshold)
print("Dilate :", args.dilate)
print("Closing :", args.close)
print("\nLoading ONNX model...")
onnx_session = create_session(model_path)
print("Model loaded.\n")
valid_ext = [".jpg", ".jpeg", ".png", ".bmp", ".webp"]
print("Start processing images...\n")
for filename in os.listdir(input_dir):
if not any(filename.lower().endswith(ext) for ext in valid_ext):
continue
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(
output_dir, os.path.splitext(filename)[0] + ".png"
)
print("Processing:", filename)
bgr = cv2.imread(input_path)
if bgr is None:
print("Failed to read:", input_path)
continue
mask = run_inference(onnx_session, bgr)
# 元画像サイズにリサイズ
mask = cv2.resize(mask, (bgr.shape[1], bgr.shape[0]))
# しきい値処理
mask = np.where(mask >= threshold, 255, 0).astype(np.uint8)
# 穴埋め(closing)
if args.close > 0:
kernel_close = np.ones((args.close, args.close), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel_close)
# 膨張(甘め)
if args.dilate > 0:
kernel_dilate = np.ones((args.dilate, args.dilate), np.uint8)
mask = cv2.dilate(mask, kernel_dilate, iterations=1)
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
rgba = np.dstack([rgb, mask])
Image.fromarray(rgba).save(output_path)
print("\nAll images processed successfully.")
if __name__ == "__main__":
main()
うまくいかない時
https://developer.download.nvidia.com/compute/cudnn/redist/cudnn/windows-x86_64
自分の環境にあったのをダウンロードして次のホルダーに入れる
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\bin\x64"
↓
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\bin"
確認
where cudnn*.dll
バージョン
pip install onnxruntime-gpu==1.20.0








ディスカッション
コメント一覧
まだ、コメントがありません