こういう構想を温めている。
darknet — 推論特化フォーク
darker than darknet — 上流より依存が少なく(暗く)、ビット深度も暗い(int8)。
Darknet/YOLO(Stéphane Charette 版)からフォークした、
組み込み用途に特化した推論エンジンです。上流が「学習からアノテーション、デモまで揃った
CV ワークベンチ」を目指すのに対して、このフォークは他人のアプリケーションに埋め込まれる
推論部品として最適化しています。
特徴
-
OpenCV 非依存 — 推論側は OpenCV を一切リンクしません。画像の decode / 配管はホスト側
(Windows: GDI+/D3D11、Linux: GStreamer、組み込み: 任意)に任せ、エンジンは
「interleaved 8bit + stride」の生バッファ契約だけを持ちます。dll は約 0.7MB。 -
狭い C ABI(14 関数) — opaque handle + プリミティブ型のみ。C++ 型・コールバック・
所有権の受け渡しなし。C# ラッパーと GStreamer プラグインはこの ABI 経由で実運用中。
Python(ctypes)と C# のサンプル(src-examples-py//src-examples-cs/)が
束縛の実例で、他の FFI 言語(Java の FFM / jextract 等)も同じ距離感で繋がります。 -
INT8 量子化(PTQ)を CPU / GPU 両対応で内蔵 — 独自の
.i8フォーマット
(DI8_FORMAT.md、凍結仕様)。較正器もエンジンに内蔵
(dn_calib_accumulate/dn_calib_write_i8)。- CPU: oneDNN(AVX2-VNNI / AVX512-VNNI の brgemm カーネル)。u8 チェーンで
レイヤー間の量子化往復を省略。 - GPU: cudnn-frontend の fused int8 conv + s8 パススルーチェーン
(maxpool / route / upsample が s8 のまま流れる)。
- CPU: oneDNN(AVX2-VNNI / AVX512-VNNI の brgemm カーネル)。u8 チェーンで
-
GPU 推論の近代化 — cudnn-frontend fused conv(conv+bias+act 融合、mish/SiLU 対応)、
CUDA Graph capture、YOLO デコードの GPU 化(候補のみ D2H 転送)、CUDA デバイスメモリ
直接入力(dn_detect_rgb_gpu、GStreamer GstCudaMemory 等からゼロコピー)。 -
省 VRAM — 遅延 fp16 変換・共有ワークスペース・NCHW elision 等で、
LPR モデル(tiny-3l 1280×736)の常駐 VRAM を 1435MB → 561MB(−61%)。 -
ONNX エクスポート内蔵 — fp32 / fp16 に加え、QDQ 形式の int8 ONNX
(ONNX Runtime で QLinearConv に融合)と、TensorRT / DLA 向けの-s8対称版。 -
モデル互換 — 上流 darknet の
.cfg/.weights/.namesをそのまま読みます。
学習は上流(または本フォークの学習側ツリー)で行い、成果物を無変換で配備できます。
YOLOv3 世代の既存資産も再学習ゼロで復活します — 較正数分で.i8化(実測 int8 税 0.2pt、
GPU 6.2ms/162fps @608)と int8 ONNX 化(leaky は QLinearConv に完全融合)が通ります。
実測値(参考)
伝統のグラフです。ただし一点だけ流儀が違います — 全点を同一マシンで実測しています
(YOLO26 の mAP のみ公称値)。2021 年製の yolov4-csp-swish が、全段 INT8(DI8)+
cudnn-frontend 融合 conv + CUDA Graph の研ぎで、現行世代と同じ速度帯に立ちます。
COCO の再学習は一切していません — 既製の重みを較正しただけです。
| 経路 | 機材 | モデル | 結果 |
|---|---|---|---|
| CPU int8 (oneDNN) | i7-12650H (AVX2-VNNI) | tiny-3l 1280×736 | 51.5ms/枚 = fp32 比 3.13× |
| GPU int8 (fe + s8 chain + GPU decode) | RTX 4060 Laptop | 同上 | 1.90ms / 525fps(f16 起点 1.7×) |
| GPU 多レーン | RTX 4060 Laptop | 同上 ×4 ストリーム | 集約 ~430fps、VRAM 計 555MB |
読み取り精度は全量オラクル A/B(11 万枚超)で fp32 とほぼ完全一致(実誤読差 0.013%)を確認済み。
リポジトリ構成
src-lib/ エンジン本体(darknet_capi.h = 公開 C ABI、darknet_abi.def = 公開シンボル)
src-cli-inference/ darknet_detect CLI(検出・ベンチ・fp16/int8 エクスポート)
src-examples-py/ C ABI サンプル(Python / ctypes 束縛 dn.py + 上流サンプル対応番号)
src-examples-cs/ C ABI サンプル(C# / P-Invoke + GDI+、上流サンプル対応番号)
int8_check/ INT8 検証・ベンチ・ONNX エクスポータのツール群
DI8_FORMAT.md .i8 フォーマット仕様(凍結)
C ABI サンプルは上流 src-examples/(C++ / OpenCV)のラインナップに番号を揃えた
別実装で、Python・C# とも 01-08 / 11 / 12 を揃えています(09-10 の keypoints は
エンジン対応外のため対象外): 01=静止画推論+注釈保存 / 02=静止画表示 / 03・04=動画表示・処理 /
05=マルチスレッド(ハンドル並列の掟と DN_INFER_THREADS の按分の実演)/ 06=JSON 出力 /
07・08=RTSP・webcam / 11=YOLO 形式の自動アノテーション / 12=フォーク独自の
ffmpeg パイプサンプル。
フロントエンドの流儀が言語で異なるのが見どころです:
-
Python — 表示・動画系は opencv-python(デコード/表示のフロントエンド役。エンジン自体は
OpenCV-free のまま)、12 のみ ffmpeg パイプ + Pillow。 -
C# — OpenCV 完全不使用。動画の decode/encode は ffmpeg パイプ(bgr24 は GDI+ の
24bpp と同じ並びなのでdn_detect_rgbへ無変換直渡し)、動画表示は ffplay への
パイプ(03/07/08、12 の--play)、静止画表示(02)は sixel でターミナル内に
インライン描画(Windows Terminal 1.22+ 等)。GUI ツールキット不要でウィンドウも
ターミナル画像も出せます。
12 の入力は ffmpeg が読めるもの全部(ファイル / rtsp:// / dshow デバイス)。
05 は複数ハンドル並列時の掟(スレッド毎ハンドル + DN_INFER_THREADS の按分、
C# はネイティブ側に届く SetEngineEnv 経由)を実演します。.weights の代わりに .i8 を
渡せばそのまま INT8 で走ります。エンジン自体は OpenCV-free のまま — 表示・動画系
サンプルの opencv-python はデコード/表示のフロントエンド役で、これは ABI が呼び出し側に
委ねている役割そのものです。
周辺エコシステム(別リポジトリ): C# ラッパー、GStreamer プラグイン
(darknetinfer / darknetoverlay、共有エンジン refcount 方式)、TFLite コンバータ、
ブラウザ完結の int8 ONNX デモ。
C ABI 最小例
#include "darknet_capi.h"
dn_handle h;
if (dn_create("model.cfg", "model.i8", "model.names", /*gpu=*/0, &h) != 0) { /* dn_last_error() */ }
dn_box boxes[64]; int n = 0;
dn_detect_rgb(h, pixels, width, height, /*channels=*/3, /*stride_bytes=*/0,
DN_PIXEL_RGB, /*threshold=*/0.25f, /*nms=*/0.45f,
boxes, 64, &n);
/* boxes[0..n) を使う */
dn_destroy(h);
-
.weightsを渡せば fp32、.i8を渡せば int8 で動きます(magic sniff で自動判別)。 - 1 ハンドルは 1 スレッド専用。複数ストリームはハンドルを分けてください
(CPU は真に並列、GPU は内部でエンジンロックにより直列化)。 - 同一プロセスでの GPU / CPU ハンドル混在は非対応です。
ビルド
2 つの構成があります。CMake の既定は上流同等のフル構成
(学習 + OpenCV + 元の CLI + サンプルプログラム 11 本)で、上流のワークフローがそのまま再現できます。
推論特化構成は -DDARKNET_INFERENCE_ONLY=ON(さらに OpenCV を切るなら
-DDARKNET_USE_OPENCV=OFF)で、サンプルと元 CLI の代わりに OpenCV 非依存の
darknet_detect CLI がビルドされます。以下は推論特化構成の例です。
Windows (VS2022)
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
cmake --build build_onednn --config Release --target darknet & rem CPU (oneDNN) -> darknet_cpu.dll
cmake --build build_gpu --config Release --target darknet & rem GPU (CUDA) -> darknet_gpu.dll
注意: darknet_detect.exe は同一ディレクトリの dll をロードします。ビルド後は
src-lib\Release\darknet_*.dll を exe 側へコピーしてください(古い dll が残っていると
コード変更が反映されない「stale-dll 罠」を踏みます)。
注意: int8(.i8)を実行するビルドは oneDNN リンクが必須です。oneDNN 非リンクの
ビルドに .i8 を渡すと、警告なく fp32 実行に落ちます。
Linux
通常の CMake ビルドで、CPU(oneDNN)/GPU(CUDA + cudnn-frontend)とも同一ソースが通ります。
実行時トグル(環境変数)
| 変数 | 既定 | 意味 |
|---|---|---|
DN_INFER_THREADS |
P-core 数 | CPU 推論スレッド数 |
DN_DISABLE_INT8=1 |
off |
.i8 を同解像度の fp32 として実行(切り分け用) |
DN_I8_CHAIN=0 / DN_I8_CHAIN2=0
|
on | CPU u8 チェーン最適化の段階的オプトアウト |
DN_FE_CONV=0 |
on | GPU fused-conv(cudnn-frontend)経路の無効化 |
DN_FE_CUDAGRAPH=0 |
on | CUDA Graph capture の無効化 |
DN_FE_PLAN_CACHE |
on | プランキャッシュ + tune-on-miss。既定でモデルの隣に <weights>.plans.tsv を作り、初回起動時に最適エンジンプランを実測選定(~1 分/モデル)して保存、以後の起動は +1.5s 程度で再生します。=<file> で保存先を指定、=0 でキャッシュと自動チューニングごと無効(ヒューリスティクス選定のみ) |
DN_FE_AUTOTUNE=1 |
off | 強制再チューニング(キャッシュを実測で作り直す)。tune-on-miss が既定で効くため通常は不要 |
DN_GPU_YOLO=0 |
on | YOLO デコードの GPU 実行を無効化(CPU スキャンに戻す) |
DN_NMS_PERCLASS=1 |
off | NMS をクラス別に(既定はクラス非依存 = OCR/ANPR 向き) |
DN_VERBOSE=1 |
off | CLI の詳細出力 |
すべての性能系トグルは「未設定 = 最速」に揃えてあります。 環境変数は診断・切り分け・
特殊配備(例: モデル置き場が読み取り専用で .plans.tsv を書けない場合の
DN_FE_PLAN_CACHE=<書き込み可能なパス>)のためのものです。
ベンチマークの流儀
GPU 経路は初回に数秒の初期化(cuDNN・autotune・グラフ capture)を払います。
短いクリップの「総時間 ÷ 枚数」を fps と呼ばないでください。 定常スループットは
ウォームアップ後に計測するか、枚数 2 点の差分で startup を消去して求めます。
darknet_detect --bench は前処理込み、ONNX Runtime 比較時は前処理の扱いの差に注意。
上流との関係
- 学習器・
.cfg/.weights互換性は上流に追従します(定期的に上流の変更を取り込み)。 - 本フォークの変更(OpenCV 切除・C ABI・INT8・fe 経路)は上流の設計方針
(OpenCV 非 optional 化、cv::Mat への統合)と方向が逆のため、上流へのマージは想定していません。 - ライセンスは上流 Darknet/YOLO のライセンスに従います。
謝辞
Joseph Redmon(原作)、Alexey Bochkovskiy(YOLOv4 系譜と CPU/XNOR 最適化)、
Stéphane Charette(現行上流のモダナイズと保守)。この推論エンジンは巨人の肩の上の
小さな暗がりです。