Skip to content

Feature: Expand OpenCV API Bindings #2

@luckyyyyy

Description

@luckyyyyy

Description

The goal of this issue is to systematically expand the API surface of node-opencv, making the library more powerful and comprehensive for NodeJS developers. This involves identifying high-value OpenCV functions, wrapping them from the underlying opencv-rust crate, and exposing them to JavaScript using napi-rs.

This task can be broken down into implementing functions from several key OpenCV modules. Contributors can pick a single function or a whole module to work on.

To-Do List: API Modules to Implement

Please check off items as you begin working on them and link your Pull Request to this issue.

कोर Functionality (core)

  • cv::core::flip() - Flip an image horizontally, vertically, or both.
  • cv::core::rotate() - Rotate an image by 90, 180, or 270 degrees.
  • cv::core::merge() - Merge several single-channel Mats into a multi-channel Mat.
  • cv::core::split() - Split a multi-channel Mat into several single-channel Mats.
  • cv::core::in_range() - Check if array elements lie between the elements of two other arrays.

Image Processing (imgproc)

  • cv::imgproc::gaussian_blur() - (Already exists, but could be a reference).
  • cv::imgproc::threshold() - Apply a fixed-level threshold to a single-channel array. (Different threshold types like THRESH_BINARY, THRESH_OTSU should be supported).
  • cv::imgproc::adaptive_threshold() - Apply an adaptive threshold to an array.
  • cv::imgproc::find_contours() - Find contours in a binary image. This will be complex, as it needs to return an array of points.
  • cv::imgproc::draw_contours() - Draw contours on an image.
  • cv::imgproc::canny() - Find edges in an image using the Canny algorithm.
  • cv::imgproc::hough_lines_p() - Find line segments in a binary image using the probabilistic Hough transform.

Feature Detection and Description (features2d)

This module is more complex as it often involves classes.

  • cv::features2d::ORB detector.
    • ORB::create() - A static method to create an ORB detector instance.
    • ORB::detect_and_compute() - To find keypoints and compute descriptors. The return value should be a JS object like { keypoints: KeyPoint[], descriptors: Buffer }.
  • cv::features2d::BFMatcher (Brute-Force Matcher).
    • BFMatcher::create()
    • BFMatcher::knn_match() - To find the k best matches for each descriptor.

Object Detection (objdetect)

  • cv::objdetect::CascadeClassifier
    • CascadeClassifier::new() - To create a new classifier.
    • CascadeClassifier::load() - To load a pre-trained model from an XML file (e.g., Haar cascades). This function should accept a file path as a string.
    • CascadeClassifier::detect_multi_scale() - To detect objects of different sizes in the input image. Should return an array of rectangles (Rect).

Implementation Workflow for a Single Function

Here is the general process for wrapping a new function:

  1. Select a Function: Pick an unchecked item from the to-do list above.

  2. Research the Signature: Look up the function in the opencv-rust documentation to understand its parameters and return types.

  3. Create the N-API Wrapper:

    • In the appropriate Rust module (e.g., src/imgproc.rs), create a new pub fn and annotate it with #[napi].
    • The function should take JavaScript-compatible arguments (e.g., Buffer for image data, i32 for numbers, String for paths).
    • It should return a napi::Result containing the JS-compatible output.

    Example Template (canny):

    // in src/imgproc.rs
    use napi::bindgen_prelude::*;
    use opencv::{core, imgproc, prelude::*};
    // ... other imports
    
    #[napi]
    pub fn canny(src_buf: Buffer, threshold1: f64, threshold2: f64) -> Result<Buffer> {
        // 1. Convert JS Buffer to cv::Mat
        let src_mat = buffer_to_mat(src_buf)?; // Assume helper function exists
    
        // 2. Prepare the output Mat
        let mut dst_mat = Mat::default();
    
        // 3. Call the OpenCV function
        imgproc::canny(&src_mat, &mut dst_mat, threshold1, threshold2, 3, false)
            .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
    
        // 4. Convert output cv::Mat back to JS Buffer
        mat_to_buffer(&dst_mat) // Assume helper function exists
    }
  4. Write a Test:

    • Add a new test case in the __test__/ directory (e.g., imgproc.spec.ts).
    • The test should import the new function, load a sample image, call the function, and assert something about the output. For example, check that the output Buffer is not empty and has the expected length.
  5. Document the API:

    • Add JSDoc comments to the new function in the corresponding index.d.ts file. Describe what the function does, its parameters, and what it returns.

Acceptance Criteria

For each function implemented, the following must be true:

  • The function is implemented in Rust with the #[napi] macro.
  • Input and output types are correctly and safely handled between JavaScript and Rust (e.g., Buffer <=> cv::Mat).
  • A corresponding JavaScript test using Jest is written and passes successfully.
  • The new API is documented in index.d.ts with clear JSDoc comments.
  • The code is formatted with cargo fmt and passes cargo clippy.

Resources

Let's make node-opencv even better! Thank you for your contribution.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions