darknet2onnx
Convert Darknet .cfg + .weights to ONNX format.
A standalone Go CLI tool that produces a single static binary with no Python or pip dependencies.
Table of Contents
Installation
From Go
go install github.com/LdDl/darknet2onnx@latest
Pre-built binaries
Download the latest release for your platform from Releases:
Extract and place the binary somewhere in your $PATH.
Supported models
- YOLOv3, YOLOv3-tiny
- YOLOv4, YOLOv4-tiny
- YOLOv7, YOLOv7-tiny
The YOLO detection head decode logic (sigmoid, grid offsets, anchor application) is embedded into the ONNX graph. All heads are concatenated into a single output tensor.
Coordinates cx, cy, w, h are in absolute pixel units relative to the input image dimensions.
Two output formats are available via --format:
| Format |
Shape |
Description |
yolov5 (default) |
[1, N, 5+C] |
With objectness: cx, cy, w, h, obj, cls0..clsN |
yolov8 |
[1, 4+C, N] |
Without objectness: cx, cy, w, h, cls0..clsN (obj baked into cls scores) |
where N is the total number of predictions and C is the number of classes.
Input tensor is named images, output tensor is named output0. This follows the Ultralytics naming convention, so the output ONNX should be compatible with most inference pipelines that expect this convention. Note that this is not "traditional" YOLO output format, but widly supported I believe.
This could not work for you, but in my case these formats are compatible with od_opencv:
yolov5 -> Model::yolov5_ort()
yolov8 -> Model::ort()
Build from source
Simple build for the current platform:
go build -o darknet2onnx .
Cross-compile for all platforms (linux/windows/macOS, amd64/arm64):
./build.sh
Usage
./darknet2onnx --cfg model.cfg --weights model.weights --output model.onnx
Flags
| Flag |
Default |
Description |
--cfg |
(required) |
Path to Darknet .cfg file |
--weights |
(required) |
Path to Darknet .weights file |
--output |
model.onnx |
Output ONNX file path |
--opset |
12 |
ONNX opset version |
--format |
yolov5 |
Output format: yolov5 or yolov8 |
Example
./darknet2onnx \
--cfg pretrained/yolov3-tiny.cfg \
--weights pretrained/yolov3-tiny.weights \
--output pretrained/yolov3-tiny.onnx
Validate output
Install onnx in a Python virtual environment:
python3 -m venv .venv
.venv/bin/pip install onnx
Then validate:
.venv/bin/python3 -c "
import onnx
m = onnx.load('model.onnx')
onnx.checker.check_model(m)
print('Valid')
"
Clean up:
rm -rf .venv
Supported layer types
| Darknet layer |
ONNX op(s) |
[convolutional] |
Conv + BatchNormalization + activation |
[maxpool] |
MaxPool |
[route] |
Concat or passthrough (+ Slice for groups) |
[shortcut] |
Add + activation |
[upsample] |
Resize (nearest) |
[yolo] |
Decode subgraph (Reshape, Sigmoid, Add, Exp, Mul, Concat) |
Activations: leaky (LeakyRelu), mish (Softplus + Tanh + Mul), swish (Sigmoid + Mul), logistic (Sigmoid), linear (none).
Protobuf source
The ONNX protobuf schema (proto/onnx.proto3) is downloaded from the official ONNX repository:
https://raw.githubusercontent.com/onnx/onnx/main/onnx/onnx.proto3
To regenerate Go bindings, you need protoc and protoc-gen-go:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
Then run:
protoc -I proto proto/onnx.proto3 --go_out=./onnxpb --go_opt=paths=source_relative --experimental_allow_proto3_optional
How it works
@todo
License
Just MIT, see LICENSE.