Skip to content

Commit 2e573fa

Browse files
committed
Support OpenCV 5, drop support for 3.2
1 parent 03b9bd2 commit 2e573fa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1305
-647
lines changed

.github/workflows/opencv-rust.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
- os-image: ubuntu-22.04
2323
opencv-version: 4.11.0
2424
linkage: static
25+
- os-image: ubuntu-22.04
26+
opencv-version: 5.0.0-alpha
27+
linkage: dynamic
2528
- os-image: ubuntu-22.04
2629
opencv-version: 3.4.20
2730
linkage: dynamic

Cargo.toml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ maintenance = { status = "actively-developed" }
2222
members = ["binding-generator"]
2323

2424
[dependencies]
25+
half = { version = "2", optional = true }
2526
libc = "0.2"
2627
num-traits = "0.2"
2728
once_cell = "1"
@@ -61,29 +62,35 @@ vcpkg = "0.2.9"
6162

6263
[features]
6364
default = [
65+
"3d",
6466
"alphamat",
6567
"aruco",
6668
"aruco_detector",
6769
"barcode",
6870
"bgsegm",
6971
"bioinspired",
72+
"calib",
7073
"calib3d",
74+
#"cannops",
7175
"ccalib",
7276
"cudaarithm",
7377
"cudabgsegm",
7478
"cudacodec",
7579
"cudafeatures2d",
7680
"cudafilters",
7781
"cudaimgproc",
82+
"cudalegacy",
7883
"cudaobjdetect",
7984
"cudaoptflow",
8085
"cudastereo",
8186
"cudawarping",
87+
#"cudev",
8288
"cvv",
8389
"dnn",
8490
"dnn_superres",
8591
"dpm",
8692
"face",
93+
"features",
8794
"features2d",
8895
"flann",
8996
"freetype",
@@ -128,32 +135,39 @@ default = [
128135
"ximgproc",
129136
"xobjdetect",
130137
"xphoto",
138+
"xstereo",
131139
]
132140

133141
# OpenCV module features
142+
3d = []
134143
alphamat = []
135144
aruco = []
136145
aruco_detector = ["aruco"]
137146
barcode = []
138147
bgsegm = ["video"]
139148
bioinspired = []
149+
calib = ["features"]
140150
calib3d = ["features2d"]
151+
#cannops = []
141152
ccalib = ["features2d"]
142153
cudaarithm = []
143154
cudabgsegm = ["video"]
144155
cudacodec = []
145156
cudafeatures2d = ["features2d"]
146157
cudafilters = []
147158
cudaimgproc = ["imgproc"]
159+
cudalegacy = []
148160
cudaobjdetect = ["objdetect"]
149161
cudaoptflow = []
150162
cudastereo = ["calib3d"]
151163
cudawarping = []
164+
#cudev = []
152165
cvv = []
153166
dnn = []
154167
dnn_superres = []
155168
dpm = []
156169
face = ["objdetect"]
170+
features = ["flann"]
157171
features2d = ["flann"]
158172
flann = []
159173
freetype = []
@@ -193,14 +207,16 @@ video = []
193207
videoio = []
194208
videostab = ["features2d"]
195209
viz = []
210+
wechat_qrcode = []
196211
xfeatures2d = ["features2d"]
197212
ximgproc = ["calib3d"]
198213
xobjdetect = []
199214
xphoto = ["photo"]
200-
wechat_qrcode = []
215+
xstereo = []
201216

202217
# General features
203218
clang-runtime = ["opencv-binding-generator/clang-runtime"]
219+
f16 = ["dep:half"]
204220

205221
[package.metadata.docs.rs]
206222
no-default-features = true

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The API is usable, but unstable and not very battle-tested; use at your own risk
1414

1515
## Quickstart
1616

17-
Make sure the supported OpenCV version (3.4 or 4.x) and Clang (part of LLVM, needed for automatic binding
17+
Make sure the supported OpenCV version (3.4, 4.x or 5.x) and Clang (part of LLVM, needed for automatic binding
1818
generation) are installed in your system.
1919

2020
Update your Cargo.toml
@@ -145,6 +145,7 @@ The following variables affect the building the of the `opencv` crate, but belon
145145
* `clang-runtime` - enables the runtime detection of libclang (`runtime` feature of `clang-sys`). Useful as a
146146
workaround for when your dependencies (like `bindgen`) pull in `clang-sys` with hard `runtime` feature.
147147
* `rgb` - allow using [`rgb`](https://crates.io/crates/rgb) crate types as `Mat` elements
148+
* `f16` - add intergration with `f16` type from the `half` crate
148149

149150
## API details
150151

@@ -158,6 +159,7 @@ The following OpenCV versions are supported at the moment:
158159

159160
* 3.4
160161
* 4.x
162+
* 5.x (preliminary)
161163

162164
### Minimum rustc version (MSRV)
163165

@@ -279,7 +281,7 @@ version because the crate has gone through the considerable rewrite since.
279281
### OpenCV 3.2
280282

281283
The last version with confirmed OpenCV 3.2 support is 0.75.0, after that this branch of OpenCV is no longer
282-
tested and supported. It may still work though.
284+
tested and supported. Since version 0.94.0 the support of OpenCV 3.2 is removed from the codebase.
283285

284286
## Contributor's Guide
285287

binding-generator/src/bin/binding-generator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,5 @@ fn main() {
8282
.map(Path::new)
8383
.collect::<Vec<_>>();
8484
let bindings_writer = RustNativeBindingWriter::new(&src_cpp_dir, &out_dir, module, &version, debug);
85-
Generator::new(&opencv_header_dir, &additional_include_dirs, &src_cpp_dir).generate(module, bindings_writer);
85+
Generator::new(&opencv_header_dir, &additional_include_dirs, &src_cpp_dir).generate(module, !debug, bindings_writer);
8686
}

binding-generator/src/class/desc.rs

Lines changed: 17 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,69 +43,24 @@ impl<'tu, 'ge> ClassDesc<'tu, 'ge> {
4343
}
4444
}
4545

46-
/// `cv::Scalar`
47-
pub fn cv_scalar() -> Class<'tu, 'ge> {
48-
Class::new_desc(Self::simple("cv::Scalar", "core"))
46+
/// `cv::Scalar_`
47+
pub fn cv_scalar_() -> Class<'tu, 'ge> {
48+
Class::new_desc(Self::simple("cv::Scalar_", "core"))
4949
}
5050

51-
/// `cv::Size`
52-
pub fn cv_size() -> Class<'tu, 'ge> {
53-
Class::new_desc(Self::simple("cv::Size", "core"))
51+
/// `cv::Size_`
52+
pub fn cv_size_() -> Class<'tu, 'ge> {
53+
Class::new_desc(Self::simple("cv::Size_", "core"))
5454
}
5555

56-
/// `cv::Point`
57-
pub fn cv_point() -> Class<'tu, 'ge> {
58-
Class::new_desc(Self::simple("cv::Point", "core"))
56+
/// `cv::Point_`
57+
pub fn cv_point_() -> Class<'tu, 'ge> {
58+
Class::new_desc(Self::simple("cv::Point_", "core"))
5959
}
6060

61-
/// `cv::Point2f`
62-
pub fn cv_point2f() -> Class<'tu, 'ge> {
63-
Class::new_desc(Self::simple("cv::Point2f", "core"))
64-
}
65-
66-
/// `cv::Point2d`
67-
pub fn cv_point2d() -> Class<'tu, 'ge> {
68-
Class::new_desc(Self::simple("cv::Point2d", "core"))
69-
}
70-
71-
/// `cv::Point3i`
72-
pub fn cv_point3i() -> Class<'tu, 'ge> {
73-
Class::new_desc(Self::simple("cv::Point3i", "core"))
74-
}
75-
76-
/// `cv::Point3f`
77-
pub fn cv_point3f() -> Class<'tu, 'ge> {
78-
Class::new_desc(Self::simple("cv::Point3f", "core"))
79-
}
80-
81-
/// `cv::Point3d`
82-
pub fn cv_point3d() -> Class<'tu, 'ge> {
83-
Class::new_desc(Self::simple("cv::Point3d", "core"))
84-
}
85-
86-
/// `cv::Vec2f`
87-
pub fn cv_vec2f() -> Class<'tu, 'ge> {
88-
Class::new_desc(Self::simple("cv::Vec2f", "core"))
89-
}
90-
91-
/// `cv::Vec2d`
92-
pub fn cv_vec2d() -> Class<'tu, 'ge> {
93-
Class::new_desc(Self::simple("cv::Vec2d", "core"))
94-
}
95-
96-
/// `cv::Vec3f`
97-
pub fn cv_vec3f() -> Class<'tu, 'ge> {
98-
Class::new_desc(Self::simple("cv::Vec3f", "core"))
99-
}
100-
101-
/// `cv::Vec3d`
102-
pub fn cv_vec3d() -> Class<'tu, 'ge> {
103-
Class::new_desc(Self::simple("cv::Vec3d", "core"))
104-
}
105-
106-
/// `cv::Vec4i`
107-
pub fn cv_vec4i() -> Class<'tu, 'ge> {
108-
Class::new_desc(Self::simple("cv::Vec4i", "core"))
61+
/// `cv::Vec`
62+
pub fn cv_vec() -> Class<'tu, 'ge> {
63+
Class::new_desc(Self::simple("cv::Vec", "core"))
10964
}
11065

11166
/// `cv::String`
@@ -156,4 +111,9 @@ impl<'tu, 'ge> ClassDesc<'tu, 'ge> {
156111
pub fn cv_dnn_dict_value() -> Class<'tu, 'ge> {
157112
Class::new_desc(Self::boxed("cv::dnn::DictValue", "dnn"))
158113
}
114+
115+
/// `cv::Feature2D`
116+
pub fn cv_keypoint() -> Class<'tu, 'ge> {
117+
Class::new_desc(Self::boxed("cv::KeyPoint", "core"))
118+
}
159119
}

binding-generator/src/constant.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,21 @@ pub fn render_constant_rust(tokens: &[Token]) -> Option<Value> {
4444
let spelling = t.get_spelling();
4545
if spelling.contains(['"', '\'']) {
4646
out.kind = ValueKind::String;
47+
out.value += &spelling;
4748
} else if spelling.contains('.') {
48-
out.kind = ValueKind::Float;
49+
if let Some(float) = spelling.strip_suffix(['F', 'f']) {
50+
out.kind = ValueKind::Float;
51+
out.value += float;
52+
} else {
53+
out.kind = ValueKind::Double;
54+
out.value += &spelling;
55+
}
4956
} else if let Some(unsigned_value) = spelling.strip_suffix(['U', 'u']) {
5057
out.kind = ValueKind::UnsignedInteger;
5158
out.value += unsigned_value;
52-
continue;
59+
} else {
60+
out.value += &spelling;
5361
}
54-
out.value += &spelling;
5562
}
5663
TokenKind::Punctuation => {
5764
let spelling = t.get_spelling();
@@ -85,7 +92,7 @@ pub fn render_evaluation_result_rust(result: EvaluationResult) -> Value {
8592
value: x.to_string(),
8693
},
8794
EvaluationResult::Float(x) => Value {
88-
kind: ValueKind::Float,
95+
kind: ValueKind::Double,
8996
value: x.to_string(),
9097
},
9198
EvaluationResult::String(x)
@@ -181,6 +188,7 @@ pub enum ValueKind {
181188
Integer,
182189
UnsignedInteger,
183190
Float,
191+
Double,
184192
String,
185193
}
186194

@@ -192,7 +200,7 @@ pub struct Value {
192200

193201
impl fmt::Display for Value {
194202
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195-
if self.kind == ValueKind::Float && !self.value.contains('.') {
203+
if self.kind == ValueKind::Double && !self.value.contains('.') {
196204
write!(f, "{}.", self.value)
197205
} else {
198206
write!(f, "{}", self.value)

binding-generator/src/func.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl<'tu, 'ge> Func<'tu, 'ge> {
191191
cpp_body: FuncCppBody::Auto,
192192
rust_body: FuncRustBody::Auto,
193193
rust_extern_definition: FuncRustExtern::Auto,
194+
cfg_attr: Rc::new(None),
194195
})
195196
}
196197
Func::Desc(desc) => {
@@ -631,7 +632,11 @@ impl<'tu, 'ge> Func<'tu, 'ge> {
631632
pub fn cfg_attrs(&self) -> Option<(&str, &str)> {
632633
match self {
633634
Self::Clang { gen_env, .. } => gen_env.settings.func_cfg_attr.get(&mut self.matcher()).copied(),
634-
Self::Desc(_) => None,
635+
Self::Desc(desc) => desc
636+
.cfg_attr
637+
.as_ref()
638+
.as_ref()
639+
.map(|(rust, cpp)| (rust.as_str(), cpp.as_str())),
635640
}
636641
}
637642
}

binding-generator/src/func/desc.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct FuncDesc<'tu, 'ge> {
2626
pub cpp_body: FuncCppBody,
2727
pub rust_body: FuncRustBody,
2828
pub rust_extern_definition: FuncRustExtern,
29+
pub cfg_attr: Rc<Option<(String, String)>>,
2930
}
3031

3132
impl<'tu, 'ge> FuncDesc<'tu, 'ge> {
@@ -54,6 +55,7 @@ impl<'tu, 'ge> FuncDesc<'tu, 'ge> {
5455
cpp_body: FuncCppBody::Auto,
5556
rust_body: FuncRustBody::Auto,
5657
rust_extern_definition: FuncRustExtern::Auto,
58+
cfg_attr: Rc::new(None),
5759
}
5860
}
5961

@@ -105,6 +107,12 @@ impl<'tu, 'ge> FuncDesc<'tu, 'ge> {
105107
self
106108
}
107109

110+
#[inline]
111+
pub fn cfg_attr(mut self, cfg_attr: Option<(String, String)>) -> Self {
112+
self.cfg_attr = cfg_attr.into();
113+
self
114+
}
115+
108116
pub fn method_delete(class_desc: Class<'tu, 'ge>) -> Func<'tu, 'ge> {
109117
Func::new_desc(
110118
FuncDesc::new(

binding-generator/src/generator.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,12 @@ impl<'tu, V: GeneratorVisitor<'tu>> EntityWalkerVisitor<'tu> for OpenCvWalker<'t
104104
"GAPI_EXPORTS_W",
105105
"GAPI_WRAP",
106106
];
107-
const SIMPLE: [&str; 3] = ["CV_EXPORTS_W_SIMPLE", "CV_EXPORTS_W_MAP", "GAPI_EXPORTS_W_SIMPLE"];
107+
const SIMPLE: [&str; 4] = [
108+
"CV_EXPORTS_W_SIMPLE",
109+
"CV_EXPORTS_W_PARAMS",
110+
"CV_EXPORTS_W_MAP",
111+
"GAPI_EXPORTS_W_SIMPLE",
112+
];
108113
const RENAME: [&str; 2] = ["CV_EXPORTS_AS", "CV_WRAP_AS"];
109114
if BOXED.contains(&name.as_str()) {
110115
self.gen_env.make_export_config(entity);
@@ -309,17 +314,16 @@ impl<'tu, 'r, V: GeneratorVisitor<'tu>> OpenCvWalker<'tu, 'r, V> {
309314
if typedef.exclude_kind().is_included() {
310315
match typedef {
311316
NewTypedefResult::Typedef(typedef) => {
312-
let type_ref = typedef.type_ref();
313-
let export = gen_env.get_export_config(typedef_decl).is_some()
314-
// we need to have a typedef even if it's not exported for e.g. cv::Size
315-
|| type_ref.is_data_type()
316-
|| {
317+
let export = gen_env.get_export_config(typedef_decl).is_some() || {
317318
let underlying_type = typedef.underlying_type_ref();
318319
underlying_type.kind().is_function()
319320
|| !underlying_type.exclude_kind().is_ignored()
320-
|| underlying_type.template_kind().as_template_specialization().map_or(false, |templ| {
321-
settings::IMPLEMENTED_GENERICS.contains(templ.cpp_name(CppNameStyle::Reference).as_ref())
322-
})
321+
|| underlying_type
322+
.template_kind()
323+
.as_template_specialization()
324+
.map_or(false, |templ| {
325+
settings::IMPLEMENTED_GENERICS.contains(templ.cpp_name(CppNameStyle::Reference).as_ref())
326+
})
323327
};
324328

325329
if export {
@@ -455,8 +459,8 @@ impl Generator {
455459
}
456460

457461
/// Runs the full binding generation process using the supplied `visitor`
458-
pub fn generate(&self, module: &str, visitor: impl for<'tu> GeneratorVisitor<'tu>) {
459-
self.pre_process(module, true, |root_entity| {
462+
pub fn generate(&self, module: &str, panic_on_error: bool, visitor: impl for<'tu> GeneratorVisitor<'tu>) {
463+
self.pre_process(module, panic_on_error, |root_entity| {
460464
let gen_env = GeneratorEnv::global(module, root_entity);
461465
let opencv_walker = OpenCvWalker::new(module, &self.opencv_module_header_dir, visitor, gen_env);
462466
root_entity.walk_opencv_entities(opencv_walker);

0 commit comments

Comments
 (0)