From e4e5ca7679196faac3fa072447a58b7b99f89cf7 Mon Sep 17 00:00:00 2001 From: nLevin13 Date: Fri, 22 Jan 2021 00:10:55 -0800 Subject: [PATCH 1/2] Ported combinedFilter to vis format, and fixed dimension bug in window builder --- perception/__init__.py | 5 +- .../tasks/gate/GateSegmentationAlgoA.py | 6 +- .../tasks/gate/GateSegmentationAlgoB.py | 6 +- .../tasks/gate/GateSegmentationAlgoC.py | 6 +- .../tasks/segmentation/combinedFilter.py | 58 ++++++------------- perception/vis/Visualizer.py | 5 ++ 6 files changed, 36 insertions(+), 50 deletions(-) diff --git a/perception/__init__.py b/perception/__init__.py index 74b1032..35d15e8 100644 --- a/perception/__init__.py +++ b/perception/__init__.py @@ -3,12 +3,13 @@ import perception.tasks.gate.GateSegmentationAlgoA as GateSegA import perception.tasks.gate.GateSegmentationAlgoB as GateSegB import perception.tasks.gate.GateSegmentationAlgoC as GateSegC -# import perception.tasks as tasks +import perception.tasks.segmentation.combinedFilter as CombinedFilter ALGOS = { 'test': TestAlgo.TestAlgo, 'gateseg': GateSeg.GateCenterAlgo, 'gatesegA': GateSegA.GateSegmentationAlgoA, 'gatesegB': GateSegB.GateSegmentationAlgoB, - 'gatesegC': GateSegC.GateSegmentationAlgoC + 'gatesegC': GateSegC.GateSegmentationAlgoC, + 'combined_segmentations': CombinedFilter.CombinedFilter } diff --git a/perception/tasks/gate/GateSegmentationAlgoA.py b/perception/tasks/gate/GateSegmentationAlgoA.py index 5e3173f..c5d5619 100644 --- a/perception/tasks/gate/GateSegmentationAlgoA.py +++ b/perception/tasks/gate/GateSegmentationAlgoA.py @@ -1,7 +1,7 @@ from perception.tasks.TaskPerceiver import TaskPerceiver from typing import Tuple -from perception.tasks.segmentation.combinedFilter import init_combined_filter +from perception.tasks.segmentation.combinedFilter import CombinedFilter import numpy as np import cv2 as cv @@ -11,7 +11,7 @@ class GateSegmentationAlgoA(TaskPerceiver): def __init__(self): super().__init__() - self.combined_filter = init_combined_filter() + self.combined_filter = CombinedFilter().combined_filter # TODO: fix return typing def analyze(self, frame: np.ndarray, debug: bool, slider_vals=None) -> Tuple[float, float]: @@ -25,7 +25,7 @@ def analyze(self, frame: np.ndarray, debug: bool, slider_vals=None) -> Tuple[flo """ rect1, rect2 = None, None - filtered_frame = self.combined_filter(frame, display_figs=False) + filtered_frame = self.combined_filter(frame)[2] max_brightness = max([b for b in filtered_frame[:, :, 0][0]]) lowerbound = max(0.84 * max_brightness, 120) diff --git a/perception/tasks/gate/GateSegmentationAlgoB.py b/perception/tasks/gate/GateSegmentationAlgoB.py index 8f0a54e..906bce0 100644 --- a/perception/tasks/gate/GateSegmentationAlgoB.py +++ b/perception/tasks/gate/GateSegmentationAlgoB.py @@ -1,7 +1,7 @@ from typing import Tuple from perception.tasks.TaskPerceiver import TaskPerceiver -from perception.tasks.segmentation.combinedFilter import init_combined_filter +from perception.tasks.segmentation.combinedFilter import CombinedFilter import numpy as np import cv2 as cv import statistics @@ -12,7 +12,7 @@ class GateSegmentationAlgoB(TaskPerceiver): def __init__(self): super().__init__() - self.combined_filter = init_combined_filter() + self.combined_filter = CombinedFilter().combined_filter def analyze(self, frame: np.ndarray, debug: bool) -> Tuple[float, float]: """Takes in the background removed image and returns the center between @@ -24,7 +24,7 @@ def analyze(self, frame: np.ndarray, debug: bool) -> Tuple[float, float]: (x,y) coordinate with center of gate """ gate_center = (250, 250) - filtered_frame = self.combined_filter(frame, display_figs=False) + filtered_frame = self.combined_filter(frame)[2] max_brightness = max([b for b in filtered_frame[:, :, 0][0]]) lowerbound = max(0.84*max_brightness, 120) diff --git a/perception/tasks/gate/GateSegmentationAlgoC.py b/perception/tasks/gate/GateSegmentationAlgoC.py index f3bdc55..0b452c7 100644 --- a/perception/tasks/gate/GateSegmentationAlgoC.py +++ b/perception/tasks/gate/GateSegmentationAlgoC.py @@ -2,7 +2,7 @@ from typing import Tuple from collections import namedtuple -from perception.tasks.segmentation.combinedFilter import init_combined_filter +from perception.tasks.segmentation.combinedFilter import CombinedFilter import numpy as np import cv2 as cv @@ -16,7 +16,7 @@ class GateSegmentationAlgoC(TaskPerceiver): def __init__(self, alpha=0.1): super().__init__() self.__alpha = alpha - self.combined_filter = init_combined_filter() + self.combined_filter = CombinedFilter().combined_filter # TODO: fix return typing def analyze(self, frame: np.ndarray, debug: bool) -> Tuple[float, float]: @@ -29,7 +29,7 @@ def analyze(self, frame: np.ndarray, debug: bool) -> Tuple[float, float]: (x,y) coordinate with center of gate """ gate_center = self.output_class(250, 250) - filtered_frame = self.combined_filter(frame, display_figs=False) + filtered_frame = self.combined_filter(frame)[2] filtered_frame_copies = [filtered_frame for _ in range(3)] stacked_filter_frames = np.concatenate(filtered_frame_copies, axis=2) mask = cv.inRange( diff --git a/perception/tasks/segmentation/combinedFilter.py b/perception/tasks/segmentation/combinedFilter.py index ec32624..2907ba8 100644 --- a/perception/tasks/segmentation/combinedFilter.py +++ b/perception/tasks/segmentation/combinedFilter.py @@ -1,24 +1,26 @@ import cv2 import numpy as np -# TODO: port to vis + TaskPerciever format or remove - -from sys import argv as args from perception.tasks.segmentation.aggregateRescaling import init_aggregate_rescaling from perception.tasks.segmentation.peak_removal_adaptive_thresholding import filter_out_highest_peak_multidim +from perception.tasks.TaskPerceiver import TaskPerceiver +from typing import Dict, Tuple -if __name__ == "__main__": - if args[1] == '0': - cap = cv2.VideoCapture(0) - else: - cap = cv2.VideoCapture(args[1]) +class CombinedFilter(TaskPerceiver): + + def __init__(self): + super().__init__() + self.aggregate_rescaling = init_aggregate_rescaling(False) -# Returns a grayscale image -def init_combined_filter(): - aggregate_rescaling = init_aggregate_rescaling(False) + def analyze(self, frame: np.ndarray, debug: bool, slider_vals: Dict[str, int]=None) -> Tuple[float, float]: + filtered_frames = self.combined_filter(frame) - def combined_filter(frame, custom_weights=None, display_figs=False, print_weights=False): - pca_frame = aggregate_rescaling(frame) # this resizes the frame within its body + if debug: + return None, filtered_frames # returns None because it's a more general algorithm + return None + + def combined_filter(self, frame, custom_weights=None, print_weights=False): + pca_frame = self.aggregate_rescaling(frame) # this resizes the frame within its body __, other_frame = filter_out_highest_peak_multidim( np.dstack([pca_frame[:,:,0], frame]), @@ -27,31 +29,9 @@ def combined_filter(frame, custom_weights=None, display_figs=False, print_weight other_frame = other_frame[:, :, :1] - if display_figs: - cv2.imshow('original', frame) - cv2.imshow('Aggregate Rescaling via PCA', pca_frame) - cv2.imshow('Peak Removal Thresholding after PCA', other_frame) - return other_frame - return combined_filter + return [frame, pca_frame, other_frame] if __name__ == "__main__": - ret = True - ret_tries = 0 - - # for i in range(3000): - # cap.read() - - combined_filter = init_combined_filter() - - while 1 and ret_tries < 50: - ret, frame = cap.read() - if ret: - frame = cv2.resize(frame, None, fx=0.4, fy=0.4) - filtered_frame = combined_filter(frame, display_figs=True) - - ret_tries = 0 - k = cv2.waitKey(60) & 0xff - if k == 27: - break - else: - ret_tries += 1 + from perception.vis.vis import run + + run(['..\..\..\data\GOPR1142.MP4'], CombinedFilter(), False) diff --git a/perception/vis/Visualizer.py b/perception/vis/Visualizer.py index 65c7bb2..6b795c3 100644 --- a/perception/vis/Visualizer.py +++ b/perception/vis/Visualizer.py @@ -22,6 +22,8 @@ def three_stack(self, frames: List[np.ndarray]) -> List[np.ndarray]: for frame in frames: if len(frame.shape) == 2 or frame.shape[2] == 1: frame = np.stack((frame, frame, frame), axis=2) + if len(frame.shape) == 4: + frame = frame[:, :, :, 0] newLst.append((frame)) return newLst @@ -33,6 +35,8 @@ def reshape(self, frames: List[np.ndarray]) -> List[np.ndarray]: width = img.shape[1] dim = (width, height) for frame in frames: + if len(frame.shape) > 3: + raise Exception('All of your debug frames should have 2 or 3 dimensions') if frame.shape[0] != height or frame.shape[1] != width: frame = cv.resize(frame, dim, interpolation=cv.INTER_AREA) newLst.append(frame) @@ -64,6 +68,7 @@ def display(self, frames: List[np.ndarray]) -> np.ndarray: to_add = frames[frame_num] this_row = np.hstack((this_row, to_add)) else: + a = frames[0] this_row = np.hstack((this_row, np.zeros(frames[0].shape, dtype=np.uint8))) if not isinstance(to_show, int): to_show = np.vstack((to_show, this_row)) From bc348c7f647bbebfba948fe07d11eaedbd918922 Mon Sep 17 00:00:00 2001 From: nLevin13 Date: Sun, 7 Mar 2021 15:56:48 -0800 Subject: [PATCH 2/2] resizing images --- .../tasks/gate/GateSegmentationAlgoA.py | 8 ++++++- perception/vis/vis.py | 21 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/perception/tasks/gate/GateSegmentationAlgoA.py b/perception/tasks/gate/GateSegmentationAlgoA.py index c5d5619..ea4e1d1 100644 --- a/perception/tasks/gate/GateSegmentationAlgoA.py +++ b/perception/tasks/gate/GateSegmentationAlgoA.py @@ -58,9 +58,15 @@ def analyze(self, frame: np.ndarray, debug: bool, slider_vals=None) -> Tuple[flo cv.rectangle(debug_filter, (x1, y1), (x1 + w1, y1 + h1), (0, 255, 0), 2) cv.rectangle(debug_filter, (x2, y2), (x2 + w2, y2 + h2), (0, 255, 0), 2) + """ for csv pytest""" + act_y = min(y1, y2) + boundRect = (x1, act_y, x2 - x1 + w2, max(y1 - act_y + h1, y2 - act_y + h2)) + cv.rectangle(debug_filter, (int(boundRect[0]), int(boundRect[1])), \ + (int(boundRect[0] + boundRect[2]), int(boundRect[1] + boundRect[3])), (0, 0, 255), 2) + if debug: return (rect1, rect2), (frame, debug_filter) - return (rect1, rect2) + return boundRect if __name__ == '__main__': diff --git a/perception/vis/vis.py b/perception/vis/vis.py index ee6a12b..0c583b7 100644 --- a/perception/vis/vis.py +++ b/perception/vis/vis.py @@ -5,14 +5,16 @@ from perception.vis.FrameWrapper import FrameWrapper import cv2 as cv from perception.vis.Visualizer import Visualizer -import cProfile +import cProfile as cp +import pstats import imageio -def run(data_sources, algorithm, save_video=False): +def run(data_sources, algorithm, save_video=False, resize=0.25): + # print(resize) out = None window_builder = Visualizer(algorithm.kwargs) - data = FrameWrapper(data_sources, 0.25) + data = FrameWrapper(data_sources, resize) frame_count = 0 speed = 1 @@ -51,13 +53,13 @@ def run(data_sources, algorithm, save_video=False): out.close() -def profile(*args, stats='all'): - with cProfile.Profile() as pr: - run(*args) +def profile(stats='all'): + pr = pstats.Stats('algo_stats') if stats == 'all': pr.print_stats() else: pr.print_stats(stats) + os.remove('algo_stats') if __name__ == '__main__': @@ -66,6 +68,7 @@ def profile(*args, stats='all'): parser.add_argument('--data', default='webcam', type=str) parser.add_argument('--algorithm', type=str, required=True) parser.add_argument('--profile', default=None, type=str) + parser.add_argument('--resize', default=0.25, type=float) parser.add_argument('--save_video', action='store_true') args = parser.parse_args() @@ -81,6 +84,8 @@ def profile(*args, stats='all'): data_sources = [args.data] if args.profile is None: - run(data_sources, algorithm, args.save_video) + run(data_sources, algorithm, args.save_video, args.resize) else: - profile(data_sources, algorithm, args.save_video, stats=args.profile) + # print(args.save_video) + cp.run('run(data_sources, algorithm, args.save_video, args.resize)', 'algo_stats') + profile(stats=args.profile)