Created
January 10, 2016 18:16
-
-
Save kevinhughes27/93f639e421cfc75d7678 to your computer and use it in GitHub Desktop.
the script I used to average every episode of That 70's Show into a singe video
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# first mount the samba share (use the gui) | |
# then link the mounted smb share somewhere more convientent | |
# sudo ln -s /run/user/1000/gvfs/smb-share:server=dlink-71f6dd,share=volume_1-1 /mnt/network | |
# then run as usual | |
# python avgEpisode.py /mnt/network/TV\ Shows/That\ \'70s\ Show/ output.avi | |
import os | |
import sys | |
import cv2 | |
import numpy as np | |
#from multiprocessing.dummy import Pool | |
import time | |
from tqdm import * | |
import pdb | |
CODEC = cv2.cv.CV_FOURCC('D','I','V','X') | |
class AvgEpisode(object): | |
def __init__(self, inputPath, outputPath): | |
self.inputPath = inputPath | |
self.outputPath = outputPath | |
# find all the files | |
self.files = self.all_files(self.inputPath) | |
# open all the files | |
self.episodes = [Episode(f, start_at=idx*30) for idx, f in enumerate(self.files)] | |
# set some basic parameters | |
self.width = 640 | |
self.height = 480 | |
self.fps = 24 | |
self.length = self.episodes[0].length() | |
# create the output video | |
self.output = cv2.VideoWriter(self.outputPath,CODEC,self.fps,(self.width, self.height)) | |
def start(self): | |
# create a progress bar | |
t = 1 | |
for i in tqdm(range(self.length)): | |
# build the average frame | |
self.build_avg_frame() | |
# write to output | |
self.output.write(self.avg_frame) | |
# show the image | |
cv2.imshow("avg_frame", self.avg_frame) | |
key = 0xFF & cv2.waitKey(1) | |
if(key == 27): break | |
# inc t for progress bar | |
t = t + 1 | |
self.finish() | |
def finish(self): | |
# close output | |
self.output.release() | |
# close videos | |
for episode in self.episodes: | |
episode.release() | |
def all_files(self, path): | |
all_files = [] | |
extensions = tuple(['jpg', 'db', 'txt']) | |
if os.path.exists(path): | |
for dirpath, dirnames, files in os.walk(path): | |
for name in files: | |
f = os.path.join(dirpath, name) | |
# reject some extensions | |
if not f.endswith(extensions): | |
all_files.append(f) | |
#if(len(all_files) > 24): return all_files | |
#num_files = len(all_files) | |
#print 'found', num_files, 'files' | |
return all_files | |
else: | |
print path, 'does not exist' | |
def build_avg_frame(self): | |
# init the average frame as zeros | |
self.avg_frame = np.zeros((self.height, self.width, 3), dtype=np.float64) | |
# add all the frames together | |
self.frames_read = 0 | |
for idx, episode in enumerate(self.episodes): | |
frame = episode.read_frame() | |
if(frame == None): continue | |
self.add_frame(frame, episode.filename) | |
# pool_size = 8 | |
# pool = Pool(pool_size) | |
# | |
# for episodes in batch(self.episodes, pool_size): | |
# frames = pool.map(thread_read_frame, episodes) | |
# | |
# # join processes and add the frame | |
# for idx, frame in enumerate(frames): | |
# if(frame == None): continue | |
# self.add_frame(frame, episodes[idx].filename) | |
# divide by the number of frames_read to average | |
self.avg_frame = np.divide(self.avg_frame, self.frames_read) | |
# normalize the avg frame | |
self.avg_frame = cv2.normalize(self.avg_frame, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX).astype(np.uint8) | |
def add_frame(self, frame, file_name): | |
try: | |
frame = frame.astype(np.float64) | |
frame = cv2.resize(frame, (self.width, self.height)) | |
self.avg_frame = np.add(self.avg_frame, frame) | |
self.frames_read += 1 | |
except: | |
print file_name, ' add failed', sys.exc_info()[0] | |
class Episode: | |
def __init__(self, filename, start_at=0): | |
self.filename = filename | |
self.cap = cv2.VideoCapture(self.filename) | |
self.start_at = start_at | |
self.frame_count = 0 | |
self.finished = False | |
def length(self): | |
return int(self.cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)) | |
def read_frame(self): | |
if(self.finished == True): return | |
try: | |
frame = self._read() | |
self.frame_count += 1 | |
if(self.frame_count < self.start_at): return | |
return frame | |
except: | |
print self.filename, '.read() crashed', sys.exc_info()[0] | |
return | |
def _read(self): | |
flag, frame = self.cap.read() | |
if(flag == False): | |
print self.filename, '.read() failed' | |
self.finished = True | |
return | |
return frame | |
def release(self): | |
self.cap.release() | |
# # iterate in batches (for passing to threads) | |
# def batch(iterable, n=1): | |
# l = len(iterable) | |
# for ndx in range(0, l, n): | |
# yield iterable[ndx:min(ndx + n, l)] | |
# | |
# | |
# # read frame from a thread | |
# def thread_read_frame(episode): | |
# return episode.read_frame() | |
if __name__ == "__main__": | |
inputPath = sys.argv[1] | |
outputPath = sys.argv[2] | |
AvgEpisode(inputPath, outputPath).start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment