Skip to content

Commit 1060cf2

Browse files
Merge branch 'master' into r0.4.0-rc0
2 parents af38bf7 + 7efb354 commit 1060cf2

40 files changed

+1747
-120
lines changed

tensorflow_lite_support/c/task/processor/classification_result.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ void TfLiteClassificationResultDelete(
2727
for (int head = 0; head < classification_result->size; ++head) {
2828
TfLiteClassifications classifications =
2929
classification_result->classifications[head];
30+
free(classifications.head_name);
3031
for (int rank = 0; rank < classifications.size; ++rank) {
3132
TfLiteCategoryDelete(&(classifications.categories[rank]));
3233
}

tensorflow_lite_support/examples/colab/on_device_text_to_image_search_tflite.ipynb

Lines changed: 1249 additions & 0 deletions
Large diffs are not rendered by default.

tensorflow_lite_support/examples/task/text/desktop/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ cc_binary(
134134
name = "text_searcher_demo",
135135
srcs = ["text_searcher_demo.cc"],
136136
deps = [
137+
":universal_sentence_encoder_qa_op_resolver",
137138
"//tensorflow_lite_support/cc/port:configuration_proto_inc",
138139
"//tensorflow_lite_support/cc/port:status_macros",
139140
"//tensorflow_lite_support/cc/task/core/proto:base_options_cc_proto",
@@ -161,6 +162,7 @@ cc_binary(
161162
name = "text_embedder_demo",
162163
srcs = ["text_embedder_demo.cc"],
163164
deps = [
165+
":universal_sentence_encoder_qa_op_resolver",
164166
"//tensorflow_lite_support/cc/port:configuration_proto_inc",
165167
"//tensorflow_lite_support/cc/port:status_macros",
166168
"//tensorflow_lite_support/cc/task/core/proto:base_options_cc_proto",

tensorflow_lite_support/examples/task/text/desktop/README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,111 @@ Output answers 2: He looks good. Score: 8.80944
162162
Output answers 1: Paris is the capital of France. Score: 5.63752
163163
```
164164

165+
## TextEmbedder
166+
167+
#### Prerequisites
168+
169+
You will need:
170+
171+
* a TFLite text embedder model such as the universal sentence encoder QA model
172+
from [TensorFlow Hub][6].
173+
174+
#### Usage
175+
176+
The TextEmbedder demo tool takes two sentences as inputs, and outputs the
177+
[cosine similarity][7] between their embeddings.
178+
179+
In the console, run:
180+
181+
```bash
182+
# Download the model:
183+
curl \
184+
-L 'https://tfhub.dev/google/lite-model/universal-sentence-encoder-qa-ondevice/1?lite-format=tflite' \
185+
-o /tmp/universal_sentence_encoder_qa_with_metadata.tflite
186+
187+
# Run the embedder tool:
188+
bazel run -c opt \
189+
tensorflow_lite_support/examples/task/text/desktop:text_embedder_demo -- \
190+
--model_path=/tmp/universal_sentence_encoder_qa_with_metadata.tflite \
191+
--l2_normalize \
192+
--first_sentence="It was a very sunny day." \
193+
--second_sentence="The sun was shining brightly."
194+
```
195+
196+
#### Results
197+
198+
In the console, you should get:
199+
200+
```
201+
Cosine similarity: 0.952549
202+
```
203+
204+
## TextSearcher
205+
206+
#### Prerequisites
207+
208+
TODO(b/231294362): update link to Model Maker.
209+
210+
You will need:
211+
212+
* a TFLite text embedder model such as the universal sentence encoder QA model
213+
from [TensorFlow Hub][6],
214+
* an index built from that embedder model using [Model Maker][8].
215+
216+
Model Maker also provides the ability to add the index directly to the embedder
217+
model metadata. The demo also supports this : just omit the `--index_path`
218+
argument.
219+
220+
#### Usage
221+
222+
In this example, we'll be using a test index built from the universal sentence
223+
encoder QA model, which only contains 5 embeddings.
224+
225+
In the console, run:
226+
227+
```bash
228+
# Download the model:
229+
curl \
230+
-L 'https://tfhub.dev/google/lite-model/universal-sentence-encoder-qa-ondevice/1?lite-format=tflite' \
231+
-o /tmp/universal_sentence_encoder_qa_with_metadata.tflite
232+
233+
# Run the searcher tool:
234+
bazel run -c opt \
235+
tensorflow_lite_support/examples/task/text/desktop:text_searcher_demo -- \
236+
--model_path=/tmp/universal_sentence_encoder_qa_with_metadata.tflite \
237+
--l2_normalize \
238+
--index_path=$(pwd)/third_party/tensorflow_lite_support/cc/test/testdata/task/text/universal_sentence_encoder_index.ldb \
239+
--input_sentence="The sun was very bright."
240+
```
241+
242+
#### Results
243+
244+
In the console, you should get:
245+
246+
```
247+
Results:
248+
Rank#0:
249+
metadata: The sun was shining on that day.
250+
distance: 0.04618
251+
Rank#1:
252+
metadata: It was a sunny day.
253+
distance: 0.10856
254+
Rank#2:
255+
metadata: The weather was excellent.
256+
distance: 0.15223
257+
Rank#3:
258+
metadata: The cat is chasing after the mouse.
259+
distance: 0.34271
260+
Rank#4:
261+
metadata: He was very happy with his newly bought car.
262+
distance: 0.37703
263+
```
264+
165265
[1]: https://tfhub.dev/tensorflow/lite-model/mobilebert/1/default/1
166266
[2]: https://tfhub.dev/tensorflow/lite-model/albert_lite_base/squadv1/1
167267
[3]: https://www.tensorflow.org/lite/models/text_classification/overview
168268
[4]: https://github.com/tensorflow/tflite-support/blob/fe8b69002f5416900285dc69e2baa078c91bd994/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h#L55
169269
[5]: http://bert/nl/classifier/model
170270
[6]: https://tfhub.dev/google/lite-model/universal-sentence-encoder-qa-ondevice/1
271+
[7]: https://en.wikipedia.org/wiki/Cosine_similarity
272+
[8]: https://www.tensorflow.org/lite/guide/model_maker

tensorflow_lite_support/examples/task/text/desktop/text_embedder_demo.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ limitations under the License.
3434
#include "tensorflow_lite_support/cc/task/processor/proto/embedding.pb.h"
3535
#include "tensorflow_lite_support/cc/task/text/proto/text_embedder_options.pb.h"
3636
#include "tensorflow_lite_support/cc/task/text/text_embedder.h"
37+
#include "tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h"
3738

3839
ABSL_FLAG(std::string, model_path, "",
3940
"Absolute path to the '.tflite' text embedder model.");
@@ -79,8 +80,9 @@ TextEmbedderOptions BuildOptions() {
7980
absl::Status ComputeCosineSimilarity() {
8081
// Build TextEmbedder.
8182
const TextEmbedderOptions options = BuildOptions();
82-
ASSIGN_OR_RETURN(std::unique_ptr<TextEmbedder> text_embedder,
83-
TextEmbedder::CreateFromOptions(options));
83+
ASSIGN_OR_RETURN(
84+
std::unique_ptr<TextEmbedder> text_embedder,
85+
TextEmbedder::CreateFromOptions(options, CreateQACustomOpResolver()));
8486

8587
// Run search and display results.
8688
auto start_embed = steady_clock::now();

tensorflow_lite_support/examples/task/text/desktop/text_searcher_demo.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ limitations under the License.
3737
#include "tensorflow_lite_support/cc/task/processor/proto/search_result.pb.h"
3838
#include "tensorflow_lite_support/cc/task/text/proto/text_searcher_options.pb.h"
3939
#include "tensorflow_lite_support/cc/task/text/text_searcher.h"
40+
#include "tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h"
4041

4142
ABSL_FLAG(std::string, model_path, "",
4243
"Absolute path to the '.tflite' text embedder model.");
4344
ABSL_FLAG(std::string, index_path, "",
44-
"Absolute path to the index to search into.");
45+
"Absolute path to the index to search into. Mandatory only if the "
46+
"index is not attached to the output tensor metadata of the embedder "
47+
"model as an AssociatedFile with type SCANN_INDEX_FILE.");
4548
ABSL_FLAG(std::string, input_sentence, "",
4649
"Input sentence whose nearest-neighbors to search for in the index.");
4750
ABSL_FLAG(int32, max_results, 5,
@@ -70,8 +73,10 @@ TextSearcherOptions BuildOptions() {
7073
if (absl::GetFlag(FLAGS_l2_normalize)) {
7174
options.mutable_embedding_options()->set_l2_normalize(true);
7275
}
73-
options.mutable_search_options()->mutable_index_file()->set_file_name(
74-
absl::GetFlag(FLAGS_index_path));
76+
if (!absl::GetFlag(FLAGS_index_path).empty()) {
77+
options.mutable_search_options()->mutable_index_file()->set_file_name(
78+
absl::GetFlag(FLAGS_index_path));
79+
}
7580
options.mutable_search_options()->set_max_results(
7681
absl::GetFlag(FLAGS_max_results));
7782
if (absl::GetFlag(FLAGS_use_coral)) {
@@ -96,8 +101,9 @@ void DisplayResults(const processor::SearchResult& result) {
96101
absl::Status Search() {
97102
// Build TextSearcher.
98103
const TextSearcherOptions options = BuildOptions();
99-
ASSIGN_OR_RETURN(std::unique_ptr<TextSearcher> text_searcher,
100-
TextSearcher::CreateFromOptions(options));
104+
ASSIGN_OR_RETURN(
105+
std::unique_ptr<TextSearcher> text_searcher,
106+
TextSearcher::CreateFromOptions(options, CreateQACustomOpResolver()));
101107

102108
// Run search and display results.
103109
auto start_search = steady_clock::now();
@@ -128,10 +134,6 @@ int main(int argc, char** argv) {
128134
std::cerr << "Missing mandatory 'model_path' argument.\n";
129135
return 1;
130136
}
131-
if (absl::GetFlag(FLAGS_index_path).empty()) {
132-
std::cerr << "Missing mandatory 'index_path' argument.\n";
133-
return 1;
134-
}
135137
if (absl::GetFlag(FLAGS_input_sentence).empty()) {
136138
std::cerr << "Missing mandatory 'input_sentence' argument.\n";
137139
return 1;

tensorflow_lite_support/examples/task/vision/desktop/README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,112 @@ And `/tmp/segmentation-output.jpg` should contain the segmentation mask:
259259

260260
![segmentation-output](g3doc/segmentation-output.png)
261261

262+
## ImageEmbedder
263+
264+
#### Prerequisites
265+
266+
You will need:
267+
268+
* a TFLite image embedder model (e.g. [mobilenet v3][5], a generic image
269+
embedder trained on ImageNet),
270+
* two PNG, JPEG or GIF image to extract embeddings from.
271+
272+
#### Usage
273+
274+
The ImageEmbedder demo tool takes two images as inputs, and outputs the
275+
[cosine similarity][6] between their embeddings.
276+
277+
In the console, run:
278+
279+
```bash
280+
# Download the model:
281+
curl \
282+
-L 'https://tfhub.dev/google/lite-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/metadata/1?lite-format=tflite' \
283+
-o /tmp/mobilenet_v3_embedder.tflite
284+
285+
# Run the embedder tool:
286+
bazel run -c opt \
287+
tensorflow_lite_support/examples/task/vision/desktop:image_embedder_demo -- \
288+
--model_path=/tmp/mobilenet_v3_embedder.tflite \
289+
--l2_normalize \
290+
--first_image_path=$(pwd)/tensorflow_lite_support/cc/test/testdata/task/vision/burger.jpg \
291+
--second_image_path=$(pwd)/tensorflow_lite_support/cc/test/testdata/task/vision/burger_crop.jpg
292+
```
293+
294+
#### Results
295+
296+
In the console, you should get:
297+
298+
```
299+
Cosine similarity: 0.932738
300+
```
301+
302+
## ImageSearcher
303+
304+
#### Prerequisites
305+
306+
TODO(b/231294362): update link to Model Maker.
307+
308+
You will need:
309+
310+
* a TFLite image embedder model (e.g. [mobilenet v3][5], a generic image
311+
embedder trained on ImageNet),
312+
* an index built from that embedder model using [Model Maker][7].
313+
314+
Model Maker also provides the ability to add the index directly to the embedder
315+
model metadata. The demo also supports this : just omit the `--index_path`
316+
argument.
317+
318+
#### Usage
319+
320+
In this example, we'll be using a test index built from the mobilenet v3
321+
embedder model, which only contains 5 embeddings extracted from images of a
322+
burger, a cat, a dog, a bird and a car.
323+
324+
In the console, run:
325+
326+
```bash
327+
# Download the model:
328+
curl \
329+
-L 'https://tfhub.dev/google/lite-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/metadata/1?lite-format=tflite' \
330+
-o /tmp/mobilenet_v3_embedder.tflite
331+
332+
# Run the searcher tool:
333+
bazel run -c opt \
334+
tensorflow_lite_support/examples/task/vision/desktop:image_searcher_demo -- \
335+
--model_path=/tmp/mobilenet_v3_embedder.tflite \
336+
--l2_normalize \
337+
--index_path=$(pwd)/third_party/tensorflow_lite_support/cc/test/testdata/task/vision/searcher_index.ldb \
338+
--image_path=$(pwd)/third_party/tensorflow_lite_support/cc/test/testdata/task/vision/burger_crop.jpg
339+
```
340+
341+
#### Results
342+
343+
In the console, you should get:
344+
345+
```
346+
Results:
347+
Rank#0:
348+
metadata: burger
349+
distance: 0.13452
350+
Rank#1:
351+
metadata: car
352+
distance: 1.81935
353+
Rank#2:
354+
metadata: bird
355+
distance: 1.96617
356+
Rank#3:
357+
metadata: dog
358+
distance: 2.05610
359+
Rank#4:
360+
metadata: cat
361+
distance: 2.06347
362+
```
363+
262364
[1]: https://tfhub.dev/google/lite-model/aiy/vision/classifier/birds_V1/3
263365
[2]: https://tfhub.dev/tensorflow/lite-model/ssd_mobilenet_v1/1/metadata/2
264366
[3]: https://tfhub.dev/tensorflow/lite-model/deeplabv3/1/metadata/2
265367
[4]: https://coral.ai/docs/edgetpu/inference/
368+
[5]: https://tfhub.dev/google/lite-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/metadata/1
369+
[6]: https://en.wikipedia.org/wiki/Cosine_similarity
370+
[7]: https://www.tensorflow.org/lite/guide/model_maker

tensorflow_lite_support/examples/task/vision/desktop/image_searcher_demo.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ limitations under the License.
4545
ABSL_FLAG(std::string, model_path, "",
4646
"Absolute path to the '.tflite' image embedder model.");
4747
ABSL_FLAG(std::string, index_path, "",
48-
"Absolute path to the index to search into.");
48+
"Absolute path to the index to search into. Mandatory only if the "
49+
"index is not attached to the output tensor metadata of the embedder "
50+
"model as an AssociatedFile with type SCANN_INDEX_FILE.");
4951
ABSL_FLAG(std::string, image_path, "",
5052
"Absolute path to the image to search. The image must be RGB or "
5153
"RGBA (grayscale is not supported). The image EXIF orientation "
@@ -76,8 +78,10 @@ ImageSearcherOptions BuildOptions() {
7678
if (absl::GetFlag(FLAGS_l2_normalize)) {
7779
options.mutable_embedding_options()->set_l2_normalize(true);
7880
}
79-
options.mutable_search_options()->mutable_index_file()->set_file_name(
80-
absl::GetFlag(FLAGS_index_path));
81+
if (!absl::GetFlag(FLAGS_index_path).empty()) {
82+
options.mutable_search_options()->mutable_index_file()->set_file_name(
83+
absl::GetFlag(FLAGS_index_path));
84+
}
8185
options.mutable_search_options()->set_max_results(
8286
absl::GetFlag(FLAGS_max_results));
8387
if (absl::GetFlag(FLAGS_use_coral)) {
@@ -152,10 +156,6 @@ int main(int argc, char** argv) {
152156
std::cerr << "Missing mandatory 'model_path' argument.\n";
153157
return 1;
154158
}
155-
if (absl::GetFlag(FLAGS_index_path).empty()) {
156-
std::cerr << "Missing mandatory 'index_path' argument.\n";
157-
return 1;
158-
}
159159
if (absl::GetFlag(FLAGS_image_path).empty()) {
160160
std::cerr << "Missing mandatory 'image_path' argument.\n";
161161
return 1;

tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,18 @@ NS_SWIFT_NAME(ClassificationCategory)
3434
@property(nonatomic, readonly, nullable) NSString *displayName;
3535

3636
/**
37-
* Initializes TFLCategory.
37+
* Initializes a new `TFLCategory` with the given index, score, label and display name.
3838
*
3939
* @param index Index of the class in the corresponding label map, usually packed in the TFLite
4040
* Model Metadata.
4141
*
42-
* @param score Confidence score for this class .
42+
* @param score Confidence score for this class.
4343
*
4444
* @param label Class name of the class.
4545
*
4646
* @param displayName Display name of the class.
4747
*
48-
* @return An instance of TFLCategory initialized to
49-
* the specified values.
48+
* @return An instance of `TFLCategory` initialized with the given index, score, label and display name.
5049
*/
5150
- (instancetype)initWithIndex:(NSInteger)index
5251
score:(float)score

tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
2020
@interface TFLClassificationResult (Helpers)
2121

2222
/**
23-
* Creates and retrurns a TFLClassificationResult from a TfLiteClassificationResult returned by
23+
* Creates and returns a TFLClassificationResult from a TfLiteClassificationResult returned by
2424
* TFLite Task C Library Classification tasks.
2525
*
2626
* @param cClassificationResult Classification results returned by TFLite Task C Library

0 commit comments

Comments
 (0)