Multi Threaded Camera Spawn (Alpha)
parent
c943eedddc
commit
da53108ba9
|
@ -59,8 +59,6 @@ loadLib('ffmpeg')(s,config,lang,function(ffmpeg){
|
|||
loadLib('monitor')(s,config,lang)
|
||||
//event functions : motion, object matrix handler
|
||||
loadLib('events')(s,config,lang)
|
||||
//built-in detector functions : pam-diff..
|
||||
loadLib('detector')(s,config)
|
||||
//recording functions
|
||||
loadLib('videos')(s,config,lang)
|
||||
//branding functions and config defaults
|
||||
|
|
|
@ -1,46 +1,57 @@
|
|||
// Matrix In Region Libs >
|
||||
var fs = require('fs')
|
||||
var SAT = require('sat')
|
||||
var V = SAT.Vector;
|
||||
var P = SAT.Polygon;
|
||||
// Matrix In Region Libs />
|
||||
var P2P = require('pipe2pam')
|
||||
// pamDiff is based on https://www.npmjs.com/package/pam-diff
|
||||
var PamDiff = require('pam-diff')
|
||||
module.exports = function(s,config){
|
||||
s.createPamDiffEngine = function(e){
|
||||
module.exports = function(jsonData,pamDiffResponder){
|
||||
var s = {};
|
||||
var noiseFilterArray = {};
|
||||
const groupKey = jsonData.rawMonitorConfig.ke
|
||||
const monitorId = jsonData.rawMonitorConfig.mid
|
||||
const triggerTimer = {}
|
||||
var pamDiff
|
||||
var p2p
|
||||
var writeToStderr = function(text){
|
||||
fs.appendFileSync('/home/Shinobi/test.log',text + '\n','utf8')
|
||||
}
|
||||
createPamDiffEngine = function(){
|
||||
var width,
|
||||
height,
|
||||
globalSensitivity,
|
||||
globalColorThreshold,
|
||||
fullFrame = false
|
||||
if(s.group[e.ke].rawMonitorConfigurations[e.id].details.detector_scale_x===''||s.group[e.ke].rawMonitorConfigurations[e.id].details.detector_scale_y===''){
|
||||
width = s.group[e.ke].rawMonitorConfigurations[e.id].details.detector_scale_x;
|
||||
height = s.group[e.ke].rawMonitorConfigurations[e.id].details.detector_scale_y;
|
||||
}else{
|
||||
width = e.width
|
||||
height = e.height
|
||||
if(jsonData.rawMonitorConfig.details.detector_scale_x===''||jsonData.rawMonitorConfig.details.detector_scale_y===''){
|
||||
width = jsonData.rawMonitorConfig.details.detector_scale_x;
|
||||
height = jsonData.rawMonitorConfig.details.detector_scale_y;
|
||||
}
|
||||
if(e.details.detector_sensitivity===''){
|
||||
else{
|
||||
width = jsonData.rawMonitorConfig.width
|
||||
height = jsonData.rawMonitorConfig.height
|
||||
}
|
||||
if(jsonData.rawMonitorConfig.details.detector_sensitivity===''){
|
||||
globalSensitivity = 10
|
||||
}else{
|
||||
globalSensitivity = parseInt(e.details.detector_sensitivity)
|
||||
globalSensitivity = parseInt(jsonData.rawMonitorConfig.details.detector_sensitivity)
|
||||
}
|
||||
if(e.details.detector_color_threshold===''){
|
||||
if(jsonData.rawMonitorConfig.details.detector_color_threshold===''){
|
||||
globalColorThreshold = 9
|
||||
}else{
|
||||
globalColorThreshold = parseInt(e.details.detector_color_threshold)
|
||||
globalColorThreshold = parseInt(jsonData.rawMonitorConfig.details.detector_color_threshold)
|
||||
}
|
||||
|
||||
globalThreshold = parseInt(e.details.detector_threshold) || 0
|
||||
globalThreshold = parseInt(jsonData.rawMonitorConfig.details.detector_threshold) || 0
|
||||
|
||||
var regionJson
|
||||
try{
|
||||
regionJson = JSON.parse(s.group[e.ke].rawMonitorConfigurations[e.id].details.cords)
|
||||
regionJson = JSON.parse(jsonData.rawMonitorConfig.details.cords)
|
||||
}catch(err){
|
||||
regionJson = s.group[e.ke].rawMonitorConfigurations[e.id].details.cords
|
||||
regionJson = jsonData.rawMonitorConfig.details.cords
|
||||
}
|
||||
|
||||
if(Object.keys(regionJson).length === 0 || e.details.detector_frame === '1'){
|
||||
if(Object.keys(regionJson).length === 0 || jsonData.rawMonitorConfig.details.detector_frame === '1'){
|
||||
fullFrame = {
|
||||
name:'FULL_FRAME',
|
||||
sensitivity:globalSensitivity,
|
||||
|
@ -54,26 +65,27 @@ module.exports = function(s,config){
|
|||
}
|
||||
}
|
||||
|
||||
e.triggerTimer = {}
|
||||
|
||||
var regions = s.createPamDiffRegionArray(regionJson,globalColorThreshold,globalSensitivity,fullFrame)
|
||||
var regions = createPamDiffRegionArray(regionJson,globalColorThreshold,globalSensitivity,fullFrame)
|
||||
writeToStderr(JSON.stringify(regions,null,3))
|
||||
var pamDiffOptions = {
|
||||
grayscale: 'luminosity',
|
||||
regions : regions.forPam
|
||||
}
|
||||
if(e.details.detector_show_matrix==='1'){
|
||||
writeToStderr(JSON.stringify(pamDiffOptions,null,3))
|
||||
if(jsonData.rawMonitorConfig.details.detector_show_matrix==='1'){
|
||||
pamDiffOptions.response = 'bounds'
|
||||
}
|
||||
s.group[e.ke].activeMonitors[e.id].pamDiff = new PamDiff(pamDiffOptions);
|
||||
s.group[e.ke].activeMonitors[e.id].p2p = new P2P()
|
||||
pamDiff = new PamDiff(pamDiffOptions)
|
||||
p2p = new P2P()
|
||||
var regionArray = Object.values(regionJson)
|
||||
if(config.detectorMergePamRegionTriggers === true){
|
||||
if(jsonData.globalInfo.config.detectorMergePamRegionTriggers === true){
|
||||
// merge pam triggers for performance boost
|
||||
var buildTriggerEvent = function(trigger){
|
||||
var detectorObject = {
|
||||
f:'trigger',
|
||||
id:e.id,
|
||||
ke:e.ke,
|
||||
id:monitorId,
|
||||
ke:groupKey,
|
||||
name:trigger.name,
|
||||
details:{
|
||||
plug:'built-in',
|
||||
|
@ -82,8 +94,8 @@ module.exports = function(s,config){
|
|||
confidence:trigger.percent
|
||||
},
|
||||
plates:[],
|
||||
imgHeight:e.details.detector_scale_y,
|
||||
imgWidth:e.details.detector_scale_x
|
||||
imgHeight:jsonData.rawMonitorConfig.details.detector_scale_y,
|
||||
imgWidth:jsonData.rawMonitorConfig.details.detector_scale_x
|
||||
}
|
||||
if(trigger.merged){
|
||||
if(trigger.matrices)detectorObject.details.matrices = trigger.matrices
|
||||
|
@ -91,13 +103,13 @@ module.exports = function(s,config){
|
|||
var filteredCountSuccess = 0
|
||||
trigger.merged.forEach(function(triggerPiece){
|
||||
var region = regionArray.find(x => x.name == triggerPiece.name)
|
||||
s.checkMaximumSensitivity(e, region, detectorObject, function(err1) {
|
||||
s.checkTriggerThreshold(e, region, detectorObject, function(err2) {
|
||||
checkMaximumSensitivity(region, detectorObject, function(err1) {
|
||||
checkTriggerThreshold(region, detectorObject, function(err2) {
|
||||
++filteredCount
|
||||
if(!err1 && !err2)++filteredCountSuccess
|
||||
if(filteredCount === trigger.merged.length && filteredCountSuccess > 0){
|
||||
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
|
||||
s.triggerEvent(detectorObject)
|
||||
detectorObject.doObjectDetection = (jsonData.globalInfo.isAtleatOneDetectorPluginConnected && jsonData.rawMonitorConfig.details.detector_use_detect_object === '1')
|
||||
pamDiffResponder.write(Buffer.from(JSON.stringify(detectorObject)))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -105,38 +117,36 @@ module.exports = function(s,config){
|
|||
}else{
|
||||
if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix]
|
||||
var region = regionArray.find(x => x.name == detectorObject.name)
|
||||
s.checkMaximumSensitivity(e, region, detectorObject, function(err1) {
|
||||
s.checkTriggerThreshold(e, region, detectorObject, function(err2) {
|
||||
checkMaximumSensitivity(region, detectorObject, function(err1) {
|
||||
checkTriggerThreshold(region, detectorObject, function(err2) {
|
||||
if(!err1 && !err2){
|
||||
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
|
||||
s.triggerEvent(detectorObject)
|
||||
detectorObject.doObjectDetection = (jsonData.globalInfo.isAtleatOneDetectorPluginConnected && jsonData.rawMonitorConfig.details.detector_use_detect_object === '1')
|
||||
pamDiffResponder.write(Buffer.from(JSON.stringify(detectorObject)))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if(e.details.detector_noise_filter==='1'){
|
||||
if(!s.group[e.ke].activeMonitors[e.id].noiseFilterArray)s.group[e.ke].activeMonitors[e.id].noiseFilterArray = {}
|
||||
var noiseFilterArray = s.group[e.ke].activeMonitors[e.id].noiseFilterArray
|
||||
if(jsonData.rawMonitorConfig.details.detector_noise_filter==='1'){
|
||||
Object.keys(regions.notForPam).forEach(function(name){
|
||||
if(!noiseFilterArray[name])noiseFilterArray[name]=[];
|
||||
})
|
||||
s.group[e.ke].activeMonitors[e.id].pamDiff.on('diff', (data) => {
|
||||
pamDiff.on('diff', (data) => {
|
||||
var filteredCount = 0
|
||||
var filteredCountSuccess = 0
|
||||
data.trigger.forEach(function(trigger){
|
||||
s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(err){
|
||||
filterTheNoise(noiseFilterArray,regions,trigger,function(err){
|
||||
++filteredCount
|
||||
if(!err)++filteredCountSuccess
|
||||
if(filteredCount === data.trigger.length && filteredCountSuccess > 0){
|
||||
buildTriggerEvent(s.mergePamTriggers(data))
|
||||
buildTriggerEvent(mergePamTriggers(data))
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}else{
|
||||
s.group[e.ke].activeMonitors[e.id].pamDiff.on('diff', (data) => {
|
||||
buildTriggerEvent(s.mergePamTriggers(data))
|
||||
pamDiff.on('diff', (data) => {
|
||||
buildTriggerEvent(mergePamTriggers(data))
|
||||
})
|
||||
}
|
||||
}else{
|
||||
|
@ -145,8 +155,8 @@ module.exports = function(s,config){
|
|||
var buildTriggerEvent = function(trigger){
|
||||
var detectorObject = {
|
||||
f:'trigger',
|
||||
id:e.id,
|
||||
ke:e.ke,
|
||||
id: monitorId,
|
||||
ke: groupKey,
|
||||
name:trigger.name,
|
||||
details:{
|
||||
plug:'built-in',
|
||||
|
@ -155,38 +165,36 @@ module.exports = function(s,config){
|
|||
confidence:trigger.percent
|
||||
},
|
||||
plates:[],
|
||||
imgHeight:e.details.detector_scale_y,
|
||||
imgWidth:e.details.detector_scale_x
|
||||
imgHeight:jsonData.rawMonitorConfig.details.detector_scale_y,
|
||||
imgWidth:jsonData.rawMonitorConfig.details.detector_scale_x
|
||||
}
|
||||
if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix]
|
||||
var region = Object.values(regionJson).find(x => x.name == detectorObject.name)
|
||||
s.checkMaximumSensitivity(e, region, detectorObject, function(err1) {
|
||||
s.checkTriggerThreshold(e, region, detectorObject, function(err2) {
|
||||
checkMaximumSensitivity(region, detectorObject, function(err1) {
|
||||
checkTriggerThreshold(region, detectorObject, function(err2) {
|
||||
if(!err1 && ! err2){
|
||||
detectorObject.doObjectDetection = (s.isAtleatOneDetectorPluginConnected && e.details.detector_use_detect_object === '1')
|
||||
s.triggerEvent(detectorObject)
|
||||
detectorObject.doObjectDetection = (jsonData.globalInfo.isAtleatOneDetectorPluginConnected && jsonData.rawMonitorConfig.details.detector_use_detect_object === '1')
|
||||
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if(e.details.detector_noise_filter==='1'){
|
||||
if(!s.group[e.ke].activeMonitors[e.id].noiseFilterArray)s.group[e.ke].activeMonitors[e.id].noiseFilterArray = {}
|
||||
var noiseFilterArray = s.group[e.ke].activeMonitors[e.id].noiseFilterArray
|
||||
if(jsonData.rawMonitorConfig.details.detector_noise_filter==='1'){
|
||||
Object.keys(regions.notForPam).forEach(function(name){
|
||||
if(!noiseFilterArray[name])noiseFilterArray[name]=[];
|
||||
})
|
||||
s.group[e.ke].activeMonitors[e.id].pamDiff.on('diff', (data) => {
|
||||
pamDiff.on('diff', (data) => {
|
||||
data.trigger.forEach(function(trigger){
|
||||
s.filterTheNoise(e,noiseFilterArray,regions,trigger,function(){
|
||||
s.createMatrixFromPamTrigger(trigger)
|
||||
filterTheNoise(noiseFilterArray,regions,trigger,function(){
|
||||
createMatrixFromPamTrigger(trigger)
|
||||
buildTriggerEvent(trigger)
|
||||
})
|
||||
})
|
||||
})
|
||||
}else{
|
||||
s.group[e.ke].activeMonitors[e.id].pamDiff.on('diff', (data) => {
|
||||
pamDiff.on('diff', (data) => {
|
||||
data.trigger.forEach(function(trigger){
|
||||
s.createMatrixFromPamTrigger(trigger)
|
||||
createMatrixFromPamTrigger(trigger)
|
||||
buildTriggerEvent(trigger)
|
||||
})
|
||||
})
|
||||
|
@ -194,7 +202,7 @@ module.exports = function(s,config){
|
|||
}
|
||||
}
|
||||
|
||||
s.createPamDiffRegionArray = function(regions,globalColorThreshold,globalSensitivity,fullFrame){
|
||||
createPamDiffRegionArray = function(regions,globalColorThreshold,globalSensitivity,fullFrame){
|
||||
var pamDiffCompliantArray = [],
|
||||
arrayForOtherStuff = [],
|
||||
json
|
||||
|
@ -236,11 +244,11 @@ module.exports = function(s,config){
|
|||
return {forPam:pamDiffCompliantArray,notForPam:arrayForOtherStuff};
|
||||
}
|
||||
|
||||
s.filterTheNoise = function(e,noiseFilterArray,regions,trigger,callback){
|
||||
filterTheNoise = function(noiseFilterArray,regions,trigger,callback){
|
||||
if(noiseFilterArray[trigger.name].length > 2){
|
||||
var thePreviousTriggerPercent = noiseFilterArray[trigger.name][noiseFilterArray[trigger.name].length - 1];
|
||||
var triggerDifference = trigger.percent - thePreviousTriggerPercent;
|
||||
var noiseRange = e.details.detector_noise_filter_range
|
||||
var noiseRange = jsonData.rawMonitorConfig.details.detector_noise_filter_range
|
||||
if(!noiseRange || noiseRange === ''){
|
||||
noiseRange = 6
|
||||
}
|
||||
|
@ -267,48 +275,48 @@ module.exports = function(s,config){
|
|||
}
|
||||
}
|
||||
|
||||
s.checkMaximumSensitivity = function(monitor, region, detectorObject, callback) {
|
||||
checkMaximumSensitivity = function(region, detectorObject, callback) {
|
||||
var logName = detectorObject.id + ':' + detectorObject.name
|
||||
var globalMaxSensitivity = parseInt(monitor.details.detector_max_sensitivity) || undefined
|
||||
var globalMaxSensitivity = parseInt(jsonData.rawMonitorConfig.details.detector_max_sensitivity) || undefined
|
||||
var maxSensitivity = parseInt(region.max_sensitivity) || globalMaxSensitivity
|
||||
if (maxSensitivity === undefined || detectorObject.details.confidence <= maxSensitivity) {
|
||||
callback(null)
|
||||
} else {
|
||||
callback(true)
|
||||
if (monitor.triggerTimer[detectorObject.name] !== undefined) {
|
||||
clearTimeout(monitor.triggerTimer[detectorObject.name].timeout)
|
||||
monitor.triggerTimer[detectorObject.name] = undefined
|
||||
if (triggerTimer[detectorObject.name] !== undefined) {
|
||||
clearTimeout(triggerTimer[detectorObject.name].timeout)
|
||||
triggerTimer[detectorObject.name] = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.checkTriggerThreshold = function(monitor, region, detectorObject, callback){
|
||||
checkTriggerThreshold = function(region, detectorObject, callback){
|
||||
var threshold = parseInt(region.threshold) || globalThreshold
|
||||
if (threshold <= 1) {
|
||||
callback(null)
|
||||
} else {
|
||||
if (monitor.triggerTimer[detectorObject.name] === undefined) {
|
||||
monitor.triggerTimer[detectorObject.name] = {
|
||||
if (triggerTimer[detectorObject.name] === undefined) {
|
||||
triggerTimer[detectorObject.name] = {
|
||||
count : threshold,
|
||||
timeout : null
|
||||
}
|
||||
}
|
||||
if (--monitor.triggerTimer[detectorObject.name].count == 0) {
|
||||
if (--triggerTimer[detectorObject.name].count == 0) {
|
||||
callback(null)
|
||||
clearTimeout(monitor.triggerTimer[detectorObject.name].timeout)
|
||||
monitor.triggerTimer[detectorObject.name] = undefined
|
||||
clearTimeout(triggerTimer[detectorObject.name].timeout)
|
||||
triggerTimer[detectorObject.name] = undefined
|
||||
} else {
|
||||
callback(true)
|
||||
var fps = parseFloat(monitor.details.detector_fps) || 2
|
||||
if (monitor.triggerTimer[detectorObject.name].timeout !== null)
|
||||
clearTimeout(monitor.triggerTimer[detectorObject.name].timeout)
|
||||
monitor.triggerTimer[detectorObject.name].timeout = setTimeout(function() {
|
||||
monitor.triggerTimer[detectorObject.name] = undefined
|
||||
var fps = parseFloat(jsonData.rawMonitorConfig.details.detector_fps) || 2
|
||||
if (triggerTimer[detectorObject.name].timeout !== null)
|
||||
clearTimeout(triggerTimer[detectorObject.name].timeout)
|
||||
triggerTimer[detectorObject.name].timeout = setTimeout(function() {
|
||||
triggerTimer[detectorObject.name] = undefined
|
||||
}, ((threshold+0.5) * 1000) / fps)
|
||||
}
|
||||
}
|
||||
}
|
||||
s.mergePamTriggers = function(data){
|
||||
mergePamTriggers = function(data){
|
||||
if(data.trigger.length > 1){
|
||||
var n = 0
|
||||
var sum = 0
|
||||
|
@ -318,7 +326,7 @@ module.exports = function(s,config){
|
|||
name.push(trigger.name + ' ('+trigger.percent+'%)')
|
||||
++n
|
||||
sum += trigger.percent
|
||||
s.createMatrixFromPamTrigger(trigger)
|
||||
createMatrixFromPamTrigger(trigger)
|
||||
if(trigger.matrix)matrices.push(trigger.matrix)
|
||||
})
|
||||
var average = sum / n
|
||||
|
@ -332,7 +340,7 @@ module.exports = function(s,config){
|
|||
}
|
||||
}else{
|
||||
var trigger = data.trigger[0]
|
||||
s.createMatrixFromPamTrigger(trigger)
|
||||
createMatrixFromPamTrigger(trigger)
|
||||
trigger.matrices = [trigger.matrix]
|
||||
}
|
||||
return trigger
|
||||
|
@ -372,7 +380,7 @@ module.exports = function(s,config){
|
|||
if(callback)callback(foundInRegion,collisions)
|
||||
return foundInRegion
|
||||
}
|
||||
s.createMatrixFromPamTrigger = function(trigger){
|
||||
createMatrixFromPamTrigger = function(trigger){
|
||||
if(
|
||||
trigger.minX &&
|
||||
trigger.maxX &&
|
||||
|
@ -396,4 +404,14 @@ module.exports = function(s,config){
|
|||
}
|
||||
return trigger
|
||||
}
|
||||
|
||||
return function(cameraProcess){
|
||||
if(jsonData.rawMonitorConfig.details.detector === '1' && jsonData.rawMonitorConfig.coProcessor === false){
|
||||
//frames from motion detect
|
||||
if(jsonData.rawMonitorConfig.details.detector_pam === '1'){
|
||||
createPamDiffEngine()
|
||||
cameraProcess.stdio[3].pipe(p2p).pipe(pamDiff)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
const fs = require('fs')
|
||||
const spawn = require('child_process').spawn
|
||||
const logIt = function(text){
|
||||
stdioWriters[i].write(text)
|
||||
}
|
||||
|
||||
process.send = process.send || function () {};
|
||||
process.on('uncaughtException', function (err) {
|
||||
writeToStderr('Uncaught Exception occured!');
|
||||
writeToStderr(err.stack);
|
||||
});
|
||||
// [CTRL] + [C] = exit
|
||||
process.on('SIGINT', function() {
|
||||
cameraProcess.kill('SIGTERM')
|
||||
});
|
||||
|
||||
if(!process.argv[2] || !process.argv[3]){
|
||||
return writeToStderr('Missing FFMPEG Command String or no command operator')
|
||||
}
|
||||
var jsonData = JSON.parse(fs.readFileSync(process.argv[3],'utf8'))
|
||||
const ffmpegAbsolutePath = process.argv[2].trim()
|
||||
const ffmpegCommandString = jsonData.cmd
|
||||
const stdioPipes = jsonData.pipes || []
|
||||
var newPipes = []
|
||||
var stdioWriters = [];
|
||||
// var writeToStderr = function(text){
|
||||
// process.stderr.write(Buffer.from(text))
|
||||
// }
|
||||
fs.appendFileSync('/home/Shinobi/test.log','---------------' + '\n','utf8')
|
||||
fs.appendFileSync('/home/Shinobi/test.log','---------------' + '\n','utf8')
|
||||
fs.appendFileSync('/home/Shinobi/test.log','---------------' + '\n','utf8')
|
||||
var writeToStderr = function(text){
|
||||
fs.appendFileSync('/home/Shinobi/test.log',text + '\n','utf8')
|
||||
}
|
||||
for(var i=0; i < stdioPipes; i++){
|
||||
switch(i){
|
||||
case 3:
|
||||
newPipes.push('pipe')
|
||||
stdioWriters[i] = fs.createWriteStream(null, {fd: i});
|
||||
break;
|
||||
default:
|
||||
stdioWriters[i] = fs.createWriteStream(null, {fd: i});
|
||||
newPipes.push(stdioWriters[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
var cameraProcess = spawn(ffmpegAbsolutePath,ffmpegCommandString,{detached: true,stdio:newPipes})
|
||||
setTimeout(function(){
|
||||
writeToStderr('Start Process Now')
|
||||
try{
|
||||
const attachDetector = require(__dirname + '/detector.js')(jsonData,stdioWriters[3])
|
||||
attachDetector(cameraProcess)
|
||||
}catch(err){
|
||||
writeToStderr(err.stack)
|
||||
}
|
||||
},3000)
|
|
@ -1,692 +0,0 @@
|
|||
//
|
||||
// Shinobi - fork of pam-diff
|
||||
// Copyright (C) 2018 Kevin Godell
|
||||
// Author : Kevin Godell, https://github.com/kevinGodell
|
||||
// npmjs : https://www.npmjs.com/package/pam-diff
|
||||
// Github : https://github.com/kevinGodell/pam-diff
|
||||
//
|
||||
'use strict';
|
||||
|
||||
const { Transform } = require('stream');
|
||||
|
||||
const PP = require('polygon-points');
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
var _getMatrixFromPoints = function(thisRegion) {
|
||||
var coordinates = [
|
||||
thisRegion.topLeft,
|
||||
{"x" : thisRegion.bottomRight.x, "y" : thisRegion.topLeft.y},
|
||||
thisRegion.bottomRight
|
||||
]
|
||||
var width = Math.sqrt( Math.pow(coordinates[1].x - coordinates[0].x, 2) + Math.pow(coordinates[1].y - coordinates[0].y, 2));
|
||||
var height = Math.sqrt( Math.pow(coordinates[2].x - coordinates[1].x, 2) + Math.pow(coordinates[2].y - coordinates[1].y, 2))
|
||||
return {
|
||||
x: coordinates[0].x,
|
||||
y: coordinates[0].y,
|
||||
width: width,
|
||||
height: height,
|
||||
tag: thisRegion.name
|
||||
}
|
||||
}
|
||||
class PamDiff extends Transform {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param [options] {Object}
|
||||
* @param [callback] {Function}
|
||||
*/
|
||||
constructor(options, callback) {
|
||||
super(options);
|
||||
Transform.call(this, {objectMode: true});
|
||||
this.difference = PamDiff._parseOptions('difference', options);//global option, can be overridden per region
|
||||
this.percent = PamDiff._parseOptions('percent', options);//global option, can be overridden per region
|
||||
this.regions = PamDiff._parseOptions('regions', options);//can be no regions or a single region or multiple regions. if no regions, all pixels will be compared.
|
||||
this.drawMatrix = PamDiff._parseOptions('drawMatrix', options);//can be no regions or a single region or multiple regions. if no regions, all pixels will be compared.
|
||||
this.callback = callback;//callback function to be called when pixel difference is detected
|
||||
this._parseChunk = this._parseFirstChunk;//first parsing will be reading settings and configuring internal pixel reading
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param option {String}
|
||||
* @param options {Object}
|
||||
* @return {*}
|
||||
* @private
|
||||
*/
|
||||
static _parseOptions(option, options) {
|
||||
if (options && options.hasOwnProperty(option)) {
|
||||
return options[option];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @param def {Number}
|
||||
* @param low {Number}
|
||||
* @param high {Number}
|
||||
* @return {Number}
|
||||
* @private
|
||||
*/
|
||||
static _validateNumber(number, def, low, high) {
|
||||
if (isNaN(number)) {
|
||||
return def;
|
||||
} else if (number < low) {
|
||||
return low;
|
||||
} else if (number > high) {
|
||||
return high;
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated
|
||||
* @param string {String}
|
||||
*/
|
||||
setGrayscale(string) {
|
||||
console.warn('grayscale option has been removed, "average" has proven to most accurate and is the default');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
*/
|
||||
set difference(number) {
|
||||
this._difference = PamDiff._validateNumber(parseInt(number), 5, 1, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
get difference() {
|
||||
return this._difference;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setDifference(number) {
|
||||
this.difference = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
*/
|
||||
set percent(number) {
|
||||
this._percent = PamDiff._validateNumber(parseInt(number), 5, 1, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
get percent() {
|
||||
return this._percent;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setPercent(number) {
|
||||
this.percent = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array {Array}
|
||||
*/
|
||||
set regions(array) {
|
||||
if (!array) {
|
||||
if (this._regions) {
|
||||
delete this._regions;
|
||||
delete this._regionsLength;
|
||||
delete this._minDiff;
|
||||
}
|
||||
this._diffs = 0;
|
||||
} else if (!Array.isArray(array) || array.length < 1) {
|
||||
throw new Error(`Regions must be an array of at least 1 region object {name: 'region1', difference: 10, percent: 10, polygon: [[0, 0], [0, 50], [50, 50], [50, 0]]}`);
|
||||
} else {
|
||||
this._regions = [];
|
||||
this._minDiff = 255;
|
||||
for (const region of array) {
|
||||
if (!region.hasOwnProperty('name') || !region.hasOwnProperty('polygon')) {
|
||||
throw new Error('Region must include a name and a polygon property');
|
||||
}
|
||||
const polygonPoints = new PP(region.polygon);
|
||||
const difference = PamDiff._validateNumber(parseInt(region.difference), this._difference, 1, 255);
|
||||
const percent = PamDiff._validateNumber(parseInt(region.percent), this._percent, 1, 100);
|
||||
this._minDiff = Math.min(this._minDiff, difference);
|
||||
this._regions.push(
|
||||
{
|
||||
name: region.name,
|
||||
polygon: polygonPoints,
|
||||
difference: difference,
|
||||
percent: percent,
|
||||
diffs: 0
|
||||
}
|
||||
);
|
||||
}
|
||||
this._regionsLength = this._regions.length;
|
||||
this._createPointsInPolygons(this._regions, this._width, this._height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
get regions() {
|
||||
return this._regions;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array {Array}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setRegions(array) {
|
||||
this.regions = array;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param func {Function}
|
||||
*/
|
||||
set callback(func) {
|
||||
if (!func) {
|
||||
delete this._callback;
|
||||
} else if (typeof func === 'function' && func.length === 1) {
|
||||
this._callback = func;
|
||||
} else {
|
||||
throw new Error('Callback must be a function that accepts 1 argument.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
get callback() {
|
||||
return this._callback;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param func {Function}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setCallback(func) {
|
||||
this.callback = func;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
resetCache() {
|
||||
//delete this._oldPix;
|
||||
//delete this._newPix;
|
||||
//delete this._width;
|
||||
//delete this._length;
|
||||
this._parseChunk = this._parseFirstChunk;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param regions {Array}
|
||||
* @param width {Number}
|
||||
* @param height {Number}
|
||||
* @private
|
||||
*/
|
||||
_createPointsInPolygons(regions, width, height) {
|
||||
if (regions && width && height) {
|
||||
this._pointsInPolygons = [];
|
||||
for (const region of regions) {
|
||||
const bitset = region.polygon.getBitset(this._width, this._height);
|
||||
region.pointsLength = bitset.count;
|
||||
this._pointsInPolygons.push(bitset.buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_blackAndWhitePixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i++) {
|
||||
const diff = this._oldPix[i] !== this._newPix[i];
|
||||
if (this._regions && diff === true) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][i]) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else if (diff === true) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_grayScalePixelDiffWithMatrices(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
this._regions[j].topLeft = {
|
||||
x: this._width,
|
||||
y: this._height
|
||||
}
|
||||
this._regions[j].bottomRight = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
this.topLeft = {
|
||||
x: this._width,
|
||||
y: this._height
|
||||
}
|
||||
this.bottomRight = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
for (let y = 0, i = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i++) {
|
||||
if (this._oldPix[i] !== this._newPix[i]) {
|
||||
const diff = Math.abs(this._oldPix[i] - this._newPix[i]);
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][i] && diff >= this._regions[j].difference) {
|
||||
var theRegion = this._regions[j]
|
||||
theRegion.diffs++;
|
||||
if(theRegion.topLeft.x > x && theRegion.topLeft.y > y){
|
||||
theRegion.topLeft.x = x
|
||||
theRegion.topLeft.y = y
|
||||
}
|
||||
if(theRegion.bottomRight.x < x && theRegion.bottomRight.y < y){
|
||||
theRegion.bottomRight.x = x
|
||||
theRegion.bottomRight.y = y
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
if(this.topLeft.x > x && this.topLeft.y > y){
|
||||
this.topLeft.x = x
|
||||
this.topLeft.y = y
|
||||
}
|
||||
if(this.bottomRight.x < x && this.bottomRight.y < y){
|
||||
this.bottomRight.x = x
|
||||
this.bottomRight.y = y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
var thisRegion = this._regions[i]
|
||||
const percent = Math.floor(100 * thisRegion.diffs / thisRegion.pointsLength);
|
||||
if (percent >= thisRegion.percent) {
|
||||
// create matrix from points >>
|
||||
thisRegion._matrix = _getMatrixFromPoints(thisRegion)
|
||||
// create matrix from points />>
|
||||
regionDiffArray.push({name: thisRegion.name, percent: percent, matrix: thisRegion._matrix});
|
||||
}
|
||||
thisRegion.diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
this._matrix = _getMatrixFromPoints(this)
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam, matrix: this._matrix};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
this._matrix = _getMatrixFromPoints(this)
|
||||
const data = {trigger: [{name: 'percent', percent: percent, matrix: this._matrix}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_grayScalePixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i++) {
|
||||
if (this._oldPix[i] !== this._newPix[i]) {
|
||||
const diff = Math.abs(this._oldPix[i] - this._newPix[i]);
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][i] && diff >= this._regions[j].difference) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_rgbPixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i += 3, p++) {
|
||||
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
|
||||
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_rgbAlphaPixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i += 4, p++) {
|
||||
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
|
||||
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_parseFirstChunk(chunk) {
|
||||
this._width = parseInt(chunk.width);
|
||||
this._height = parseInt(chunk.height);
|
||||
this._oldPix = chunk.pixels;
|
||||
this._length = this._width * this._height;
|
||||
this._createPointsInPolygons(this._regions, this._width, this._height);
|
||||
switch (chunk.tupltype) {
|
||||
case 'blackandwhite' :
|
||||
this._parseChunk = this._blackAndWhitePixelDiff;
|
||||
break;
|
||||
case 'grayscale' :
|
||||
if(this.drawMatrix === "1"){
|
||||
this._parseChunk = this._grayScalePixelDiffWithMatrices;
|
||||
}else{
|
||||
this._parseChunk = this._grayScalePixelDiff;
|
||||
}
|
||||
break;
|
||||
case 'rgb' :
|
||||
this._parseChunk = this._rgbPixelDiff;
|
||||
//this._increment = 3;//future use
|
||||
break;
|
||||
case 'rgb_alpha' :
|
||||
this._parseChunk = this._rgbAlphaPixelDiff;
|
||||
//this._increment = 4;//future use
|
||||
break;
|
||||
default :
|
||||
throw Error(`Unsupported tupltype: ${chunk.tupltype}. Supported tupltypes include grayscale(gray), blackandwhite(monob), rgb(rgb24), and rgb_alpha(rgba).`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @param encoding
|
||||
* @param callback
|
||||
* @private
|
||||
*/
|
||||
_transform(chunk, encoding, callback) {
|
||||
this._parseChunk(chunk);
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callback
|
||||
* @private
|
||||
*/
|
||||
_flush(callback) {
|
||||
this.resetCache();
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {PamDiff}
|
||||
*/
|
||||
module.exports = PamDiff;
|
||||
//todo get bounding box of all regions combined to exclude some pixels before checking if they exist inside specific regions
|
|
@ -1017,7 +1017,23 @@ module.exports = function(s,config,lang,onFinish){
|
|||
//clean the string of spatial impurities and split for spawn()
|
||||
x.ffmpegCommandString = s.splitForFFPMEG(x.ffmpegCommandString)
|
||||
//launch that bad boy
|
||||
return spawn(config.ffmpegDir,x.ffmpegCommandString,{detached: true,stdio:x.stdioPipes})
|
||||
// return spawn(config.ffmpegDir,x.ffmpegCommandString,{detached: true,stdio:x.stdioPipes})
|
||||
fs.writeFileSync(e.sdir + 'cmd.txt',JSON.stringify({
|
||||
cmd: x.ffmpegCommandString,
|
||||
pipes: x.stdioPipes.length,
|
||||
rawMonitorConfig: s.group[e.ke].rawMonitorConfigurations[e.id],
|
||||
globalInfo: {
|
||||
config: config,
|
||||
isAtleatOneDetectorPluginConnected: s.isAtleatOneDetectorPluginConnected
|
||||
}
|
||||
},null,3),'utf8')
|
||||
var cameraCommandParams = [
|
||||
s.mainDirectory + '/libs/cameraThread/singleCamera.js',
|
||||
config.ffmpegDir,
|
||||
e.sdir + 'cmd.txt'
|
||||
]
|
||||
console.log(cameraCommandParams.join(' '))
|
||||
return spawn('node',cameraCommandParams,{detached: true,stdio:x.stdioPipes})
|
||||
}
|
||||
if(!config.ffmpegDir){
|
||||
ffmpeg.checkForWindows(function(){
|
||||
|
|
|
@ -1035,8 +1035,11 @@ module.exports = function(s,config,lang){
|
|||
s.ocvTx({f:'init_monitor',id:e.id,ke:e.ke})
|
||||
//frames from motion detect
|
||||
if(e.details.detector_pam === '1'){
|
||||
s.createPamDiffEngine(e)
|
||||
s.group[e.ke].activeMonitors[e.id].spawn.stdio[3].pipe(s.group[e.ke].activeMonitors[e.id].p2p).pipe(s.group[e.ke].activeMonitors[e.id].pamDiff)
|
||||
// s.group[e.ke].activeMonitors[e.id].spawn.stdio[3].pipe(s.group[e.ke].activeMonitors[e.id].p2p).pipe(s.group[e.ke].activeMonitors[e.id].pamDiff)
|
||||
s.group[e.ke].activeMonitors[e.id].spawn.stdio[3].on('data',function(buf){
|
||||
var data = JSON.parse(buf)
|
||||
s.triggerEvent(data)
|
||||
})
|
||||
if(e.details.detector_use_detect_object === '1'){
|
||||
s.group[e.ke].activeMonitors[e.id].spawn.stdio[4].on('data',function(data){
|
||||
s.onMonitorDetectorDataOutputSecondary(e,data)
|
||||
|
|
Loading…
Reference in New Issue