Real-ESRGAN → OpenVINO INT4
把 Real-ESRGAN 的 RealESRGAN_x4plus
(RRDBNet,23 個 RRDB block,16.7 M 參數)轉成 OpenVINO IR,並用 NNCF 做成
INT4 / INT8 / FP16 多種精度版本。所有模型都是純 OpenVINO 推論,
執行時不需要 PyTorch,只要 openvino + opencv + numpy(首次使用會自動從本 repo 下載權重)。
| 模型 key | 檔案 | 精度 | 大小 (xml+bin) | 說明 |
|---|---|---|---|---|
int4 |
models/realesrgan_x4plus_int4_w4a16.* |
W4A16(權重 u4 per-channel asym,activation FP16) |
11.0 MB | 純 4-bit,351 個 conv 全部 4-bit,體積最小 |
int4-mixed |
models/realesrgan_x4plus_int4_mixed_w4a16.* |
W4/W8 混合 | 15.2 MB | 約一半權重 4-bit、最敏感的一批保留 INT8,畫質明顯較好 |
int4-w4a8 |
models/realesrgan_x4plus_int4_w4a8.* |
W4A8(權重 4-bit、activation INT8) | 11.8 MB | 純 4-bit 權重 + INT8 計算路徑 |
int8 |
models/realesrgan_x4plus_int8_w8a8.* |
W8A8 | 19.5 MB | CPU 上最快,畫質/速度最佳平衡點 |
fp16 |
models/realesrgan_x4plus_fp16.* |
FP16 | 35.1 MB | 幾乎無損(對 FP32 約 48 dB),當作 reference 基準 |
fp32 |
用 export_openvino_int4.py 產生 |
FP32 | 66.8 MB | 未壓縮,僅供對照/量測 PSNR 用 |
原始 PyTorch 權重檔:
RealESRGAN_x4plus.pth(67 MB,來自 Real-ESRGAN v0.1.0 release), checkpoint 內的 key 是params_ema。本 repo 的轉換管線已驗證 與 BasicSRRRDBNet逐 bit 相同 (max|diff| = 0.0)。
1. 實測結果
測試機:Intel Xeon Platinum 8559C(Emerald Rapids,16 vCPU,含 AMX-INT8 / AVX512-VNNI / AVX512-FP16)、 OpenVINO 2026.4.1、tile=128、tile_pad=16。
畫質(3 張 inputs/ 測試圖,PSNR / SSIM 對 fp16 版本;fp16 與 PyTorch FP32 差異 < 0.3 dB):
| 模型 | 大小 | PSNR ↑ | SSIM ↑ | PSNR vs. 原圖 ↑(bicubic LR 輸入) |
|---|---|---|---|---|
fp16 |
35.1 MB | 基準 | 1.0000 | 18.90 dB |
int8 (W8A8) |
19.5 MB | 29.62 dB | 0.927 | 19.25 dB |
int4-mixed |
15.2 MB | 24.73 dB | 0.897 | 17.77 dB |
int4 (W4A16) |
11.0 MB | 18.41 dB | 0.679 | 16.83 dB |
int4-w4a8 |
11.8 MB | 18.72 dB | 0.618 | 16.95 dB |
速度(合成 512×256 輸入、tile=128、取 3 次最佳):
| 模型 | 秒 / 張 | 輸入 MPix/s | 備註 |
|---|---|---|---|
int8 (W8A8) |
1.30 s | 0.10 | AMX/VNNI INT8 路徑,比 FP32 快約 1.9× |
fp16 |
2.48 s | 0.05 | |
int4-mixed |
2.28 s | 0.06 | |
int4 (W4A16) |
2.32 s | 0.06 | |
int4-w4a8 |
2.49 s | 0.05 | INT8 quantize/dequantize 節點反而稍慢 |
為什麼 INT4 沒有比較快?
OpenVINO CPU plugin 執行 u4 權重時會在 runtime 解壓回 FP32/FP16 再做卷積,
所以 4-bit 的收益是 模型體積 / 記憶體(4×)而不是速度;要速度請用 int8(W8A8)。
4-bit 權重大多數時候適合「記憶體受限 / 想把模型塞進邊緣裝置 / 減少下載量」的場景。
為什麼 INT4 畫質掉得比較多?
Real-ESRGAN 是純卷積的深層殘差網路(23 個 RRDB,每層輸出 x*0.2 + conv(x)),
誤差會沿 351 層累積。4-bit 每層權重 SQNR 只有 ~17 dB,累積後 PSNR 掉到 ~18 dB。
因此本 repo 同時提供:
int4-mixed:由 NNCF 敏感度分析挑出「最不能壓」的層保留 INT8,其餘 4-bit → 幾乎無損的畫質(SSIM 0.90+),大小只多 38%。int8:想要又快又準就用這個。
1.5 效果對比(同一張圖:原始 PyTorch vs 各個 OpenVINO 版本)
測試照片是 NASA 肯尼迪太空中心的公有領域白頭海雕照片 (KSC-20230425-PH-JBS02_0003), 裁切 1024×768 當 Ground Truth,bicubic 降 4 倍成 256×192 餵進模型, 所有模型都用 tile=128 推論成 768×1024。
細節並排比較(左上 bicubic、右上原始 PyTorch FP32、中上 FP16、左下 INT8、下中 INT4 混合、右下純 INT4):
| 模型 | 大小 | PSNR vs PyTorch FP32 ↑ | SSIM ↑ | PSNR vs 原圖 ↑ | 推論時間 |
|---|---|---|---|---|---|
pytorch_fp32(原始 PyTorch,基準) |
67.0 MB | 基準 | 1.0000 | 20.12 dB | 4.46 s |
| bicubic x4(對照) | – | 22.54 dB | 0.7049 | 21.70 dB | – |
openvino_fp16.jpg |
35.1 MB | 48.38 dB | 0.9981 | 20.14 dB | 0.60 s |
openvino_int8_w8a8.jpg |
19.5 MB | 27.76 dB | 0.8675 | 20.39 dB | 0.39 s |
openvino_int4_mixed_w4a16.jpg |
15.2 MB | 22.84 dB | 0.8160 | 18.68 dB | 0.61 s |
openvino_int4_w4a16.jpg |
11.0 MB | 18.02 dB | 0.4879 | 17.19 dB | 0.60 s |
openvino_int4_w4a8.jpg |
11.8 MB | 17.89 dB | 0.4624 | 17.09 dB | 0.69 s |
重現方式、完整檔案清單與說明見 **samples/eagle_4x/README.md**,
照片授權為 NASA 公有領域(Public Domain)。
1.6 影片對比(放大前 vs 各個量化版本,repo 內可直接播放)
除了靜態圖,repo 也放了一段公有領域的 NASA 影片(ISS 氣輝夜景,GSFC_20181022_ICON_m12902_Airglow),
用原始 PyTorch 模型與所有 OpenVINO 版本做 640×360 → 2560×1440 的 4 倍放大,逐影格記錄時間與畫質。
① 放大前(模型輸入,640×360,1.5 s / 45 影格)
② 並排比較影片(bicubic / PyTorch FP32 / FP16 / INT8 / INT4 mixed / INT4,含標籤)
若播放器不支援 HTML video,可直接看這支 GIF:
③ 各個模型的 4x 放大影片(2560×1440)
原始 PyTorch FP32(放大後)
OpenVINO FP16
OpenVINO INT8(W8A8)
OpenVINO INT4 混合精度(W4/W8)
OpenVINO 純 INT4(W4A16)
④ 城市燈光帶 1:1 放大比較(最能看出量化差別)
⑤ 時間與畫質紀錄
| 模型 | 大小 | 45 影格總時間 | ms/影格 | 張/秒 | vs PyTorch PSNR ↑ | SSIM ↑ | 加速比 ↑ |
|---|---|---|---|---|---|---|---|
pytorch_fp32(原始) |
67.0 MB | 663.5 s | 14745 | 0.07 | 基準 | 1.0000 | 1.0× |
openvino_fp16 |
35.1 MB | 211.5 s | 4700 | 0.21 | 45.41 dB | 0.9927 | 3.1× |
openvino_int8_w8a8 |
19.5 MB | 124.8 s | 2773 | 0.36 | 36.90 dB | 0.9284 | 5.3× |
openvino_int4_mixed_w4a16 |
15.2 MB | 214.6 s | 4769 | 0.21 | 31.31 dB | 0.9344 | 3.1× |
openvino_int4_w4a16 |
11.0 MB | 246.8 s | 5485 | 0.18 | 25.40 dB | 0.7894 | 2.7× |
直接下載:samples/video_airglow/00_source_lr.mp4、10_pytorch_fp32_4x.mp4、11_openvino_fp16_4x.mp4、
12_openvino_int8_w8a8_4x.mp4、13_openvino_int4_mixed_4x.mp4、14_openvino_int4_4x.mp4、
20_side_by_side_1920x780.mp4(完整說明見 samples/video_airglow/README.md)
重點結論:INT8 (W8A8) 在 CPU 上比 PyTorch FP32 快 5.3× 且畫質僅 36.9 dB / SSIM 0.93;
INT4 在 CPU 上不會更快(CPU plugin 執行時會把 4-bit 權重解壓回 FP32/FP16),
它的優勢是模型只有 11 MB;若要在 4-bit 尺寸下兼顧畫質,請用 int4-mixed。
Intel GPU(NPU / AUTO 同理)可以執行嗎?
可以。這些都是標準 OpenVINO IR(動態 shape),不綁定 plugin,-d GPU / -d NPU / -d AUTO / -d HETERO 都能跑:
python realesrgan_ov.py -i input.jpg -d GPU -m int8 -t 128 # Intel GPU 上推薦 INT8
python realesrgan_ov.py -i input.jpg -d AUTO -m fp16 # 自動挑最快裝置
| 模型 | Intel GPU 支援 | 說明 |
|---|---|---|
fp16 |
✅ | Xe / Arc 上 FP16 有硬體加速;更舊的 UHD/Iris 會以 f32 執行 |
int8 (W8A8) |
✅ GPU 上最快 | GPU plugin 對 INT8 卷積有最佳路徑(Xe-LP+ / Arc / Alchemist) |
int4-mixed / int4 / int4-w4a8 |
⚠️ 可執行、通常不快 | GPU plugin 支援 4-bit 權重,但卷積沒有 4-bit 加速路徑,會在 runtime 解壓成 FP16/FP32;收益只有 VRAM。純 4-bit 的模型還多了 dequantize 節點,GPU 上反而變慢 |
fp32 |
✅ | 相容但最慢,僅供對照 |
若要給 Intel GPU 專用的量化模型(INT8 的 activation 範圍與 SmoothQuant 會依 GPU 特性不同而調整):
python export_openvino_int4.py --weights RealESRGAN_x4plus.pth --target-device gpu \
--a8-bits 8 --a8-name int8_w8a8_gpu --no-w4a16
備註:本 repo 的模型是在沒有 GPU 的機器上驗證的(available_devices = ['CPU']),
以上 Intel GPU 的說明是依 OpenVINO plugin 的能力整理,不是本機實測數據。
2. 安裝
pip install openvino opencv-python numpy huggingface_hub
# 只有要「自己重新轉換模型」才需要:
pip install torch onnx onnxscript nncf
realesrgan_ov.py 會在第一次執行時自動從本 repo 下載 *.xml / *.bin,
並快取到 ~/.cache/realesrgan_openvino(可用環境變數 REALESRGAN_OV_CACHE 改位置)。
也可以手動下載後用 --model-path / -m /path/to/model.xml 指定本機檔案。
3. 快速開始:單一 py 檔
下載兩個檔案即可(realesrgan_ov.py + benchmark_models.py),模型會自動下載。
# quick_start.py
import cv2
from realesrgan_ov import RealESRGAN
upscaler = RealESRGAN(model='int4') # int4 | int4-mixed | int8 | fp16 | 自訂 .xml 路徑
img = cv2.imread('input.jpg') # BGR uint8
sr, scale = upscaler.enhance(img, tile=128) # 4 倍超解析(記憶體吃太多時用 tile 分塊)
cv2.imwrite('output.png', sr)
print('output:', sr.shape, 'scale:', scale)
inputs/ 內附 3 張測試圖(來自 Real-ESRGAN 官方 inputs),samples/ 內附 1 張公有領域照片與
1 段公有領域影片(都已用所有模型跑過),可直接試跑:
python realesrgan_ov.py -i inputs/00003.png -o results/ -m int4-mixed -t 128
# 命令列
python realesrgan_ov.py -i input.jpg # 4x 超解析,輸出 results/
python realesrgan_ov.py -i ./photos -o out/ -m int8 # 整個資料夾
python realesrgan_ov.py -i clip.mp4 -o clip_4x.mp4 # 影片逐影格
python realesrgan_ov.py -i big.png -t 64 --tile-pad 16 # 大圖分塊(256→1024 這類)
python realesrgan_ov.py -i input.jpg --outscale 2 # 只放大 2 倍(先 4x 再 downscale)
python realesrgan_ov.py -d GPU -m int8 -i input.jpg # 用 GPU / NPU / AUTO
python realesrgan_ov.py --benchmark --images input.jpg # 只測效能
python benchmark_models.py --images a.png b.png # 比較所有版本的畫質/速度
支援 PNG/BMP/JPG/WEBP(含 alpha 通道,alpha 會用 bicubic 放大)、資料夾遞迴、影片(mp4/avi/mov/mkv)。
4. Python API
from realesrgan_ov import RealESRGAN
up = RealESRGAN(
model='int4', # int4 / int4-mixed / int4-w4a8 / int8 / fp16 / '/path/model.xml'
device='CPU', # CPU / GPU / NPU / AUTO
precision='auto', # auto(預設)/ f32 / f16 / bf16
num_threads=8, # 0 = 使用全部核心
)
sr, scale = up.enhance(img, tile=128, tile_pad=16, pre_pad=0, outscale=4)
sr_bgra = up.enhance_alpha(bgra_img, tile=128) # 自動處理 alpha
precision 說明(很重要):新版 OpenVINO CPU 對 FP32 graph 的預設
INFERENCE_PRECISION_HINT 是 bf16,會讓這個網路的 PSNR 掉約 20 dB。
realesrgan_ov.py 的 auto 會對 FP32/FP16/INT4(FP16 activation) 的模型自動釘成 f32,
INT8 graph 不受影響。若你自己用 ov.Core().compile_model(),請記得傳
{'INFERENCE_PRECISION_HINT': 'f32'}。
5. 從 PyTorch 權重重新轉換成 OpenVINO INT4
python export_openvino_int4.py \
--weights RealESRGAN_x4plus.pth \
--data-dir inputs \ # 校準用的低解析度圖
--out-dir models \
--calib-tile 128 --calib-samples 6 \
--weight-ratio 1.0 \ # 1.0 = 全部 4-bit;0.5 = 一半 4-bit、其餘 INT8
--a8-bits 8 --a8-name int8_w8a8
流程:RRDBNet(重建) → strict=True 載入 checkpoint → ONNX(opset17, 動態 H/W) → OpenVINO FP32/FP16 → NNCF 量化 → IR
這個管線裡有兩個必須處理的地方(否則 INT4 會被靜默降級成 INT8):
nncf.compress_weights(mode='int4_*')預設只把 MatMul 壓成 4-bit,卷積一律落到 INT8 backup →enable_int4_for_convolutions()擴充_get_ratio_defining_params,讓 Conv 也吃 4-bit。- NNCF 的 CPU hardware config 只允許 8/16-bit 權重 →
enable_int4_weights_in_cpu_hw_config()把q4_w加進 Convolution 的 qspace,產生u4常數(OpenVINO CPU plugin 可執行)。 openvino.convert_model()預設會把權重壓成 FP16(本模型會掉到 ~27 dB)→convert_onnx()以compress_to_fp16=False轉換,得到真正的 FP32 graph。
驗證方式(本 repo 產出的模型都跑過):
python - <<'PY'
from openvino import Core
m = Core().read_model('models/realesrgan_x4plus_int4_w4a16.xml')
print(sorted({str(n.get_element_type()) for n in m.get_ops() if n.get_type_name() == 'Constant'}))
PY
# 應該看到 '<Type: 'uint4_t'>',代表權重真的是 4-bit
export_openvino_int4.py 也能轉換其他 Real-ESRGAN 權重,只要架構相同(--stem 改檔名):
RealESRGAN_x4plus.pth(本 repo 使用,num_feat=64 / num_block=23 / num_grow_ch=32)RealESRNet_x4plus.pth、RealESRGAN_x4plus_anime_6B.pth、RealESRGAN_x2plus.pth(需在rrdbnet_arch.py對應調整scale/num_block/num_feat)
6. 疑難排解
| 症狀 | 原因 / 解決 |
|---|---|
| 輸出整張有雜訊、幾乎是亂圖 | 用了 int4:Real-ESRGAN 對 4-bit 非常敏感,請改用 int4-mixed 或 int8 |
| 輸出整體偏色 / 邊緣有雜訊 | 沒有指定 INFERENCE_PRECISION_HINT='f32',CPU 預設跑 bf16。用 precision='f32' 或 -m int8 |
| 大圖 OOM | 用 -t 128(或 64)分塊,--tile-pad 16;不要 -t 0 |
| 分塊後有接縫 | --tile-pad 調大到 20~32 |
| 下載權重失敗 | export HF_TOKEN=hf_xxx(私有 repo)或先手動下載 models/*.xml *.bin 後用 -m 指定 |
匯出時 KeyError: 'input' |
LWC 傳入 dataset 的已知問題,script 預設不傳(--lwc-dataset 可開啟 AWQ / scale-estimation) |
| 想改輸出的放大倍率 | --outscale 2(>4 會再 cubic 放大) |
7. 出處與授權
- 程式碼/權重出處:xinntao/Real-ESRGAN、XPixelGroup/BasicSR(Apache-2.0)
rrdbnet_arch.py為 BasicSRRRDBNet的獨立重寫(不需安裝 BasicSR),參數名稱與官方 checkpoint 完全一致- 量化:OpenVINO NNCF
- 本 repo 的推論程式、轉換腳本與本說明文檔為本專案新增。
- 樣品照片:NASA Kennedy Space Center(公有領域),見
samples/eagle_4x/README.md的來源與授權說明 - 樣品影片:NASA/Goddard ICON 任務 ISS 氣輝畫面(公有領域),見
samples/video_airglow/README.md - License:Apache-2.0(見
LICENSE)。


