add support for OpenCV 4.1
MODIFY
.travis.yml
.travis.yml
@@ -44,8 +44,8 @@ env:
- Atlas_ROOT_DIR=/usr/include/ # for cmake to find lapacke.h
- LC_CTYPE=C.UTF-8 # makes python3 locale.getpreferredencoding() return utf8 encoding instead of ansi
matrix:
- - OPENCV_VERSION=3.4.6 OPENCV_PKGCONFIG=opencv
- - OPENCV_VERSION=4.1.0 OPENCV_PKGCONFIG=opencv4
+ - OPENCV_VERSION=3.4.6 OPENCV_PKGCONFIG=opencv CARGO_FEATURES=opencv-34
+ - OPENCV_VERSION=4.1.0 OPENCV_PKGCONFIG=opencv4 CARGO_FEATURES=opencv-41
before_script:
- mkdir -p ~/build/opencv
@@ -60,6 +60,9 @@ before_script:
- pkg-config --cflags $OPENCV_PKGCONFIG
- pkg-config --libs $OPENCV_PKGCONFIG
+script:
+ - cargo test --verbose --no-default-features --features $CARGO_FEATURES
+
matrix:
allow_failures:
- rust: nightly

MODIFY
Cargo.toml
Cargo.toml
@@ -33,10 +33,10 @@ semver = "0.9"
matches = "0.1"
[features]
-default = ["opencv_34"]
+default = ["opencv-34"]
buildtime_bindgen = []
-opencv_34 = []
-opencv_41 = []
+opencv-34 = []
+opencv-41 = []
[package.metadata.docs.rs]
rustc-args = [ "--cfg feature=\"docs-only\"" ]

MODIFY
README.md
README.md
[![Build Status](https://travis-ci.org/twistedfall/opencv-rust.svg?branch=master)](https://travis-ci.org/twistedfall/opencv-rust)
[![docs.rs](https://docs.rs/opencv/badge.svg)](https://docs.rs/opencv)
-Experimental Rust bindings for OpenCV 3.
+Experimental Rust bindings for OpenCV 3 and 4.
The API is usable but unstable and not very battle-tested; use at your own risk.

MODIFY
build.rs
build.rs
@@ -16,23 +16,31 @@ use semver::{Version, VersionReq};
use glob::glob;
fn link_wrapper() -> Result<pkg_config::Library, Box<dyn Error>> {
- let (opencv, pkg_name) = if let Ok(library) = pkg_config::probe_library("opencv") {
- (library, "opencv")
- } else if let Ok(library) = pkg_config::probe_library("opencv4") {
- (library, "opencv4")
+ let (opencv, pkg_name) = if cfg!(feature = "opencv-34") {
+ let (opencv, pkg_name) = if let Ok(opencv) = pkg_config::probe_library("opencv") {
+ (opencv, "opencv")
} else {
panic!("package opencv is not found by pkg-config")
};
-
- if cfg!(feature = "opencv_34") {
- if !VersionReq::parse("~3.4")?.matches(&Version::parse(&opencv.version)?) {
- panic!("OpenCV version from pkg-config: {} must be from 3.4 branch because of the feature: opencv_34", opencv.version);
+ if !VersionReq::parse("~3")?.matches(&Version::parse(&opencv.version)?) {
+ panic!("OpenCV version from pkg-config: {} must be from 3.4 branch because of the feature: opencv-34", opencv.version);
}
- } else if cfg!(feature = "opencv_4") {
+ (opencv, pkg_name)
+ } else if cfg!(feature = "opencv-41") {
+ let (opencv, pkg_name) = if let Ok(opencv) = pkg_config::probe_library("opencv4") {
+ (opencv, "opencv4")
+ } else {
+ panic!("package opencv4 is not found by pkg-config")
+ };
if !VersionReq::parse("~4.1")?.matches(&Version::parse(&opencv.version)?) {
- panic!("OpenCV version from pkg-config: {} must be from 4.1 branch because of the feature: opencv_41", opencv.version);
- }
+ panic!("OpenCV version from pkg-config: {} must be from 4.1 branch because of the feature: opencv-41", opencv.version);
}
+ (opencv, pkg_name)
+ } else {
+ unreachable!("Cannot be until we allow custom headers");
+ };
+
+ eprintln!("Using OpenCV library version: {} from: {}", opencv.version, pkg_config::get_variable(pkg_name, "libdir")?);
// add 3rdparty lib dit. pkgconfig forgets it somehow.
let third_party_dir1 = format!("{}/share/OpenCV/3rdparty/lib", pkg_config::get_variable(pkg_name, "prefix")?);
@@ -88,15 +96,20 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
let out_dir_as_str = out_dir.to_str().unwrap();
let mut hub_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?).join("src");
let manual_dir = hub_dir.join("manual");
- if cfg!(feature = "opencv_34") {
+ if cfg!(feature = "opencv-34") {
hub_dir.push("opencv_34");
+ } else if cfg!(feature = "opencv-41") {
+ hub_dir.push("opencv_41");
}
let module_dir = hub_dir.join("hub");
let opencv_dir = opencv_header_dir.join("opencv2");
- println!("OpenCV lives in {}", opencv_dir.display());
- println!("Generating code in {}", out_dir_as_str);
+ eprintln!("Using OpenCV headers from: {}", opencv_dir.display());
+ eprintln!("Generating code in: {}", out_dir_as_str);
+ if cfg!(feature = "buildtime_bindgen") {
+ eprintln!("Placing generated bindings into: {}", hub_dir.display());
+ }
let mut gcc = cc::Build::new();
gcc.cpp(true)
@@ -117,6 +130,7 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
"core_detect",
"face",
"flann",
+ "gapi",
"hal",
"hdf", // includes platform-specific headers like /usr/include/x86_64-pc-linux-gnu/opencv2/hdf/hdf5.hpp
"hfs",
@@ -125,6 +139,7 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
"opencv",
"opencv_modules",
"optflow",
+ "quality",
"rgbd",
"saliency",
"stereo",
@@ -132,7 +147,6 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
"surface_matching",
"text",
"tracking",
- "viz", // includes platform-specific headers like /usr/include/x86_64-pc-linux-gnu/opencv2/viz.hpp
"xfeatures2d", // only appears in some builds, maybe platform or opencv compile flag specific
"ximgproc",
"xobjdetect",
@@ -147,6 +161,7 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
"core/ocl_genbase.hpp", // ?
"core/opengl.hpp", // ?
"core/cvstd.hpp", // contains functions with Rust native counterparts and c++ specific classes
+ "core/cvstd_wrapper.hpp",
"core/eigen.hpp",
"core/fast_math.hpp", // contains functions with Rust native counterparts
"core/utils/filesystem.hpp", // contains functions with Rust native counterparts
@@ -194,6 +209,9 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
write!(&mut types, "#include <opencv2/{}.hpp>\n", m.0)?;
if m.0 == "dnn" {
// include it manually, otherwise it's not included
+ if cfg!(feature = "opencv-41") {
+ write!(&mut types, "#include <opencv2/{}/version.hpp>\n", m.0)?;
+ }
write!(&mut types, "#include <opencv2/{}/all_layers.hpp>\n", m.0)?;
}
}
@@ -350,14 +368,19 @@ fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
}
fn main() -> Result<(), Box<dyn Error>> {
+ let features = [cfg!(feature = "opencv-34"), cfg!(feature = "opencv-41")].iter().map(|&x| if x { 1 } else { 0 }).sum::<i32>();
+ if features != 1 {
+ // todo: allow building with custom headers
+ panic!("Please select exactly one of the features: opencv-34, opencv-41");
+ }
let opencv_header_dir = env::var("OPENCV_HEADER_DIR").map(PathBuf::from).unwrap_or_else(|_| {
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set"));
- if cfg!(feature = "opencv_34") {
+ if cfg!(feature = "opencv-34") {
manifest_dir.join("headers/3.4")
- } else if cfg!(feature = "opencv_41") {
+ } else if cfg!(feature = "opencv-41") {
manifest_dir.join("headers/4.1")
} else {
- panic!("Please select one OpenCV major version using one of the opencv_* features or specify OpenCV header path manually via OPENCV_HEADER_DIR environment var");
+ panic!("Please select one OpenCV major version using one of the opencv-* features or specify OpenCV header path manually via OPENCV_HEADER_DIR environment var");
}
});

MODIFY
examples/video_capture.rs
examples/video_capture.rs
@@ -7,7 +7,7 @@ use opencv::videoio;
fn run() -> opencv::Result<()> {
let window = "video capture";
highgui::named_window(window, 1)?;
- let mut cam = videoio::VideoCapture::new(0)?; // 0 is the default camera
+ let mut cam = videoio::VideoCapture::new_with_backend(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
panic!("Unable to open default camera!");

MODIFY
examples/video_facedetect.rs
examples/video_facedetect.rs
@@ -14,7 +14,7 @@ fn run() -> opencv::Result<()> {
let window = "video capture";
let xml = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml";
highgui::named_window(window, 1)?;
- let mut cam = videoio::VideoCapture::new(0)?; // 0 is the default camera
+ let mut cam = videoio::VideoCapture::new_with_backend(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
panic!("Unable to open default camera!");

MODIFY
examples/video_features.rs
examples/video_features.rs
@@ -9,22 +9,12 @@ use opencv::videoio;
fn run() -> opencv::Result<()> {
let window = "video capture";
highgui::named_window(window, 1)?;
- let mut cam = videoio::VideoCapture::new(0)?; // 0 is the default camera
+ let mut cam = videoio::VideoCapture::new_with_backend(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
panic!("Unable to open default camera!");
}
- let mut orb = features2d::ORB::create(
- 500,
- 1.2f32,
- 8,
- 31,
- 0,
- 2,
- features2d::ORB_HARRIS_SCORE,
- 31,
- 20
- )?;
+ let mut orb = features2d::ORB::default()?;
loop {
let mut frame = core::Mat::new()?;
cam.read(&mut frame)?;
@@ -41,12 +31,16 @@ fn run() -> opencv::Result<()> {
let mask = core::Mat::new()?;
orb.detect(&gray, &mut kps, &mask)?;
let mut display = core::Mat::new()?;
+ #[cfg(not(feature = "opencv-41"))]
+ let default_draw_matches_flags = features2d::DrawMatchesFlags_DEFAULT;
+ #[cfg(feature = "opencv-41")]
+ let default_draw_matches_flags = features2d::DrawMatchesFlags::DEFAULT;
features2d::draw_keypoints(
&gray,
&kps,
&mut display,
core::Scalar::all(-1f64),
- features2d::DrawMatchesFlags_DEFAULT
+ default_draw_matches_flags
)?;
highgui::imshow(window, &display)?;
}

MODIFY
examples/video_to_gray.rs
examples/video_to_gray.rs
@@ -8,7 +8,7 @@ use opencv::videoio;
fn run() -> opencv::Result<()> {
let window = "video capture";
highgui::named_window(window, 1)?;
- let mut cam = videoio::VideoCapture::new(0)?; // 0 is the default camera
+ let mut cam = videoio::VideoCapture::new_with_backend(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
panic!("Unable to open default camera!");

MODIFY
examples/warp_perspective_demo.rs
examples/warp_perspective_demo.rs
@@ -36,6 +36,10 @@ fn help() {
static WINDOW_TITLE: &str = "Perspective Transformation Demo";
static LABELS: [&str; 4] = ["TL", "TR", "BR", "BL"];
+#[cfg(not(feature = "opencv-41"))]
+use self::core::LINE_8;
+#[cfg(feature = "opencv-41")]
+use self::imgproc::LINE_8;
fn main() -> Result<(), Box<Error>> {
let roi_corners = Arc::new(Mutex::new(VectorOfPoint::new()));
@@ -105,11 +109,11 @@ fn main() -> Result<(), Box<Error>> {
{
let roi_corners = roi_corners.lock().unwrap();
for i in 0..roi_corners_len {
- imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, core::LINE_8, 0)?;
+ imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, LINE_8, 0)?;
if i > 0 {
- imgproc::line(&mut image, roi_corners.get(i - 1)?, roi_corners.get(i)?, Scalar::new(0., 0., 255., 0.), 2, core::LINE_8, 0)?;
- imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, core::LINE_8, 0)?;
- imgproc::put_text(&mut image, LABELS[i], roi_corners.get(i)?, highgui::QT_FONT_NORMAL, 0.8, Scalar::new(255., 0., 0., 0.), 2, core::LINE_8, false)?;
+ imgproc::line(&mut image, roi_corners.get(i - 1)?, roi_corners.get(i)?, Scalar::new(0., 0., 255., 0.), 2, LINE_8, 0)?;
+ imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, LINE_8, 0)?;
+ imgproc::put_text(&mut image, LABELS[i], roi_corners.get(i)?, highgui::QT_FONT_NORMAL, 0.8, Scalar::new(255., 0., 0., 0.), 2, LINE_8, false)?;
}
}
}
@@ -120,9 +124,9 @@ fn main() -> Result<(), Box<Error>> {
{
let roi_corners = roi_corners.lock().unwrap();
for i in 0..4 {
- imgproc::line(&mut image, roi_corners.get(i)?, roi_corners.get((i + 1) % 4)?, Scalar::new(0., 0., 255., 0.), 2, core::LINE_8, 0)?;
- imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, core::LINE_8, 0)?;
- imgproc::put_text(&mut image, LABELS[i], roi_corners.get(i)?, highgui::QT_FONT_NORMAL, 0.8, Scalar::new(255., 0., 0., 0.), 2, core::LINE_8, false)?;
+ imgproc::line(&mut image, roi_corners.get(i)?, roi_corners.get((i + 1) % 4)?, Scalar::new(0., 0., 255., 0.), 2, LINE_8, 0)?;
+ imgproc::circle(&mut image, roi_corners.get(i)?, 5, Scalar::new(0., 255., 0., 0.), 3, LINE_8, 0)?;
+ imgproc::put_text(&mut image, LABELS[i], roi_corners.get(i)?, highgui::QT_FONT_NORMAL, 0.8, Scalar::new(255., 0., 0., 0.), 2, LINE_8, false)?;
}
highgui::imshow(WINDOW_TITLE, &image)?;
dst_corners.set(0, Point::new(0, 0))?;

MODIFY
gen_rust.py
gen_rust.py
@@ -114,9 +114,11 @@ func_rename = {
### calib3d ###
"cv_findEssentialMat_Mat_Mat_Mat_int_double_double_Mat": "+_matrix",
"cv_findHomography_Mat_Mat_int_double_Mat_int_double": "+_full",
+ "cv_undistortPoints_Mat_Mat_Mat_Mat_Mat_Mat_TermCriteria": "+_with_criteria",
"cv_fisheye_projectPoints_Mat_Mat_Mat_Mat_Mat_Mat_double_Mat": "fisheye_+",
"cv_fisheye_undistortImage_Mat_Mat_Mat_Mat_Mat_Size": "fisheye_+",
"cv_fisheye_undistortPoints_Mat_Mat_Mat_Mat_Mat_Mat": "fisheye_+",
+ "cv_fisheye_initUndistortRectifyMap_Mat_Mat_Mat_Mat_Size_int_Mat_Mat": "fisheye_+",
"cv_recoverPose_Mat_Mat_Mat_Mat_Mat_Mat_Mat": "+_camera_with_points",
"cv_recoverPose_Mat_Mat_Mat_Mat_Mat_Mat_double_Mat_Mat": "+_camera",
"cv_solvePnP_Mat_Mat_Mat_Mat_Mat_Mat_bool_int": "solve_pnp",
@@ -125,8 +127,10 @@ func_rename = {
"cv_calibrateCamera_VectorOfMat_VectorOfMat_Size_Mat_Mat_VectorOfMat_VectorOfMat_Mat_Mat_Mat_int_TermCriteria": "+_with_stddev",
"cv_stereoCalibrate_VectorOfMat_VectorOfMat_VectorOfMat_Mat_Mat_Mat_Mat_Size_Mat_Mat_Mat_Mat_int_TermCriteria": "+_camera",
"cv_stereoCalibrate_VectorOfMat_VectorOfMat_VectorOfMat_Mat_Mat_Mat_Mat_Size_Mat_Mat_Mat_Mat_Mat_int_TermCriteria": "+_camera_with_errors",
+ "cv_calibrateCameraRO_VectorOfMat_VectorOfMat_Size_int_Mat_Mat_VectorOfMat_VectorOfMat_Mat_Mat_Mat_Mat_Mat_int_TermCriteria": "+_with_stddev",
"cv_stereoRectify_Mat_Mat_Mat_Mat_Size_Mat_Mat_Mat_Mat_Mat_Mat_Mat_int_double_Size_Rect_X_Rect_X": "+_camera",
"cv_findFundamentalMat_Mat_Mat_int_double_double_Mat": "-", # duplicate of cv_findFundamentalMat_Mat_Mat_Mat_int_double_double, but with different order of arguments
+ "cv_initWideAngleProjMap_Mat_Mat_Size_int_int_Mat_Mat_int_double": "+_with_type",
### core ###
"cv_addImpl_int_const_char_X": "-",
@@ -241,7 +245,8 @@ func_rename = {
### features2d ###
"cv_AGAST_Mat_VectorOfKeyPoint_int_bool": "AGAST",
- "cv_AGAST_Mat_VectorOfKeyPoint_int_bool_int": "AGAST_with_type",
+ "cv_AGAST_Mat_VectorOfKeyPoint_int_bool_int": "AGAST_with_type", # 3.x only
+ "cv_AGAST_Mat_VectorOfKeyPoint_int_bool_AgastFeatureDetector_DetectorType": "AGAST_with_type",
"cv_BOWKMeansTrainer_cluster_const": "default",
"cv_BOWKMeansTrainer_cluster_const_Mat": "new",
"cv_BOWKMeansTrainer_BOWKMeansTrainer_int_TermCriteria_int_int": "new_with_criteria",
@@ -255,7 +260,8 @@ func_rename = {
"cv_DescriptorMatcher_radiusMatch_const_Mat_Mat_VectorOfVectorOfDMatch_float_Mat_bool": "train_radius_matches",
"cv_DescriptorMatcher_radiusMatch_Mat_VectorOfVectorOfDMatch_float_VectorOfMat_bool": "radius_matches",
"cv_FAST_Mat_VectorOfKeyPoint_int_bool": "FAST",
- "cv_FAST_Mat_VectorOfKeyPoint_int_bool_int": "FAST_with_type",
+ "cv_FAST_Mat_VectorOfKeyPoint_int_bool_int": "FAST_with_type", # 3.x only
+ "cv_FAST_Mat_VectorOfKeyPoint_int_bool_FastFeatureDetector_DetectorType": "FAST_with_type",
"cv_Feature2D_detect_VectorOfMat_VectorOfVectorOfKeyPoint_VectorOfMat": "+_multiple",
"cv_KeyPoint_KeyPoint": "default",
"cv_KeyPoint_KeyPoint_Point2f_float_float_float_int_int": "new_point",
@@ -263,14 +269,15 @@ func_rename = {
"cv_KeyPoint_convert_VectorOfKeyPoint_VectorOfPoint2f_VectorOfint": "convert_from",
"cv_KeyPoint_convert_VectorOfPoint2f_VectorOfKeyPoint_float_float_int_int": "convert_to",
"cv_MatStep_MatStep": "default",
- "cv_drawMatches_Mat_VectorOfKeyPoint_Mat_VectorOfKeyPoint_VectorOfDMatch_Mat_Scalar_Scalar_VectorOfchar_int": "draw_matches",
- "cv_drawMatches_Mat_VectorOfKeyPoint_Mat_VectorOfKeyPoint_VectorOfVectorOfDMatch_Mat_Scalar_Scalar_VectorOfVectorOfchar_int": "draw_vector_matches",
+ "cv_drawMatches_Mat_VectorOfKeyPoint_Mat_VectorOfKeyPoint_VectorOfVectorOfDMatch_Mat_Scalar_Scalar_VectorOfVectorOfchar_int": "+_vector",
+ "cv_drawMatches_Mat_VectorOfKeyPoint_Mat_VectorOfKeyPoint_VectorOfVectorOfDMatch_Mat_Scalar_Scalar_VectorOfVectorOfchar_DrawMatchesFlags": "+_vector",
"cv_BRISK_create_VectorOffloat_VectorOfint_float_float_VectorOfint": "create_with_pattern",
"cv_BRISK_create_int_int_VectorOffloat_VectorOfint_float_float_VectorOfint": "create_with_pattern_threshold_octaves",
"cv_BOWTrainer_cluster_const_Mat": "cluster_with_descriptors",
"cv_GFTTDetector_create_int_double_double_int_int_bool_double": "+_with_gradient",
"cv_Feature2D_compute_VectorOfMat_VectorOfVectorOfKeyPoint_VectorOfMat": "+_multiple",
- "cv_DescriptorMatcher_create_int": "+_with_matcher_type",
+ "cv_DescriptorMatcher_create_int": "+_with_matcher_type", # 3.x only
+ "cv_DescriptorMatcher_create_DescriptorMatcher_MatcherType": "+_with_matcher_type",
"cv_BOWImgDescriptorExtractor_BOWImgDescriptorExtractor_PtrOfFeature2D_PtrOfDescriptorMatcher": "new_with_dextractor",
"cv_ORB_create": "default",
@@ -294,7 +301,8 @@ func_rename = {
"cv_GeneralizedHough_detect_Mat_Mat_Mat_Mat_Mat": "+_with_edges",
"cv_goodFeaturesToTrack_Mat_Mat_int_double_double_Mat_int_int_bool_double": "+_with_gradient",
"cv_getAffineTransform_Mat_Mat": "+_mat",
- "cv_getPerspectiveTransform_Mat_Mat": "+_mat",
+ "cv_getPerspectiveTransform_Mat_Mat": "+_mat", # 3.x only
+ "cv_getPerspectiveTransform_Mat_Mat_int": "+_mat",
### ml ###
"cv_ml_ParamGrid_ParamGrid_double_double_double": "for_range",
@@ -304,6 +312,8 @@ func_rename = {
"cv_CascadeClassifier_detectMultiScale_Mat_VectorOfRect_VectorOfint_VectorOfdouble_double_int_int_Size_Size_bool": "detect_multi_scale_levels",
"cv_CascadeClassifier_detectMultiScale_Mat_VectorOfRect_VectorOfint_double_int_int_Size_Size": "detect_multi_scale_num",
"cv_CascadeClassifier_detectMultiScale_Mat_VectorOfRect_double_int_int_Size_Size": "detect_multi_scale",
+ "cv_HOGDescriptor_HOGDescriptor": "default",
+ "cv_HOGDescriptor_HOGDescriptor_String": "new_from_file",
"cv_HOGDescriptor_HOGDescriptor_HOGDescriptor": "copy",
"cv_HOGDescriptor_detectMultiScale_const_Mat_VectorOfRect_VectorOfdouble_double_Size_Size_double_double_bool": "detect_multi_scale",
"cv_HOGDescriptor_detectMultiScale_const_Mat_VectorOfRect_double_Size_Size_double_double_bool": "detect_multi_scale_weights",
@@ -386,6 +396,9 @@ class_ignore_list = (
"cv::MatConstIterator",
"cv::_InputArray", "cv::_OutputArray", "cv::_InputOutputArray",
+ ### features2d ###
+ "cv::DrawMatchesFlags", # dummy type only used to contain anonymous enum, 3.x only
+
### stitching ###
"cv::CylindricalWarperGpu", "cv::PlaneWarperGpu", "cv::SphericalWarperGpu",
@@ -421,6 +434,11 @@ const_ignore_list = (
"CV__DNN_EXPERIMENTAL_NS_",
"CV_Sts",
"CV_ALWAYS_INLINE",
+ "CV_16FC",
+ "CV__DNN_INLINE_NS",
+ "ENUM_LOG_LEVEL_FORCE_INT",
+ "DEPTH_MASK_16F", "DEPTH_MASK_ALL_16F",
+ "CV_USRTYPE1",
)
# set of functions that should have unsafe in their declaration, element is FuncInfo.identifier
@@ -625,14 +643,55 @@ force_class_not_simple = {
"cv::dnn::Net", # marked as Simple, but it's actually boxed
}
-# set of enum's that need to be generated, other enums are just expanded to constants, elements are EnumInfo.fullname
enum_generate = {
+ ### calib3d ###
+ "cv::HandEyeCalibrationMethod",
+
+ ### core ###
+ "cv::AccessFlag",
+ "cv::Formatter::FormatType",
+ "cv::instr::FLAGS",
+ "cv::instr::IMPL",
+ "cv::instr::TYPE",
+ "cv::UMatUsageFlags",
+ "cv::UndistortTypes",
+ "cv::WindowFlags",
+ "cv::WindowPropertyFlags",
+
+ ### dnn ###
+ "cv::dnn::Backend",
+ "cv::dnn::Target",
+
+ ### features2d ###
+ "cv::AgastFeatureDetector::DetectorType",
+ "cv::AKAZE::DescriptorType",
+ "cv::DescriptorMatcher::MatcherType",
+ "cv::DrawMatchesFlags",
+ "cv::FastFeatureDetector::DetectorType",
+ "cv::KAZE::DiffusivityType",
+ "cv::ORB::ScoreType",
+
+ ### imgproc ###
+ "cv::InterpolationFlags",
+
+ ### objdetect ###
+ "cv::HOGDescriptor::HistogramNormType",
+
+ ### stitching ###
+ "cv::Stitcher::Mode",
+ "cv::Stitcher::Status",
+
+ ### videoio ###
+ "cv::VideoCaptureAPIs",
}
# dict of enum discriminants to exclude from the bindings (e.g. due to duplicate values)
# key: EnumInfo.fullname
# value: set of ConstInfo.name
enum_ignore_discriminant = {
+ "cv::AccessFlag": {"ACCESS_MASK", },
+ "cv::WindowFlags": {"WINDOW_FULLSCREEN", "WINDOW_KEEPRATIO", "WINDOW_GUI_EXPANDED"},
+ "cv::VideoCaptureAPIs": {"CAP_VFW", "CAP_V4L2", "CAP_FIREWARE", "CAP_IEEE1394", "CAP_DC1394", "CAP_CMU1394", "CAP_REALSENSE"},
}
# dict of reserved Rust keywords and their replacement to be used in var, function and class names
@@ -2890,6 +2949,7 @@ class RustWrapperGenerator(object):
self.add_decl(module, decl)
for m, decls in decls_manual_post.items():
+ if m == module:
for decl in decls:
logging.info("\n--- Manual ---\n%s", pformat(decl, 4))
self.add_decl(m, decl)
@@ -2948,8 +3008,6 @@ class RustWrapperGenerator(object):
with open("{}/{}.consts.cpp".format(cpp_dir, module), "w") as f:
f.write("""#include <cstdio>\n""")
f.write("""#include "opencv2/%s.hpp"\n"""%(module))
- for include in includes:
- f.write(include+"\n")
f.write("""using namespace cv;\n""")
f.write("int main(int, char**) {\n")
f.write(self.moduleCppConsts.getvalue())

MODIFY
hdr_parser.py
hdr_parser.py
@@ -234,7 +234,7 @@ class CppHeaderParser(object):
if add_star:
arg_type += "*"
- arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", ""), ("::", "_")])
+ arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", "")])
return arg_type, arg_name, modlist, argno
@@ -338,7 +338,6 @@ class CppHeaderParser(object):
implmatch = re.match(r"(\(.*?\))\s*:\s*(\w+\(.*?\),?\s*)+", fdecl[apos:])
if bool(implmatch):
fdecl = fdecl[:apos] + implmatch.group(1)
- decl[2].append("/I")
args0str = fdecl[apos+1:fdecl.rfind(")")].strip()
@@ -459,7 +458,7 @@ class CppHeaderParser(object):
# it means class methods, not instance methods
decl_str = self.batch_replace(decl_str, [("static inline", ""), ("inline", ""),\
("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("CV_CDECL", ""), ("CV_WRAP ", " "), ("CV_INLINE", ""),
- ("CV_DEPRECATED", ""), ("CV_DEPRECATED_EXTERNAL", "")]).strip()
+ ("CV_DEPRECATED", ""), ("CV_DEPRECATED_EXTERNAL", ""), ("CV_NORETURN", "")]).strip()
if decl_str.strip().startswith('virtual'):

MODIFY
src/lib.rs
src/lib.rs
extern crate cpp;
pub use error::{Error, Result};
+#[cfg(feature = "opencv-34")]
pub use opencv_34::hub::*;
+#[cfg(feature = "opencv-41")]
+pub use opencv_41::hub::*;
#[macro_use]
mod templ;
+#[cfg(feature = "opencv-34")]
mod opencv_34;
+#[cfg(feature = "opencv-41")]
+mod opencv_41;
mod manual;
mod error;

ADD
src/opencv_41/mod.rs
+#[allow(unused_imports, non_snake_case, dead_code)]
+#[allow(non_upper_case_globals, overflowing_literals)]
+#[allow(non_camel_case_types)]
+pub mod hub;

MODIFY
src/templ.rs
src/templ.rs
@@ -16,12 +16,14 @@ macro_rules! string_arg {
};
}
+#[cfg(feature = "opencv-34")]
macro_rules! string_arg_output_send {
(via $name_via: ident) => {
let mut $name_via = ::std::ptr::null_mut();
};
}
+#[cfg(feature = "opencv-34")]
macro_rules! string_arg_output_receive {
($name_via: ident => $name: ident) => {
*$name = $crate::templ::receive_string_mut($name_via);

MODIFY
tests/objdetect.rs
tests/objdetect.rs
@@ -36,6 +36,7 @@ fn qr_code() -> Result<()> {
assert!(!straight.empty()?);
}
+ #[cfg(feature = "opencv-34")]
{
let src = imgcodecs::imread(qr_path.to_str().unwrap(), imgcodecs::IMREAD_COLOR)?;
let mut pts = VectorOfPoint::new();

MODIFY
tests/types.rs
tests/types.rs
@@ -27,6 +27,10 @@ fn vec() -> Result<()> {
p1.at_row_mut::<i32>(2)?.copy_from_slice(&[9, 9]);
ps.push(p1);
assert_eq!(ps.len(), 1);
+ #[cfg(not(feature = "opencv-41"))]
+ use self::core::LINE_8;
+ #[cfg(feature = "opencv-41")]
+ use self::imgproc::LINE_8;
imgproc::fill_poly(&mut m, &ps, Scalar::new(127., 127., 127., 0.), LINE_8, 0, Point::default())?;
assert_eq!(*m.at_2d::<Vec3b>(0, 0)?, Vec3b::from([127, 127, 127]));
assert_eq!(*m.at_2d::<Vec3b>(0, 9)?, Vec3b::default());

add support for OpenCV 4.1