opencv-rust: OpenCV bindings the author calls unstable
OpenCV API bindings for Rust
At a glance
- What is it?
- A Rust binding generator that reads OpenCV headers at build time. It has 2,493 stars, no GitHub releases, and a README that tells you to use it at your own risk while its own manifest claims active development.
- Who is it for?
- This binding is the most practical route to OpenCV from Rust, and the build-time header generation is the right architecture because it tracks whatever OpenCV you actually have installed rather than a snapshot frozen at release time.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Bindings are generated from your installed headers
The core mechanism is worth understanding before anything else, because it explains both the flexibility and the fragility. Rather than hand-writing a Rust module for each OpenCV class, this crate runs a binding generator during the build and reads the headers of the OpenCV installation on your machine. The result is a Rust API that matches the OpenCV you have, including the parts of it you enabled when you compiled it.
That is a genuinely good design for a library like this, because OpenCV is configurable at build time. Modules can be switched off, third-party modules can be compiled in, and the version can be 4.x or 5.x. Hand-written bindings would have to make choices about all of that. Generating from headers means the binding surface follows your installation.
The cost is that the build becomes a real build. You need Clang, which the README lists alongside the supported OpenCV version as a prerequisite, because parsing C++ headers requires it. You also need the OpenCV development headers rather than just the runtime library. And because generation happens per project, a change to your OpenCV installation can change your Rust API without any change to the crate version.
The quickstart reflects how little setup is needed once those are in place. Two lines, one in your manifest and one in your source:
opencv = "0.101.0"use opencv::prelude::*;The prelude is doing real work here. OpenCV's API is enormous and mostly discovered through traits rather than inherent methods, so importing the prelude is what makes the generated types usable at all.
The manifest says actively developed, the README says unstable
This is the most direct conflict in the repository, and it is worth surfacing rather than resolving.
The package manifest declares a maintenance status:
[badges]
maintenance = { status = "actively-developed" }Three lines into the README, the project says the opposite about the same code. The API is usable, but unstable and not very battle-tested, and readers are told to use it at their own risk.
Both statements can be defended, and understanding why tells you more than picking one. The maintenance badge describes the project as a project: commits are landing, the version is moving, and someone is responding to issues. The README sentence describes the artifact: the generated API surface is large, auto-generated, and not covered by the kind of hand-written test suite that would justify calling it battle-tested. A crate can be well maintained and still have an API you should approach carefully.
What this means for you in practice is that the semver guarantee should not be read as an API stability guarantee. The crate is at 0.101.0, and a version below 1.0 in Cargo's semver rules explicitly means the API may break in any release. The README's warning and the pre-1.0 version number agree with each other, and it is only the badge that stands apart.
There is a related detail in the manifest worth noting for anyone reading the docs. The library section sets doctest to false. Documentation examples in the Rust source are therefore not executed as tests, which is a sensible choice for generated code and one more reason not to treat the docs.rs pages as verified examples.
Finding OpenCV is the hard part, not writing the code
The README is mostly a catalogue of environment variables, and that is not padding. It is an accurate description of where the difficulty lives. Because the build script probes the system for OpenCV, there are several discovery mechanisms, and each can be pointed at the wrong thing.
The default order relies on pkg-config, cmake and vcpkg. When none of those will cooperate, three variables let you describe the installation by hand: OPENCV_LINK_LIBS for library names, OPENCV_LINK_PATHS for where to find them, and OPENCV_INCLUDE_PATHS for the headers. Each of the three accepts a leading plus sign, which appends to whatever the system probe found rather than replacing it. The README gives the reason that matters most: when a system probe produces a mostly working setup with an incomplete or wrongly ordered link list, static linking in particular, appending is often the fix.
OPENCV_DISABLE_PROBES exists for the case where a higher-priority discovery mechanism is actively giving you the wrong answer. It takes a list of mechanisms to skip, including the environment mechanism itself, so you can isolate which one is lying to you. That is a well-designed escape hatch and it suggests the author has debugged this problem on real machines rather than only on one.
There is a second class of variables that belong to external components and are listed for completeness rather than for everyday use. PKG_CONFIG_PATH must contain opencv.pc or opencv4.pc. OpenCV_DIR points at the directory holding the OpenCV cmake config files. VCPKG_ROOT and its companion variables control the vcpkg route. LD_LIBRARY_PATH, DYLD_LIBRARY_PATH and PATH handle runtime loading on Linux, macOS and Windows respectively, and the README notes that Windows paths inside PATH should use forward slashes because a colon may be read as the entry separator.
Version support spans OpenCV 3.4 through 5.x
The README states that 4.x and 5.x are supported, and that OpenCV 3.4 is still supported but deprecated and will be removed in a future release. That is an unusually wide span for a binding crate, and it is a direct consequence of generating from headers rather than wrapping a fixed API.
The practical implication is that your crate version and your OpenCV major version move together in practice even though they are declared independently. Upgrading OpenCV under a pinned crate version can produce compile errors in code that previously built, and downgrading it can remove modules you were calling. Because the generated API follows your installation, there is no single version of this crate that is correct for everyone.
Two version details inside the manifest are easy to miss. The crate requires edition 2024 and states a minimum Rust version of 1.88.0, so the toolchain floor is recent. And the build dependency on the binding generator is a higher version, 0.106.0, than the crate's own 0.101.0. That is not a mistake: the generator is developed on its own cadence as a workspace member, and the crate depends on it at build time to produce the bindings. But it does mean the two version numbers in the file cannot be compared the way you would compare two releases of the same thing.
The repository publishes no GitHub releases. Version history is in CHANGES.md in the repository root, which the README links directly. For a crate this actively changing, that file is the changelog you should be reading, and the version in Cargo.toml is the number to pin.
The examples directory is the real documentation
For a generated API, the fastest way to find out what works is to look at working code, and the repository has a substantial examples directory. The listing runs from camera_calibration through create_mask, cuda, discrete_fourier_transform, dnn_face_detect, gapi_api_example, hough_circle, hough_lines, opencl, text_detection, and a set of video examples covering capture, HTTP streaming, face detection, feature extraction, grayscale conversion and perspective warping.
Read that list as a map of which OpenCV modules are known to work through the Rust binding. The presence of a CUDA example and an OpenCL example tells you those interop paths have been exercised. The presence of a G-API example is interesting, since G-API is a comparatively recent and less commonly wrapped part of OpenCV. Video capture over HTTP stream alongside plain video capture tells you the network and device paths are both covered.
There is an examples/README.md in that directory, which is where per-example requirements usually live. For a crate whose build varies with the user's OpenCV installation, that file is likely to carry the notes about which OpenCV build options each example needs, and it is the file to read before assuming an example will compile for you.
The repository tree also shows the machinery around the crate. There is a binding-generator directory, registered as a workspace member, plus src_cpp for the hand-written C++ shims that the generated code calls into, a cmake directory for the discovery logic, a build directory, ci, tools, and separate INSTALL.md and TROUBLESHOOTING.md documents at the root. The presence of TROUBLESHOOTING.md as a first-class document rather than a wiki page is a good sign, and it is the second file to read after the README.
Editorial conclusion
This binding is the most practical route to OpenCV from Rust, and the build-time header generation is the right architecture because it tracks whatever OpenCV you actually have installed rather than a snapshot frozen at release time. What you are accepting is a crate whose own documentation tells you it is unstable and not battle-tested, whose compatibility surface is therefore tied to your OpenCV version rather than to a semver promise, and which will move your build when you move OpenCV. Pin the crate version and your OpenCV major version together, and read TROUBLESHOOTING.md before your first build rather than after it fails. If your workload is inference rather than classical vision, a wrapper around an ONNX runtime is a smaller dependency; if it is classical vision, this is still the shortest path, and the examples directory is the fastest way to find out which modules already work.
Frequently asked questions
Is opencv-rust a stable alternative to writing C++ bindings by hand?
It is the practical alternative, but the README describes the API as usable, unstable and not very battle-tested, and the crate is at 0.101.0, where Cargo semver explicitly allows breaking changes. Treat it as a well-maintained project with an API you should pin and approach carefully.
What do I need installed before opencv-rust will build?
A supported OpenCV version, either 4.x or 5.x, with OpenCV 3.4 still supported but deprecated, plus Clang from LLVM, which the binding generator needs in order to parse the C++ headers. You also need the OpenCV development headers rather than only the runtime library.
Why did my build fail to find OpenCV even though I installed it?
The build probes for OpenCV through pkg-config, cmake and vcpkg in turn, and any of them can return the wrong answer. Set OPENCV_DISABLE_PROBES to skip the mechanisms you do not trust, or set OPENCV_LINK_LIBS, OPENCV_LINK_PATHS and OPENCV_INCLUDE_PATHS by hand. TROUBLESHOOTING.md in the repository covers the common cases.
Does opencv-rust work with OpenCV 3.4?
Yes, but the README marks it deprecated and says it will be removed in a future release. The currently supported lines are OpenCV 4.x and 5.x.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/twistedfall-opencv-rust)