├── public
├── .gitignore
├── jquery-ui
│ ├── css
│ │ ├── 1
│ │ └── smoothness
│ │ │ ├── 1
│ │ │ ├── images
│ │ │ ├── 1
│ │ │ ├── animated-overlay.gif
│ │ │ ├── ui-icons_222222_256x240.png
│ │ │ ├── ui-icons_2e83ff_256x240.png
│ │ │ ├── ui-icons_454545_256x240.png
│ │ │ ├── ui-icons_888888_256x240.png
│ │ │ ├── ui-icons_cd0a0a_256x240.png
│ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ │ └── jquery-ui-1.10.4.custom.min.css
│ ├── Readme.md
│ ├── jquery-ui.zip
│ └── index.html
├── readme.md
├── frames
│ ├── .gitignore
│ └── .htaccess
├── box.jpg
├── lock.jpg
├── magic.mp3
├── favicon.ico
├── secret.png
├── classify.jpg
├── entering1.png
├── entering2.png
├── entering3.png
├── entering4.png
├── outofcar1.png
├── outofcar2.png
├── outofcar3.png
├── sequence1.jpg
├── sequence2.jpg
├── sequence3.jpg
├── sequence4.jpg
├── tight-bad.jpg
├── tight-good.jpg
├── everyobject.jpg
├── outsideoccluded.jpg
├── index.html
├── job.js
├── preload.js
├── videoplayer.js
├── bootstrap.js
├── jquery-migrate-1.2.1.min.js
├── stylesheet.css
├── instructions.js
├── ui.js
└── objectui.js
├── arial.ttf
├── .gitignore
├── CONTRIBUTING.md
├── config.py-example
├── vatic-install.sh
├── LICENSE
├── DEVELOPERS
├── match.py
├── qa.py
├── server.py
├── merge.py
├── models.py
└── README.md
/public/.gitignore:
--------------------------------------------------------------------------------
1 | turkic
2 |
--------------------------------------------------------------------------------
/public/jquery-ui/css/1:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/jquery-ui/css/smoothness/1:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/jquery-ui/css/smoothness/images/1:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/readme.md:
--------------------------------------------------------------------------------
1 | https://github.com/cvondrick/vatic
2 |
--------------------------------------------------------------------------------
/public/frames/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.htaccess
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/public/jquery-ui/Readme.md:
--------------------------------------------------------------------------------
1 | please zip jquery-ui.zip in here
2 |
--------------------------------------------------------------------------------
/arial.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/arial.ttf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | config.py
3 | tmp
4 | backups
5 | vatic.tar.gz
6 | .DS_Store
7 | *.swp
8 |
--------------------------------------------------------------------------------
/public/box.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/box.jpg
--------------------------------------------------------------------------------
/public/lock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/lock.jpg
--------------------------------------------------------------------------------
/public/magic.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/magic.mp3
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/secret.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/secret.png
--------------------------------------------------------------------------------
/public/classify.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/classify.jpg
--------------------------------------------------------------------------------
/public/entering1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/entering1.png
--------------------------------------------------------------------------------
/public/entering2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/entering2.png
--------------------------------------------------------------------------------
/public/entering3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/entering3.png
--------------------------------------------------------------------------------
/public/entering4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/entering4.png
--------------------------------------------------------------------------------
/public/outofcar1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/outofcar1.png
--------------------------------------------------------------------------------
/public/outofcar2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/outofcar2.png
--------------------------------------------------------------------------------
/public/outofcar3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/outofcar3.png
--------------------------------------------------------------------------------
/public/sequence1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/sequence1.jpg
--------------------------------------------------------------------------------
/public/sequence2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/sequence2.jpg
--------------------------------------------------------------------------------
/public/sequence3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/sequence3.jpg
--------------------------------------------------------------------------------
/public/sequence4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/sequence4.jpg
--------------------------------------------------------------------------------
/public/tight-bad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/tight-bad.jpg
--------------------------------------------------------------------------------
/public/tight-good.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/tight-good.jpg
--------------------------------------------------------------------------------
/public/everyobject.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/everyobject.jpg
--------------------------------------------------------------------------------
/public/outsideoccluded.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/outsideoccluded.jpg
--------------------------------------------------------------------------------
/public/jquery-ui/jquery-ui.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZQ0723/vatic_BasicFinder-HIVE/HEAD/public/jquery-ui/jquery-ui.zip
--------------------------------------------------------------------------------
/public/frames/.htaccess:
--------------------------------------------------------------------------------
1 |
Sorry! This application does not currently support Internet Explorer. Please upgrade to a more modern browser to complete this HIT. We recommend Google Chrome or Mozilla Firefox.
"); 25 | return; 26 | } 27 | 28 | var parameters = mturk_parameters(); 29 | if (!parameters["id"]) 30 | { 31 | brandingscreen(); 32 | return; 33 | } 34 | 35 | if (!mturk_isassigned()) 36 | { 37 | mturk_acceptfirst(); 38 | } 39 | else 40 | { 41 | mturk_showstatistics(); 42 | } 43 | 44 | mturk_disabletimer(); 45 | 46 | function dispatch(training) 47 | { 48 | training = training ? 1 : 0; 49 | server_request("getjob", [parameters["id"], training], function(data) { 50 | loadingscreen(job_import(data)); 51 | }); 52 | } 53 | 54 | worker_isverified(function() { 55 | console.log("Worker is verified"); 56 | dispatch(false); 57 | }, function() { 58 | console.log("Worker is NOT verified"); 59 | dispatch(true); 60 | }); 61 | } 62 | 63 | function loadingscreen(job) 64 | { 65 | var ls = $(""); 66 | ls.append("vatic is an online, interactive video annotation tool for computer vision research that crowdsources work to Amazon's Mechanical Turk. Our tool makes it easy to build massive, affordable video data sets and can be deployed on a cloud. Written in Python + C + Javascript, vatic is free and open-source software.
"); 132 | d.append(""); 133 | d.hide(); 134 | d.appendTo(container); 135 | d.show("explode", 1000); 136 | 137 | $("body").animate({"background-color": "#666"}, 1000); 138 | } 139 | -------------------------------------------------------------------------------- /merge.py: -------------------------------------------------------------------------------- 1 | """ 2 | Merges paths across segments. Typical usage: 3 | 4 | >>> for boxes, paths in merge(segments): 5 | ... pass 6 | """ 7 | 8 | from match import match 9 | from vision.track.interpolation import Linear 10 | 11 | import logging 12 | 13 | logger = logging.getLogger("vatic.merge") 14 | 15 | def percentoverlap(first, second): 16 | """ 17 | Scores two paths, first and second, to see if they are the same path. 18 | 19 | A lower score is better. 0 is a perfect match. This method will assign a 20 | an extremely high score to paths that disagree on labels (a car cannot 21 | suddenly transform into a person). If labels match, then scores based 22 | off percent overlap in the intersecting timeline. 23 | """ 24 | firstboxes = first.getboxes(interpolate = True) 25 | secondboxes = second.getboxes(interpolate = True) 26 | secondboxes = dict((x.frame, x) for x in secondboxes) 27 | 28 | if first.label != second.label: 29 | return max(len(firstboxes), len(secondboxes)) + 1 30 | 31 | cost = 0 32 | for firstbox in firstboxes: 33 | if firstbox.frame in secondboxes: 34 | secondbox = secondboxes[firstbox.frame] 35 | if firstbox.lost != secondbox.lost: 36 | cost += 1 37 | else: 38 | cost += 1 - firstbox.percentoverlap(secondbox) 39 | return cost 40 | 41 | def overlapsize(first, second): 42 | """ 43 | Counts the number of frames in first that temporally overlap with second. 44 | """ 45 | return len(set(f.frame for f in first.getboxes(interpolate = True)) & 46 | set(s.frame for s in second.getboxes(interpolate = True))) 47 | 48 | def merge(segments, method = percentoverlap, threshold = 0.5): 49 | """ 50 | Takes a list of segments and attempts to find a correspondance between 51 | them by returning a list of merged paths. 52 | 53 | Uses 'method' to score two candidate paths. If the score returned by 54 | 'method' is greater than the number of overlaping frames times the 55 | threshold, then the correspondance is considered bunk and a new path 56 | is created instead. 57 | 58 | In general, if 'method' returns 0 for a perfect match and 1 for a 59 | horrible match, then 'threshold' = 0.5 is pretty good. 60 | """ 61 | logger.debug("Starting to merge!") 62 | paths = {} 63 | segments.sort(key = lambda x: x.start) 64 | for path in segments[0].paths: 65 | paths[path.id] = path.getboxes(), [path] 66 | for x, y in zip(segments, segments[1:]): 67 | logger.debug("Merging segments {0} and {1}".format(x.id, y.id)) 68 | if x.stop < y.start: 69 | logger.debug("Segments {0} and {1} do not overlap" 70 | .format(x.id, y.id)) 71 | for path in y.paths: 72 | paths[path.id] = path.getboxes(), [path] 73 | else: 74 | for first, second, score in match(x.paths, y.paths, method): 75 | logger.debug("{0} associated to {1} with score {2}" 76 | .format(first, second, score)) 77 | if second is None: 78 | continue 79 | 80 | isbirth = first is None 81 | if not isbirth: 82 | scorerequirement = threshold * overlapsize(first, second) 83 | if score > scorerequirement: 84 | logger.debug("Score {0} exceeds merge threshold of {1}" 85 | .format(score, scorerequirement)) 86 | isbirth = True 87 | else: 88 | logger.debug("Score {0} satisfies merge threshold of " 89 | "{1}" .format(score, scorerequirement)) 90 | 91 | if isbirth: 92 | paths[second.id] = second.getboxes(), [second] 93 | else: 94 | path = mergepath(paths[first.id][0], second.getboxes()) 95 | paths[first.id][1].append(second) 96 | paths[second.id] = (path, paths[first.id][1]) 97 | del paths[first.id] 98 | logger.debug("Done merging!") 99 | return paths.values() 100 | 101 | def mergepath(left, right): 102 | """ 103 | Takes two paths, left and right, and combines them into a single path by 104 | removing the duplicate annotations in the overlap region. 105 | """ 106 | 107 | rightmin = min(x.frame for x in right) 108 | 109 | boundary = (max((x.frame, x) for x in left if x.frame < rightmin), 110 | min((x.frame, x) for x in left if x.frame >= rightmin)) 111 | 112 | leftfill = Linear(boundary[0][1], boundary[1][1]) 113 | pivot = [x for x in leftfill if x.frame == rightmin][0] 114 | 115 | response = [x for x in left if x.frame < rightmin] 116 | response.append(pivot) 117 | response.extend(right[1:]) 118 | return response 119 | -------------------------------------------------------------------------------- /public/jquery-migrate-1.2.1.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Migrate v1.2.1 | (c) 2005, 2013 jQuery Foundation, Inc. and other contributors | jquery.org/license */ 2 | jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0),function(e,t,n){function r(n){var r=t.console;i[n]||(i[n]=!0,e.migrateWarnings.push(n),r&&r.warn&&!e.migrateMute&&(r.warn("JQMIGRATE: "+n),e.migrateTrace&&r.trace&&r.trace()))}function a(t,a,i,o){if(Object.defineProperty)try{return Object.defineProperty(t,a,{configurable:!0,enumerable:!0,get:function(){return r(o),i},set:function(e){r(o),i=e}}),n}catch(s){}e._definePropertyBroken=!0,t[a]=i}var i={};e.migrateWarnings=[],!e.migrateMute&&t.console&&t.console.log&&t.console.log("JQMIGRATE: Logging is active"),e.migrateTrace===n&&(e.migrateTrace=!0),e.migrateReset=function(){i={},e.migrateWarnings.length=0},"BackCompat"===document.compatMode&&r("jQuery is not compatible with Quirks Mode");var o=e("",{size:1}).attr("size")&&e.attrFn,s=e.attr,u=e.attrHooks.value&&e.attrHooks.value.get||function(){return null},c=e.attrHooks.value&&e.attrHooks.value.set||function(){return n},l=/^(?:input|button)$/i,d=/^[238]$/,p=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,f=/^(?:checked|selected)$/i;a(e,"attrFn",o||{},"jQuery.attrFn is deprecated"),e.attr=function(t,a,i,u){var c=a.toLowerCase(),g=t&&t.nodeType;return u&&(4>s.length&&r("jQuery.fn.attr( props, pass ) is deprecated"),t&&!d.test(g)&&(o?a in o:e.isFunction(e.fn[a])))?e(t)[a](i):("type"===a&&i!==n&&l.test(t.nodeName)&&t.parentNode&&r("Can't change the 'type' of an input or button in IE 6/7/8"),!e.attrHooks[c]&&p.test(c)&&(e.attrHooks[c]={get:function(t,r){var a,i=e.prop(t,r);return i===!0||"boolean"!=typeof i&&(a=t.getAttributeNode(r))&&a.nodeValue!==!1?r.toLowerCase():n},set:function(t,n,r){var a;return n===!1?e.removeAttr(t,r):(a=e.propFix[r]||r,a in t&&(t[a]=!0),t.setAttribute(r,r.toLowerCase())),r}},f.test(c)&&r("jQuery.fn.attr('"+c+"') may use property instead of attribute")),s.call(e,t,a,i))},e.attrHooks.value={get:function(e,t){var n=(e.nodeName||"").toLowerCase();return"button"===n?u.apply(this,arguments):("input"!==n&&"option"!==n&&r("jQuery.fn.attr('value') no longer gets properties"),t in e?e.value:null)},set:function(e,t){var a=(e.nodeName||"").toLowerCase();return"button"===a?c.apply(this,arguments):("input"!==a&&"option"!==a&&r("jQuery.fn.attr('value', val) no longer sets properties"),e.value=t,n)}};var g,h,v=e.fn.init,m=e.parseJSON,y=/^([^<]*)(<[\w\W]+>)([^>]*)$/;e.fn.init=function(t,n,a){var i;return t&&"string"==typeof t&&!e.isPlainObject(n)&&(i=y.exec(e.trim(t)))&&i[0]&&("<"!==t.charAt(0)&&r("$(html) HTML strings must start with '<' character"),i[3]&&r("$(html) HTML text after last tag is ignored"),"#"===i[0].charAt(0)&&(r("HTML string cannot start with a '#' character"),e.error("JQMIGRATE: Invalid selector string (XSS)")),n&&n.context&&(n=n.context),e.parseHTML)?v.call(this,e.parseHTML(i[2],n,!0),n,a):v.apply(this,arguments)},e.fn.init.prototype=e.fn,e.parseJSON=function(e){return e||null===e?m.apply(this,arguments):(r("jQuery.parseJSON requires a valid JSON string"),null)},e.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||0>e.indexOf("compatible")&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e.browser||(g=e.uaMatch(navigator.userAgent),h={},g.browser&&(h[g.browser]=!0,h.version=g.version),h.chrome?h.webkit=!0:h.webkit&&(h.safari=!0),e.browser=h),a(e,"browser",e.browser,"jQuery.browser is deprecated"),e.sub=function(){function t(e,n){return new t.fn.init(e,n)}e.extend(!0,t,this),t.superclass=this,t.fn=t.prototype=this(),t.fn.constructor=t,t.sub=this.sub,t.fn.init=function(r,a){return a&&a instanceof e&&!(a instanceof t)&&(a=t(a)),e.fn.init.call(this,r,a,n)},t.fn.init.prototype=t.fn;var n=t(document);return r("jQuery.sub() is deprecated"),t},e.ajaxSetup({converters:{"text json":e.parseJSON}});var b=e.fn.data;e.fn.data=function(t){var a,i,o=this[0];return!o||"events"!==t||1!==arguments.length||(a=e.data(o,t),i=e._data(o,t),a!==n&&a!==i||i===n)?b.apply(this,arguments):(r("Use of jQuery.fn.data('events') is deprecated"),i)};var j=/\/(java|ecma)script/i,w=e.fn.andSelf||e.fn.addBack;e.fn.andSelf=function(){return r("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),w.apply(this,arguments)},e.clean||(e.clean=function(t,a,i,o){a=a||document,a=!a.nodeType&&a[0]||a,a=a.ownerDocument||a,r("jQuery.clean() is deprecated");var s,u,c,l,d=[];if(e.merge(d,e.buildFragment(t,a).childNodes),i)for(c=function(e){return!e.type||j.test(e.type)?o?o.push(e.parentNode?e.parentNode.removeChild(e):e):i.appendChild(e):n},s=0;null!=(u=d[s]);s++)e.nodeName(u,"script")&&c(u)||(i.appendChild(u),u.getElementsByTagName!==n&&(l=e.grep(e.merge([],u.getElementsByTagName("script")),c),d.splice.apply(d,[s+1,0].concat(l)),s+=l.length));return d});var Q=e.event.add,x=e.event.remove,k=e.event.trigger,N=e.fn.toggle,T=e.fn.live,M=e.fn.die,S="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",C=RegExp("\\b(?:"+S+")\\b"),H=/(?:^|\s)hover(\.\S+|)\b/,A=function(t){return"string"!=typeof t||e.event.special.hover?t:(H.test(t)&&r("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'"),t&&t.replace(H,"mouseenter$1 mouseleave$1"))};e.event.props&&"attrChange"!==e.event.props[0]&&e.event.props.unshift("attrChange","attrName","relatedNode","srcElement"),e.event.dispatch&&a(e.event,"handle",e.event.dispatch,"jQuery.event.handle is undocumented and deprecated"),e.event.add=function(e,t,n,a,i){e!==document&&C.test(t)&&r("AJAX events should be attached to document: "+t),Q.call(this,e,A(t||""),n,a,i)},e.event.remove=function(e,t,n,r,a){x.call(this,e,A(t)||"",n,r,a)},e.fn.error=function(){var e=Array.prototype.slice.call(arguments,0);return r("jQuery.fn.error() is deprecated"),e.splice(0,0,"error"),arguments.length?this.bind.apply(this,e):(this.triggerHandler.apply(this,e),this)},e.fn.toggle=function(t,n){if(!e.isFunction(t)||!e.isFunction(n))return N.apply(this,arguments);r("jQuery.fn.toggle(handler, handler...) is deprecated");var a=arguments,i=t.guid||e.guid++,o=0,s=function(n){var r=(e._data(this,"lastToggle"+t.guid)||0)%o;return e._data(this,"lastToggle"+t.guid,r+1),n.preventDefault(),a[r].apply(this,arguments)||!1};for(s.guid=i;a.length>o;)a[o++].guid=i;return this.click(s)},e.fn.live=function(t,n,a){return r("jQuery.fn.live() is deprecated"),T?T.apply(this,arguments):(e(this.context).on(t,this.selector,n,a),this)},e.fn.die=function(t,n){return r("jQuery.fn.die() is deprecated"),M?M.apply(this,arguments):(e(this.context).off(t,this.selector||"**",n),this)},e.event.trigger=function(e,t,n,a){return n||C.test(e)||r("Global events are undocumented and deprecated"),k.call(this,e,t,n||document,a)},e.each(S.split("|"),function(t,n){e.event.special[n]={setup:function(){var t=this;return t!==document&&(e.event.add(document,n+"."+e.guid,function(){e.event.trigger(n,null,t,!0)}),e._data(this,n,e.guid++)),!1},teardown:function(){return this!==document&&e.event.remove(document,n+"."+e._data(this,n)),!1}}})}(jQuery,window); -------------------------------------------------------------------------------- /public/stylesheet.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | -webkit-user-select: none; 4 | -khtml-user-select: none; 5 | -moz-user-select: none; 6 | -o-user-select: none; 7 | user-select: none; 8 | } 9 | 10 | label, .button 11 | { 12 | font-size : 12px !important; 13 | } 14 | 15 | table td 16 | { 17 | vertical-align : top; 18 | } 19 | 20 | h1 21 | { 22 | font-family : Arial; 23 | margin : 0; 24 | padding : 0; 25 | font-size : 30px; 26 | font-weight : bold; 27 | } 28 | 29 | h2 30 | { 31 | font-family : Arial; 32 | margin : 0; 33 | padding : 0; 34 | font-size : 26px; 35 | font-weight : bold; 36 | } 37 | 38 | h3 39 | { 40 | font-family : Arial; 41 | font-size : 20px; 42 | font-weight : bold; 43 | padding : 5px 0; 44 | margin : 0; 45 | } 46 | 47 | p, li 48 | { 49 | font-family : Arial; 50 | font-size : 16px; 51 | } 52 | 53 | ul 54 | { 55 | margin-top : 10px; 56 | margin-bottom : 10px; 57 | } 58 | 59 | code 60 | { 61 | padding : 0 5px; 62 | } 63 | 64 | #turkic_acceptfirst 65 | { 66 | background-color : #cd0a0a; 67 | color : #fff; 68 | } 69 | 70 | #turkic_workerstats 71 | { 72 | background-color : #E4E4E4; 73 | } 74 | 75 | #loadingscreen 76 | { 77 | width : 700px; 78 | margin : 0 auto; 79 | margin-top : 100px; 80 | } 81 | 82 | #loadingscreentext 83 | { 84 | font-weight : bold; 85 | font-size : 20px; 86 | font-family : Arial; 87 | } 88 | 89 | #loadingscreenslider 90 | { 91 | background-color : #D5E8FF; 92 | width : 100%; 93 | height : 50px; 94 | } 95 | 96 | #loadingscreenslider .progressbar 97 | { 98 | background-color : #0F7BFF; 99 | } 100 | 101 | #loadingscreenslider .text 102 | { 103 | color : #fff; 104 | font-weight : bold; 105 | margin-top : 15px; 106 | margin-left :10px; 107 | font-family : Arial; 108 | } 109 | 110 | .loadingscreentip 111 | { 112 | font-family : Arial; 113 | margin-top : 25px; 114 | color : #333; 115 | } 116 | 117 | #loadingscreeninstructions 118 | { 119 | float : right; 120 | margin-top : -10px; 121 | font-weight : bold; 122 | } 123 | 124 | #annotatescreen 125 | { 126 | width : 925px; 127 | margin : 0 auto; 128 | } 129 | 130 | #videoframe 131 | { 132 | background-color : #000; 133 | display : block; 134 | } 135 | 136 | #playbutton 137 | { 138 | font-weight : bold; 139 | width : 80px; 140 | } 141 | 142 | #newobjectcontainer 143 | { 144 | text-align : center; 145 | } 146 | 147 | #newobjectbutton 148 | { 149 | font-weight : bold; 150 | } 151 | 152 | #speedcontrol 153 | { 154 | display : inline; 155 | } 156 | 157 | #annotateoptions 158 | { 159 | display : inline; 160 | } 161 | 162 | #openadvancedoptions 163 | { 164 | float : right; 165 | } 166 | 167 | #advancedoptions 168 | { 169 | float : right; 170 | } 171 | 172 | #music 173 | { 174 | position : absolute; 175 | top : -100000px; 176 | left : -100000px; 177 | width : 1px; 178 | height : 1px; 179 | } 180 | 181 | 182 | #objectcontainer 183 | { 184 | overflow : auto; 185 | height : 100%; 186 | } 187 | 188 | #failedverificationdialog 189 | { 190 | position : fixed; 191 | top : 50px; 192 | left : 50%; 193 | width : 550px; 194 | margin-left : -275px; 195 | z-index : 10000000; 196 | padding : 10px; 197 | border : 5px solid #EB1414; 198 | background-color : #FFC2C2; 199 | overflow : auto; 200 | } 201 | 202 | #failedverificationbutton 203 | { 204 | font-weight : bold; 205 | } 206 | 207 | #instructions 208 | { 209 | font-family : Arial; 210 | font-size : 16px; 211 | padding : 5px 0; 212 | } 213 | 214 | #instructionsbutton 215 | { 216 | float : right; 217 | } 218 | 219 | #instructionsdialog 220 | { 221 | position : fixed; 222 | top : 50px; 223 | left : 50%; 224 | height : 480px; 225 | width : 720px; 226 | margin-left : -360px; 227 | background-color : #fff; 228 | z-index : 10000000000000; 229 | padding : 10px; 230 | border : 2px solid #000; 231 | overflow : auto; 232 | } 233 | 234 | #instructionsclosetop 235 | { 236 | float : right; 237 | font-weight : bold; 238 | } 239 | 240 | .keyboardshortcuts 241 | { 242 | list-style-type : none; 243 | margin : 0; 244 | margin-left : 10px; 245 | padding : 0; 246 | } 247 | 248 | .keyboardshortcuts code 249 | { 250 | display : block; 251 | width : 100px; 252 | float : left; 253 | } 254 | 255 | .trackobject 256 | { 257 | border : 2px solid black; 258 | font-family : Arial; 259 | font-size : 14px; 260 | } 261 | 262 | .trackobjectfoldedup 263 | { 264 | } 265 | 266 | .trackobjectfoldeddown 267 | { 268 | } 269 | 270 | .trackobject p, .trackobject li, .trackobject label 271 | { 272 | font-family : Arial; 273 | font-size : 14px !important; 274 | } 275 | 276 | .trackobject .label:hover 277 | { 278 | font-weight : bold; 279 | } 280 | 281 | .trackobject p 282 | { 283 | padding : 2px; 284 | margin : 0; 285 | } 286 | 287 | .trackobject ul, ol 288 | { 289 | margin : 0; 290 | padding : 0; 291 | margin-left : 30px; 292 | } 293 | 294 | .trackobjectheader 295 | { 296 | margin : 0; 297 | padding : 3px !important; 298 | /*cursor : pointer;*/ 299 | } 300 | 301 | .trackobjectheader:hover 302 | { 303 | /*text-decoration : underline;*/ 304 | } 305 | 306 | .trackobjectheader .ui-icon 307 | { 308 | float : left; 309 | } 310 | 311 | .boundingbox 312 | { 313 | position : absolute !important; 314 | border-style : solid; 315 | border-width : 2px; 316 | z-index : 5; 317 | } 318 | 319 | .boundingbox .boundingboxtext 320 | { 321 | font-size : 14px; 322 | /*margin-top : -18px;*/ 323 | color : #fff; 324 | 325 | position : absolute; 326 | margin-left : -80px; 327 | margin-top : -2px; 328 | width : 75px; 329 | text-align : right; 330 | 331 | padding : 1px; 332 | padding-right : 3px; 333 | cursor : default; 334 | z-index : 0; 335 | 336 | text-shadow: -1px 0 2px #000, 0px 1px 2px #000, 1px 0 2px #000, 0 -1px 2px #000; 337 | -moz-text-shadow: -1px 0 2px #000, 0px 1px 2px #000, 1px 0 2px #000, 0 -1px 2px #000; 338 | -webkit-text-shadow: -1px 0 2px #000, 0px 1px 2px #000, 1px 0 2px #000, 0 -1px 2px #000; 339 | } 340 | 341 | .boundingboxhighlight .boundingboxtext 342 | { 343 | text-shadow: -1px 0 5px #000, 0px 1px 5px #000, 1px 0 5px #000, 0 -1px 5px #000; 344 | -moz-text-shadow: -1px 0 5px #000, 0px 1px 5px #000, 1px 0 5px #000, 0 -1px 5px #000; 345 | -webkit-text-shadow: -1px 0 5px #000, 0px 1px 5px #000, 1px 0 5px #000, 0 -1px 5px #000; 346 | z-index : 1; 347 | } 348 | 349 | .boundingbox .fill 350 | { 351 | width : 100%; 352 | height : 100%; 353 | display : block; 354 | display : none; 355 | } 356 | 357 | .boundingboxhighlight 358 | { 359 | z-index : 10; 360 | } 361 | 362 | .boundingboxhighlight .fill 363 | { 364 | opacity : 0.25; 365 | display : block; 366 | } 367 | 368 | .boundingboxoccluded 369 | { 370 | border-style : dashed; 371 | } 372 | 373 | .ui-resizable-disabled 374 | { 375 | opacity : 1.0 !important; 376 | } 377 | 378 | .boundingboxdim 379 | { 380 | opacity : 0.3 !important; 381 | } 382 | 383 | .boundingboxlocked 384 | { 385 | z-index : 0; 386 | opacity : 0.3 !important; 387 | } 388 | 389 | .boundingboxhighlight 390 | { 391 | opacity : 1 !important; 392 | } 393 | 394 | #submitbar 395 | { 396 | text-align : center; 397 | vertical-align : bottom; 398 | } 399 | 400 | #submitdialog 401 | { 402 | position : absolute; 403 | top : 200px; 404 | left : 0; 405 | width : 100%; 406 | text-align : center; 407 | font-size : 100px; 408 | font-weight : bold; 409 | font-family : Arial; 410 | z-index : 100000; 411 | } 412 | 413 | .boxtooltip 414 | { 415 | position : absolute; 416 | width : 200px; 417 | height : 200px; 418 | z-index : 100; 419 | border : 5px solid #000; 420 | background-color : #000; 421 | background-repeat : no-repeat; 422 | -moz-box-shadow: 2px 2px 10px #000, -2px 2px 10px #000, 2px -2px 10px #000, -2px -2px 10px #000; 423 | -webkit-box-shadow: 2px 2px 10px #000, -2px 2px 10px #000, 2px -2px 10px #000, -2px -2px 10px #000; 424 | box-shadow: 2px 2px 10px #000, -2px 2px 10px #000, 2px -2px 10px #000, -2px -2px 10px #000; 425 | } 426 | 427 | .boxtooltip .boundingbox 428 | { 429 | position : relative; 430 | z-index : 101; 431 | } 432 | -------------------------------------------------------------------------------- /public/instructions.js: -------------------------------------------------------------------------------- 1 | function instructions(job, h) 2 | { 3 | h.append("In this task, we ask you to annotate a video. You are to draw a box around every object of interest and track each object for the entire video. These instructions will give you tips on how to best use our tool.
"); 5 | 6 | h.append("
");
31 | h.append("Click the New Object button to start annotating your first object. Position your cursor over the view screen to click on the corner of an object of interest. Use the cross hairs to line up your click. Click on another corner to finish drawing the box. The rectangle should tightly and completely enclose the object you are annotating. Resize the box, if necessary, by dragging the edges of the box.
"); 32 | 33 | h.append("
");
34 | h.append("On the right, directly below the New Object button, you will find a colorful box. The box is prompting you to input which type of object you have labeled. Click the correst response.
"); 35 | 36 | if (job.skip > 0) 37 | { 38 | h.append("Press the Play button. The video will play. When the video automatically pauses, adjust the boxes. Using your mouse, drag-and-drop the box to the correct position and resize if necessary. Continue in this fashion until you have reached the end of the video.
"); 39 | } 40 | else 41 | { 42 | h.append("Press the Play button. The video will begin to play forward. After the object you are tracking has moved a bit, click Pause. Using your mouse, drag-and-drop the box to the correct position and resize if necessary. Continue in this fashion until you have reached the end of the video.
"); 43 | } 44 | 45 | if (job.perobject > 0) 46 | { 47 | h.append("Once you have reached the end, you should rewind by pressing the rewind button (next to Play) and repeat this process for every object of interest. You are welcome to annotate multiple objects each playthrough. We will pay you a bonus for every object that you annotate.
"); 48 | } 49 | else 50 | { 51 | h.append("Once you have reached the end, you should rewind by pressing the rewind button (next to Play) and repeat this process for every object of interest. You are welcome to annotate multiple objects each playthrough.
"); 52 | } 53 | 54 | h.append("
");
55 | h.append("If an object leaves the screen, mark the Outside of view frame checkbox for the corresponding sidebar rectangle. Make sure you click the right button. When you mouse over the controls, the corresponding rectangle will light up in the view screen. Likewise, if the object you are tracking is still in the view frame but the view is obstructed (e.g., inside a car), mark the Occluded or obstructed checkbox. When the object becomes visible again, remember to uncheck these boxes. If there are additional checkboxes describing attributes, mark those boxes for the duration that it applies. For example, only mark \"Walking\" when the person is walking.
"); 56 | 57 | h.append("If there are many objects on the screen, it can become difficult to select the right bounding box. By pressing the lock button
on an object's sidebar rectangle, you can prevent changes to that track. Press the lock button again to renable modifications.
Remembering which box correspond to which box can be confusing. If you click on a box in the view screen, a tooltip will pop that will attempt to remind you of the box's identity.
"); 60 | 61 | h.append("When you are ready to submit your work, rewind the video and watch it through one more time. Does each rectangle follow the object it is tracking for the entire sequence? If you find a spot where it misses, press Pause and adjust the box. After you have checked your work, press the Submit HIT button. We will pay you as soon as possible.
"); 62 | 63 | h.append("We will hand review your work and we will only accept high quality work. Your annotations are not compared against other workers. Follow these guidelines to ensure your work is accepted:
"); 65 | 66 | h.append("
");
69 | //h.append("
");
70 |
71 | if (job.perobject > 0)
72 | {
73 | h.append("Every object of interest should be labeled for the entire video. The above work was accepted because every object has a box around it. An object is not labeled more than once. Even if the object does not move, you must label it. We will pay you a bonus for every object you annotate.
"); 74 | } 75 | else 76 | { 77 | h.append("Every object of interest should be labeled for the entire video. The above work was accepted because every object has a box around it. An object is not labeled more than once. Even if the object does not move, you must label it.
"); 78 | } 79 | 80 | h.append("![]() | ![]() |
| Good | Bad |
|---|
The boxes you draw must be tight. They boxes must fit around the object as close as possible. The loose annotation on the right would be rejected while the tight annotation on the left will be accepted.
"); 83 | 84 | h.append("
");
86 | h.append("
");
87 | h.append("
The entire video sequence must be labeled. When an object moves, you must update its position. A box must describe only one object. You should never change which object identity a particular box tracks.
"); 89 | 90 | h.append("In order for your work to be accepted, you must correctly label objects as they enter and leave the scene. We want you to annotate the moment each object enters and leaves the scene. As it is often difficult to pinpoint the exact moment an object enters or leaves the scene, we allow some mistakes here, but only slightly!
"); 92 | 93 | h.append("

If one object enters another object (such as a person getting inside a car), you should mark the disappearing object as outside of the view frame. Likewise, you should start annotating an object the moment it steps out of the enclosing object.
"); 96 | 97 | h.append("
If an object disappears from the scene and the exact same object reappears later in the scene, you must mark that object as back inside the view frame. Do not draw a new object for its second appearance. Simply find the corresponding right-column rectangle and uncheck the Outside of view frame checkbox and position the box.
"); 100 | 101 | h.append("We have provided some advanced tools for videos that are especially difficult. Clicking the Options button will enable the advanced options.
"); 103 | h.append("These keyboard shortcuts are available for your convenience:
"); 111 | h.append('n creates a new objectt toggles play/pause on the videor rewinds the video to the starth hides/shows the boxes (only after clicking Options button)d jump the video forward a bitf jump the video backward a bitv step the video forward a tiny bitc step the video backward a tiny bitAnnotate every object, even stationary and obstructed objects, for the entire video. | " +
33 | "" + 34 | " |
| " + 37 | " | " + 38 | " |
| " + 41 | " | |
| " + 44 | " | " + 45 | " |
Sorry, but your work is low quality. We would normally reject this assignment, but we are giving you the opportunity to correct your mistakes since you are a new user.
"); 563 | 564 | h.append("Please review the instructions, double check your annotations, and submit again. Remember:
"); 565 | 566 | var str = "When you are ready to continue, press the button below.
"); 574 | 575 | $('').appendTo(h).button({ 576 | icons: { 577 | primary: "ui-icon-refresh" 578 | } 579 | }).click(function() { 580 | $("#turkic_overlay").remove(); 581 | h.remove(); 582 | }).wrap(""); 583 | } 584 | 585 | function ui_showinstructions(job) 586 | { 587 | console.log("Popup instructions"); 588 | 589 | if ($("#instructionsdialog").size() > 0) 590 | { 591 | return; 592 | } 593 | 594 | eventlog("instructions", "Popup instructions"); 595 | 596 | $('').appendTo("#container"); 597 | var h = $('').appendTo("#container"); 598 | 599 | $('').appendTo(h).button({ 600 | icons: { 601 | primary: "ui-icon-circle-close" 602 | } 603 | }).click(ui_closeinstructions); 604 | 605 | instructions(job, h) 606 | 607 | ui_disable(); 608 | } 609 | 610 | function ui_closeinstructions() 611 | { 612 | console.log("Popdown instructions"); 613 | $("#turkic_overlay").remove(); 614 | $("#instructionsdialog").remove(); 615 | eventlog("instructions", "Popdown instructions"); 616 | 617 | ui_enable(); 618 | } 619 | 620 | function ui_disable() 621 | { 622 | if (ui_disabled++ == 0) 623 | { 624 | $("#newobjectbutton").button("option", "disabled", true); 625 | $("#playbutton").button("option", "disabled", true); 626 | $("#rewindbutton").button("option", "disabled", true); 627 | $("#submitbutton").button("option", "disabled", true); 628 | $("#playerslider").slider("option", "disabled", true); 629 | 630 | console.log("Disengaged UI"); 631 | } 632 | 633 | console.log("UI disabled with count = " + ui_disabled); 634 | } 635 | 636 | function ui_enable() 637 | { 638 | if (--ui_disabled == 0) 639 | { 640 | $("#newobjectbutton").button("option", "disabled", false); 641 | $("#playbutton").button("option", "disabled", false); 642 | $("#rewindbutton").button("option", "disabled", false); 643 | $("#submitbutton").button("option", "disabled", false); 644 | $("#playerslider").slider("option", "disabled", false); 645 | 646 | console.log("Engaged UI"); 647 | } 648 | 649 | ui_disabled = Math.max(0, ui_disabled); 650 | 651 | console.log("UI disabled with count = " + ui_disabled); 652 | } 653 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Please note: the community is working on a modernized version in the [contrib](https://github.com/cvondrick/vatic/tree/contrib) branch. Please check it out and commit any pull requests there. Thank you! - December 3, 2016 2 | 3 | # VATIC - Video Annotation Tool from Irvine, California 4 | 5 | 6 | 7 | VATIC is an online video annotation tool for computer vision research that 8 | crowdsources work to Amazon's Mechanical Turk. Our tool makes it easy to build 9 | massive, affordable video data sets. 10 | 11 |
12 |
13 | # INSTALLATION
14 |
15 | Note: VATIC has only been tested on Ubuntu with Apache 2.2 HTTP server and a
16 | MySQL server. This document will describe installation on this platform,
17 | however it should work any operating system and with any server.
18 |
19 | ## Download
20 |
21 | You can download and extract VATIC from our website. Note: do NOT run the
22 | installer as root.
23 |
24 | $ wget http://mit.edu/vondrick/vatic/vatic-install.sh
25 | $ chmod +x vatic-install.sh
26 | $ ./vatic-install.sh
27 | $ cd vatic
28 |
29 | ## HTTP Server Configuration
30 |
31 | Open the Apache configuration file. On Ubuntu, this file is located at:
32 |
33 | /etc/apache2/sites-enabled/000-default
34 |
35 | If you do not use Apache on this computer for any other purpose, replace the
36 | contents of the file with:
37 |
38 | WSGIDaemonProcess www-data
39 | WSGIProcessGroup www-data
40 |
41 | In this video, please track all of these objects:
"; 151 | html += "Draw a box around one of these objects:
"; 289 | 290 | html += "Do not annotate the same object twice.
"; 297 | 298 | this.drawinst = $("What type of object did you just annotate?
"; 327 | for (var i in job.labels) 328 | { 329 | var id = "classification" + this.id + "_" + i; 330 | html += "" + this.job.labels[this.label] + " " + (this.id + 1) + "
").appendTo(this.handle).hide().slideDown(); 363 | //this.opencloseicon = $('').prependTo(this.header); 364 | this.details = $("").appendTo(this.handle).hide(); 365 | 366 | this.setupdetails(); 367 | 368 | this.updateboxtext(); 369 | 370 | this.track.initattributes(this.job.attributes[this.track.label]); 371 | 372 | this.header.mouseup(function() { 373 | me.click(); 374 | }); 375 | 376 | this.ready = true; 377 | this._callback(this.onready); 378 | 379 | this.player.onupdate.push(function() { 380 | me.updateboxtext(); 381 | }); 382 | } 383 | 384 | this.updateboxtext = function() 385 | { 386 | var str = "" + this.job.labels[this.label] + " " + (this.id + 1) + ""; 387 | 388 | var count = 0; 389 | for (var i in this.job.attributes[this.track.label]) 390 | { 391 | if (this.track.estimateattribute(i, this.player.frame)) 392 | { 393 | str += "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
234 |