Tensorflow functions and applications

* initial step
 * Tensorflow models functional model redesign

      -- Based on https://tzolov.github.io/mind-model-services
      -- Resolves #5

 * Add object detection processor README
 * Add image recognition processor README
 * Initial Tensorflow commonn README
 * Initial Tensorflow commonn README
 * Tensorflow common diagram
 * Tensorflow docs code
 * Tensorflow docs code snippets improve
 * Tensorflow docs code snippets improve
 * Tensorflow docs code snippets improve
 * Tensorflow docs code snippets improve
 * Add semantic segmentation function. add object detecteion function readme
 * oo images
 * Furether oo readme improvments
 * Final obj detection readme fixes
 * Add image recognition readme
 * Add image recognition readme 2
 * Semantic segmentation readme
 * Segmentation readme
 * Semantic segmentation readme 3
 * Fix image recognition and object detcion app starter dependecies

 * Add metadata for Tensorflow apps
This commit is contained in:
Christian Tzolov
2020-06-11 17:07:44 +02:00
committed by Soby Chacko
parent 052f86cf91
commit ebe05bc315
100 changed files with 11343 additions and 15 deletions

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2020-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.app.processor.object.detection;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.function.Function;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.fn.common.tensorflow.deprecated.JsonMapperFunction;
import org.springframework.cloud.fn.object.detection.ObjectDetectionImageAugmenter;
import org.springframework.cloud.fn.object.detection.ObjectDetectionService;
import org.springframework.cloud.fn.object.detection.domain.ObjectDetection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.util.CollectionUtils;
/**
* @author Christian Tzolov
*/
@Configuration
@EnableConfigurationProperties(ObjectDetectionProcessorProperties.class)
public class ObjectDetectionProcessorConfiguration {
private static final Log logger = LogFactory.getLog(ObjectDetectionProcessorConfiguration.class);
/**
* Name of the Message header containing the JSON encoded detected objects.
*/
public static final String DETECTED_OBJECTS_HEADER = "detected_objects";
@Bean
public ObjectDetectionService objectDetectionService(ObjectDetectionProcessorProperties properties) {
return new ObjectDetectionService(properties.getModel(),
properties.getLabels(), properties.getConfidence(), properties.isWithMasks(),
properties.isCacheModel());
}
@Bean
public Function<Message<byte[]>, Message<byte[]>> objectDetection(
ObjectDetectionService objectDetectionService,
ObjectDetectionProcessorProperties properties) {
return input -> {
// You can use file:, http: or classpath: to provide the path to the input image.
byte[] inputImage = input.getPayload();
List<ObjectDetection> detectedObjects = objectDetectionService.detect(inputImage);
if (!CollectionUtils.isEmpty(detectedObjects) && properties.getResponseSize() < detectedObjects.size()) {
detectedObjects = detectedObjects.subList(0, properties.getResponseSize());
}
// Draw the predicted labels on top of the input image.
byte[] augmentedImage = new ObjectDetectionImageAugmenter().apply(inputImage, detectedObjects);
String jsonDetectedObjects = new JsonMapperFunction().apply(detectedObjects);
Message<byte[]> outMessage = MessageBuilder
.withPayload(augmentedImage)
.setHeader(DETECTED_OBJECTS_HEADER, jsonDetectedObjects)
.build();
if (properties.isDebugOutput()) {
try {
logger.info("detected objects = " + jsonDetectedObjects);
IOUtils.write(augmentedImage, new FileOutputStream(properties.getDebugOutputPath()));
}
catch (IOException e) {
logger.warn("Cloud not produce debug output", e);
}
}
return outMessage;
};
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2020-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.app.processor.object.detection;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
/**
* @author Christian Tzolov
*/
@ConfigurationProperties("object.detection")
@Validated
public class ObjectDetectionProcessorProperties {
/**
* pre-trained tensorflow object detection model.
*/
private String model = "https://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz#frozen_inference_graph.pb";
/**
* Labels URI.
*/
private String labels = "https://storage.googleapis.com/scdf-tensorflow-models/object-detection/mscoco_label_map.pbtxt";
private float confidence = 0.4f;
private boolean withMasks;
private boolean cacheModel = true;
private boolean debugOutput = false;
private String debugOutputPath = "object-detection-result.png";
private int responseSize = Integer.MAX_VALUE;
public boolean isDebugOutput() {
return debugOutput;
}
public void setDebugOutput(boolean debugOutput) {
this.debugOutput = debugOutput;
}
public String getDebugOutputPath() {
return debugOutputPath;
}
public void setDebugOutputPath(String debugOutputPath) {
this.debugOutputPath = debugOutputPath;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getLabels() {
return labels;
}
public void setLabels(String labels) {
this.labels = labels;
}
public float getConfidence() {
return confidence;
}
public void setConfidence(float confidence) {
this.confidence = confidence;
}
public boolean isWithMasks() {
return withMasks;
}
public void setWithMasks(boolean withMasks) {
this.withMasks = withMasks;
}
public boolean isCacheModel() {
return cacheModel;
}
public void setCacheModel(boolean cacheModel) {
this.cacheModel = cacheModel;
}
public int getResponseSize() {
return responseSize;
}
public void setResponseSize(int responseSize) {
this.responseSize = responseSize;
}
}

View File

@@ -0,0 +1,2 @@
configuration-properties.classes=\
org.springframework.cloud.stream.app.processor.object.detection.ObjectDetectionProcessorProperties

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2020-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.app.processor.object.detection;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.fn.common.tensorflow.deprecated.GraphicsUtils;
import org.springframework.cloud.stream.binder.test.InputDestination;
import org.springframework.cloud.stream.binder.test.OutputDestination;
import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Christian Tzolov
*/
public class ObjectDetectionProcessorTests {
@Test
public void testObjectDetectionProcessor() throws IOException {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(ObjectDetectionProcessorTestApplication.class))
.web(WebApplicationType.NONE)
.run("--spring.cloud.function.definition=objectDetection",
"--object.detection.model=https://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz#frozen_inference_graph.pb",
"--object.detection.labels=https://storage.googleapis.com/scdf-tensorflow-models/object-detection/mscoco_label_map.pbtxt",
"--object.detection.responseSize=10",
"--object.detection..debugOutput=true",
"--object.detection..debugOutputPath=./target/object-detection-1.png")) {
InputDestination processorInput = context.getBean(InputDestination.class);
OutputDestination processorOutput = context.getBean(OutputDestination.class);
byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/pivotal.jpeg");
processorInput.send(new GenericMessage<>(inputImage));
Message<byte[]> sourceMessage = processorOutput.receive(10000);
String jsonRecognizedObjects = (String) sourceMessage.getHeaders().get(ObjectDetectionProcessorConfiguration.DETECTED_OBJECTS_HEADER);
assertThat(jsonRecognizedObjects).isNotEmpty();
//assertThat(jsonRecognizedObjects)
// .isEqualTo("[{\"label\":\"giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca\",\"probability\":0.962329626083374}," +
// "{\"label\":\"badger\",\"probability\":0.006058811210095882}," +
// "{\"label\":\"ram, tup\",\"probability\":0.0010668420000001788}]");
}
}
//@Test
public void testObjectDetectionProcessoriNaturalistSpecies() throws IOException {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(ObjectDetectionProcessorTestApplication.class))
.web(WebApplicationType.NONE)
.run(
//"--spring.cloud.function.definition=objectDetection",
"--object.detection.model=http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_fgvc_2018_07_19.tar.gz#frozen_inference_graph.pb",
"--object.detection.labels=https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/fgvc_2854_classes_label_map.pbtxt",
"--object.detection..debugOutput=true",
"--object.detection..debugOutputPath=./target/object-detection-2.png")) {
InputDestination processorInput = context.getBean(InputDestination.class);
OutputDestination processorOutput = context.getBean(OutputDestination.class);
byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/animals2.jpg");
processorInput.send(new GenericMessage<>(inputImage));
Message<byte[]> sourceMessage = processorOutput.receive(10000);
String jsonRecognizedObjects = (String) sourceMessage.getHeaders().get(ObjectDetectionProcessorConfiguration.DETECTED_OBJECTS_HEADER);
//assertThat(jsonRecognizedObjects)
// .isEqualTo("[{\"label\":\"giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca\",\"probability\":0.962329626083374}," +
// "{\"label\":\"badger\",\"probability\":0.006058811210095882}," +
// "{\"label\":\"ram, tup\",\"probability\":0.0010668420000001788}]");
}
}
@SpringBootApplication
@Import({ ObjectDetectionProcessorConfiguration.class })
public static class ObjectDetectionProcessorTestApplication {
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB