#!/usr/bin/env python # -*- coding: utf-8 -*- # TODO import as cv import cv2 import numpy as np from .helpers import luminance from copy import deepcopy # subclassing numpy ndarray # Vorgehen: https://docs.scipy.org/doc/numpy/user/basics.subclassing.html # resize Probleme https://sourceforge.net/p/numpy/mailman/message/12594801/ # andere ownership Probleme könne angeblich mit out= gelöst werden # "Use __new__ when you need to control the creation of a new instance. # Use __init__ when you need to control initialization of a new instance." class Contrast(np.ndarray): """Core class for a color contrast in a movie subclasses a numpy array""" def __new__(cls, frames, input_array=None): obj = input_array if type(obj) == np.ndarray: obj = np.asarray(input_array, dtype=np.uint8).view(cls).copy() else: input_array = np.zeros((0), dtype=np.uint8) obj = np.asarray(input_array).view(cls).copy() obj._frames = frames obj._channel = 2 obj._frm_step = 50 obj._save = False return obj def __array_finalize__(self, obj): if obj is None: return self._frames = getattr(obj, '_frames', None) self._channel = getattr(obj, '_channel', None) self._frm_step = getattr(obj, '_frame_step', None) self._bins = getattr(obj, '_bins', None) self._threshold = getattr(obj, '_threshold', None) self._save = getattr(obj, '_save', None) def __array_wrap__(self, out_arr, context=None): return np.ndarray.__array_wrap__(self, out_arr, context) # subclassing subclass of numpy http://stackoverflow.com/questions/7342637/how-to-subclass-a-subclass-of-numpy-ndarray # TODO es gibt noch das Problem, dass numpy nach mehreren Berechnungen von drive eine max recursion Warnung ausgiebt, warum? Brauche ich __del__ class VHistStack(Contrast): def __new__(cls, frames, input_array=None): obj = Contrast.__new__(cls, frames, input_array) obj._bins = 16 obj._threshold = 60000 return obj def __array_finalize__(self, obj): if obj is None: return Contrast.__array_finalize__(self, obj) self._bins = getattr(obj, '_bins', None) self._threshold = getattr(obj, '_threshold', None) # TODO jetzt ausschließlich mit self numpy rechnen statt mit contrast_points liste def derive(self): contrast_points = [] # pwd list sollte in Frames sein und hier nur durchlaufen werden for frm_nr in range(self._frames.start, self._frames.end, self._frm_step): pwd = self._frames.folder + self._frames.prefix + str(frm_nr) + '.png' img = cv2.imread(pwd) if self._channel == 2: _img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) luminances = luminance(_img) hist_value, _ = np.histogram(luminances, bins=self._bins, range=(0, 255)) else: img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL) hist_value = cv2.calcHist([img_hsv], [self._channel], None, [16], [0, 256]) for bin_index, point in enumerate(hist_value): if point > self._threshold: contrast_points.append((frm_nr, bin_index, int(point))) contrast_points = np.asarray(contrast_points, np.uint8) shape = contrast_points.shape self.resize(shape, refcheck=False) self[:, :] = contrast_points return deepcopy(self) # TODO does not create a new object