UNPKG

synopsis-video

Version:

Create Video Synopsis from provided videos. Frames are extracted from each video provided and backgrounds are subtracted around moving elements and merged into a single video for quick review.

103 lines (98 loc) 3.04 kB
const fs = require('fs'); const cv = require('opencv4nodejs'); const mainDirectory = process.cwd() + '/' const firstFrameDirectory = mainDirectory + 'firstFrame/' const rawDirectory = mainDirectory + 'rawSubtractions/' exports.rawDirectory = rawDirectory exports.mainDirectory = mainDirectory exports.firstFrameDirectory = firstFrameDirectory exports.mergedFramesDirectory = mainDirectory + 'mergedFrames/' exports.createBaseFolder = (folderName) => { try{ fs.mkdirSync(folderName) }catch(err){ } } exports.makeVideoImagesFolder = (folderName) => { try{ fs.mkdirSync(rawDirectory + folderName) }catch(err){ } } exports.grabFrames = (videoFile, delay, onFrame, onDone) => { const cap = new cv.VideoCapture(videoFile); let done = false; const intvl = setInterval(() => { let frame = cap.read(); if (frame.empty) { done = true clearInterval(intvl); onDone(); return } onFrame(frame); const key = cv.waitKey(delay); done = key !== -1 && key !== 255; if (done) { clearInterval(intvl); console.log('Key pressed, exiting.'); } }, 0); }; exports.grabFirstFrame = (videoFile) => { const cap = new cv.VideoCapture(videoFile); let frame = cap.read(); // loop back to start on end of stream reached if (frame.empty) { return null; } cv.imwrite(`${firstFrameDirectory}${videoFile.split('.')[0]}.jpg`, frame); }; exports.getMatricesOfContours = (binaryImg, minPxSize, fixedRectWidth, dstImage) => { const { centroids, stats } = binaryImg.connectedComponentsWithStats(); const matrices = []; // pretend label 0 is background for (let label = 1; label < centroids.rows; label += 1) { const [x1, y1] = [stats.at(label, cv.CC_STAT_LEFT), stats.at(label, cv.CC_STAT_TOP)]; const [x2, y2] = [ x1 + (fixedRectWidth || stats.at(label, cv.CC_STAT_WIDTH)), y1 + (fixedRectWidth || stats.at(label, cv.CC_STAT_HEIGHT)) ]; const size = stats.at(label, cv.CC_STAT_AREA); const blue = new cv.Vec(255, 0, 0); if (minPxSize < size) { if(dstImage){ dstImage.drawRectangle( new cv.Point(x1, y1), new cv.Point(x2, y2), { color: blue, thickness: 2 } ); }else{ matrices.push([label,x1,y1,x2,y2]); } } } return dstImage ? dstImage : matrices }; exports.stripNameJpg = (name) => { return parseInt(name.replace('.jpg','')) } exports.stripNamePng = (name) => { return parseInt(name.replace('img','').replace('.png','')) } exports.splitForFfmpeg = (ffmpegCommandAsString) => { //this function ignores spaces inside quotes. return ffmpegCommandAsString.replace(/\s+/g,' ').trim().match(/\\?.|^$/g).reduce((p, c) => { if(c === '"'){ p.quote ^= 1; }else if(!p.quote && c === ' '){ p.a.push(''); }else{ p.a[p.a.length-1] += c.replace(/\\(.)/,"$1"); } return p; }, {a: ['']}).a }