diff --git a/README.md b/README.md index a7fb9a0..2481280 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,36 @@ module.exports = { The TypeScript type declarations may not be up to date with the latest OpenCV.js. Refer to [cvKeys.json](doc/cvKeys.json) to check the available methods and properties at runtime. +# Optional Modules + +Some OpenCV modules are disabled by default in the pre-built `opencv.js` file to reduce file size. This includes: + +- **stitching** - Image stitching for creating panoramas (includes the `Stitcher` class) +- **videoio** - Video I/O operations +- **highgui** - High-level GUI operations +- **ml** - Machine learning algorithms + +TypeScript type definitions are provided for these modules (e.g., `Stitcher` class), but they will not be available at runtime unless you rebuild OpenCV.js with these modules enabled. + +## Using the Stitcher Class + +The `Stitcher` class is part of the stitching module and provides high-level functionality for image stitching and panorama creation. To use it: + +1. **Check if available**: First verify the module is enabled in your build: +```js +if ('Stitcher' in cv) { + // Stitcher is available + const stitcher = cv.Stitcher.create(); + // Use stitcher... +} else { + console.log('Stitcher module not available in current build'); +} +``` + +2. **Rebuild with stitching module**: To enable the stitching module, rebuild OpenCV.js using the workflow in `.github/workflows/build-opencv-js.yml`. The current build has this module disabled to reduce file size. + +For more information on the Stitcher API, see the [OpenCV Stitcher documentation](https://docs.opencv.org/4.x/d2/d8d/classcv_1_1Stitcher.html). + # Star History [![Star History Chart](https://api.star-history.com/svg?repos=techstark/opencv-js&type=Date)](https://star-history.com/#techstark/opencv-js&Date) diff --git a/package-lock.json b/package-lock.json index 2507829..49506c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3321,10 +3321,11 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -7112,9 +7113,9 @@ "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "requires": { "argparse": "^1.0.7", diff --git a/src/types/opencv/Stitcher.ts b/src/types/opencv/Stitcher.ts new file mode 100644 index 0000000..c130bca --- /dev/null +++ b/src/types/opencv/Stitcher.ts @@ -0,0 +1,263 @@ +import type { + bool, + double, + InputArray, + InputArrayOfArrays, + int, + IntVector, + Mat, + OutputArray, + Ptr, + Rect, + UMat, +} from "./_types"; + +/** + * High level image stitcher. + * + * It's possible to use this class to create panoramas by stitching together multiple images. + * The stitcher combines several algorithms in a configurable pipeline to perform the stitching. + * + * Source: + * [opencv2/stitching.hpp](https://github.com/opencv/opencv/tree/master/modules/stitching/include/opencv2/stitching.hpp). + * + * @note + * This class is part of the stitching module which may not be enabled in the OpenCV.js build. + * Check the build configuration or rebuild OpenCV.js with the stitching module enabled to use this class. + */ +export declare class Stitcher { + /** + * Creates a Stitcher configured in one of the stitching modes. + * + * @param mode Scenario for stitcher operation. This is usually used to determine how to + * set each of the stitcher properties to optimum values. + * Stitcher.PANORAMA mode expects images under horizontal perspective. + * Stitcher.SCANS mode is designed for scanned images. + * If not specified, defaults to Stitcher.PANORAMA mode. + * + * @returns An instance of Stitcher class. + */ + public static create(mode?: int): Stitcher; + + /** + * @returns Registration resolution in megapixels + */ + public registrationResol(): double; + + /** + * Sets the registration resolution. + * + * @param resol_mpx Resolution for image registration in megapixels. + * -1 for original resolution. + */ + public setRegistrationResol(resol_mpx: double): void; + + /** + * @returns Seam estimation resolution in megapixels + */ + public seamEstimationResol(): double; + + /** + * Sets the seam estimation resolution. + * + * @param resol_mpx Resolution for seam estimation in megapixels. + * -1 for original resolution. + */ + public setSeamEstimationResol(resol_mpx: double): void; + + /** + * @returns Compositing resolution in megapixels + */ + public compositingResol(): double; + + /** + * Sets the compositing resolution. + * + * @param resol_mpx Resolution for compositing in megapixels. + * -1 for original resolution. + */ + public setCompositingResol(resol_mpx: double): void; + + /** + * @returns Panorama confidence threshold + */ + public panoConfidenceThresh(): double; + + /** + * Sets the panorama confidence threshold. + * + * @param conf_thresh Threshold for the panorama confidence. + * The stitch() method returns ERR_NEED_MORE_IMGS if the confidence is below this threshold. + */ + public setPanoConfidenceThresh(conf_thresh: double): void; + + /** + * @returns Wave correction flag + */ + public waveCorrection(): bool; + + /** + * Sets wave correction on or off. + * + * @param flag true to enable wave correction, false to disable. + */ + public setWaveCorrection(flag: bool): void; + + /** + * @returns Interpolation method used for all resizing operations. + */ + public interpolationFlags(): int; + + /** + * Sets the interpolation method for all resizing operations. + * + * @param interp_flags Interpolation method. + */ + public setInterpolationFlags(interp_flags: int): void; + + /** + * @returns Wave correction kind + */ + public waveCorrectKind(): int; + + /** + * Sets the kind of wave correction. + * + * @param kind Wave correction kind (horizontal or vertical). + */ + public setWaveCorrectKind(kind: int): void; + + /** + * Estimates the transformation matrices for each input image. + * + * @param images Input images. + * @param masks Optional masks for each input image. + * + * @returns Status code. + */ + public estimateTransform(images: InputArrayOfArrays): int; + public estimateTransform( + images: InputArrayOfArrays, + masks: InputArrayOfArrays, + ): int; + + /** + * Tries to stitch the given images. + * + * @param images Input images. + * @param pano Final panorama (stitched image). + * + * @returns Status code. + */ + public stitch(images: InputArrayOfArrays, pano: OutputArray): int; + + /** + * Tries to stitch the given images with optional masks. + * + * @param images Input images. + * @param masks Masks for each input image specifying where to look for keypoints (optional). + * @param pano Final panorama (stitched image). + * + * @returns Status code. + */ + public stitch( + images: InputArrayOfArrays, + masks: InputArrayOfArrays, + pano: OutputArray, + ): int; + + /** + * Tries to compose the given images (or images stored internally from the other function + * calls) into the final pano under the assumption that the image transformations + * were estimated before. + * + * @param pano Final panorama (stitched image). + * + * @returns Status code. + */ + public composePanorama(pano: OutputArray): int; + + /** + * Tries to compose the given images into the final panorama. + * + * @param images Input images. + * @param pano Final panorama (stitched image). + * + * @returns Status code. + */ + public composePanorama(images: InputArrayOfArrays, pano: OutputArray): int; + + /** + * Gets the connected components of the stitched images. + * + * @returns Array containing the indices of images in each connected component. + * Images that could not be stitched together will be in separate components. + */ + public component(): IntVector; + + /** + * @returns Indices (0-based) of ROI for each image. + */ + public workScale(): double; + + /** + * Releases the object. + */ + public delete(): void; +} + +/** + * Status codes returned by the stitching pipeline. + */ +export type StitcherStatus = int; + +/** + * Stitching completed successfully. + */ +export declare const Stitcher_OK: StitcherStatus; // initializer: = 0 + +/** + * Error: not enough input images provided for stitching. + */ +export declare const Stitcher_ERR_NEED_MORE_IMGS: StitcherStatus; // initializer: = 1 + +/** + * Error: homography estimation failed. + */ +export declare const Stitcher_ERR_HOMOGRAPHY_EST_FAIL: StitcherStatus; // initializer: = 2 + +/** + * Error: camera parameters adjustment failed. + */ +export declare const Stitcher_ERR_CAMERA_PARAMS_ADJUST_FAIL: StitcherStatus; // initializer: = 3 + +/** + * Stitcher operating modes. + */ +export type StitcherMode = int; + +/** + * Mode for creating photo panoramas. Expects images under perspective transformation and + * projects resulting panorama to sphere. + */ +export declare const Stitcher_PANORAMA: StitcherMode; // initializer: = 0 + +/** + * Mode for stitching scanned images. Images are expected to be similar and under affine transformation. + */ +export declare const Stitcher_SCANS: StitcherMode; // initializer: = 1 + +/** + * Wave correction kinds. + */ +export type WaveCorrectKind = int; + +/** + * Horizontal wave correction. + */ +export declare const WAVE_CORRECT_HORIZ: WaveCorrectKind; // initializer: = 0 + +/** + * Vertical wave correction. + */ +export declare const WAVE_CORRECT_VERT: WaveCorrectKind; // initializer: = 1 diff --git a/src/types/opencv/_types.ts b/src/types/opencv/_types.ts index a3ff3c9..e9aa9cd 100644 --- a/src/types/opencv/_types.ts +++ b/src/types/opencv/_types.ts @@ -41,9 +41,12 @@ export * from "./objdetect"; export * from "./ORB"; export * from "./PCA"; export * from "./photo_inpaint"; +export * from "./QRCodeDetector"; +export * from "./QRCodeDetectorAruco"; export * from "./RotatedRect"; export * from "./softdouble"; export * from "./softfloat"; +export * from "./Stitcher"; export * from "./video_track"; export * from "./_hacks"; export * from "./Tracker"; diff --git a/test/Stitcher.test.ts b/test/Stitcher.test.ts new file mode 100644 index 0000000..3238bb8 --- /dev/null +++ b/test/Stitcher.test.ts @@ -0,0 +1,106 @@ +import { setupOpenCv } from "./cv"; + +beforeAll(async () => { + await setupOpenCv(); +}); + +// Helper function to check if Stitcher is available +const isStitcherAvailable = () => "Stitcher" in cv && typeof cv.Stitcher !== "undefined"; + +describe("Stitcher", () => { + it("should pass TypeScript type validations", () => { + // This test ensures that the Stitcher type definitions compile correctly + // even if the stitching module is not available in the current OpenCV.js build + expect(true).toBe(true); + }); + + it("should check if Stitcher is available in current build", () => { + if (!isStitcherAvailable()) { + console.log( + "⚠️ Stitcher class is not available in the current OpenCV.js build.\n" + + " The stitching module is disabled by default.\n" + + " To use Stitcher, rebuild OpenCV.js with the stitching module enabled.\n" + + " See .github/workflows/build-opencv-js.yml for build instructions." + ); + } + + // This test doesn't fail - it's informational + expect(typeof isStitcherAvailable()).toBe("boolean"); + }); + + // Conditional tests that only run if Stitcher is available + describe("when Stitcher is available", () => { + + it("should be available as a class", () => { + if (!isStitcherAvailable()) { + console.log("Skipping: Stitcher not available in current build"); + return; + } + expect(cv.Stitcher).toBeDefined(); + }); + + it("should have create static method", () => { + if (!isStitcherAvailable()) return; + expect(cv.Stitcher.create).toBeDefined(); + expect(typeof cv.Stitcher.create).toBe("function"); + }); + + it("should be able to create Stitcher instance", () => { + if (!isStitcherAvailable()) return; + const stitcher = cv.Stitcher.create(); + expect(stitcher).toBeDefined(); + stitcher.delete(); + }); + + it("should have stitch method", () => { + if (!isStitcherAvailable()) return; + const stitcher = cv.Stitcher.create(); + expect(stitcher.stitch).toBeDefined(); + expect(typeof stitcher.stitch).toBe("function"); + stitcher.delete(); + }); + + it("should have estimateTransform method", () => { + if (!isStitcherAvailable()) return; + const stitcher = cv.Stitcher.create(); + expect(stitcher.estimateTransform).toBeDefined(); + expect(typeof stitcher.estimateTransform).toBe("function"); + stitcher.delete(); + }); + + it("should have composePanorama method", () => { + if (!isStitcherAvailable()) return; + const stitcher = cv.Stitcher.create(); + expect(stitcher.composePanorama).toBeDefined(); + expect(typeof stitcher.composePanorama).toBe("function"); + stitcher.delete(); + }); + + it("should have configuration methods", () => { + if (!isStitcherAvailable()) return; + const stitcher = cv.Stitcher.create(); + + expect(stitcher.setRegistrationResol).toBeDefined(); + expect(stitcher.setSeamEstimationResol).toBeDefined(); + expect(stitcher.setCompositingResol).toBeDefined(); + expect(stitcher.setPanoConfidenceThresh).toBeDefined(); + expect(stitcher.setWaveCorrection).toBeDefined(); + + stitcher.delete(); + }); + + it("should have status constants", () => { + if (!isStitcherAvailable()) return; + expect(cv.Stitcher_OK).toBeDefined(); + expect(cv.Stitcher_ERR_NEED_MORE_IMGS).toBeDefined(); + expect(cv.Stitcher_ERR_HOMOGRAPHY_EST_FAIL).toBeDefined(); + expect(cv.Stitcher_ERR_CAMERA_PARAMS_ADJUST_FAIL).toBeDefined(); + }); + + it("should have mode constants", () => { + if (!isStitcherAvailable()) return; + expect(cv.Stitcher_PANORAMA).toBeDefined(); + expect(cv.Stitcher_SCANS).toBeDefined(); + }); + }); +});