Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Commit

Permalink
Made suggested changes
Browse files Browse the repository at this point in the history
-Abstracted reviewer and exporter from DetectionAlgorithmManager

- Added hover on load video
  • Loading branch information
aribornstein committed Apr 4, 2017
1 parent 0c1ff39 commit 3dd2a1a
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 86 deletions.
14 changes: 7 additions & 7 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@
</head>
<body>
<div id="container">

<div id ='load-message' onclick="fileSelected();">
<div id = "load-text"><h2>Please <b>Drag in</b> or <b>Click</b> to load a video for tagging.</h2></div>
<img id="vidImage" src ="./public/images/Wikiversity-Mooc-Icon-Video.svg.png" ></img>
<div id ='load-message' onclick="fileSelected();">
<img id="vidImage" src ="./public/images/Load-Video.png" ></img>
<div id = "load-text"><h2>Please <b>Drag in</b> or <b>Click</b> to load a video for tagging.</h2></div>
</div>
<div id ='load-form-container' style ="display: none">
<h2>Tagging Job Configuration</h2>

<div class="form-group" id="framerateGroup">
<label for="exampleTextarea" title="(How many frames to extract per a second of video!)">Frame Extraction Rate (frames per a video second)</label>
<input id="framerate" type="number" min="1" max="60" value="1" maxlength="3" size="3" class="form-control" />
<input id="framerate" type="number" min="1" max="60" value="1" maxlength="3" size="3" class="form-control" style ="max-width: 5em"/>
</div>
<div class="form-group">
<label for="exampleTextarea" title="(Type of region selector to tag frames)">Region Type</label>
<select id="regiontype" class="form-control" id="text" onchange="checkPointRegion();">
<select id="regiontype" class="form-control" id="text" onchange="checkPointRegion();" style ="max-width: 8em">
<option selected="selected">Rectangle</option>
<!--option>Point</option-->
<option>Square</option>
Expand All @@ -56,7 +56,7 @@ <h2>Tagging Job Configuration</h2>
</div>

<div class="form-group">
<label for="Tags"> Labels* (Comma Seperated)</label>
<label for="Tags"> Labels<div id="required">*</div> (Comma Seperated)</label>
<input id="inputtags" class="form-control" type="text" data-role="tagsinput" required/>
</div>

Expand Down
14 changes: 14 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ var visitedFrames, //keep track of the visited frames

$(document).ready(() => {//init confirm keys figure out why this doesn't work
$('#inputtags').tagsinput({confirmKeys: [13, 32, 44, 45, 46, 59, 188]});

// hover support
$('#load-message').hover(() => {$("#vidImage").attr('src', './public/images/Load-Video-Active.png')},
() => {$("#vidImage").attr('src', './public/images/Load-Video.png')});

});

//ipc rendering
Expand Down Expand Up @@ -87,17 +92,26 @@ document.addEventListener('drop', (e) => {
if (e.dataTransfer.files[0].type == "video/mp4") {
fileSelected(e.dataTransfer.files[0]);
}
$("#vidImage").attr('src', './public/images/Load-Video.png');
return false;
});

document.addEventListener('dragover', (e) => {
e.preventDefault();
if (e.dataTransfer.files[0].type == "video/mp4") {
e.dataTransfer.dropEffect = "copy";
$("#vidImage").attr('src', './public/images/Load-Video-Active.png');

}
e.stopPropagation();
});

document.addEventListener('dragleave', (e) => {
e.preventDefault();
$("#vidImage").attr('src', './public/images/Load-Video.png');
e.stopPropagation();
});

document.addEventListener('dragstart', (e) => {
e.preventDefault();
let file = e.dataTransfer.files[0];
Expand Down
31 changes: 11 additions & 20 deletions src/lib/detection_algorithm_manager/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,32 @@ Object.keys(config).forEach((key) => {
detection_modules[key] = require(path.join(__dirname, config[key]));
});

var export_algorithm, review_algorthim;

function DetectionAlgorithmManager() {
var self = this;
//this returns a list of the availble detection modules
this.getAvailbleAlgorthims = function() {
this.getAvailbleAlgorthims = function getAvailbleAlgorthims() {
return Object.keys(config);
},

//returns export detection algorithm
this.getCurrentExportAlgorithm = function() {
return export_algorithm;
},

//returns current review algorithm
this.getCurrentReviewAlgorithm = function() {
return review_algorthim;
},

//Set the exporter to the specified detection module
this.setExporter = function(algorithm, exportDirPath, classes, posFramesCount, frameWidth, frameHeight, testSplit) {
this.initExporter = function(algorithm, exportDirPath, classes, posFramesCount, frameWidth, frameHeight, testSplit, cb) {
if (!Object.keys(config).includes(algorithm)){
throw (`Error ${algorithm} module is not recognized`);
}
this.exporter = new detection_modules[algorithm].Exporter(exportDirPath, classes, posFramesCount, frameWidth, frameHeight, testSplit);
export_algorithm = algorithm;
var exporter = new detection_modules[algorithm].Exporter(exportDirPath, classes, posFramesCount, frameWidth, frameHeight, testSplit);
exporter.init().then(()=> {
return cb(null, exporter.exportFrame);
}).catch((err) =>{
return cb(err);
});
},

//Set the reviewer for to the specified detection module
this.setReviewer = function(algorithm, modelPath) {
this.initReviewer = function (algorithm, modelPath, cb) {
if (!Object.values(config).includes(algorithm)){
throw (`Error ${algorithm} module is not recognized`);
}
this.reviewer = new detection_modules[algorithm].Reviewer(modelPath);
review_algorthim = algorithm;
var reviewer = new detection_modules[algorithm].Reviewer(modelPath);
return cb(reviewer.reviewImagesFolder);
}

}
Expand Down
112 changes: 56 additions & 56 deletions src/lib/videotagging_extensions/detection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ function Detection(videotagging, visitedFrames) {

var self = this;

//maps every frame in the video to an imageCanvas NOTE mapVideo clears the oncanplay eventListener
this.mapVideo = function(frameHandler, exportUntil) {
//maps every frame in the video to an imageCanvas until a specified point NOTE mapVideo clears the oncanplay eventListener
this.mapVideo = function(frameHandler, until) {
return new Promise((resolve, reject) => {
//init canvas buffer
var frameCanvas = document.createElement("canvas");
Expand All @@ -25,12 +25,12 @@ function Detection(videotagging, visitedFrames) {

//resolve export until
var isLastFrame;
if (exportUntil === "tagged") {
if (until === "tagged") {
isLastFrame = function(frameId) {
return (!Object.keys(self.videotagging.frames).length) || (frameId >= parseInt(Object.keys(self.videotagging.frames)[Object.keys(self.videotagging.frames).length-1]));
}
}
else if (exportUntil === "visited") {
else if (until === "visited") {
isLastFrame = function(frameId) {
var lastVisitedFrameId = Math.max.apply(Math, Array.from(self.visitedFrames));
return (frameId >= lastVisitedFrameId);
Expand Down Expand Up @@ -64,27 +64,27 @@ function Detection(videotagging, visitedFrames) {
// TODO: Abstract to a module that receives a "framesReader" object as input
//exports frames to the selected detection algorithm format for model training
this.export = function(method, exportUntil, exportPath, testSplit, cb) {

self.detectionAlgorithmManager.setExporter(method, exportPath, self.videotagging.inputtagsarray,
self.detectionAlgorithmManager.initExporter(method, exportPath, self.videotagging.inputtagsarray,
Object.keys(self.videotagging.frames).length,
self.videotagging.video.videoWidth,
self.videotagging.video.videoHeight,
testSplit);

self.detectionAlgorithmManager.exporter.init()
.then(() => {
this.mapVideo(exportFrame,exportUntil).then(() => {
testSplit,
(err, exporter) => {
if (err){
cb(err);
}
this.mapVideo(exportFrame.bind(err, exporter), exportUntil).then(() => {
let notification = new Notification('Offline Video Tagger', {
body: `Successfully exported ${self.detectionAlgorithmManager.getCurrentExportAlgorithm()} files.`
body: `Successfully exported ${method} files.`
});
cb();
})
}, (err) => {
console.info(`Error on ${self.detectionAlgorithmManager.getCurrentExportAlgorithm()} init:`, err);
cb(err)
console.info(`Error on ${method} init:`, err);
cb(err);
});
});

function exportFrame(frameId, frameCanvas, canvasContext, frameExportCb) {
function exportFrame(exporter, frameId, frameCanvas, canvasContext, frameExportCb) {
if (!self.visitedFrames.has(frameId)) {
return frameExportCb();
}
Expand Down Expand Up @@ -113,7 +113,7 @@ function Detection(videotagging, visitedFrames) {
//draw the frame to the canvas
var frameFileName = `${path.basename(self.videotagging.src, path.extname(self.videotagging.src))}_frame_${frameId}.jpg`;
var buf = self.canvasToJpgBuffer(frameCanvas, canvasContext);
self.detectionAlgorithmManager.exporter.exportFrame(frameFileName, buf, frameTags)
exporter(frameFileName, buf, frameTags)
.then(()=>{
frameExportCb();
}, (err) => {
Expand All @@ -122,7 +122,6 @@ function Detection(videotagging, visitedFrames) {
});
}
}


//allows user to review model suggestions on a video
this.review = function(method, modelPath, reviewPath, cb) {
Expand All @@ -140,45 +139,46 @@ function Detection(videotagging, visitedFrames) {

function reviewModel() {
//run the model on the reviewPath directory
self.detectionAlgorithmManager.setReviewer(method, modelPath);
self.detectionAlgorithmManager.reviewer.reviewImagesFolder(reviewPath).then( (modelTags) => {
self.videotagging.frames = [];
self.videotagging.optionalTags.createTagControls(Object.keys(modelTags.classes));

//Create regions based on the provided modelTags
Object.keys(modelTags.frames).map( (pathId) => {
var frameImage = new Image();
frameImage.src = path.join(reviewPath, pathId);
frameImage.onload = loadFrameRegions;

function loadFrameRegions() {
var imageWidth = this.width;
var imageHeight = this.height;
frameId = pathId.replace(".jpg", "");//remove.jpg
self.videotagging.frames[frameId] = [];
modelTags.frames[pathId].regions.forEach( (region) => {
self.videotagging.frames[frameId].push({
x1:region.x1,
y1:region.y1,
x2:region.x2,
y2:region.y2,
id:self.videotagging.uniqueTagId++,
width:imageWidth,
height:imageHeight,
type:self.videotagging.regiontype,
tags:Object.keys(modelTags.classes).filter( (key) => {return modelTags.classes[key] === region.class }),
name:(self.videotagging.frames[frameId].length + 1),
blockSuggest: true
});
});
}
self.detectionAlgorithmManager.initReviewer(method, modelPath, (reviewImagesFolder) =>{
reviewImagesFolder(reviewPath).then( (modelTags) => {
self.videotagging.frames = [];
self.videotagging.optionalTags.createTagControls(Object.keys(modelTags.classes));

//Create regions based on the provided modelTags
Object.keys(modelTags.frames).map( (pathId) => {
var frameImage = new Image();
frameImage.src = path.join(reviewPath, pathId);
frameImage.onload = loadFrameRegions;

function loadFrameRegions() {
var imageWidth = this.width;
var imageHeight = this.height;
frameId = pathId.replace(".jpg", "");//remove.jpg
self.videotagging.frames[frameId] = [];
modelTags.frames[pathId].regions.forEach( (region) => {
self.videotagging.frames[frameId].push({
x1:region.x1,
y1:region.y1,
x2:region.x2,
y2:region.y2,
id:self.videotagging.uniqueTagId++,
width:imageWidth,
height:imageHeight,
type:self.videotagging.regiontype,
tags:Object.keys(modelTags.classes).filter( (key) => {return modelTags.classes[key] === region.class }),
name:(self.videotagging.frames[frameId].length + 1),
blockSuggest: true
});
});
}
});
self.videotagging.showAllRegions();
//cleanup and notify
self.videotagging.video.currentTime = 0;
self.videotagging.playingCallback();
let notification = new Notification('Offline Video Tagger', { body: 'Model Ready For Review.' });
cb();
});
self.videotagging.showAllRegions();
//cleanup and notify
self.videotagging.video.currentTime = 0;
self.videotagging.playingCallback();
let notification = new Notification('Offline Video Tagger', { body: 'Model Ready For Review.' });
cb();
});
}

Expand Down
9 changes: 6 additions & 3 deletions src/public/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ html, body {
padding: 0 20px;
}

#required{
display: inline;
}

#load-text{
margin-top: 20px;
text-align: center;
Expand Down Expand Up @@ -34,7 +38,7 @@ html, body {
}

#vidImage{
width:50%;
width:480px;
display:block;
position:absolute;
left:0;
Expand All @@ -44,7 +48,6 @@ html, body {
margin:auto;
}


.form-control {
max-width:800px;
}
Expand All @@ -64,7 +67,7 @@ html, body {

.bootstrap-tagsinput {
display: block;
max-width: 800px;
max-width: 500px;
}

.loader {
Expand Down
Binary file added src/public/images/Load-Video-Active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3dd2a1a

Please sign in to comment.