Ejemplo n.º 1
0
class EAOScore(Analysis):

    eaocurve = Include(EAOCurve)
    low = Integer()
    high = Integer()

    @property
    def title(self):
        return "EAO analysis"

    def describe(self):
        return Measure("Expected average overlap", "EAO", 0, 1,
                       Sorting.DESCENDING),

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, SupervisedExperiment)

    def dependencies(self):
        return self.eaocurve,

    def compute(self, experiment: Experiment, trackers: List[Tracker],
                sequences: List[Sequence], dependencies: List[Grid]) -> Grid:
        return dependencies[0].foreach(
            lambda x, i, j: (float(np.mean(x[0][self.low:self.high + 1])), ))

    @property
    def axes(self):
        return Axes.TRACKERS
Ejemplo n.º 2
0
class TrackerSorter(Attributee):

    experiment = String(default=None)
    analysis = String(default=None)
    result = Integer(val_min=0, default=0)

    def __call__(self, experiments, trackers, sequences):
        if self.experiment is None or self.analysis is None:
            return range(len(trackers))

        experiment = next(
            filter(lambda x: x.identifier == self.experiment, experiments),
            None)

        if experiment is None:
            raise RuntimeError("Experiment not found")

        analysis = next(
            filter(lambda x: x.name == self.analysis, experiment.analyses),
            None)

        if analysis is None:
            raise RuntimeError("Analysis not found")

        future = analysis.commit(experiment, trackers, sequences)
        result = future.result()

        scores = [x[self.result] for x in result]
        indices = [
            i[0] for i in sorted(
                enumerate(scores), reverse=True, key=lambda x: x[1])
        ]

        return indices
Ejemplo n.º 3
0
class _Thresholds(SequenceAggregator):

    resolution = Integer(default=100)

    @property
    def title(self):
        return "Thresholds for tracking precision/recall"

    def describe(self):
        return None,

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, UnsupervisedExperiment)

    def dependencies(self):
        return _ConfidenceScores(),

    def aggregate(self, tracker: Tracker, sequences: List[Sequence],
                  results: Grid) -> Tuple[Any]:

        thresholds = determine_thresholds(
            itertools.chain(*[result[0] for result in results]),
            self.resolution),

        return thresholds,
Ejemplo n.º 4
0
class SequenceAccuracy(SeparableAnalysis):

    burnin = Integer(default=10, val_min=0)
    ignore_unknown = Boolean(default=True)
    bounded = Boolean(default=True)

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, MultiRunExperiment)

    @property
    def title(self):
        return "Sequence accurarcy"

    def describe(self):
        return Measure("Accuracy", "AUC", 0, 1, Sorting.DESCENDING),

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequence: Sequence, dependencies: List[Grid]) -> Tuple[Any]:

        assert isinstance(experiment, MultiRunExperiment)

        trajectories = experiment.gather(tracker, sequence)

        if len(trajectories) == 0:
            raise MissingResultsException()

        cummulative = 0
        for trajectory in trajectories:
            accuracy, _ = compute_accuracy(trajectory.regions(), sequence,
                                           self.burnin, self.ignore_unknown,
                                           self.bounded)
            cummulative = cummulative + accuracy

        return cummulative / len(trajectories),
Ejemplo n.º 5
0
class Redetection(Transformer):

    length = Integer(default=100, val_min=1)
    initialization = Integer(default=5, val_min=1)
    padding = Float(default=2, val_min=0)
    scaling = Float(default=1, val_min=0.1, val_max=10)

    def __call__(self, sequence: Sequence) -> Sequence:

        chache_dir = self._cache.directory(self, arg_hash(sequence.name, **self.dump()))

        if not os.path.isfile(os.path.join(chache_dir, "sequence")):
            generated = InMemorySequence(sequence.name, sequence.channels())
            size = (int(sequence.size[0] * self.scaling), int(sequence.size[1] * self.scaling))

            initial_images = dict()
            redetect_images = dict()
            for channel in sequence.channels():
                rect = sequence.frame(0).groundtruth().convert(RegionType.RECTANGLE)

                halfsize = int(max(rect.width, rect.height) * self.scaling / 2)
                x, y = rect.center()

                image = Image.fromarray(sequence.frame(0).image())
                box = (x - halfsize, y - halfsize, x + halfsize, y + halfsize)
                template = image.crop(box)
                initial = Image.new(image.mode, size)
                initial.paste(image, (0, 0))
                redetect = Image.new(image.mode, size)
                redetect.paste(template, (size[0] - template.width, size[1] - template.height))
                initial_images[channel] = initial
                redetect_images[channel] = redetect

            generated.append(initial_images, sequence.frame(0).groundtruth())
            generated.append(redetect_images, sequence.frame(0).groundtruth().move(size[0] - template.width, size[1] - template.height))

            write_sequence(chache_dir, generated)

        source = VOTSequence(chache_dir, name=sequence.name)
        mapping = [0] * self.initialization + [1] * (self.length - self.initialization)
        return FrameMapSequence(source, mapping)
Ejemplo n.º 6
0
class MultiRunExperiment(Experiment):

    repetitions = Integer(val_min=1, default=1)
    early_stop = Boolean(default=True)

    def _can_stop(self, tracker: Tracker, sequence: Sequence):
        if not self.early_stop:
            return False
        trajectories = self.gather(tracker, sequence)
        if len(trajectories) < 3:
            return False

        for trajectory in trajectories[1:]:
            if not trajectory.equals(trajectories[0]):
                return False

        return True

    def scan(self, tracker: Tracker, sequence: Sequence):

        results = self.results(tracker, sequence)

        files = []
        complete = True

        for i in range(1, self.repetitions + 1):
            name = "%s_%03d" % (sequence.name, i)
            if Trajectory.exists(results, name):
                files.extend(Trajectory.gather(results, name))
            elif self._can_stop(tracker, sequence):
                break
            else:
                complete = False
                break

        return complete, files, results

    def gather(self, tracker: Tracker, sequence: Sequence):
        trajectories = list()
        results = self.results(tracker, sequence)
        for i in range(1, self.repetitions + 1):
            name = "%s_%03d" % (sequence.name, i)
            if Trajectory.exists(results, name):
                trajectories.append(Trajectory.read(results, name))
        return trajectories
Ejemplo n.º 7
0
class AccuracyRobustness(SeparableAnalysis):

    sensitivity = Float(default=30, val_min=1)
    burnin = Integer(default=10, val_min=0)
    ignore_unknown = Boolean(default=True)
    bounded = Boolean(default=True)

    @property
    def title(self):
        return "AR analysis"

    def describe(self):
        return Measure("Accuracy", "A", minimal=0, maximal=1, direction=Sorting.DESCENDING), \
             Measure("Robustness", "R", minimal=0, direction=Sorting.ASCENDING), \
             Point("AR plot", dimensions=2, abbreviation="AR", minimal=(0, 0), \
                maximal=(1, 1), labels=("Robustness", "Accuracy"), trait="ar"), \
             None

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, SupervisedExperiment)

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequence: Sequence, dependencies: List[Grid]) -> Tuple[Any]:
        trajectories = experiment.gather(tracker, sequence)

        if len(trajectories) == 0:
            raise MissingResultsException()

        accuracy = 0
        failures = 0
        for trajectory in trajectories:
            failures += count_failures(trajectory.regions())[0]
            accuracy += compute_accuracy(trajectory.regions(), sequence,
                                         self.burnin, self.ignore_unknown,
                                         self.bounded)[0]

        ar = (math.exp(-(float(failures) / len(trajectories)) *
                       self.sensitivity), accuracy / len(trajectories))

        return accuracy / len(trajectories), failures / len(
            trajectories), ar, len(trajectories[0])
Ejemplo n.º 8
0
class SupervisedExperiment(MultiRunExperiment):

    skip_initialize = Integer(val_min=1, default=1)
    skip_tags = List(String(), default=[])
    failure_overlap = Float(val_min=0, val_max=1, default=0)

    def execute(self,
                tracker: Tracker,
                sequence: Sequence,
                force: bool = False,
                callback: Callable = None):

        results = self.results(tracker, sequence)

        with self._get_runtime(tracker, sequence) as runtime:

            for i in range(1, self.repetitions + 1):
                name = "%s_%03d" % (sequence.name, i)

                if Trajectory.exists(results, name) and not force:
                    continue

                if self._can_stop(tracker, sequence):
                    return

                trajectory = Trajectory(sequence.length)

                frame = 0
                while frame < sequence.length:

                    _, properties, elapsed = runtime.initialize(
                        sequence.frame(frame),
                        self._get_initialization(sequence, frame))

                    properties["time"] = elapsed

                    trajectory.set(frame, Special(Special.INITIALIZATION),
                                   properties)

                    frame = frame + 1

                    while frame < sequence.length:

                        region, properties, elapsed = runtime.update(
                            sequence.frame(frame))

                        properties["time"] = elapsed

                        if calculate_overlap(
                                region, sequence.groundtruth(frame),
                                sequence.size) <= self.failure_overlap:
                            trajectory.set(frame, Special(Special.FAILURE),
                                           properties)
                            frame = frame + self.skip_initialize

                            if self.skip_tags:
                                while frame < sequence.length:
                                    if not [
                                            t for t in sequence.tags(frame)
                                            if t in self.skip_tags
                                    ]:
                                        break
                                    frame = frame + 1
                            break
                        else:
                            trajectory.set(frame, region, properties)
                        frame = frame + 1

                if callback:
                    callback(i / self.repetitions)

                trajectory.write(results, name)
Ejemplo n.º 9
0
class EAOCurve(TrackerSeparableAnalysis):

    burnin = Integer(default=10, val_min=0)
    bounded = Boolean(default=True)

    @property
    def title(self):
        return "EAO Curve"

    def describe(self):
        return Plot("Expected Average Overlap",
                    "EAO",
                    minimal=0,
                    maximal=1,
                    trait="eao"),

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, SupervisedExperiment)

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequences: List[Sequence],
                   dependencies: List[Grid]) -> Tuple[Any]:

        overlaps_all = []
        weights_all = []
        success_all = []

        for sequence in sequences:

            trajectories = experiment.gather(tracker, sequence)

            if len(trajectories) == 0:
                raise MissingResultsException()

            for trajectory in trajectories:

                overlaps = calculate_overlaps(
                    trajectory.regions(), sequence.groundtruth(),
                    (sequence.size) if self.bounded else None)
                fail_idxs, init_idxs = locate_failures_inits(
                    trajectory.regions())

                if len(fail_idxs) > 0:

                    for i in range(len(fail_idxs)):
                        overlaps_all.append(
                            overlaps[init_idxs[i]:fail_idxs[i]])
                        success_all.append(False)
                        weights_all.append(1)

                    # handle last initialization
                    if len(init_idxs) > len(fail_idxs):
                        # tracker was initilized, but it has not failed until the end of the sequence
                        overlaps_all.append(overlaps[init_idxs[-1]:])
                        success_all.append(True)
                        weights_all.append(1)

                else:
                    overlaps_all.append(overlaps)
                    success_all.append(True)
                    weights_all.append(1)

        return compute_eao_curve(overlaps_all, weights_all, success_all),
Ejemplo n.º 10
0
class InjectConfig(Attributee):
    # Not implemented yet
    placeholder = Integer(default=1)
Ejemplo n.º 11
0
class RealtimeConfig(Attributee):

    grace = Integer(val_min=0, default=0)
    fps = Float(val_min=0, default=20)
Ejemplo n.º 12
0
class AccuracyRobustness(SeparableAnalysis):

    burnin = Integer(default=10, val_min=0)
    grace = Integer(default=10, val_min=0)
    bounded = Boolean(default=True)
    threshold = Float(default=0.1, val_min=0, val_max=1)

    @property
    def title(self):
        return "AR Analysis"

    def describe(self):
        return Measure("Accuracy", "A", minimal=0, maximal=1, direction=Sorting.DESCENDING), \
             Measure("Robustness", "R", minimal=0, direction=Sorting.DESCENDING), \
             Point("AR plot", dimensions=2, abbreviation="AR",
                minimal=(0, 0), maximal=(1, 1), labels=("Robustness", "Accuracy"), trait="ar"), \
             None, None

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, MultiStartExperiment)

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequence: Sequence, dependencies: List[Grid]) -> Tuple[Any]:

        results = experiment.results(tracker, sequence)

        forward, backward = find_anchors(sequence, experiment.anchor)

        if not forward and not backward:
            raise RuntimeError("Sequence does not contain any anchors")

        robustness = 0
        accuracy = 0
        total = 0
        for i, reverse in [(f, False) for f in forward] + [(f, True)
                                                           for f in backward]:
            name = "%s_%08d" % (sequence.name, i)

            if not Trajectory.exists(results, name):
                raise MissingResultsException()

            if reverse:
                proxy = FrameMapSequence(sequence,
                                         list(reversed(range(0, i + 1))))
            else:
                proxy = FrameMapSequence(sequence,
                                         list(range(i, sequence.length)))

            trajectory = Trajectory.read(results, name)

            overlaps = calculate_overlaps(
                trajectory.regions(), proxy.groundtruth(),
                (proxy.size) if self.burnin else None)

            grace = self.grace
            progress = len(proxy)

            for j, overlap in enumerate(overlaps):
                if overlap <= self.threshold and not proxy.groundtruth(
                        j).is_empty():
                    grace = grace - 1
                    if grace == 0:
                        progress = j + 1 - self.grace  # subtract since we need actual point of the failure
                        break
                else:
                    grace = self.grace

            robustness += progress  # simplified original equation: len(proxy) * (progress / len(proxy))
            accuracy += sum(overlaps[0:progress])
            total += len(proxy)

        ar = (robustness / total,
              accuracy / robustness if robustness > 0 else 0)

        return accuracy / robustness if robustness > 0 else 0, robustness / total, ar, robustness, len(
            sequence)
Ejemplo n.º 13
0
class EAOCurves(SeparableAnalysis):

    burnin = Integer(default=10, val_min=0)
    grace = Integer(default=10, val_min=0)
    bounded = Boolean(default=True)
    threshold = Float(default=0.1, val_min=0, val_max=1)

    high = Integer()

    @property
    def title(self):
        return "EAO Curve"

    def describe(self):
        return Plot("Expected average overlap",
                    "EAO",
                    minimal=0,
                    maximal=1,
                    wrt="frames",
                    trait="eao"),

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, MultiStartExperiment)

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequence: Sequence, dependencies: List[Grid]) -> Tuple[Any]:

        results = experiment.results(tracker, sequence)

        forward, backward = find_anchors(sequence, experiment.anchor)

        if len(forward) == 0 and len(backward) == 0:
            raise RuntimeError("Sequence does not contain any anchors")

        overlaps_all = []
        success_all = []

        for i, reverse in [(f, False) for f in forward] + [(f, True)
                                                           for f in backward]:
            name = "%s_%08d" % (sequence.name, i)

            if not Trajectory.exists(results, name):
                raise MissingResultsException()

            if reverse:
                proxy = FrameMapSequence(sequence,
                                         list(reversed(range(0, i + 1))))
            else:
                proxy = FrameMapSequence(sequence,
                                         list(range(i, sequence.length)))

            trajectory = Trajectory.read(results, name)

            overlaps = calculate_overlaps(trajectory.regions(),
                                          proxy.groundtruth(),
                                          proxy.size if self.burnin else None)

            grace = self.grace
            progress = len(proxy)

            for j, overlap in enumerate(overlaps):
                if overlap <= self.threshold and not proxy.groundtruth(
                        j).is_empty():
                    grace = grace - 1
                    if grace == 0:
                        progress = j + 1 - self.grace  # subtract since we need actual point of the failure
                        break
                else:
                    grace = self.grace

            success = True
            if progress < len(overlaps):
                # tracker has failed during this run
                overlaps[progress:] = (len(overlaps) - progress) * [float(0)]
                success = False

            overlaps_all.append(overlaps)
            success_all.append(success)

        return compute_eao_partial(overlaps_all, success_all, self.high), 1
Ejemplo n.º 14
0
class MultiStartFragments(SeparableAnalysis):

    burnin = Integer(default=10, val_min=0)
    grace = Integer(default=10, val_min=0)
    bounded = Boolean(default=True)
    threshold = Float(default=0.1, val_min=0, val_max=1)

    @property
    def title(self):
        return "Fragment Analysis"

    def describe(self):
        return Curve("Success",
                     2,
                     "Sc",
                     minimal=(0, 0),
                     maximal=(1, 1),
                     trait="points"), Curve("Accuracy",
                                            2,
                                            "Ac",
                                            minimal=(0, 0),
                                            maximal=(1, 1),
                                            trait="points")

    def compatible(self, experiment: Experiment):
        return isinstance(experiment, MultiStartExperiment)

    def subcompute(self, experiment: Experiment, tracker: Tracker,
                   sequence: Sequence, dependencies: List[Grid]) -> Tuple[Any]:

        results = experiment.results(tracker, sequence)

        forward, backward = find_anchors(sequence, experiment.anchor)

        if not forward and not backward:
            raise RuntimeError("Sequence does not contain any anchors")

        accuracy = []
        success = []

        for i, reverse in [(f, False) for f in forward] + [(f, True)
                                                           for f in backward]:
            name = "%s_%08d" % (sequence.name, i)

            if not Trajectory.exists(results, name):
                raise MissingResultsException()

            if reverse:
                proxy = FrameMapSequence(sequence,
                                         list(reversed(range(0, i + 1))))
            else:
                proxy = FrameMapSequence(sequence,
                                         list(range(i, sequence.length)))

            trajectory = Trajectory.read(results, name)

            overlaps = calculate_overlaps(
                trajectory.regions(), proxy.groundtruth(),
                (proxy.size) if self.burnin else None)

            grace = self.grace
            progress = len(proxy)

            for j, overlap in enumerate(overlaps):
                if overlap <= self.threshold and not proxy.groundtruth(
                        j).is_empty():
                    grace = grace - 1
                    if grace == 0:
                        progress = j + 1 - self.grace  # subtract since we need actual point of the failure
                        break
                else:
                    grace = self.grace

            success.append((i / len(sequence), progress / len(proxy)))
            accuracy.append(
                (i / len(sequence), sum(overlaps[0:progress] / len(proxy))))

        return success, accuracy