File size: 4,171 Bytes
96d549d 7406982 96d549d 7406982 96d549d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# -*- coding: utf-8 -*-
import argparse
import cProfile
import logging
import pstats
import cv2
from tqdm import tqdm
import imgcomparison
import mediaoutput
import timeline
from analyzer import Analyzer
from slides import Slide
class InfiniteCounter(object):
"""
InfiniteCounter is a class that represents a counter that will
return the next number indefinitely. When the user calls count()
return the current number. Then it will increment the current
number by the specified steps.
"""
def __init__(self, start=0, step=1):
"""
Default Initializer
:param start: the starting value of the counter
:param step: the amount that should be added at each step
"""
self.current = start
self.step = step
def increment(self):
self.current += self.step
def count(self):
"""
The count method yields the current number and then
increments the current number by the specified step in the
default initializer
:return: the successor from the previous number
"""
while True:
yield self.current
self.current += self.step
class Detector(Analyzer):
def __init__(self, device, outpath=None, fileformat=".png"):
cap = cv2.VideoCapture(sanitize_device(device))
self.sequence = timeline.Timeline(cap)
self.writer = mediaoutput.NullWriter()
if outpath is not None:
self.writer = mediaoutput.TimestampImageWriter(self.sequence.fps, outpath, fileformat)
self.comparator = imgcomparison.AbsDiffHistComparator(0.97)
def detect_slides(self):
frames = []
name_getter = mediaoutput.TimestampImageWriter(self.sequence.fps)
with tqdm(total=self.sequence.len, desc='Detecting Slides: ') as pbar:
for i, frame in self.check_transition():
if frame is not None:
if i % 10 == 0:
logging.info(f"{i} Slides detected")
frames.append(Slide(name_getter.next_name([i]), frame))
pbar.update(1)
self.sequence.release_stream()
return frames
def check_transition(self):
prev_frame = self.sequence.next_frame()
self.writer.write(prev_frame, 0)
yield 0, prev_frame
frame_counter = InfiniteCounter()
for frame_count in frame_counter.count():
frame = self.sequence.next_frame()
if frame is None:
break
elif not self.comparator.are_same(prev_frame, frame):
while True:
if self.comparator.are_same(prev_frame, frame):
break
prev_frame = frame
frame = self.sequence.next_frame()
frame_counter.increment()
self.writer.write(frame, frame_count)
yield frame_count, frame
prev_frame = frame
yield frame_count, None
def analyze(self):
for i, frame in self.check_transition():
time = mediaoutput.TimestampImageWriter(self.sequence.fps).next_name([i])
yield Slide(time, frame)
def sanitize_device(device):
"""returns device id if device can be converted to an integer"""
try:
return int(device)
except (TypeError, ValueError):
return device
if __name__ == "__main__":
Parser = argparse.ArgumentParser(description="Slide Detector")
Parser.add_argument("-d", "--device", help="video device number or path to video file")
Parser.add_argument("-o", "--outpath", help="path to output video file", default="slides/", nargs='?')
Parser.add_argument("-f", "--fileformat", help="file format of the output images e.g. '.jpg'",
default=".jpg", nargs='?')
Args = Parser.parse_args()
def run():
detector = Detector(Args.device, Args.outpath, Args.fileformat)
detector.detect_slides()
cProfile.run('run()', 'profiling_stats.prof')
p = pstats.Stats('profiling_stats.prof')
p.sort_stats('cumulative').print_stats(10)
|