#!/ur/bin/env python # -*- coding: utf-8 -*- from pathlib import Path # TODO wie kann ich third-party module nach außen verstecken # TODO Ist der import aus dem selben Pakte so korrekt? from . import views from . import visuals import numpy as np # zum Problem mit privaten und öffentlichen Eigenschaften http://www.python-course.eu/python3_properties.php und 'Fluent Python' relativ weit vorne # numpy gibt beim Versuch zB. size zu schreiben auch ein AttributeError() aus. class Movie(object): """main class to interact with the colorspace of movieframes""" def __init__(self, prefix, folder='./'): # TODO platform independent self._frames = Frames(folder, prefix) self.fsize = self._frames.frm_cnt # TODO Warum ist die hier? def light_dark(self): """compute the light/dark contrast of the movie """ light_dark_ctrst = views.LightDark(self._frames) return light_dark_ctrst.hist_vstack() def describe(self, desc=False, start=1, end=0, stp=5): """Calculates each feature provided by Itten for the movie instance Summary values will be returned in a python dictionary. Contrast sequences will not be returned due to save memory. The method which will be used to compute each contrast is the contrast class' default method. Instead the will be plotted using Itten Sequence Plots. More precisely MultivariatePlot and UnivariatePlot will be stored on disk for each contrast type. The filename follows the Pattern prefix + contrast. Parameters ---------- start: Int which defines the start frame for the description end: Int which defines the end frame for the description (0 defines the unknown end frame) Returns ------- Dictionary: Dictionary which contains summarizing statistics The Dictionary keys carry the names of the type of summarization. For each contrast it contains: min, max, mean, median, 25, 75, standard deviation, variance. And for each of this values the same set of values are computed. ToDo ---- - outsource summary/feature loop to function which can be accessed by the view class - pickle view data """ # set properties of the current function call self._frames.start = start self._frames.end = end prefix = self._frames.prefix if not(desc): desc = 'Frame ' + str(start) + ' bis ' + str(end) # Summary Dictionary title = prefix[:-1] summary = {title: {}} # available contrasts contrasts = ['saturation', 'light_dark'] # compute all available statistics for each contrast for ctrst in contrasts: summary[title][ctrst] = {} # compute multivariatee contrast representation multivariate = views.MultivariateSequence(self._frames) multivariate.populate(ctrst=ctrst, frm_stp=stp) # TODO: pickle instance instead of just deleating it! # plot multivariate view vis = visuals.MultivariatePlot(multivariate) vis.plot(multivariate) header = prefix[:-1] + ' MultivariatePlot for ' + ctrst + ' - ' + desc filename = prefix + 'multivariateplot_' + ctrst + '_' + desc vis.saveplt(fname=filename, title=header) # compute summarizations for current contrast univariate = views.UnivariateSequence(self._frames) # TODO Workaround, becaus frm_stp is not part of Frames classbut # view class so when I instantiate vis below it defaults to the # __init__ value 10 and not the value set by the call of describe. # This leads to a matplotlib error univariate._frame_step = stp # instantiate plot for all univariate summarizations vis = visuals.UnivariatePlot(univariate) # summarizing methods of univariate class summarizations = ['seqmean', 'seqmad', 'seqvar'] # TODO Varianz funktioniert so nicht for feature in summarizations: # compute summarizations for given univariate value getattr(univariate, feature)(ctrst=ctrst, frm_stp=stp) # TODO Pickle current instance state # describe current feature by summarizing statistics summary[title][ctrst][feature[3:]] = { 'minv': int(univariate.min()), 'maxv': int(univariate.max()), 'mean': int(univariate.mean()), 'median': int(np.median(univariate)), 'perc25': int(np.percentile(univariate, 25)), 'perc75': int(np.percentile(univariate, 75)), 'std': int(univariate.std()), 'var': int(univariate.var()) } # plot current summarization current univariate contrast plot vis.plot(univariate) # save univariate plot header = prefix[:-1] + ' UnivariatePlot for ' + ctrst + ' - ' + desc filename = self._frames.prefix + 'univariateplot_' + ctrst + '_' + desc vis.saveplt(fname=filename, title=header) return summary class Frames(object): # TODO getters und setters für start und end setzen # TODO frm_stp sollte definitiv Teil der Frames Klasse werden """Parses movie frames properties""" def __init__(self, folder, prefix, start=1, end=0): self.folder = folder self.prefix = prefix self.frames = self.get_frame_list() self.frm_length = self.count_total_frames() self.start = start self.end = end self.frm_cnt = 0 # TODO start als property erzeugt bisher eine Endlosschleife wei # count_frames sart und end brauchen und so gegenseitig sart und end nicht # gesetzt wird @property def end(self): return self.__end @end.setter def end(self, nr): if nr == 0: self.__end = self.frm_length self.frm_cnt = self.count_frames() elif nr > self.frm_length: self.__end = self.frm_length - 1 self.frm_cnt = self.count_frames() elif nr < self.start: self.__end = self.start + 1 self.frm_cnt = self.count_frames() else: self.__end = nr self.frm_cnt = self.count_frames() @property def frm_cnt(self): return self.__frm_cnt @frm_cnt.setter def frm_cnt(self, nr): count = self.count_frames() self.__frm_cnt = count def get_frame_list(self): frm_path = Path(self.folder) return list(frm_path.glob('*.png')) def count_total_frames(self): return len(self.frames) def count_frames(self): return self.end - (self.start - 1) def _get_end_frame(self, end): if end == 0: return self.frm_length else: return end