mirror of https://github.com/vladmandic/human
add histogram equalization
parent
0fa9498afe
commit
db63a70c8a
6
TODO.md
6
TODO.md
|
@ -2,17 +2,15 @@
|
|||
|
||||
## Work in Progress
|
||||
|
||||
- Switch to custom `tfjs` for main `human` ESM bundle
|
||||
- Sort out incompatibility with latest `long.js` 5.0.0 due to CJS to ESM switch
|
||||
|
||||
<br>
|
||||
|
||||
### Exploring
|
||||
|
||||
- Optical Flow: <https://docs.opencv.org/3.3.1/db/d7f/tutorial_js_lucas_kanade.html>
|
||||
- Histogram Equalization: Regular, Adaptive, Contrast Limited
|
||||
- Histogram Equalization: Regular, Adaptive, Contrast Limited, CLAHE
|
||||
- TFLite Models: <https://js.tensorflow.org/api_tflite/0.0.1-alpha.4/>
|
||||
- Body segmentation: `robust-video-matting`
|
||||
- TFJS incompatibility with latest `long.js` 5.0.0 due to CJS to ESM switch
|
||||
|
||||
<br><hr><br>
|
||||
|
||||
|
|
|
@ -26,5 +26,6 @@
|
|||
<pre id="status" style="position: absolute; top: 12px; right: 20px; background-color: grey; padding: 8px; box-shadow: 2px 2px black"></pre>
|
||||
<pre id="log" style="padding: 8px"></pre>
|
||||
<div id="performance" style="position: absolute; bottom: 0; width: 100%; padding: 8px; font-size: 0.8rem;"></div>
|
||||
<canvas id="test" style="position: absolute; bottom: 0; right: 0; width: 30%"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -122,16 +122,20 @@ export interface SegmentationConfig extends GenericConfig {
|
|||
export interface FilterConfig {
|
||||
/** @property are image filters enabled? */
|
||||
enabled: boolean,
|
||||
/** Resize input width
|
||||
/** @property perform image histogram equalization */
|
||||
equalization: boolean,
|
||||
/** resize input width
|
||||
* - if both width and height are set to 0, there is no resizing
|
||||
* - if just one is set, second one is scaled automatically
|
||||
* - if both are set, values are used as-is
|
||||
* @property
|
||||
*/
|
||||
width: number,
|
||||
/** Resize input height
|
||||
/** resize input height
|
||||
* - if both width and height are set to 0, there is no resizing
|
||||
* - if just one is set, second one is scaled automatically
|
||||
* - if both are set, values are used as-is
|
||||
* @property
|
||||
*/
|
||||
height: number,
|
||||
/** @property return processed canvas imagedata in result */
|
||||
|
@ -262,6 +266,7 @@ const config: Config = {
|
|||
skipAllowed: false,
|
||||
filter: {
|
||||
enabled: true,
|
||||
equalization: false,
|
||||
width: 0,
|
||||
height: 0,
|
||||
flip: false,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Image enhancements
|
||||
*/
|
||||
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import type { Tensor } from '../exports';
|
||||
|
||||
export function histogramEqualization(input: Tensor): Tensor {
|
||||
const channels = tf.split(input, 3, 2);
|
||||
const min: Tensor[] = [tf.min(channels[0]), tf.min(channels[1]), tf.min(channels[2])];
|
||||
const max: Tensor[] = [tf.max(channels[0]), tf.max(channels[1]), tf.max(channels[2])];
|
||||
const sub = [tf.sub(channels[0], min[0]), tf.sub(channels[1], min[1]), tf.sub(channels[2], min[2])];
|
||||
const range = [tf.sub(max[0], min[0]), tf.sub(max[1], min[1]), tf.sub(max[2], min[2])];
|
||||
const fact = [tf.div(255, range[0]), tf.div(255, range[1]), tf.div(255, range[2])];
|
||||
const enh = [tf.mul(sub[0], fact[0]), tf.mul(sub[1], fact[1]), tf.mul(sub[2], fact[2])];
|
||||
const rgb = tf.stack([enh[0], enh[1], enh[2]], 2);
|
||||
const reshape = tf.reshape(rgb, [1, input.shape[0], input.shape[1], 3]);
|
||||
tf.dispose([...channels, ...min, ...max, ...sub, ...range, ...fact, ...enh, rgb]);
|
||||
return reshape;
|
||||
}
|
|
@ -7,6 +7,7 @@ import * as fxImage from './imagefx';
|
|||
import type { Input, AnyCanvas, Tensor, Config } from '../exports';
|
||||
import { env } from '../util/env';
|
||||
import { log, now } from '../util/util';
|
||||
import * as enhance from './enhance';
|
||||
|
||||
const maxSize = 2048;
|
||||
// internal temp canvases
|
||||
|
@ -201,7 +202,7 @@ export function process(input: Input, config: Config, getTensor: boolean = true)
|
|||
}
|
||||
if (!pixels) throw new Error('cannot create tensor from input');
|
||||
const casted = tf.cast(pixels, 'float32');
|
||||
const tensor = tf.expandDims(casted, 0);
|
||||
const tensor = config.filter.equalization ? enhance.histogramEqualization(casted) : tf.expandDims(casted, 0);
|
||||
tf.dispose([pixels, casted]);
|
||||
return { tensor, canvas: (config.filter.return ? outCanvas : null) };
|
||||
}
|
||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
|||
Subproject commit 5e89af1004860ea9f302e516699b5e0b4e0a825f
|
||||
Subproject commit 6abe315e2ae3e3aa457c4c728d9e2959d7e023db
|
Loading…
Reference in New Issue