image-js
Version:
Image processing and manipulation in JavaScript
91 lines • 3.77 kB
JavaScript
import { match } from 'ts-pattern';
import { imageToOutputMask } from '../utils/getOutputImage.js';
import huang from './thresholds/huang.js';
import intermodes from './thresholds/intermodes.js';
import isodata from './thresholds/isodata.js';
import li from './thresholds/li.js';
import maxEntropy from './thresholds/maxEntropy.js';
import mean from './thresholds/mean.js';
import minError from './thresholds/minError.js';
import minimum from './thresholds/minimum.js';
import moments from './thresholds/moments.js';
import { otsu } from './thresholds/otsu.js';
import percentile from './thresholds/percentile.js';
import renyiEntropy from './thresholds/renyiEntropy.js';
import shanbhag from './thresholds/shanbhag.js';
import { triangle } from './thresholds/triangle.js';
import yen from './thresholds/yen.js';
export const ThresholdAlgorithm = {
HUANG: 'huang',
INTERMODES: 'intermodes',
ISODATA: 'isodata',
LI: 'li',
MAX_ENTROPY: 'maxEntropy',
MEAN: 'mean',
MIN_ERROR: 'minError',
MINIMUM: 'minimum',
MOMENTS: 'moments',
OTSU: 'otsu',
PERCENTILE: 'percentile',
RENYI_ENTROPY: 'renyiEntropy',
SHANBHAG: 'shanbhag',
TRIANGLE: 'triangle',
YEN: 'yen',
};
/**
* Compute threshold value for an image using the specified algorithm.
* @param image - The grey image.
* @param options - Threshold options.
* @returns The threshold value for the image.
*/
export function computeThreshold(image, options = {}) {
const { algorithm = 'otsu', slots } = options;
if (image.channels !== 1) {
throw new TypeError('threshold can only be computed on images with one channel');
}
const histogram = image.histogram({ slots });
const scale = slots ? 2 ** image.bitDepth / slots : 1;
return match(algorithm)
.with('huang', () => huang(histogram) * scale)
.with('intermodes', () => intermodes(histogram) * scale)
.with('isodata', () => isodata(histogram) * scale)
.with('li', () => li(histogram, image.size) * scale)
.with('maxEntropy', () => maxEntropy(histogram, image.size) * scale)
.with('mean', () => mean(histogram, image.size) * scale)
.with('minimum', () => minimum(histogram) * scale)
.with('minError', () => minError(histogram, image.size) * scale)
.with('moments', () => moments(histogram, image.size) * scale)
.with('otsu', () => otsu(histogram, image.size) * scale)
.with('percentile', () => percentile(histogram) * scale)
.with('renyiEntropy', () => renyiEntropy(histogram, image.size) * scale)
.with('shanbhag', () => shanbhag(histogram, image.size) * scale)
.with('triangle', () => triangle(histogram) * scale)
.with('yen', () => yen(histogram, image.size) * scale)
.exhaustive();
}
// See: https://docs.opencv.org/4.0.1/d7/d1b/group__imgproc__misc.html#gaa9e58d2860d4afa658ef70a9b1115576
/**
* Create a black and white image based on a threshold value.
* @param image - The grey image to convert.
* @param options - Threshold options.
* @returns The resulting mask.
*/
export function threshold(image, options = {}) {
let thresholdValue;
if ('threshold' in options) {
const threshold = options.threshold;
if (threshold < 0 || threshold > 1) {
throw new RangeError('threshold must be a value between 0 and 1');
}
thresholdValue = threshold * image.maxValue;
}
else {
thresholdValue = computeThreshold(image, options);
}
const result = imageToOutputMask(image, options);
for (let i = 0; i < image.size; i++) {
result.setBitByIndex(i, image.getValueByIndex(i, 0) > thresholdValue ? 1 : 0);
}
return result;
}
//# sourceMappingURL=threshold.js.map