From 2d45a8f7d2f50a2c7435ff93dd39d47707d47350 Mon Sep 17 00:00:00 2001 From: Brad Rees Date: Wed, 18 Feb 2026 10:55:37 +0800 Subject: [PATCH 1/2] Fix macOS OpenCV 4.13/Ruby 4 build and document setup --- README.md | 32 ++++++++++++++++++++++++ ext/opencv2/core/bindings_utils-rb.cpp | 17 ++++++++++--- ext/opencv2/core/mat-rb.cpp | 4 +-- ext/opencv2/imgproc-rb.cpp | 8 +++--- ext/opencv2/video/background_segm-rb.cpp | 6 ++--- 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c886439c..96202c6f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,38 @@ Ruby bindings for OpenCV4 based on its C++ API. Almost all of OpenCV's API is ex See [installation](https://cfis.github.io/opencv-ruby/installation/) +## Build from Source on macOS + +The following setup was used to successfully build `opencv-ruby` on Apple Silicon macOS with Homebrew OpenCV 4.13 and Ruby 4.0.x (RVM): + +* Xcode Command Line Tools (`xcode-select --install`) +* CMake 3.26+ (`brew install cmake`) +* Ninja (`brew install ninja`) +* OpenCV (`brew install opencv`) +* pkg-config (`brew install pkg-config`) + +Recommended install command: + +```sh +RUBY_EXE="$(rvm which ruby)" +RUBY_LIB="$(ruby -rrbconfig -e 'puts File.join(RbConfig::CONFIG[\"libdir\"], RbConfig::CONFIG[\"LIBRUBY_SO\"])')" +RUBY_HDR="$(ruby -rrbconfig -e 'puts RbConfig::CONFIG[\"rubyhdrdir\"]')" +RUBY_ARCH_HDR="$(ruby -rrbconfig -e 'puts RbConfig::CONFIG[\"rubyarchhdrdir\"]')" + +gem install opencv-ruby -- --preset macos-release \ + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=ON \ + -DRuby_EXECUTABLE="$RUBY_EXE" \ + -DRuby_LIBRARY="$RUBY_LIB" \ + -DRuby_INCLUDE_DIR="$RUBY_HDR" \ + -DRuby_CONFIG_INCLUDE_DIR="$RUBY_ARCH_HDR" +``` + +Notes: + +* `-DCMAKE_NO_SYSTEM_FROM_IMPORTED=ON` avoids header-order conflicts when legacy headers are present in `/usr/local/include/opencv2`. +* Passing explicit `Ruby_*` paths helps when RVM has multiple Rubies installed and CMake picks the wrong one. +* The final link step can take several minutes and may show high CPU in `ld`; this is expected. + ## Getting Started See [getting started](https://cfis.github.io/opencv-ruby/getting-started/) diff --git a/ext/opencv2/core/bindings_utils-rb.cpp b/ext/opencv2/core/bindings_utils-rb.cpp index 63494aa7..bf9af979 100644 --- a/ext/opencv2/core/bindings_utils-rb.cpp +++ b/ext/opencv2/core/bindings_utils-rb.cpp @@ -11,6 +11,17 @@ Rice::Class rb_cCvUtilsFunctionParams; Rice::Class rb_cCvUtilsNestedOriginalClassName; Rice::Class rb_cCvUtilsNestedOriginalClassNameParams; +static int set_log_level_int(int level) +{ + return static_cast(cv::utils::logging::setLogLevel( + static_cast(level))); +} + +static int get_log_level_int() +{ + return static_cast(cv::utils::logging::getLogLevel()); +} + void Init_BindingsUtils() { Module rb_mCv = define_module("Cv"); @@ -159,8 +170,8 @@ void Init_BindingsUtils() rb_mCvUtilsFs.define_module_function("get_cache_directory_for_downloads", &cv::utils::fs::getCacheDirectoryForDownloads); - rb_mCv.define_module_function("set_log_level", &cv::setLogLevel, + rb_mCv.define_module_function("set_log_level", &set_log_level_int, Arg("level")); - rb_mCv.define_module_function("get_log_level", &cv::getLogLevel); -} \ No newline at end of file + rb_mCv.define_module_function("get_log_level", &get_log_level_int); +} diff --git a/ext/opencv2/core/mat-rb.cpp b/ext/opencv2/core/mat-rb.cpp index 9d11a68e..1073ff16 100644 --- a/ext/opencv2/core/mat-rb.cpp +++ b/ext/opencv2/core/mat-rb.cpp @@ -593,7 +593,7 @@ void Init_Mat() Arg("i") = static_cast(-1)). define_method("submatrix?", &cv::_InputArray::isSubmatrix, Arg("i") = static_cast(-1)). - define_method("empty?", &cv::_InputArray::empty). + define_method("empty?", static_cast(&cv::_InputArray::empty)). define_method("copy_to", &cv::_InputArray::copyTo, Arg("arr")). define_method("copy_to", &cv::_InputArray::copyTo, @@ -2669,4 +2669,4 @@ void Init_Mat() define_constructor(Constructor>&>()). define_constructor(Constructor>&>()). define_constructor(Constructor>&>()); -} \ No newline at end of file +} diff --git a/ext/opencv2/imgproc-rb.cpp b/ext/opencv2/imgproc-rb.cpp index 265d24a3..f5dc453b 100644 --- a/ext/opencv2/imgproc-rb.cpp +++ b/ext/opencv2/imgproc-rb.cpp @@ -561,11 +561,11 @@ void Init_Imgproc() define_constructor(Constructor()). define_constructor(Constructor(), Arg("rect")). - define_method("init_delaunay", &cv::Subdiv2D::initDelaunay, + define_method("init_delaunay", static_cast(&cv::Subdiv2D::initDelaunay), Arg("rect")). - define_method("insert", &cv::Subdiv2D::insert, + define_method("insert", static_cast(&cv::Subdiv2D::insert), Arg("pt")). - define_method>&)>("insert", &cv::Subdiv2D::insert, + define_method("insert", static_cast&)>(&cv::Subdiv2D::insert), Arg("ptvec")). define_method("locate", &cv::Subdiv2D::locate, Arg("pt"), Arg("edge"), Arg("vertex")). @@ -1130,4 +1130,4 @@ void Init_Imgproc() define_attr("plus_shift", &cv::LineIterator::plusShift). define_attr("p", &cv::LineIterator::p). define_attr("ptmode", &cv::LineIterator::ptmode); -} \ No newline at end of file +} diff --git a/ext/opencv2/video/background_segm-rb.cpp b/ext/opencv2/video/background_segm-rb.cpp index fe119039..bec12398 100644 --- a/ext/opencv2/video/background_segm-rb.cpp +++ b/ext/opencv2/video/background_segm-rb.cpp @@ -13,7 +13,7 @@ void Init_BackgroundSegm() Module rb_mCv = define_module("Cv"); rb_cCvBackgroundSubtractor = define_class_under(rb_mCv, "BackgroundSubtractor"). - define_method("apply", &cv::BackgroundSubtractor::apply, + define_method("apply", &cv::BackgroundSubtractor::apply, Arg("image"), Arg("fgmask"), Arg("learning_rate") = static_cast(-1)). define_method("get_background_image", &cv::BackgroundSubtractor::getBackgroundImage, Arg("background_image")); @@ -55,7 +55,7 @@ void Init_BackgroundSegm() define_method("get_shadow_threshold", &cv::BackgroundSubtractorMOG2::getShadowThreshold). define_method("set_shadow_threshold", &cv::BackgroundSubtractorMOG2::setShadowThreshold, Arg("threshold")). - define_method("apply", &cv::BackgroundSubtractorMOG2::apply, + define_method("apply", &cv::BackgroundSubtractorMOG2::apply, Arg("image"), Arg("fgmask"), Arg("learning_rate") = static_cast(-1)); rb_mCv.define_module_function("create_background_subtractor_mog2", &cv::createBackgroundSubtractorMOG2, @@ -87,4 +87,4 @@ void Init_BackgroundSegm() rb_mCv.define_module_function("create_background_subtractor_knn", &cv::createBackgroundSubtractorKNN, Arg("history") = static_cast(500), Arg("dist2_threshold") = static_cast(400.0), Arg("detect_shadows") = static_cast(true)); -} \ No newline at end of file +} From ff49bf6ead377d658043389c87322a9fbbe4ed03 Mon Sep 17 00:00:00 2001 From: Brad Rees Date: Wed, 18 Feb 2026 11:15:38 +0800 Subject: [PATCH 2/2] Keep README minimal and guard log-level API by OpenCV version --- README.md | 32 -------------------------- ext/opencv2/core/bindings_utils-rb.cpp | 9 ++++++++ 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 96202c6f..c886439c 100644 --- a/README.md +++ b/README.md @@ -14,38 +14,6 @@ Ruby bindings for OpenCV4 based on its C++ API. Almost all of OpenCV's API is ex See [installation](https://cfis.github.io/opencv-ruby/installation/) -## Build from Source on macOS - -The following setup was used to successfully build `opencv-ruby` on Apple Silicon macOS with Homebrew OpenCV 4.13 and Ruby 4.0.x (RVM): - -* Xcode Command Line Tools (`xcode-select --install`) -* CMake 3.26+ (`brew install cmake`) -* Ninja (`brew install ninja`) -* OpenCV (`brew install opencv`) -* pkg-config (`brew install pkg-config`) - -Recommended install command: - -```sh -RUBY_EXE="$(rvm which ruby)" -RUBY_LIB="$(ruby -rrbconfig -e 'puts File.join(RbConfig::CONFIG[\"libdir\"], RbConfig::CONFIG[\"LIBRUBY_SO\"])')" -RUBY_HDR="$(ruby -rrbconfig -e 'puts RbConfig::CONFIG[\"rubyhdrdir\"]')" -RUBY_ARCH_HDR="$(ruby -rrbconfig -e 'puts RbConfig::CONFIG[\"rubyarchhdrdir\"]')" - -gem install opencv-ruby -- --preset macos-release \ - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=ON \ - -DRuby_EXECUTABLE="$RUBY_EXE" \ - -DRuby_LIBRARY="$RUBY_LIB" \ - -DRuby_INCLUDE_DIR="$RUBY_HDR" \ - -DRuby_CONFIG_INCLUDE_DIR="$RUBY_ARCH_HDR" -``` - -Notes: - -* `-DCMAKE_NO_SYSTEM_FROM_IMPORTED=ON` avoids header-order conflicts when legacy headers are present in `/usr/local/include/opencv2`. -* Passing explicit `Ruby_*` paths helps when RVM has multiple Rubies installed and CMake picks the wrong one. -* The final link step can take several minutes and may show high CPU in `ld`; this is expected. - ## Getting Started See [getting started](https://cfis.github.io/opencv-ruby/getting-started/) diff --git a/ext/opencv2/core/bindings_utils-rb.cpp b/ext/opencv2/core/bindings_utils-rb.cpp index bf9af979..4f609ba7 100644 --- a/ext/opencv2/core/bindings_utils-rb.cpp +++ b/ext/opencv2/core/bindings_utils-rb.cpp @@ -13,13 +13,22 @@ Rice::Class rb_cCvUtilsNestedOriginalClassNameParams; static int set_log_level_int(int level) { +#if CV_VERSION_MAJOR > 4 || (CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 13) return static_cast(cv::utils::logging::setLogLevel( static_cast(level))); +#else + return static_cast(cv::setLogLevel( + static_cast(level))); +#endif } static int get_log_level_int() { +#if CV_VERSION_MAJOR > 4 || (CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 13) return static_cast(cv::utils::logging::getLogLevel()); +#else + return static_cast(cv::getLogLevel()); +#endif } void Init_BindingsUtils()