1a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
3a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew HarpLicensed under the Apache License, Version 2.0 (the "License");
4a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpyou may not use this file except in compliance with the License.
5a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew HarpYou may obtain a copy of the License at
6a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
7a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    http://www.apache.org/licenses/LICENSE-2.0
8a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
9a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew HarpUnless required by applicable law or agreed to in writing, software
10a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpdistributed under the License is distributed on an "AS IS" BASIS,
11a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew HarpWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew HarpSee the License for the specific language governing permissions and
13a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harplimitations under the License.
14a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp==============================================================================*/
15a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
16a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// NOTE: no native object detectors are currently provided or used by the code
17a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// in this directory. This class remains mainly for historical reasons.
18a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// Detection in the TF demo is done through TensorFlowMultiBoxDetector.java.
19a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
20a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// Defines the ObjectDetector class that is the main interface for detecting
21a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// ObjectModelBases in frames.
22a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
23f8347ceebbad0e06552633fcdf8e63f52246ba62Sanjoy Das#ifndef TENSORFLOW_EXAMPLES_ANDROID_JNI_OBJECT_TRACKING_OBJECT_DETECTOR_H_
24f8347ceebbad0e06552633fcdf8e63f52246ba62Sanjoy Das#define TENSORFLOW_EXAMPLES_ANDROID_JNI_OBJECT_TRACKING_OBJECT_DETECTOR_H_
25a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
26a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <float.h>
27a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <map>
28a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <memory>
29a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <sstream>
30a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <string>
31a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include <vector>
32a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
33a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/geom.h"
34a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/image-inl.h"
35a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/image.h"
36a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/integral_image.h"
37a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#ifdef __RENDER_OPENGL__
38a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/sprite.h"
39a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#endif
40a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/utils.h"
41a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
42a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/config.h"
43a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/image_data.h"
44a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp#include "tensorflow/examples/android/jni/object_tracking/object_model.h"
45a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
46a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpnamespace tf_tracking {
47a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
48a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// Adds BoundingSquares to a vector such that the first square added is centered
49a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// in the position given and of square_size, and the remaining squares are added
50a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// concentrentically, scaling down by scale_factor until the minimum threshold
51a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// size is passed.
52a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// Squares that do not fall completely within image_bounds will not be added.
53a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpstatic inline void FillWithSquares(
54a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    const BoundingBox& image_bounds,
55a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    const BoundingBox& position,
56a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    const float starting_square_size,
57a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    const float smallest_square_size,
58a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    const float scale_factor,
59a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    std::vector<BoundingSquare>* const squares) {
60a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  BoundingSquare descriptor_area =
61a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      GetCenteredSquare(position, starting_square_size);
62a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
63a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  SCHECK(scale_factor < 1.0f, "Scale factor too large at %.2f!", scale_factor);
64a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
65a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Use a do/while loop to ensure that at least one descriptor is created.
66a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  do {
67a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    if (image_bounds.Contains(descriptor_area.ToBoundingBox())) {
68a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      squares->push_back(descriptor_area);
69a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    }
70a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    descriptor_area.Scale(scale_factor);
71a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  } while (descriptor_area.size_ >= smallest_square_size - EPSILON);
72a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  LOGV("Created %zu squares starting from size %.2f to min size %.2f "
73a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp       "using scale factor: %.2f",
74a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp       squares->size(), starting_square_size, smallest_square_size,
75a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp       scale_factor);
76a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp}
77a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
78a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
79a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// Represents a potential detection of a specific ObjectExemplar and Descriptor
80a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp// at a specific position in the image.
81a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpclass Detection {
82a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp public:
83a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  explicit Detection(const ObjectModelBase* const object_model,
84a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp                     const MatchScore match_score,
85a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp                     const BoundingBox& bounding_box)
86a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      : object_model_(object_model),
87a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        match_score_(match_score),
88a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        bounding_box_(bounding_box) {}
89a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
90a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  Detection(const Detection& other)
91a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      : object_model_(other.object_model_),
92a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        match_score_(other.match_score_),
93a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        bounding_box_(other.bounding_box_) {}
94a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
95a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual ~Detection() {}
96a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
97a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  inline BoundingBox GetObjectBoundingBox() const {
98a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    return bounding_box_;
99a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
100a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
101a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  inline MatchScore GetMatchScore() const {
102a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    return match_score_;
103a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
104a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
105a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  inline const ObjectModelBase* GetObjectModel() const {
106a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    return object_model_;
107a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
108a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
109a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  inline bool Intersects(const Detection& other) {
110a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    // Check if any of the four axes separates us, there must be at least one.
111a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    return bounding_box_.Intersects(other.bounding_box_);
112a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
113a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
114a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  struct Comp {
115a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    inline bool operator()(const Detection& a, const Detection& b) const {
116a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      return a.match_score_ > b.match_score_;
117a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    }
118a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  };
119a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
120a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // TODO(andrewharp): add accessors to update these instead.
121a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  const ObjectModelBase* object_model_;
122a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  MatchScore match_score_;
123a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  BoundingBox bounding_box_;
124a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp};
125a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
126a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpinline std::ostream& operator<<(std::ostream& stream,
127a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp                                const Detection& detection) {
128a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  const BoundingBox actual_area = detection.GetObjectBoundingBox();
129a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  stream << actual_area;
130a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  return stream;
131a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp}
132a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
133a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpclass ObjectDetectorBase {
134a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp public:
135a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  explicit ObjectDetectorBase(const ObjectDetectorConfig* const config)
136a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      : config_(config),
137a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        image_data_(NULL) {}
138a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
139a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual ~ObjectDetectorBase();
140a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
141a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Sets the current image data. All calls to ObjectDetector other than
142a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // FillDescriptors use the image data last set.
143a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  inline void SetImageData(const ImageData* const image_data) {
144a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    image_data_ = image_data;
145a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
146a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
147a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Main entry point into the detection algorithm.
148a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Scans the frame for candidates, tweaks them, and fills in the
149a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // given std::vector of Detection objects with acceptable matches.
150a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void Detect(const std::vector<BoundingSquare>& positions,
151a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp                      std::vector<Detection>* const detections) const = 0;
152a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
153a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual ObjectModelBase* CreateObjectModel(const std::string& name) = 0;
154a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
155a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void DeleteObjectModel(const std::string& name) = 0;
156a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
157a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void GetObjectModels(
158a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      std::vector<const ObjectModelBase*>* models) const = 0;
159a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
160a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Creates a new ObjectExemplar from the given position in the context of
161a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // the last frame passed to NextFrame.
162a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Will return null in the case that there's no room for a descriptor to be
163a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // created in the example area, or the example area is not completely
164a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // contained within the frame.
165a99712b6229a39d6c6a6e0bb60b8ff6934216017A. Unique TensorFlower  virtual void UpdateModel(const Image<uint8_t>& base_image,
166a99712b6229a39d6c6a6e0bb60b8ff6934216017A. Unique TensorFlower                           const IntegralImage& integral_image,
167a99712b6229a39d6c6a6e0bb60b8ff6934216017A. Unique TensorFlower                           const BoundingBox& bounding_box, const bool locked,
168a99712b6229a39d6c6a6e0bb60b8ff6934216017A. Unique TensorFlower                           ObjectModelBase* model) const = 0;
169a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
170a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void Draw() const = 0;
171a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
172a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual bool AllowSpontaneousDetections() = 0;
173a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
174a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp protected:
175a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  const std::unique_ptr<const ObjectDetectorConfig> config_;
176a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
177a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // The latest frame data, upon which all detections will be performed.
178a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // Not owned by this object, just provided for reference by ObjectTracker
179a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  // via SetImageData().
180a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  const ImageData* image_data_;
181a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
182a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp private:
183a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  TF_DISALLOW_COPY_AND_ASSIGN(ObjectDetectorBase);
184a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp};
185a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
186a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harptemplate <typename ModelType>
187a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harpclass ObjectDetector : public ObjectDetectorBase {
188a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp public:
189a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  explicit ObjectDetector(const ObjectDetectorConfig* const config)
190a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      : ObjectDetectorBase(config) {}
191a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
192a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual ~ObjectDetector() {
193a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    typename std::map<std::string, ModelType*>::const_iterator it =
194a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        object_models_.begin();
195a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    for (; it != object_models_.end(); ++it) {
196a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      ModelType* model = it->second;
197a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      delete model;
198a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    }
199a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
200a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
201a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void DeleteObjectModel(const std::string& name) {
202a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    ModelType* model = object_models_[name];
203a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    CHECK_ALWAYS(model != NULL, "Model was null!");
204a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    object_models_.erase(name);
205a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    SAFE_DELETE(model);
206a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
207a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
208a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual void GetObjectModels(
209a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      std::vector<const ObjectModelBase*>* models) const {
210a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    typename std::map<std::string, ModelType*>::const_iterator it =
211a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp        object_models_.begin();
212a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    for (; it != object_models_.end(); ++it) {
213a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp      models->push_back(it->second);
214a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    }
215a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
216a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
217a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  virtual bool AllowSpontaneousDetections() {
218a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp    return false;
219a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  }
220a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
221a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp protected:
222a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  std::map<std::string, ModelType*> object_models_;
223a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
224a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp private:
225a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp  TF_DISALLOW_COPY_AND_ASSIGN(ObjectDetector);
226a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp};
227a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
228a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp}  // namespace tf_tracking
229a30b9926bd7d5276d6ff35af9428dee3e77b7dcbAndrew Harp
230f8347ceebbad0e06552633fcdf8e63f52246ba62Sanjoy Das#endif  // TENSORFLOW_EXAMPLES_ANDROID_JNI_OBJECT_TRACKING_OBJECT_DETECTOR_H_
231