Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .github/workflows/build-opencv.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build OpenCV.js
name: Build OpenCV.js with contrib modules

on:
# push:
Expand Down Expand Up @@ -32,12 +32,23 @@ jobs:
uses: actions/checkout@v4
with:
repository: opencv/opencv
ref: 4.10.0
ref: 4.11.0
path: opencv
- name: Build opencv.js

- name: Checkout opencv_contrib
uses: actions/checkout@v4
with:
repository: opencv/opencv_contrib
ref: 4.11.0
path: opencv_contrib

- name: Build opencv.js with contrib modules
run: |
source emsdk/emsdk_env.sh
emcmake python opencv/platforms/js/build_js.py build_js --build_flags="-s WASM_ASYNC_COMPILATION=0"
emcmake python opencv/platforms/js/build_js.py build_js \
--cmake_option="-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules" \
--cmake_option="-DBUILD_opencv_ximgproc=ON" \
--build_flags="-s WASM_ASYNC_COMPILATION=0"

- name: Upload opencv_js
uses: actions/upload-artifact@v4
Expand Down
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,56 @@ The file `opencv.js` was downloaded from https://docs.opencv.org/4.11.0/opencv.j

TypeScript is supported (thanks to `mirada`).

## OpenCV Contrib Modules Support

**NEW**: This package now includes TypeScript definitions for OpenCV contrib modules including `ximgproc.thinning()`.

**Note**: The default `opencv.js` build from docs.opencv.org does not include contrib modules. To use contrib modules like `cv.ximgproc.thinning()`, you need to build OpenCV.js with contrib modules enabled.

### Using contrib modules

To use contrib modules such as `cv.ximgproc.thinning()`:

1. **Build with contrib** (recommended): Use the GitHub Actions workflow in this repository to build opencv.js with contrib modules, or build locally using the instructions below.

2. **Build locally**:
```bash
# Clone repositories
git clone --branch 4.11.0 https://github.com/opencv/opencv.git
git clone --branch 4.11.0 https://github.com/opencv/opencv_contrib.git

# Install emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk && ./emsdk install 2.0.10 && ./emsdk activate 2.0.10
source emsdk_env.sh && cd ..

# Build opencv.js with contrib
emcmake python opencv/platforms/js/build_js.py build_js \
--cmake_option="-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules" \
--cmake_option="-DBUILD_opencv_ximgproc=ON"
```

3. **Replace the opencv.js file** in this package with your contrib-enabled build.

### Example usage with contrib modules

```js
import cv from "@techstark/opencv-js";

cv.onRuntimeInitialized = () => {
// Use ximgproc thinning function
const src = cv.imread('input_image');
const dst = new cv.Mat();

// Apply thinning with Zhang-Suen algorithm
cv.ximgproc.thinning(src, dst, cv.ximgproc.THINNING_ZHANGSUEN);

console.log("Thinning complete!");
dst.delete();
src.delete();
};
```

# Basic Usage

## >=4.11
Expand Down
88 changes: 88 additions & 0 deletions examples/ximgproc-thinning.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Example: Using cv.ximgproc.thinning() with opencv-js contrib modules
//
// This example demonstrates how to use the thinning function from opencv_contrib
// Note: Requires OpenCV.js built with contrib modules

import { checkContribAvailability, getContribHelpMessage } from '../src/contrib-utils';

// In browser environment or after proper opencv.js loading
async function demonstrateThinning() {
// First, check if contrib modules are available
const availability = checkContribAvailability();

if (!availability.hasXimgproc) {
console.error(getContribHelpMessage());
return;
}

console.log('✅ OpenCV contrib modules available!');

// Create a sample binary image for thinning
const rows = 200;
const cols = 200;
const src = new cv.Mat(rows, cols, cv.CV_8UC1, new cv.Scalar(0));

// Draw some shapes to create a binary image
// Draw a rectangle
cv.rectangle(src, new cv.Point(50, 50), new cv.Point(150, 150), new cv.Scalar(255), -1);

// Draw some lines to create interesting structure for thinning
cv.line(src, new cv.Point(75, 25), new cv.Point(75, 175), new cv.Scalar(255), 10);
cv.line(src, new cv.Point(125, 25), new cv.Point(125, 175), new cv.Scalar(255), 10);

// Create destination matrix for thinning result
const dst = new cv.Mat();

try {
// Apply thinning using Zhang-Suen algorithm
cv.ximgproc.thinning(src, dst, cv.ximgproc.THINNING_ZHANGSUEN);

console.log('✅ Thinning (Zhang-Suen) completed successfully');
console.log(`Output image size: ${dst.rows}x${dst.cols}`);

// You can also use Guo-Hall algorithm
const dst2 = new cv.Mat();
cv.ximgproc.thinning(src, dst2, cv.ximgproc.THINNING_GUOHALL);

console.log('✅ Thinning (Guo-Hall) completed successfully');

// Clean up
dst2.delete();
} catch (error) {
console.error('❌ Error during thinning:', error);
} finally {
// Always clean up matrices
src.delete();
dst.delete();
}
}

// Example of checking availability without running thinning
function checkContribStatus() {
const availability = checkContribAvailability();

console.log('=== OpenCV Contrib Status ===');
console.log('Has contrib modules:', availability.hasContrib);
console.log('Has ximgproc module:', availability.hasXimgproc);
console.log('Missing modules:', availability.missingModules);

if (availability.buildInfo) {
console.log('\n=== Build Information ===');
console.log(availability.buildInfo);
}
}

// Export for use in other files
export { demonstrateThinning, checkContribStatus };

// If running directly (e.g., in node.js for testing)
if (typeof window === 'undefined' && typeof process !== 'undefined') {
console.log('🔍 Checking OpenCV contrib availability...');
checkContribStatus();

if (typeof cv !== 'undefined') {
demonstrateThinning();
} else {
console.log('ℹ️ OpenCV not loaded. This example requires OpenCV.js to be loaded first.');
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
],
"scripts": {
"build": "tsc",
"build:contrib": "./scripts/build-contrib.sh",
"prepack": "npm run build",
"format": "prettier --write \"src/**/*.ts\"",
"test": "jest"
Expand Down
44 changes: 44 additions & 0 deletions scripts/build-contrib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

# Build OpenCV.js with contrib modules
# This script builds OpenCV.js with opencv_contrib modules enabled

set -e

echo "🔧 Building OpenCV.js with contrib modules..."

# Check if directories exist
if [ ! -d "opencv" ]; then
echo "📥 Cloning OpenCV..."
git clone --depth 1 --branch 4.11.0 https://github.com/opencv/opencv.git
fi

if [ ! -d "opencv_contrib" ]; then
echo "📥 Cloning OpenCV contrib..."
git clone --depth 1 --branch 4.11.0 https://github.com/opencv/opencv_contrib.git
fi

if [ ! -d "emsdk" ]; then
echo "📥 Installing Emscripten..."
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install 2.0.10
./emsdk activate 2.0.10
cd ..
fi

echo "🏗️ Building OpenCV.js with contrib modules..."
source emsdk/emsdk_env.sh

emcmake python opencv/platforms/js/build_js.py build_opencv_contrib \
--cmake_option="-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules" \
--cmake_option="-DBUILD_opencv_ximgproc=ON" \
--cmake_option="-DBUILD_opencv_photo=ON" \
--cmake_option="-DBUILD_opencv_features2d=ON" \
--build_flags="-s WASM_ASYNC_COMPILATION=0"

echo "✅ Build complete! OpenCV.js with contrib is at: build_opencv_contrib/bin/opencv.js"
echo "📋 To use it, copy the file to replace dist/opencv.js in your project"
echo ""
echo "💡 To verify contrib modules are available, check the build information:"
echo " node -e \"const cv = require('./build_opencv_contrib/bin/opencv.js'); console.log(cv.getBuildInformation());\""
99 changes: 99 additions & 0 deletions src/contrib-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* Utility functions for checking OpenCV contrib module availability
*/

/**
* Check if opencv_contrib modules are available in the current OpenCV.js build
* @returns Object with availability status and missing modules
*/
export function checkContribAvailability() {
const result = {
hasContrib: false,
hasXimgproc: false,
missingModules: [] as string[],
buildInfo: '',
};

try {
// Check if cv is available
if (typeof cv === 'undefined') {
result.missingModules.push('OpenCV.js not loaded');
return result;
}

// Get build information
if (cv.getBuildInformation) {
result.buildInfo = cv.getBuildInformation();

// Check if contrib modules are mentioned in build info
const buildInfo = result.buildInfo.toLowerCase();
result.hasContrib = buildInfo.includes('ximgproc') || buildInfo.includes('contrib');
}

// Check specific modules
result.hasXimgproc = !!(cv as any).ximgproc;

if (!result.hasXimgproc) {
result.missingModules.push('ximgproc');
}

} catch (error) {
result.missingModules.push(`Error checking: ${error}`);
}

return result;
}

/**
* Get a helpful message about how to enable contrib modules
*/
export function getContribHelpMessage(): string {
const availability = checkContribAvailability();

if (availability.hasXimgproc) {
return '✅ OpenCV contrib modules are available!';
}

return `
❌ OpenCV contrib modules are not available in the current build.

To use cv.ximgproc.thinning() and other contrib functions:

1. Build OpenCV.js with contrib modules:
npm run build:contrib

2. Or build manually:
./scripts/build-contrib.sh

3. Or use the GitHub Actions workflow to build automatically

Missing modules: ${availability.missingModules.join(', ')}

For more information, see: https://github.com/TechStark/opencv-js#opencv-contrib-modules-support
`.trim();
}

/**
* Example usage of ximgproc.thinning (will only work with contrib build)
*/
export function exampleThinning() {
const availability = checkContribAvailability();

if (!availability.hasXimgproc) {
console.warn(getContribHelpMessage());
return;
}

console.log('✅ ximgproc module is available!');
console.log('Example: cv.ximgproc.thinning(src, dst, cv.ximgproc.THINNING_ZHANGSUEN)');

// Example code (commented out to avoid runtime errors)
/*
const src = cv.imread('input');
const dst = new cv.Mat();
cv.ximgproc.thinning(src, dst, cv.ximgproc.THINNING_ZHANGSUEN);
cv.imshow('output', dst);
dst.delete();
src.delete();
*/
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./types/opencv";
export * from "./contrib-utils";
1 change: 1 addition & 0 deletions src/types/opencv/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ export * from "./video_track";
export * from "./_hacks";
export * from "./Tracker";
export * from "./TrackerMIL";
export * from "./ximgproc";
38 changes: 38 additions & 0 deletions src/types/opencv/ximgproc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { InputArray, OutputArray, int } from './_types';

/**
* Extended Image Processing (ximgproc) module
*
* This module contains implementations of modern algorithms for image processing tasks.
* Note: This module requires opencv_contrib to be compiled with OpenCV.js
*/

// Thinning types enum
export const enum ThinningTypes {
/** Thinning technique of Zhang-Suen */
THINNING_ZHANGSUEN = 0,
/** Thinning technique of Guo-Hall */
THINNING_GUOHALL = 1
}

// Constants for thinning types
export declare const THINNING_ZHANGSUEN: ThinningTypes;
export declare const THINNING_GUOHALL: ThinningTypes;

// ximgproc module namespace - functions are accessed as cv.ximgproc.functionName
export declare const ximgproc: {
/**
* Applies a binary blob thinning operation, to achieve a skeletization of the input image.
*
* The function transforms a binary blob image into a skeletized form using the technique of Zhang-Suen.
*
* @param src Source 8-bit single-channel image, containing binary blobs, with blobs having 255 pixel values.
* @param dst Destination image of the same size and the same type as src. The function can work in-place.
* @param thinningType Value that defines which thinning algorithm should be used. See ThinningTypes
*/
thinning(src: InputArray, dst: OutputArray, thinningType?: int): void;

// Constants accessible within the module
THINNING_ZHANGSUEN: ThinningTypes.THINNING_ZHANGSUEN;
THINNING_GUOHALL: ThinningTypes.THINNING_GUOHALL;
};
Loading