def camera_path(self, path: str): if not os.path.exists(path): Logger.fatal("Camera config file {} not found".format( self.camera_path)) raise FileNotFoundError("Camera config file {} not found".format( self.camera_path)) if not path.endswith("json"): Logger.fatal("Can only parse '.json' files") raise ValueError( "Can only parse '.json' files, passed camera file is {}". format(path)) self.__camera_path = path
def cluster_segments(self) -> None: """Clusters the input segments :attr:`self.raw_segments` based on the parameters passed as argument. """ Logger.debug("Clustering segments") if self.params.cluster_type not in ["gmm", "knn"]: Logger.fatal("Invalid value for cluster type: {}".format( self.params.cluster_type)) raise ValueError( "Invalid value for 'cluster_type': {} " "'cluster_type' should be in ['gmm', 'knn']".format( self.params.cluster_type)) centers = [] angles = [] for segment in self.raw_segments: pt1 = segment[0:2] pt2 = segment[2:4] center = (pt1 + pt2) * 0.5 centers.append(center) # Segment angle lies in [0, pi], multiply by 2 such that complex number associated to similar angles are # close on the complex plane (e.g. 180° and 0°) angle = utils.angle_x(pt1, pt2) * 2 # Need to use complex representation as Euclidean distance used in clustering makes sense in complex plane, # and does not directly on angles. point = np.array([np.cos(angle), np.sin(angle)]) angles.append(point) centers = np.array(centers) centers = normalize(centers, axis=0) angles = np.array(angles) if self.params.use_angles and self.params.use_centers: features = np.hstack((angles, centers)) elif self.params.use_angles: features = angles elif self.params.use_centers: features = centers else: raise RuntimeError( "Can not perform segment clustering without any feature. " "Select 'use_angles=True' and/or 'use_centers=True'.") cluster_prediction = None if self.params.cluster_type is "knn": Logger.debug("Clustering segments using KNN") cluster_prediction = KMeans(n_clusters=self.params.num_clusters, n_init=self.params.num_init, random_state=0).fit_predict(features) elif self.params.cluster_type is "gmm": Logger.debug("Clustering segments using GMM") best_gmm = None lowest_bic = np.infty bic = [] n_components_range = range(1, self.params.num_clusters + 1) if not self.params.swipe_clusters: n_components_range = [self.params.num_clusters] for n_components in n_components_range: # Fit a Gaussian mixture with EM. gmm = GaussianMixture(n_components=n_components, covariance_type='full') gmm.fit(features) bic.append(gmm.bic(features)) if bic[-1] < lowest_bic: lowest_bic = bic[-1] best_gmm = gmm cluster_prediction = best_gmm.predict(features) # Reorder the segments as clusters. cluster_segment_list = [] cluster_feature_list = [] num_labels = np.max(cluster_prediction) + 1 for label in range(num_labels): cluster_segments = self.raw_segments[cluster_prediction == label] if len(cluster_segments) == 0: continue cluster_features = features[cluster_prediction == label] cluster_segment_list.append(cluster_segments) cluster_feature_list.append(cluster_features) self.cluster_list = cluster_segment_list self.cluster_features = cluster_feature_list
def video_path(self, path: str): if not os.path.exists(path): Logger.fatal("Video path {} does not exist".format(path)) raise FileNotFoundError("Video file {} not found".format(path)) self.__video_path = path