def main(): segment_database = SegmentDatabase() label = 'vertical_oscillation' segments = segment_database.get_with_label(label) print '#segments for label %s: %d' % (label, len(segments)) tp = 0 fp = 0 segment_count = 0 for segment in segments: try: segment_count += 1 filename = segment.get('ytid') start_frame, end_frame = segment.get('s') # print 'showing %s from %d to %d' % (filename, start_frame, end_frame) print 'segment length: %d' % (end_frame-start_frame) result, num_frames = show_video(filename, start_frame, end_frame, label) if result: tp += num_frames else: fp += num_frames print '%2.2f%% done' % (100.0 * segment_count / float(len(segments))) except Exception as e: print e print 'Label: %s' % label print 'True positives: %d' % tp print 'False positives: %d' % fp
def __init__(self, name, ingredients, datasets=[]): self.name = name self.ingredients = ingredients self.segment_database = SegmentDatabase() self.ignore_list = [] self.frames = [] self.result = dict(segments=[]) self.datasets = datasets if datasets: self.segment_database.trim_to_datasets(datasets) self.filename = filename_generator(path='./data/out/')
class Recipe: def __init__(self, name, ingredients, datasets=[]): self.name = name self.ingredients = ingredients self.segment_database = SegmentDatabase() self.ignore_list = [] self.frames = [] self.result = dict(segments=[]) self.datasets = datasets if datasets: self.segment_database.trim_to_datasets(datasets) self.filename = filename_generator(path='./data/out/') def dump_to_json(self): filename = '%s.json' % self.filename dump = dict( ingredients=[ingredient.__to_dict__() for ingredient in self.ingredients], result=self.result, filename='%s.avi' % self.filename, datasets=self.datasets, ) f = open(filename, 'w') f.write(json.dumps(dump)) f.close() def get_frames(self, segment, captions=''): # print 'segment: ', segment start, end = segment.get('start'), segment.get('end') ytid = segment.get('ytid') cap = get_capture(ytid) fps = get_fps(cap) assert(fps == 24) captions += ' :: %s' % (self.name) frames = [] if cap.set(cv.CV_CAP_PROP_POS_FRAMES, start): length = end - start print 'grabbing %d frames' % length for i in range(length): ret, frame = cap.read() if ret: # draw_str(frame, (20, 20), '%s: %s' % (ytid, captions)) frames.append(frame) else: # problem is that setting a given frame in the video capture may actually jump forward to the closest keyframe # because of limitations with the video compression algorithm. for short clips this is likely to occur print 'ERROR: segment read cut short at index %d for segment %s' % (i, json.dumps(segment)) break # raise Exception('no more frames, index = %d, segment: %s' % (i, json.dumps(segment))) else: raise Exception('unable to set seek position in video capture') print 'returning %d frames' % len(frames) return frames def bake(self): segment_database = self.segment_database frames = [] for ingredient in self.ingredients: labels, excl_labels, min_span, max_span = ingredient.labels, [], ingredient.min_span, ingredient.max_span print 'labels=%s, excl_labels=%s, min_span=%d, max_span=%d' % (labels, excl_labels, min_span, max_span) candidate_factory = CandidateFactory(segment_database) candidates = candidate_factory.get_candidates(labels) # print '#immediate candidates: %d' % len(candidates) ytids = candidate_factory.get_ytids(20) query = dict( labels=labels, required=ingredient.required_labels, forbidden=ingredient.forbidden_labels, ) interval = ingredient.interval spanAlpha = ingredient.span_alpha minSpan = ingredient.min_span maxSpan = ingredient.max_span ignore_list = self.ignore_list candidates = sortCandidates(ytids=ytids, query=query, minSpan=minSpan, maxSpan=maxSpan, interval=interval, spanAlpha=spanAlpha, segment_database=segment_database, ignoreList=ignore_list) # print '#candidates: %d' % len(candidates) if candidates: # filter out invalid candidates candidates = filter(lambda x: x.get('score') >= 0, candidates) # compute the sum-square of scores score_sum = sum([candidate.get('score')**2 for candidate in candidates]) if candidates: # if there are any valid candidates left new_candidates = [] # we want the multiplier to be atleast 1e5 min_score = candidates[-1].get('score') if min_score: multiplier = min(1e5, max(1e5, 1 / (min_score / score_sum))) else: multiplier = 1e5 # print 'multiplier: ' , multiplier for candidate in candidates: # we want atleast 1 occurence probability_score = multiplier * candidate.get('score')**2 / score_sum # print 'probability_score: ', probability_score # print 'rel. rounding error: %2.2f%%' % (100 * abs(probability_score - max(1, int(round(probability_score)))) / probability_score) new_candidates += [candidate] * max(1, int(round(probability_score))) # print len(new_candidates) candidate = random.choice(new_candidates) print candidate start = candidate.get('start') end = candidate.get('end') ytid = candidate.get('ytid') score = candidate.get('score') self.result.get('segments').append(dict(ytid=ytid, start=start, end=end, score=score)) frames += self.get_frames(candidate, captions='score: %2.2f' % (score)) candidate['start'] = max(0, start-10*24) # no consequence if this actually extends the length of the video candidate['end'] = end+10*24 self.ignore_list.append(candidate) else: print '\n******************\nno candidate matching: %s\n******************\n' % ingredient else: print '\n******************\nno candidate matching: %s\n******************\n' % ingredient self.frames = frames self.dump_to_json() return self def write_video(self, height=360, width=640, fps=24, fourcc=cv.CV_FOURCC('D','I','V','3')): filename = '%s.avi' % self.filename frames = self.frames writer = cv.CreateVideoWriter(filename, int(fourcc),fps,(int(width),int(height)),1) for frame in frames: # convert frame to iPlImage frame = cv.fromarray(frame) cv_img = cv.CreateImageHeader((width, height), cv.IPL_DEPTH_8U, 3) cv.SetData(cv_img, frame.tostring(), width * 3) # write image cv.WriteFrame(writer, cv_img) def show_video(self): fps = 24 for frame in self.frames: cv2.imshow('', frame) cv2.waitKey(int(1000/fps))