def readpaths(tracks): paths = [] logger.debug("Reading {0} total tracks".format(len(tracks))) for label, track, attributes in tracks: path = Path() path.label = session.query(Label).get(label) logger.debug("Received a {0} track".format(path.label.text)) for frame, userbox in track.items(): box = Box(path = path) box.xtl = int(userbox[0]) box.ytl = int(userbox[1]) box.xbr = int(userbox[2]) box.ybr = int(userbox[3]) box.occluded = int(userbox[4]) box.outside = int(userbox[5]) box.frame = int(frame) logger.debug("Received box {0}".format(str(box.getbox()))) for attributeid, timeline in attributes.items(): attribute = session.query(Attribute).get(attributeid) for frame, value in timeline.items(): aa = AttributeAnnotation() aa.attribute = attribute aa.frame = frame aa.value = value path.attributes.append(aa) paths.append(path) return paths
def __call__(self, args): video = session.query(Video).filter(Video.slug == args.slug) if not video.count(): print "Video {0} does not exist!".format(args.slug) return video = video.one() query = session.query(Path) query = query.join(Job) query = query.join(Segment) query = query.filter(Segment.video == video) numpaths = query.count() if numpaths and not args.force: print ("Video has {0} paths. Use --force to delete." .format(numpaths)) return for segment in video.segments: for job in segment.jobs: if job.published and not job.completed: hitid = job.disable() print "Disabled {0}".format(hitid) session.delete(video) session.commit() print "Deleted video and associated data."
def __call__(self, args): query = session.query(HIT) query = query.filter(HIT.useful == True) if args.hit: query = query.filter(HIT.hitid == args.id) else: worker = session.query(Worker).get(args.id) if not worker: print "Worker \"{0}\" not found".format(args.id) return if not args.no_block: worker.block("HIT was invalid.") print "Blocked worker \"{0}\"".format(args.id) session.add(worker) query = query.filter(HIT.workerid == args.id) for hit in query: replacement = hit.invalidate() session.add(hit) print "Invalidated {0}".format(hit.hitid) if replacement: session.add(replacement) if not args.no_publish: session.commit() replacement.publish() session.add(replacement) print "Respawned with {0}".format(replacement.hitid) session.commit()
def __call__(self, args): videos = session.query(Video) if args.training: videos = videos.filter(Video.isfortraining == True) else: videos = videos.filter(Video.isfortraining == False) if args.worker: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.workerid == args.worker) elif args.published: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.published == True) elif args.completed: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.completed == True) elif args.incomplete: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.completed == False) if args.count: print videos.count() else: newvideos = dict() print "Identifier", '-------', 'jobid', '------', 'timeonserver', ' ------------------- HitId', ' ------------------- AssignmentId', ' --------------- WorkerId' for video in videos.distinct(): # print video.slug # Print videos sorted by time test = session.query(Job).filter(Job.useful == True) test = test.join(Segment).filter(Segment.videoid == video.id) if test.count() != 1: print "Error: ", test.count() break for t in test: l = list() if t.timeonserver is None: l.append(datetime.datetime.now()) else: l.append(t.timeonserver) l.append(t) newvideos[video.slug] = l sorted_list = [x for x in newvideos.iteritems()] sorted_list.sort(key=lambda x: x[1][0]) # sort by key for k in sorted_list: print k[0], "---", k[1][1].id, "---", k[1][0], "---", k[1][1].hitid, "---", k[1][1].assignmentid, "---", k[1][1].workerid
def upload(id, environ): job = session.query(Job).get(id) data = environ["wsgi.input"] # read meta data first header = data.readline().strip() + "--" while True: chunk = data.readline() if chunk.strip() == "": break key, value = chunk.split(": ", 1) if key == "Content-Type": job.mimetype = value.strip() if key == "Content-Disposition": for item in value.split("; "): itemdata = item.split("=", 1) if len(itemdata) == 2 and itemdata[0] == "filename": job.filename = itemdata[1].strip()[1:-1] session.commit() # now read the file data, looking for the terminating sequence out = open(job.storepath, "wb") while True: chunk = data.readline(1024 * 1024) if chunk.strip() == header: break out.write(chunk) out.close() return ["<script>parent.uploaded();</script>"]
def validatejob(id, data): job = session.query(Job).get(id) paths = readpaths(data["tracks"]) predicates = readpredicates(data["predicates"]) return (job.trainingjob.validator(paths, job.trainingjob.paths) and job.trainingjob.validator(predicates, job.trainingjob.predicates))
def savejob(id, data): job = session.query(Job).get(id) for path in job.paths: session.delete(path) for pi in job.predicate_instances: for pa in pi.predicate_annotations: session.delete(pa) session.delete(pi) for s in job.sentences: for sa in s.annotations: session.delete(sa) session.delete(s) session.commit() paths = readpaths(data["tracks"]) for path in paths: job.paths.append(path) for pi in readpredicates(data["predicates"], paths): job.predicate_instances.append(pi) for s in readsentences(data['sentences']): job.sentences.append(s) session.add(job) session.commit()
def trackforward(id, frame, tracker, trackid, tracks): frame = int(frame) trackid = int(trackid) job = session.query(Job).get(id) segment = job.segment video = segment.video paths = [path for path in readpaths(tracks) if path is not None] paths = trackutils.totrackpaths(paths) logger.info("Job Id: {0}".format(id)) logger.info("Algorithm: {0}".format(tracker)) start = frame stop = segment.stop outpath = tracking.api.online(tracker, start, stop, video.location, trackid, paths) path = trackutils.fromtrackpath(outpath, job, start, stop) attrs = [(x.attributeid, x.frame, x.value) for x in path.attributes] logger.info("Path: {0}".format(path)) return { "label": 0, "boxes": [tuple(x) for x in path.getboxes()], "attributes": attrs }
def videodump(slug, outputtype, groundplane, fields=None): logger.debug(os.getcwd()) query = session.query(Video).filter(Video.slug == slug) if query.count() != 1: raise ValueError("Invalid video slug") video = query.one() #mergemethod = merge.userid groundplane = (groundplane == 1) mergemethod = merge.getpercentoverlap(groundplane) if fields is None: if groundplane: fields = dumptools.GROUND_PLANE_FORMAT else: fields = dumptools.DEFAULT_FORMAT fields = fields.split() data = dumptools.getdata(video, True, mergemethod, 0.5, None, groundplane) outfile = tempfile.TemporaryFile() if outputtype == "json": dumptools.dumpjson(outfile, data, groundplane, fields) elif outputtype == "xml": dumptools.dumpxml(outfile, data, groundplane, fields) else: dumptools.dumptext(outfile, data, groundplane, fields) outfile.seek(0) text = outfile.readlines() outfile.close() return text
def getallvideos(): query = session.query(Video) videos = [] for video in query: newvideo = { "slug": video.slug, "segments": [], } for segment in video.segments: newsegment = { "start": segment.start, "stop":segment.stop, "jobs":[], } for job in segment.jobs: newsegment["jobs"].append({ "url": job.offlineurl(config.localhost), "numobjects": len(job.paths), "numdone": len([path for path in job.paths if path.done]), }) newvideo["segments"].append(newsegment) videos.append(newvideo) return videos
def __call__(self, args): videos = session.query(Video) if args.training: videos = videos.filter(Video.isfortraining == True) else: videos = videos.filter(Video.isfortraining == False) if args.worker: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.workerid == args.worker) elif args.published: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.published == True) elif args.completed: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.completed == True) if args.count: print videos.count() else: for video in videos.distinct(): print "{0:<25}".format(video.slug), if args.stats: print "{0:>3}/{1:<8}".format(video.numcompleted, video.numjobs), print "${0:<15.2f}".format(video.cost), print ""
def __call__(self, args): videos = session.query(Video) if args.training: videos = videos.filter(Video.isfortraining == True) else: videos = videos.filter(Video.isfortraining == False) if args.worker: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.workerid == args.worker) elif args.published: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.published == True) elif args.completed: videos = videos.join(Segment) videos = videos.join(Job) videos = videos.filter(Job.completed == True) if args.count: print videos.count() else: for video in videos.distinct(): print video.slug
def savetopview(slug, image, environ): logger.info("Saving topview image") query = session.query(Video).filter(Video.slug == slug) if query.count() != 1: raise ValueError("Invalid video slug") video = query[0] savedir = video.homographylocation if savedir is None: savedir = makehomographydir(video) savelocation = os.path.join(savedir, "topview.jpg") tempformfile = tempfile.TemporaryFile() tempformfile.write(image) tempformfile.seek(0) form = cgi.FieldStorage(fp=tempformfile, environ=environ, keep_blank_values=True) outfile = open(savelocation, "w+b") shutil.copyfileobj(form['photo'].file, outfile) tempformfile.close() outfile.close() newimage = cv2.imread(savelocation) scale = 1 if newimage.shape[1] > video.width: scale = float(video.width) / float(newimage.shape[1]) newimage = cv2.resize(newimage, (0, 0), None, scale, scale) if newimage.shape[0] > video.height: scale = float(video.height) / float(newimage.shape[0]) newimage = cv2.resize(newimage, (0, 0), None, scale, scale) cv2.imwrite(savelocation, newimage)
def __call__(self, args): jobs = session.query(Job) jobs = jobs.join(Segment).join(Video) if args.id: jobs = jobs.filter(Video.slug == args.id) if args.frame is not None: jobs = jobs.filter(Segment.start <= args.frame) jobs = jobs.filter(Segment.stop >= args.frame) if args.hitid: jobs = jobs.filter(Job.hitid == args.hitid) if args.workerid: jobs = jobs.filter(Job.workerid == args.workerid) jobs = jobs.filter(turkic.models.HIT.useful == True) if jobs.count() > 0: for job in jobs: if args.ids: if job.published: print job.hitid, if job.completed: print job.assignmentid, print job.workerid, print "" else: print "(not published)" else: print job.offlineurl(config.localhost) else: print "No jobs matching this criteria."
def __call__(self, args): query = session.query(Job).filter(turkic.models.HIT.completed == True) for job in query: print job.storepath print job.mimetype for activity in job.activities: print activity.text print ""
def getboxesforjob(id): job = session.query(Job).get(id) result = [] for path in job.paths: attrs = [(x.attributeid, x.frame, x.value) for x in path.attributes] result.append({"label": path.labelid, "boxes": [tuple(x) for x in path.getboxes()], "attributes": attrs}) return result
def markcomplete(hitid, assignmentid, workerid): """ Marks a job as complete. Usually this is called right before the MTurk form is submitted. """ hit = session.query(models.HIT).filter(models.HIT.hitid == hitid).one() hit.markcompleted(workerid, assignmentid) session.add(hit) session.commit()
def getjob(id, verified): job = session.query(Job).get(id) logger.debug("Found job {0}".format(job.id)) if int(verified) and job.segment.video.trainwith: # swap segment with the training segment training = True segment = job.segment.video.trainwith.segments[0] logger.debug("Swapping actual segment with training segment") else: training = False segment = job.segment video = segment.video labels = dict((l.id, l.text) for l in video.labels) attributes = {} for label in video.labels: attributes[label.id] = dict((a.id, a.text) for a in label.attributes) roles = dict((r.id, r.text) for r in session.query(Role)) predicates = dict((p.id, p.text) for p in session.query(Predicate)) logger.debug("Giving user frames {1} to {2} of {0}".format(video.slug, segment.start, segment.stop)) return {"start": segment.start, "stop": segment.stop, "slug": video.slug, "width": video.width, "height": video.height, "skip": video.skip, "perobject": video.perobjectbonus, "completion": video.completionbonus, "blowradius": video.blowradius, "jobid": job.id, "training": int(training), "labels": labels, "attributes": attributes, "roles": roles, "predicates": predicates}
def getsentenceannotationsforjob(id): job = session.query(Job).get(id) results = [] for s in job.sentences: annotations = [(a.frame, a.value) for a in s.annotations] results.append({ 'sentence': s.text, 'annotations': annotations, }) return results
def savedonationstatus(hitid, donation): """ Saves the donation statistics """ hit = session.query(models.HIT).filter(models.HIT.hitid == hitid).one() hit.opt2donate = float(donation) hit.opt2donate = min(max(hit.opt2donate, 0), 1) session.add(hit) session.commit()
def readpath(label, userid, done, track, attributes): path = Path() path.label = session.query(Label).get(label) path.done = int(done) path.userid = int(userid) logger.debug("Received a {0} track".format(path.label.text)) visible = False for frame, userbox in track.items(): box = Box(path = path) #box.xtl = max(int(userbox[0]), 0) #box.ytl = max(int(userbox[1]), 0) #box.xbr = max(int(userbox[2]), 0) #box.ybr = max(int(userbox[3]), 0) box.xtl = int(userbox[0]) box.ytl = int(userbox[1]) box.xbr = int(userbox[2]) box.ybr = int(userbox[3]) box.occluded = int(userbox[4]) box.outside = int(userbox[5]) box.generated = int(userbox[6]) box.frame = int(frame) if not box.outside: visible = True logger.debug("Received box {0}".format(str(box.getbox()))) if not visible: logger.warning("Received empty path! Skipping") return for attributeid, timeline in attributes.items(): attribute = session.query(Attribute).get(attributeid) for frame, value in timeline.items(): aa = AttributeAnnotation() aa.attribute = attribute aa.frame = frame aa.value = value path.attributes.append(aa) return path
def savejob(id, tracks): job = session.query(Job).get(id) for path in job.paths: session.delete(path) session.commit() for path in readpaths(tracks): job.paths.append(path) session.add(job) session.commit()
def saveeventlog(hitid, events): """ Records the event log to database. """ hit = session.query(models.HIT).filter(models.HIT.hitid == hitid).one() for timestamp, domain, message in events: timestamp = datetime.fromtimestamp(int(timestamp) / 1000) event = EventLog(hit=hit, domain=domain, message=message, timestamp=timestamp) session.add(event) session.commit()
def trackfull(id, tracker): job = session.query(Job).get(id) segment = job.segment video = segment.video tracks = tracking.runfulltracker(tracker, segment.start, segment.stop, video.location) allpaths = [convert_track_to_path(segment.start, track, job) for track in tracks] allattrs = [[(x.attributeid, x.frame, x.value) for x in path.attributes] for path in allpaths] return [{ "label": 0, "boxes":[tuple(x) for x in path.getboxes()], "attributes":attrs, } for path, attrs in zip(allpaths, allattrs)]
def readpredicates(predicates, paths): predicateInstances = [] logger.debug("Reading {0} total predicate instances".format(len(predicates))) for p in predicates: pi = PredicateInstance() pi.predicate = session.query(Predicate).get(int(p['predicate'])) for pathid in p['annotations'].keys(): path = paths[int(pathid)] for frame, roleid, value in p['annotations'][pathid]: pa = PredicateAnnotation() pa.predicateinstance = pi pa.path = path pa.role = session.query(Role).get(roleid) pa.frame = frame pa.value = value predicateInstances.append(pi) return predicateInstances
def respawnjob(id): job = session.query(Job).get(id) replacement = job.markastraining() job.worker.verified = True session.add(job) session.add(replacement) session.commit() replacement.publish() session.add(replacement) session.commit()
def serverstatus(self, session): available = session.query(HIT).filter(HIT.ready == True).count() published = session.query(HIT).filter(HIT.published == True).count() completed = session.query(HIT).filter(HIT.completed == True).count() compensated = session.query(HIT).filter(HIT.compensated == True).count() remaining = published - completed print "Status:" print " Available: {0}".format(available) print " Published: {0}".format(published) print " Completed: {0}".format(completed) print " Compensated: {0}".format(compensated) print " Remaining: {0}".format(remaining) print "" if remaining > 0: print "Server is ONLINE and accepting work!" else: if compensated == completed: print "Server is offline." else: print "Server is offline, but some workers are not compensated."
def savehomography(slug, homography): query = session.query(Video).filter(Video.slug == slug) if query.count() != 1: raise ValueError("Invalid video slug") video = query[0] savedir = video.homographylocation if savedir is None: savedir = makehomographydir(video) savelocation = os.path.join(savedir, "homography.npy") np.save(savelocation, np.array(homography)) session.add(video) session.commit()
def getdata(self, args): video = session.query(Video).filter(Video.slug == args.slug) if video.count() == 0: print "Video {0} does not exist!".format(args.slug) raise SystemExit() video = video.one() mergemethod = merge.getpercentoverlap(args.groundplane) if args.merge_method == "id": mergemethod = merge.userid workers = None if args.worker: workers = set(args.worker) return video, dumptools.getdata(video, args.merge, mergemethod, args.merge_threshold, workers, args.groundplane)
def resetdatabase(self): try: hits = session.query(HIT) hits = hits.filter(HIT.published == True) hits = hits.filter(HIT.completed == False) for hit in hits: print "Disabled HIT {0}".format(hit.hitid) hit.disable() except: print "Failed disabling online HITs. Disable manually with:" print "\timport config, turkic.api" print "\tturkic.api.server.purge()" database.reinstall() print "Database reset!"
def __call__(self, args): video = session.query(Video).filter(Video.slug == args.slug) if video.count() == 0: print "Video {0} does not exist!".format(args.slug) raise SystemExit() video = video.one() print "Parsing text data" data = {} if args.json: data = self.getdatajson(args.labelfile) else: data = self.getdatatext(args.labelfile, video.totalframes) scale = args.scale if args.dimensions or args.original_video or args.original_frame: print "Computing scale" if args.original_video: w, h = ffmpeg.extract(args.original_video).next().size elif args.original_frame: w, h = Image.open(args.original_frame).size else: w, h = args.dimensions.split("x") w = float(w) h = float(h) s = float(video.width) / w if s * h > video.height: s = float(video.height) / h scale = s print "Scale = {0}".format(scale) segmentcount = 1 for segment in video.segments: print "Segment {0} of {1}".format(segmentcount, len(video.segments)) segmentcount += 1 for job in segment.jobs: for boxid in data: label = data[boxid]['label'] boxes = data[boxid]['boxes'] query = session.query(Label).filter( Label.videoid == video.id).filter(Label.text == label) if query.count() == 0: continue label = query.one() newpath = Path(label=label) visible = False for frame, boxdata in boxes.iteritems(): frame = int(frame) if frame < segment.start or segment.stop <= frame or ( frame % video.blowradius != 0): continue newbox = Box(path=newpath) #newbox.xtl = max(boxdata['xtl'], 0) #newbox.ytl = max(boxdata['ytl'], 0) #newbox.xbr = max(boxdata['xbr'], 0) #newbox.ybr = max(boxdata['ybr'], 0) newbox.xtl = boxdata['xtl'] newbox.ytl = boxdata['ytl'] newbox.xbr = boxdata['xbr'] newbox.ybr = boxdata['ybr'] newbox.occluded = boxdata['occluded'] newbox.outside = boxdata['outside'] newbox.generated = boxdata['generated'] newbox.frame = frame scalebox = newbox.getbox() scalebox = scalebox.transform(scale) newbox.xtl = scalebox.xtl newbox.ytl = scalebox.ytl newbox.xbr = scalebox.xbr newbox.ybr = scalebox.ybr if not newbox.outside: visible = True if visible: job.paths.append(newpath) session.add(job) session.commit()
def validatejob(id, tracks): job = session.query(Job).get(id) paths = readpaths(tracks) return job.trainingjob.validator(paths, job.trainingjob.paths)
def __call__(self, args, group): print "Checking integrity..." # read first frame to get sizes path = Video.getframepath(0, args.location) try: im = Image.open(path) except IOError: print "Cannot read {0}".format(path) return width, height = im.size print "Searching for last frame..." # search for last frame toplevel = max(int(x) for x in os.listdir(args.location)) secondlevel = max( int(x) for x in os.listdir("{0}/{1}".format(args.location, toplevel))) maxframes = max( int(os.path.splitext(x)[0]) for x in os.listdir("{0}/{1}/{2}".format(args.location, toplevel, secondlevel))) + 1 print "Found {0} frames.".format(maxframes) # can we read the last frame? path = Video.getframepath(maxframes - 1, args.location) try: im = Image.open(path) except IOError: print "Cannot read {0}".format(path) return # check last frame sizes if im.size[0] != width and im.size[1] != height: print "First frame dimensions differs from last frame" return if session.query(Video).filter(Video.slug == args.slug).count(): print "Video {0} already exists!".format(args.slug) return if args.train_with: if args.for_training: print "A training video cannot require training" return print "Looking for training video..." trainer = session.query(Video) trainer = trainer.filter(Video.slug == args.train_with) if not trainer.count(): print("Training video {0} does not exist!".format( args.train_with)) return trainer = trainer.one() else: trainer = None # create video video = Video(slug=args.slug, location=os.path.realpath(args.location), width=width, height=height, totalframes=maxframes, skip=args.skip, perobjectbonus=args.per_object_bonus, completionbonus=args.completion_bonus, trainwith=trainer, isfortraining=args.for_training, blowradius=args.blow_radius) if args.for_training: video.trainvalidator = qa.tolerable(args.for_training_overlap, args.for_training_tolerance, args.for_training_mistakes) print "Training validator is {0}".format(video.trainvalidator) session.add(video) print "Binding labels and attributes..." # create labels and attributes labelcache = {} attributecache = {} lastlabel = None for labeltext in args.labels: if labeltext[0] == "~": if lastlabel is None: print "Cannot assign an attribute without a label!" return labeltext = labeltext[1:] attribute = Attribute(text=labeltext) session.add(attribute) lastlabel.attributes.append(attribute) attributecache[labeltext] = attribute else: label = Label(text=labeltext) session.add(label) video.labels.append(label) labelcache[labeltext] = label lastlabel = label print "Creating symbolic link..." symlink = "public/frames/{0}".format(video.slug) try: os.remove(symlink) except: pass os.symlink(video.location, symlink) print "Creating segments..." # create shots and jobs if args.for_training: segment = Segment(video=video) if args.for_training_start: segment.start = args.for_training_start if segment.start < 0: segment.start = 0 else: segment.start = 0 if args.for_training_stop: segment.stop = args.for_training_stop if segment.stop > video.totalframes - 1: segment.stop = video.totalframes - 1 else: segment.stop = video.totalframes - 1 job = Job(segment=segment, group=group, ready=False) session.add(segment) session.add(job) elif args.use_frames: with open(args.use_frames) as useframes: for line in useframes: ustart, ustop = line.split() ustart, ustop = int(ustart), int(ustop) validlength = float(ustop - ustart) numsegments = math.ceil(validlength / args.length) segmentlength = math.ceil(validlength / numsegments) for start in range(ustart, ustop, int(segmentlength)): stop = min(start + segmentlength + args.overlap + 1, ustop) segment = Segment(start=start, stop=stop, video=video) job = Job(segment=segment, group=group) session.add(segment) session.add(job) else: startframe = args.start_frame stopframe = args.stop_frame if not stopframe: stopframe = video.totalframes - 1 for start in range(startframe, stopframe, args.length): stop = min(start + args.length + args.overlap + 1, stopframe) segment = Segment(start=start, stop=stop, video=video) job = Job(segment=segment, group=group) session.add(segment) session.add(job) if args.per_object_bonus: group.schedules.append( PerObjectBonus(amount=args.per_object_bonus)) if args.completion_bonus: group.schedules.append( CompletionBonus(amount=args.completion_bonus)) session.add(group) if args.for_training and args.for_training_data: print("Loading training ground truth annotations from {0}".format( args.for_training_data)) with open(args.for_training_data, "r") as file: pathcache = {} for line in file: (id, xtl, ytl, xbr, ybr, frame, outside, occluded, generated, label) = line.split(" ") if int(generated): continue if id not in pathcache: print "Imported new path {0}".format(id) label = labelcache[label.strip()[1:-1]] pathcache[id] = Path(job=job, label=label) box = Box(path=pathcache[id]) box.xtl = int(xtl) box.ytl = int(ytl) box.xbr = int(xbr) box.ybr = int(ybr) box.frame = int(frame) box.outside = int(outside) box.occluded = int(occluded) pathcache[id].boxes.append(box) session.commit() if args.for_training: if args.for_training and args.for_training_data: print "Video and ground truth loaded." else: print "Video loaded and ready for ground truth:" print "" print "\t{0}".format(job.offlineurl(config.localhost)) print "" print "Visit this URL to provide training with ground truth." else: print "Video loaded and ready for publication."
def __call__(self, args): try: os.makedirs(args.directory) except: pass since = None if args.since: since = parsedatetime.Calendar().parse(args.since) since = time.mktime(since[0]) since = datetime.datetime.fromtimestamp(since) if args.labels: font = ImageFont.truetype("arial.ttf", 14) else: font = None workers = session.query(turkic.models.Worker) for worker in workers: print "Sampling worker {0}".format(worker.id) jobs = session.query(Job) jobs = jobs.filter(Job.worker == worker) jobs = jobs.join(Segment) jobs = jobs.join(Video) jobs = jobs.filter(Video.isfortraining == False) if since: jobs = jobs.filter(turkic.models.HIT.timeonserver >= since) jobs = jobs.order_by(sqlalchemy.func.rand()) jobs = jobs.limit(args.number) for job in jobs: print "Visualizing HIT {0}".format(job.hitid) paths = [ x.getboxes(interpolate=True, bind=True, label=True) for x in job.paths ] if args.frames > job.segment.stop - job.segment.start: frames = range(job.segment.start, job.segment.stop + 1) else: frames = random.sample( xrange(job.segment.start, job.segment.stop + 1), args.frames) size = math.sqrt(len(frames)) video = job.segment.video bannersize = (video.width * int(math.floor(size)), video.height * int(math.ceil(size))) image = Image.new(video[0].mode, bannersize) size = int(math.floor(size)) offset = (0, 0) horcount = 0 paths = vision.visualize.highlight_paths(video, paths, font=font) for frame, framenum in paths: if framenum in frames: image.paste(frame, offset) horcount += 1 if horcount >= size: offset = (0, offset[1] + video.height) horcount = 0 else: offset = (offset[0] + video.width, offset[1]) image.save("{0}/{1}-{2}.jpg".format(args.directory, worker.id, job.hitid))
def __call__(self, args): hits = session.query(HIT).filter(HIT.donatedamount > 0) for hit in hits: print hit.workerid, hit.timeonserver, hit.donatedamount
def getjob(id): # the database is called session job = session.query(Job).get(id) activities = [x.text for x in job.activities] return {"activities": activities}
def addtracks( id, base_path='/media/leo/24DDF7874B2D4C94/FLASH_ALPHA', fname="/media/leo/24DDF7874B2D4C94/FLASH_ALPHA/401/test/401/mse0.1_track0.01_output.txt", resize=True): ''' Function for adding pre-existing tracks to the database Inputs :fname: string, path to track file Returns None ''' job = session.query(Job).get(id) logger.debug(job) labels = session.query(Label).all() slug = session.query(Video).get(id) code = slug[0:3] path = os.path.join(base_path, slug, "test", slug) for f in os.listdir(path): if "output" in f: fname = f fname = os.path.join(path, fname) # Print all labels print("There are %d labels in the track" % (len(labels))) for l in labels: print("Label id %d corresponds to %s" % (int(l.id), l.text)) # Add labels face_label = Label(text="Face") tv_label = Label(text="TV") #session.add(face_label) #session.add(tv_label) place = Attribute(text="Placeholder") gaze = Attribute(text="Gaze") no_gaze = Attribute(text="No-Gaze") uncertain = Attribute(text="Uncertain") out = Attribute(text="Out-of-Frame") attribs = [place, gaze, no_gaze, uncertain, out] for a in attribs: face_label.attributes.append(a) tv_label.attributes.append(Attribute(text="On")) if job.paths == None or len(job.paths) == 0: print("Adding tracks from file %s" % (fname)) else: print("Tracks already exist for this segment, no need to load!") print(len(job.paths)) print([j.id for j in job.paths]) for path in job.paths: session.delete(path) session.commit() #return info = np.loadtxt(fname, dtype=int) """ info[:,0] ==> frame number info[:,1] ==> left info[:,2] ==> top info[:,3] ==> right info[:,4] ==> bottom info[:,5] ==> faceID info[:,6] ==> pause flag """ """ Even with an actual label, it still says the label is none in readpath """ face_label = session.query(Label).all()[0] print(face_label.text) print(face_label.id) num_faces = np.max(info[:, 5]) scale = 1 if resize: scale = .375 print("There are %d unique faces detected." % (num_faces)) thresh = 10 for newID in range(num_faces): print(newID) if newID == thresh: break path = Path(job=job, label=session.query(Label).get(82)) # uncomment below only if necessary #path.label = 100 # label is some constant integer value #path.label = Label(text = "Face") path.userid = newID # userid is the label ID lines = info[np.where(info[:, 5] == newID)[0], :] boxes = [] # need to scale within range 1920x1080 -> 720x405 # # need to add attributes # need to add include callback? # need to include that these are of class Face for i in range(lines.shape[0]): box = Box(path=path) box.xtl = max(int(lines[i, 1]), 0) * scale box.ytl = max(int(lines[i, 2]), 0) * scale box.xbr = max(int(lines[i, 3]), 0) * scale box.ybr = max(int(lines[i, 4]), 0) * scale box.occluded = int(0) box.outside = int(0) box.generated = int(1) box.frame = int(lines[i, 0]) logger.debug("Received box {0}".format(str(box.getbox()))) """ # TODO: May need to include this if attributes load funny attributes = {} for label in video.labels: attributes[label.id] = dict((a.id, a.text) for a in label.attributes) for attributeid, timeline in attributes.items(): attribute = session.query(Attribute).get(attributeid) for frame, value in timeline.items(): aa = AttributeAnnotation() aa.attribute = attribute aa.frame = frame aa.value = value path.attributes.append(aa) """ job.paths.append(path) #print("Appended path %d"%(newID)) #for p in job.paths: # session.delete(p) session.add(job) session.commit() return min(thresh, num_faces)
def savejob(id, tracks): job = session.query(Job).get(id) # Update current job for path in job.paths: session.delete(path) session.commit() for path in readpaths(tracks): logger.info(path) job.paths.append(path) session.add(job) session.commit() # Update neigboring segments video = job.segment.video prevseg, nextseg = video.getsegmentneighbors(job.segment) mergesegments = [ s for s in [prevseg, job.segment, nextseg] if s is not None ] updatesegments = [s for s in [prevseg, nextseg] if s is not None] # Create list of merged boxes with given label and userid labeledboxes = [] for boxes, paths in merge.merge(mergesegments, threshold=0.8): path = paths[0] for p in paths: if p.job.segmentid == job.segmentid: path = p break labeledboxes.append((path.label, path.userid, boxes)) # Remove paths in neighboring segments for segment in updatesegments: for path in segment.paths: session.delete(path) session.commit() # Add merged paths to neighboring segments for label, userid, boxes in labeledboxes: frames = sorted([box.frame for box in boxes]) for segment in updatesegments: for job in segment.jobs: path = Path() path.label = label path.userid = userid addedbox = False for box in boxes: if segment.start <= box.frame <= segment.stop: newbox = Box(path=path) newbox.frombox(box) if not box.lost: addedbox = True # Some segments and paths might not overlap if addedbox: # Add in first frame if it's missing if (frames[0] < segment.start < frames[-1] and segment.start not in frames): newbox = Box(path=path) newbox.generated = False newbox.frombox([ box for box in LinearFill(boxes) if box.frame == segment.start ][0]) job.paths.append(path) session.add(job) session.commit()
def __call__(self, args): if args.load: for data in pickle.load(open(args.load)): worker = Worker.lookup(data[0]) worker.numsubmitted = data[1] worker.numacceptances = data[2] worker.numrejections = data[3] worker.blocked = data[4] worker.donatedamount = data[5] worker.bonusamount = data[6] worker.verified = data[7] print "Loaded {0}".format(worker.id) session.add(worker) session.commit() elif args.dump: data = [] for worker in session.query(Worker): data.append((worker.id, worker.numsubmitted, worker.numacceptances, worker.numrejections, worker.blocked, worker.donatedamount, worker.bonusamount, worker.verified)) print "Dumped {0}".format(worker.id) pickle.dump(data, open(args.dump, "w")) elif args.block: worker = Worker.lookup(args.block) worker.block("Poor quality work.") session.add(worker) session.commit() print "Blocked {0}".format(args.block) elif args.unblock: worker = Worker.lookup(args.unblock) worker.unblock("Continue working.") session.add(worker) session.commit() print "Unblocked {0}".format(args.unblock) elif args.search: query = session.query(Worker) query = query.filter(Worker.id.like(args.search + "%")) if query.count(): print "Matches:" for worker in query: print worker.id else: print "No matches." elif args.summary: query = session.query(Worker) query = session.filter(Worker.id == args.summary) if query.count(): worker = query.one() print "Submitted: {0}".format(worker.numsubmitted) print "Accepted: {0}".format(worker.numacceptances) print "Rejected: {0}".format(worker.numrejections) print "Bonuses: {0}".format(worker.bonusamount) print "Donated: {0}".format(worker.donatedamount) print "Verified: {0}".format(worker.verified) print "Blocked: {0}".format(worker.blocked) else: print "No matches." else: workers = session.query(Worker) workers = workers.order_by(Worker.numacceptances) for worker in workers: extra = "" if worker.blocked: extra = "BLOCKED" if worker.verified: extra = extra + " VERIFIED" extra = extra.strip() data = (worker.id, worker.numsubmitted, worker.numacceptances, worker.numrejections, extra) print "{0:<15} {1:>5} jobs {2:>5} acc {3:>5} rej {4}".format(*data)
def __call__(self, args, group): print "Checking integrity..." # read first frame to get sizes path = Video.getframepath(0, args.location) try: im = Image.open(path) except IOError: print "Cannot read {0}".format(path) return width, height = im.size print "Searching for last frame..." # search for last frame toplevel = max(int(x) for x in os.listdir(args.location)) secondlevel = max( int(x) for x in os.listdir("{0}/{1}".format(args.location, toplevel))) maxframes = max( int(os.path.splitext(x)[0]) for x in os.listdir("{0}/{1}/{2}".format(args.location, toplevel, secondlevel))) + 1 print "Found {0} frames.".format(maxframes) # can we read the last frame? path = Video.getframepath(maxframes - 1, args.location) try: im = Image.open(path) except IOError: print "Cannot read {0}".format(path) return # check last frame sizes if im.size[0] != width and im.size[1] != height: print "First frame dimensions differs from last frame" return if session.query(Video).filter(Video.slug == args.slug).count(): print "Video {0} already exists!".format(args.slug) return if args.train_with: if args.for_training: print "A training video cannot require training" return print "Looking for training video..." trainer = session.query(Video) trainer = trainer.filter(Video.slug == args.train_with) if not trainer.count(): print("Training video {0} does not exist!".format( args.train_with)) return trainer = trainer.one() else: trainer = None # create video video = Video(slug=args.slug, location=os.path.realpath(args.location), width=width, height=height, totalframes=maxframes, skip=args.skip, perobjectbonus=args.per_object_bonus, completionbonus=args.completion_bonus, trainwith=trainer, isfortraining=args.for_training, blowradius=args.blow_radius) if args.for_training: video.trainvalidator = qa.tolerable(args.for_training_overlap, args.for_training_tolerance, args.for_training_mistakes) print "Training validator is {0}".format(video.trainvalidator) session.add(video) print "Binding labels and attributes..." # create labels and attributes labelcache = {} attributecache = {} lastlabel = None for labeltext in args.labels: if labeltext[0] == "~": if lastlabel is None: print "Cannot assign an attribute without a label!" return labeltext = labeltext[1:] attribute = Attribute(text=labeltext) session.add(attribute) lastlabel.attributes.append(attribute) attributecache[labeltext] = attribute else: label = Label(text=labeltext) session.add(label) video.labels.append(label) labelcache[labeltext] = label lastlabel = label print "Creating symbolic link..." symlink = "public/frames/{0}".format(video.slug) try: os.remove(symlink) except: pass os.symlink(video.location, symlink) print "Creating segments..." # create shots and jobs job_list = [] segment_list = [] if args.for_training: segment = Segment(video=video) if args.for_training_start: segment.start = args.for_training_start if segment.start < 0: segment.start = 0 else: segment.start = 0 if args.for_training_stop: segment.stop = args.for_training_stop if segment.stop > video.totalframes - 1: segment.stop = video.totalframes - 1 else: segment.stop = video.totalframes - 1 job = Job(segment=segment, group=group, ready=False) job_list.append(job) segment_list.append(segment) session.add(segment) session.add(job) elif args.use_frames: with open(args.use_frames) as useframes: for line in useframes: ustart, ustop = line.split() ustart, ustop = int(ustart), int(ustop) validlength = float(ustop - ustart) numsegments = math.ceil(validlength / args.length) segmentlength = math.ceil(validlength / numsegments) for start in range(ustart, ustop, int(segmentlength)): stop = min(start + segmentlength + args.overlap + 1, ustop) segment = Segment(start=start, stop=stop, video=video) job = Job(segment=segment, group=group) job_list.append(job) segment_list.append(segment) session.add(segment) session.add(job) else: startframe = args.start_frame stopframe = args.stop_frame if not stopframe: stopframe = video.totalframes - 1 for start in range(startframe, stopframe, args.length): stop = min(start + args.length + args.overlap + 1, stopframe) segment = Segment(start=start, stop=stop, video=video) job = Job(segment=segment, group=group) job_list.append(job) segment_list.append(segment) session.add(segment) session.add(job) if args.per_object_bonus: group.schedules.append( PerObjectBonus(amount=args.per_object_bonus)) if args.completion_bonus: group.schedules.append( CompletionBonus(amount=args.completion_bonus)) session.add(group) if args.for_training and args.for_training_data: print("Loading training ground truth annotations from {0}".format( args.for_training_data)) with open(args.for_training_data, "r") as file: pathcache = {} for line in file: (id, xtl, ytl, xbr, ybr, frame, outside, occluded, generated, label) = line.split(" ") if int(generated): continue if id not in pathcache: print "Imported new path {0}".format(id) label = labelcache[label.strip()[1:-1]] pathcache[id] = Path(job=job, label=label) box = Box(path=pathcache[id]) box.xtl = int(xtl) box.ytl = int(ytl) box.xbr = int(xbr) box.ybr = int(ybr) box.frame = int(frame) box.outside = int(outside) box.occluded = int(occluded) pathcache[id].boxes.append(box) session.commit() # Save the annotated file in the database if args.annot is not None: with open(args.annot, 'r') as annot_file: annotated_tracks = json.load(annot_file) # Scale annotations if annot-video-height is given as argument annot_scalar = 1.0 if args.annot_video_height is not None: annot_scalar = video.height / float( args.annot_video_height) * 1.5 print('Scale factor: {}'.format(annot_scalar)) # Scale bboxes and convert labels converted_tracks = [] for a_labels, a_tracks, a_attribs in annotated_tracks: scaled_a_tracks = {} keep_tracks = a_tracks.keys() # Blow-radius for annotations if args.annot_blow_radius > 0: keep_tracks = sorted(map(int, keep_tracks)) prev_frame_id = keep_tracks[0] blown_tracks = [keep_tracks[0]] for frame_id in keep_tracks: if frame_id > prev_frame_id + args.annot_blow_radius: prev_frame_id = frame_id blown_tracks.append(frame_id) keep_tracks = map(unicode, blown_tracks) # Conversion for track_id, track_data in a_tracks.iteritems(): if track_id in keep_tracks: scaled_track = [ x * annot_scalar for x in track_data[:4] ] scaled_track.extend(track_data[4:]) scaled_a_tracks[track_id] = scaled_track converted_tracks.append( [labelcache[a_labels].id, scaled_a_tracks, a_attribs]) for j, s in zip(job_list, segment_list): job_data = [] for a_labels, a_tracks, a_attribs in converted_tracks: # Sort by track number sorted_a_tracks = natural_sort(a_tracks.keys()) sorted_a_attribs = natural_sort(a_attribs.keys()) job_tracks = {} job_attribs = {k.id: {} for k in attributecache.values()} for track_id in sorted_a_tracks: track_data = a_tracks[track_id] track_id = int(track_id) if s.start <= track_id <= s.stop: job_tracks[track_id] = track_data if track_id > s.stop: break for track_id in sorted_a_attribs: attrib_data = a_attribs[track_id] track_id = int(track_id) if s.start <= track_id <= s.stop: for k in job_attribs.keys(): job_attribs[k][track_id] = 0 job_attribs[ attributecache[attrib_data].id][track_id] = 1 if track_id > s.stop: break job_data.append([a_labels, job_tracks, job_attribs]) savejob(j.id, job_data) if args.for_training: if args.for_training and args.for_training_data: print "Video and ground truth loaded." else: print "Video loaded and ready for ground truth:" print "" print "\t{0}".format(job.offlineurl(config.localhost)) print "" print "Visit this URL to provide training with ground truth." else: print "Video loaded and ready for publication."