# yolo-tensorrt, a C++ wrapper around NVIDIA's own YOLO reference app

> yolo-tensorrt takes the YOLO detector from NVIDIA's deepstream reference applications and repackages it as a small library with a Config struct, a Detector class and a build for Windows, Ubuntu and Jetson. The benchmark tables in the readme cover FP32, FP16 and INT8 on a 1080ti, a Titan V and a Jetson NX, and the dynamic input size box is left unticked.

**enazoe/yolo-tensorrt** — TensorRT8.Support Yolov5n,s,m,l,x .darknet -> tensorrt.  Yolov4  Yolov3 use raw darknet *.weights and *.cfg fils.  If the wrapper is useful to you,please Star it.

- Repository: https://github.com/enazoe/yolo-tensorrt
- Stars: 1,199 · Forks: 308
- Language: C++
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/enazoe-yolo-tensorrt

## A repackaging of NVIDIA's deepstream YOLO app

The project's own description gives the lineage away in the first line. It is the encapsulation of NVIDIA's official yolo-tensorrt implementation, the one published in the deepstream reference applications, and the reference list at the bottom of the readme points at that upstream repository alongside two other implementations that the author used as references.

What the wrapper adds is a shape that other code can call. The upstream reference application is a complete application, and a wrapper turns it into something you initialise with a configuration and then call repeatedly with images, which is what you want when the detector is one component in a larger program rather than the whole program.

The model requirements are spelled out, and they differ between the model families. For YOLOv3 and YOLOv4 you must have the trained darknet weights file and the .cfg file. For YOLOv5, from the PyTorch ecosystem, you should prepare the model file such as yolov5s.yaml and the trained weight file such as yolov5s.pt. The distinction matters because the two families arrive in completely different formats, and a wrapper that supports both has to handle both conversions.

The supported models are listed with a tutorial attached: yolov5n, yolov5s, yolov5m, yolov5l, yolov5x and yolov5-p6, plus yolov4 and yolov3. The feature list also notes a news item dated 2021.10.31 announcing YOLOv5 v6.0 support, which is the most recent feature news in the document and a good clue about the age of the code.

## Two build systems: a Visual Studio solution and CMake

On Windows the dependency list is explicit: TensorRT 7.1.3.4, CUDA 11.0, cuDNN 8.0, OpenCV 4 and Visual Studio 2015. The build is a solution file, and the readme tells you to open sln/sln.sln in MSVC, where there are two projects: the DLL project, which is the YOLO detector as a dynamic library, and the demo project, which is the test of that DLL. The split is the point of the arrangement, since the deliverable is the library and the demo exists to prove it works.

On Ubuntu and on L4T, the Jetson platform, the project generates a libdetector.so shared library and the sample code. The build sequence is the standard out-of-source CMake flow:

```bash
git clone https://github.com/enazoe/yolo-tensorrt.git
cd yolo-tensorrt/
mkdir build
cd build/
cmake ..
make
./yolo-trt
```

For anyone integrating the library into their own project, the readme points at a CMake file under scripts/ as something that could help, which is the sort of pointer that saves an afternoon of getting include paths and library paths right.

The platform list is Windows 10, Ubuntu 18.04 and L4T for the Jetson platform. The repository layout matches the two build systems, with a CMakeLists.txt at the root, a sln/ directory for the Visual Studio solution, a scripts/ directory, a modules/ directory, an extra/ directory, samples/ with sample_detector.cpp, and a configs/ directory holding the cfg, weights and calibration files the default configuration points at.

## The Config struct is the entire configuration surface

Everything you can change about a detector is in one struct, and the readme prints it in full:

```c++
struct Config
{
	std::string file_model_cfg = "configs/yolov4.cfg";

	std::string file_model_weights = "configs/yolov4.weights";

	float detect_thresh = 0.9;

	ModelType net_type = YOLOV4;

	Precision inference_precison = INT8;

	int gpu_id = 0;

	std::string calibration_image_list_file_txt = "configs/calibration_images.txt";

};
```

Seven fields, and they cover the model, the threshold, the network family, the precision, the device and the calibration set. The defaults describe a specific configuration: a YOLOv4 darknet model at a detection threshold of 0.9, running at INT8 precision on GPU 0, with the calibration list pointing at a file in the configs directory.

Two details are worth flagging. The threshold default of 0.9 is unusually high for a detector, which suggests the code was tuned for a scenario where false positives are expensive, and you will almost certainly lower it for general use. And the field name inference_precison is misspelled, with the second i dropped, and it is part of the public struct, so that spelling is what your code has to use.

The calibration list matters more than it looks. It is the input to the INT8 calibration step, and the fact that it is a config field rather than a build-time constant means the same build can be calibrated against a different image set.

## A Detector class with a pimpl and a batched detect call

The public API is deliberately small. The class exposes a constructor and destructor, an init that takes a Config, and a detect that takes a vector of images and a vector of results:

```c++
class API Detector
{
public:
	explicit Detector();
	~Detector();

	void init(const Config &config);

	void detect(const std::vector<cv::Mat> &mat_image,std::vector<BatchResult> &vec_batch_result);

private:
	Detector(const Detector &);
	const Detector &operator =(const Detector &);
	class Impl;
	Impl *_impl;
};
```

The implementation is a pimpl, with an Impl class behind a pointer, and the copy constructor and assignment operator are declared private and left undefined, which in this idiom is how you make a resource-owning object non-copyable without writing the bodies.

The detect signature is where the design choices are visible. It takes a vector of cv::Mat, so a batch of images goes in at once, and it fills a vector of BatchResult, so the results are grouped per input. The wrapper example in the readme shows the whole usage in three lines:

```c++
Detector detector;
Config config;

std::vector<BatchResult> res;
detector.detect(vec_image, res)
```

Batch inference is one of the ticked items in the feature list, and this signature is what that means concretely. It also means the caller decides the batch size, which matters on a Jetson where the memory budget is tight, and it means the result type carries per-image structure that the caller has to know about, since BatchResult is not documented in the readme itself.

## Three precisions, with a calibration file behind INT8

The feature list has three ticked boxes and one unticked one. Ticked are inequal net width and height, batch inference, and support for FP32, FP16 and INT8. Unticked is dynamic input size, and an unticked box in a feature list is a statement about what the code does not do.

The three precisions are the reason to use TensorRT at all, and the structure of the Config shows how they are selected: a Precision enum with the default set to INT8. So out of the box this library tries to run the quantised engine, and the fp16 numbers in the x86 benchmark table are simply not present, while the Jetson and Titan V tables do carry fp16 columns.

INT8 is not free. It requires a calibration pass, and the calibration input is a text file listing images, which is what calibration_image_list_file_txt points at, with the default of configs/calibration_images.txt. That file is the only entry in the release list, tagged on 2020-08-31, and its presence as a release artefact tells you the author was circulating the calibration set along with the code.

The practical point for anyone building on this: the quality of an INT8 detector depends on the calibration set matching the deployment distribution, and the default list in the repository was compiled by the author, not by you. A deployment that sees different lighting, different camera positions or different object sizes will want its own calibration set, and the config field is where you point it.

## What the benchmark tables actually claim

The readme includes three benchmark tables, and it is worth being precise about what they measure, because inference time and detect time are different numbers.

The x86 table lists yolov5s, m, l and x at 640x640 on a 1080ti, with fp32 times of 8ms, 13ms, 20ms and 30ms, and INT8 times of 7ms, 11ms, 15ms and 23ms. The fp16 column is blank for that GPU, which is a hardware statement rather than a missing measurement.

The Jetson NX table with Jetpack 4.4.1 gives two numbers per cell, described as inference and detect time, for yolov3, yolov3-tiny, yolov4-tiny, yolov4 and the yolov5 family at 416x416. The spread is wide: yolov3-tiny at 416x416 is listed at 14ms and 23ms in fp32, while yolov5x at the same size is 351ms and 405ms. The detect time is consistently the larger of the two, and the gap between them grows with the model, which is the post-processing cost showing up in the numbers.

The third table covers Ubuntu with a Titan V, again with inference and detect pairs for yolov4 and the yolov5 family.

What the tables do not cover is as informative as what they do. There is no accuracy comparison between fp32 and INT8, no note on the batch size used, and no mention of power draw or thermal behaviour on the Jetson, which for a deployment is often the number that matters. Treat them as a rough indication of relative cost rather than as a performance guarantee.

## Where this wrapper is the wrong choice

The first constraint is the version stack. The Windows dependency list names TensorRT 7.1.3.4, CUDA 11.0 and cuDNN 8.0, and Visual Studio 2015, which are not current releases. The default branch is TRT8, which suggests a newer configuration exists on another branch, but the readme does not describe the dependency set for it, so a reader has to work that out from the branch itself. For a team on a modern CUDA stack, the porting work is the first task, not the detection code.

The second is that this is a wrapper around a wrapper. The upstream NVIDIA reference application has its own update cycle, and a fork of it inherits the cost of following that cycle, with the added cost of the fork's own divergences. The alternative is to use the deepstream reference applications directly, or one of the other implementations the readme lists, and to write the thin configuration layer yourself. That is more code for you and less code for you to maintain when the upstream moves.

The third is the model pipeline. You bring darknet weights and cfg files for YOLOv3 and YOLOv4, or a PyTorch model file and weights for YOLOv5, and the readme does not describe the conversion step, which sits in the separate yolov5_tutorial.md. Anyone starting from a PyTorch YOLOv5 checkpoint therefore has two documents to read before the first detection.

The fourth is the shape of the project. The contact details are a WeChat public account and a QR code, the community link is a Gitter room, and the last push was on 2026-04-12, with the newest feature note dating from October 2021. That is the profile of a project that works and is not being actively extended, which is fine for a stable detection workload and not fine if you need new architectures, a maintained TensorRT port or an issue response.

## Conclusion

yolo-tensorrt fits a C++ team that already has a YOLO model in darknet or PyTorch weights, runs on NVIDIA hardware, and wants a detector it can link as a DLL or a shared library instead of a Python script on top of a runtime. It does not fit a team on a current TensorRT and CUDA stack without porting, a team that needs dynamic input sizes, or anyone without an NVIDIA GPU. Before adopting it, check the branch you are on, since the default is TRT8 while the Windows dependency list still names TensorRT 7.1.3.4 with CUDA 11.0 and cuDNN 8.0, and expect to supply your own model files, since the library detects and does not train. The licence is MIT, the last push was on 2026-04-12, and the newest feature note in the readme is YOLOv5 v6.0 support from 2021-10-31.

## FAQ

### What does the yolo-tensorrt repository provide?

It encapsulates NVIDIA's official yolo-tensorrt implementation from the deepstream reference applications and repackages it as a library with a Config struct and a Detector class exposing init and a batched detect call, buildable as a DLL on Windows and as libdetector.so on Ubuntu and Jetson L4T.

### How do I build yolo-tensorrt on Ubuntu or a Jetson?

Clone the repository, create a build directory, run cmake .. and make inside it, and then run the ./yolo-trt sample. The project also generates libdetector.so, and a CMake file under scripts/ is provided to help if you want to use the library in your own project.

### What are the build dependencies for the Windows version?

TensorRT 7.1.3.4, CUDA 11.0, cuDNN 8.0, OpenCV 4 and Visual Studio 2015. The build opens the sln/sln.sln solution, which contains the DLL project for the YOLO detector and a demo project that tests it.

### How do I enable INT8 inference in yolo-tensorrt?

INT8 is the default value of the Precision field in the Config struct, and it needs a calibration image list pointed at by calibration_image_list_file_txt, which defaults to configs/calibration_images.txt. The README does not document the calibration procedure itself.

### Does yolo-tensorrt support dynamic input sizes?

No. The feature list leaves dynamic input size unticked, while inequal net width and height, batch inference and FP32, FP16 and INT8 support are all ticked. The model files and the input size are fixed by the configuration you pass in.

## Sources

- [enazoe/yolo-tensorrt on GitHub](https://github.com/enazoe/yolo-tensorrt)
- [Issues](https://github.com/enazoe/yolo-tensorrt/issues)
- [License: MIT](https://github.com/enazoe/yolo-tensorrt/blob/TRT8/LICENSE)
- [README](https://github.com/enazoe/yolo-tensorrt/blob/TRT8/README.md)
- [Releases](https://github.com/enazoe/yolo-tensorrt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/enazoe-yolo-tensorrt
