shinobi-pam-diff
v1.0.0
Published
Measure differences between pixel arrays extracted from pam images. Modified for Shinobi CCTV.
Downloads
5
Maintainers
Readme
pam-diff
Measure differences between pixel arrays extracted from pam images. Works well with node module pipe2pam to extract pam images from an ffmpeg pipe. Supported tupltypes are rgb, rgb_alpha, and grayscale. It is currently being used for a video motion detection project.
Installation:
npm install pam-diff@latest --save
Important Note: The js-only version will no longer receive any updates. All future work will be dedicated to the n-api version because it is much more efficient.
New Feature: Async made default in 0.13.6. ~~Starting with version 0.13.0, the option to use worker threads can be enabled by passing {async: true}
to the pam-diff constructor.~~
New Feature: Starting with version 0.13.2, the option to get x y bounding box coordinates can be set by passing {response: "bounds"}
to the pam-diff constructor.
New Feature: Starting with version 0.13.5, the option to get the pixel buffer containing the drawn x y bounding box can be set by passing {draw: true}
to the pam-diff constructor.
New Feature: Starting with version 0.13.6, the option to filter results by connected component labelling can be set by passing {response: "blobs"}
to the pam-diff constructor.
New Feature: Starting with version 0.13.6, async behavior will now be default. If you need the pixel difference measurements to block the event loop, use {sync: true}
.
New Feature: Starting with version 1.0.0, pre-built binaries will be used. If binaries are not available, installation will fall back to node-gyp.
Usage Options:
When comparing 2 equally sized buffers of grayscale, rgb, or rgba pixels, there are several options:
all (default)
- All pixels will be targeted when checking for differences.
- To use this option, set the configuration object without creating any regions.
const pamDiff = new PamDiff({ difference: 5, percent: 5 });
regions
- Specific regions of pixels will be targeted when checking for differences and the rest will be ignored.
- To use this option, create a regions array and pass it to the constructor.
const region1 = {
name: 'region1',
difference: 12,
percent: 22,
polygon: [
{ x: 0, y: 0 },
{ x: 0, y: 225 },
{ x: 100, y: 225 },
{ x: 100, y: 0 },
],
};
const region2 = {
name: 'region2',
difference: 14,
percent: 10,
polygon: [
{ x: 100, y: 0 },
{ x: 100, y: 225 },
{ x: 200, y: 225 },
{ x: 200, y: 0 },
],
};
const regions = [region1, region2];
const pamDiff = new PamDiff({ regions: regions });
mask
- Specific regions of pixels will be ignored when checking for differences.
- To use this option, create a regions array and set the mask option to true.
- `difference` and `percent` of the individual region is ignored. Set a global value.
const region1 = {
name: 'region1',
polygon: [
{ x: 0, y: 0 },
{ x: 0, y: 225 },
{ x: 100, y: 225 },
{ x: 100, y: 0 },
],
};
const region2 = {
name: 'region2',
polygon: [
{ x: 100, y: 0 },
{ x: 100, y: 225 },
{ x: 200, y: 225 },
{ x: 200, y: 0 },
],
};
const regions = [region1, region2];
const pamDiff = new PamDiff({ difference: 12, percent: 10, mask: true, regions: regions });
Getting results back from the pixel difference detection:
- event
- A diff event will be emitted with a data object passed as the only argument.
pamDiff.on('diff', data => {
console.log(data);
});
- callback
- A callback function will be called with a data object passed as the only argument.
- The callback can be passed as the 2nd argument to the constructor or it can be added later.
/* callback function */
function myCallback(data) {
console.log(data);
}
/* via the constructor */
const pamDiff = new pamDiff({ difference: 10, percent: 20 }, myCallback);
/* via the setter */
pamDiff.callback = myCallback;
/* via the chain-able setter */
pamDiff.setCallback(myCallback).setDifference(10).setPercent(20);
/* remove the callback */
pamDiff.callback = null;
Expected results:
- When targeting all pixels:
{
trigger: [
{ name: 'all', percent: 13 }
],
pam: <Buffer>,
headers: <Buffer>,
pixels: <Buffer>
}
- When targeting regions of pixels:
{
trigger: [
{ name: 'region1', percent: 13 },
{ name: 'region2', percent: 22 }
],
pam: <Buffer>,
headers: <Buffer>,
pixels: <Buffer>
}
- When targeting all pixels ignored by mask:
{
trigger: [
{ name: 'mask', percent: 13 }
],
pam: <Buffer>,
headers: <Buffer>,
pixels: <Buffer>
}
- When targeting all pixels and setting {response: "bounds"}:
{
trigger: [
{ name: 'all', percent: 13, minX: 42, maxX: 399, minY: 113, maxY: 198 }
],
pam: <Buffer>,
headers: <Buffer>,
pixels: <Buffer>
}
- When targeting all pixels and setting {response: "blobs"}:
{
trigger: [
{
name: "all",
percent: 9,
minX: 137,
maxX: 1782,
minY: 392,
maxY: 695,
blobs: [
{
label: 0,
percent: 3,
minX: 1192,
maxX: 1486,
minY: 392,
maxY: 695
},
{
label: 1,
percent: 3,
minX: 1488,
maxX: 1782,
minY: 392,
maxY: 695
}
]
}
],
pam: <Buffer>,
headers: <Buffer>,
pixels: <Buffer>
}
Other Resources:
View the docs, tests, or examples for more implementations.
Future Plans:
- [x] Make pre-built binaries available when using node-gyp is not an option.
- [x] Include option to return coordinates for bounding box of changed pixels.
- [x] Include option to return pixel buffer containing bounding boxes.
- [x] Introduce blob filtering to group changed pixels with their neighbors.
- [x] Include option to return pixel buffer containing bounding boxes around blobs.
- [x] Make async worker threads the default. Can be overridden with {sync: true}.