import numpy as np import cv2 import imutils from kneed import KneeLocator from sklearn.datasets import make_blobs from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt class Layer: #bounds = [[(x,y,w,h), ],] startFrame = None lastFrame = None length = None def __init__(self, startFrame, data, mask, config): '''returns a Layer object Layers are collections of contours with a StartFrame, which is the number of the frame the first contour of this layer was extraced from A Contour is a CV2 Contour, which is a y*x*3 rgb numpy array, but we only care about the corners of the contours. So we save the bounds (x,y,w,h) in bounds[] and the actual content in data[] ''' self.startFrame = startFrame self.lastFrame = startFrame self.config = config self.data = [] self.bounds = [] self.masks = [] self.stats = dict() self.bounds.append([data]) self.masks.append([mask]) #print("Layer constructed") def add(self, frameNumber, bound, mask): '''Adds a bound to the Layer at the layer index which corresponds to the given framenumber''' if self.startFrame + len(self.bounds) - 1 > frameNumber: if len(self.bounds[frameNumber - self.startFrame]) >= 1: self.bounds[frameNumber - self.startFrame].append(bound) self.masks[frameNumber - self.startFrame].append(mask) else: self.lastFrame = frameNumber self.bounds.append([bound]) self.masks.append([mask]) def calcStats(self): '''calculates average distance, variation and deviation of layer movement''' middles = [] for i, bounds in enumerate(self.bounds): for j, bound in enumerate(bounds): if None in bound: continue x = (bound[0] + bound[2]/2) y = (bound[1] + bound[3]/2) middles.append([x,y]) avg = 0 for i in range(1, len(middles), 2): avg += (((float(middles[i][0]-middles[i-1][0])/len(middles))**2 + float(middles[i][1]-middles[i-1][1])/len(middles))**2)**(1/2) self.stats = dict() self.stats["avg"] = round(avg,2) x=0 for i in range(1, len(middles), 2): x += (((((float(middles[i][0]-middles[i-1][0])/len(middles))**2 + float(middles[i][1]-middles[i-1][1])/len(middles))**2)**(1/2)) - avg)**2 x /= (len(middles)-1) self.stats["var"] = round(x,2) self.stats["dev"] = round((x)**(1/2), 2) def getLength(self): return len(self) def __len__(self): self.length = len(self.bounds) return self.length