class TLD_IVMIT:
    def __init__(self, frame, window, init_frames_count = 20):
        self.buffer = [cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)]
        self.position = Position(self.buffer, *window)
        self.learning_component = LearningComponent(self.position.calculate_patch())
        self.detector = Detector(self.position, self.learning_component)
        self.tracker = Tracker(self.position)
        self.is_visible = True
        self.integrator = Integrator(self.learning_component)
        self.init_frames_count = init_frames_count
        self.detected_windows = None
        self.tracked_window = None

    def start(self, frame):
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        if self.init_frames_count == 0:
            start = time()
            self.tracked_window = self.tracker.track(frame, self.position)
            self.buffer[0] = frame
            print "Tracking:", time()- start

            start = time()
            self.detected_windows = self.detector.detect(self.position, self.tracked_window is not None)
            print "Detected windows count:", len(self.detected_windows)
            print "Detection:", time()- start

            start = time()
            # filtered_detected_windows = [(window, patch, proba) for window, patch, proba in self.detected_windows if proba > 0.7]
            single_window, self.is_visible = self.integrator.get_single_window(self.position, self.detected_windows, self.tracked_window)
            print "Integration:", time()- start

            if self.is_visible:
                self.position.update(*single_window)
            # start = time()
            # self.learning_component.n_expert()
            # self.learning_component.p_expert()
            # print "Update training set:", time()- start
        else:
            self.tracked_window = self.tracker.track(frame, self.position)
            self.buffer[0] = frame
            if self.tracked_window is not None:
                i = 0
                while i < 5:
                    self.position.update(x=np.random.randint(0,self.buffer[0].shape[1]-self.position.width))
                    if self.position.is_correct() and windows_intersection(self.position.get_window(), self.tracked_window) == 0:
                        self.learning_component.update_negatives(self.position.calculate_patch())
                        i += 1

                self.position.update(*self.tracked_window)
                self.learning_component.update_positives(self.position.calculate_patch())

                self.init_frames_count -= 1
            else:
                self.init_frames_count = 0
                self.is_visible = False

        return self.position
max_test_count = max_train_count
start_time = time.time()
positive_samples = get_samples(folder, pos_list, samples_subfolder, max_train_count+max_test_count)
negative_samples = get_samples(folder, neg_list, "", 5*max_train_count+max_test_count)
positive_patches = [Position(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 0, 0, frame.shape[1], frame.shape[0]).calculate_patch() for frame in positive_samples]
negative_patches = [Position(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 0, 0, frame.shape[1], frame.shape[0]).calculate_patch() for frame in negative_samples]
print "Positive samples:", len(positive_samples)
print "Negative samples:", len(negative_samples)
print "Generate training set:", time.time() - start_time
print

start_time = time.time()
learning_component = LearningComponent(positive_patches[0])
detector = Detector(learning_component)
for patch in positive_patches[1:max_train_count]:
    learning_component.update_positives(patch)
for patch in negative_patches[:5*max_train_count]:
    learning_component.update_negatives(patch)
print "Update training set:", time.time() - start_time
print

start_time = time.time()
detector.ensemble_classifier.relearn()
print "Learn detector:", time.time() - start_time
print

for param in xrange(10):
    print "Param:", param/10.0
    detector.threshold_patch_variance = 0.3
    detector.threshold_ensemble = param/10.0
    detector.nearest_neighbor_classifier.tetta = 0.4