boza = objectDetectionService2.detect(inputImage);
+
+ System.out.println(boza);
+ }
+ }
+}
diff --git a/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/domain/ObjectDetection.java b/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/domain/ObjectDetection.java
new file mode 100644
index 00000000..15e10758
--- /dev/null
+++ b/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/domain/ObjectDetection.java
@@ -0,0 +1,116 @@
+/*
+ * 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.fn.object.detection.domain;
+
+import java.util.Arrays;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * @author Christian Tzolov
+ */
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ObjectDetection {
+
+ private String name;
+ private float confidence;
+ private float x1;
+ private float y1;
+ private float x2;
+ private float y2;
+ private float[][] mask;
+ private int cid;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public float getConfidence() {
+ return confidence;
+ }
+
+ public void setConfidence(float confidence) {
+ this.confidence = confidence;
+ }
+
+ public float getX1() {
+ return x1;
+ }
+
+ public void setX1(float x1) {
+ this.x1 = x1;
+ }
+
+ public float getY1() {
+ return y1;
+ }
+
+ public void setY1(float y1) {
+ this.y1 = y1;
+ }
+
+ public float getX2() {
+ return x2;
+ }
+
+ public void setX2(float x2) {
+ this.x2 = x2;
+ }
+
+ public float getY2() {
+ return y2;
+ }
+
+ public void setY2(float y2) {
+ this.y2 = y2;
+ }
+
+ public int getCid() {
+ return cid;
+ }
+
+ public void setCid(int cid) {
+ this.cid = cid;
+ }
+
+ public float[][] getMask() {
+ return mask;
+ }
+
+ public void setMask(float[][] mask) {
+ this.mask = mask;
+ }
+
+ @Override
+ public String toString() {
+ return "ObjectDetection{" +
+ "name='" + name + '\'' +
+ ", confidence=" + confidence +
+ ", x1=" + x1 +
+ ", y1=" + y1 +
+ ", x2=" + x2 +
+ ", y2=" + y2 +
+ ", mask=" + Arrays.toString(mask) +
+ ", cid=" + cid +
+ '}';
+ }
+}
diff --git a/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/protos/StringIntLabelMapOuterClass.java b/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/protos/StringIntLabelMapOuterClass.java
new file mode 100644
index 00000000..19a7177d
--- /dev/null
+++ b/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/protos/StringIntLabelMapOuterClass.java
@@ -0,0 +1,1845 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: string_int_label_map.proto
+
+package org.springframework.cloud.fn.object.detection.protos;
+
+public final class StringIntLabelMapOuterClass {
+ private StringIntLabelMapOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface StringIntLabelMapItemOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ boolean hasName();
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ java.lang.String getName();
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ com.google.protobuf.ByteString
+ getNameBytes();
+
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ boolean hasId();
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ int getId();
+
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ boolean hasDisplayName();
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ java.lang.String getDisplayName();
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ com.google.protobuf.ByteString
+ getDisplayNameBytes();
+ }
+ /**
+ * Protobuf type {@code org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem}
+ */
+ public static final class StringIntLabelMapItem extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem)
+ StringIntLabelMapItemOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use StringIntLabelMapItem.newBuilder() to construct.
+ private StringIntLabelMapItem(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private StringIntLabelMapItem() {
+ name_ = "";
+ displayName_ = "";
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private StringIntLabelMapItem(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ com.google.protobuf.ByteString bs = input.readBytes();
+ bitField0_ |= 0x00000001;
+ name_ = bs;
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ id_ = input.readInt32();
+ break;
+ }
+ case 26: {
+ com.google.protobuf.ByteString bs = input.readBytes();
+ bitField0_ |= 0x00000004;
+ displayName_ = bs;
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.class, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder.class);
+ }
+
+ private int bitField0_;
+ public static final int NAME_FIELD_NUMBER = 1;
+ private volatile java.lang.Object name_;
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ name_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int ID_FIELD_NUMBER = 2;
+ private int id_;
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public int getId() {
+ return id_;
+ }
+
+ public static final int DISPLAY_NAME_FIELD_NUMBER = 3;
+ private volatile java.lang.Object displayName_;
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public boolean hasDisplayName() {
+ return ((bitField0_ & 0x00000004) != 0);
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public java.lang.String getDisplayName() {
+ java.lang.Object ref = displayName_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ displayName_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public com.google.protobuf.ByteString
+ getDisplayNameBytes() {
+ java.lang.Object ref = displayName_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ displayName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ output.writeInt32(2, id_);
+ }
+ if (((bitField0_ & 0x00000004) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 3, displayName_);
+ }
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, id_);
+ }
+ if (((bitField0_ & 0x00000004) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, displayName_);
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem)) {
+ return super.equals(obj);
+ }
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem other = (org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem) obj;
+
+ if (hasName() != other.hasName()) return false;
+ if (hasName()) {
+ if (!getName()
+ .equals(other.getName())) return false;
+ }
+ if (hasId() != other.hasId()) return false;
+ if (hasId()) {
+ if (getId()
+ != other.getId()) return false;
+ }
+ if (hasDisplayName() != other.hasDisplayName()) return false;
+ if (hasDisplayName()) {
+ if (!getDisplayName()
+ .equals(other.getDisplayName())) return false;
+ }
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (hasName()) {
+ hash = (37 * hash) + NAME_FIELD_NUMBER;
+ hash = (53 * hash) + getName().hashCode();
+ }
+ if (hasId()) {
+ hash = (37 * hash) + ID_FIELD_NUMBER;
+ hash = (53 * hash) + getId();
+ }
+ if (hasDisplayName()) {
+ hash = (37 * hash) + DISPLAY_NAME_FIELD_NUMBER;
+ hash = (53 * hash) + getDisplayName().hashCode();
+ }
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem)
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.class, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder.class);
+ }
+
+ // Construct using org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ name_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ displayName_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getDefaultInstanceForType() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem build() {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem buildPartial() {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem result = new org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.name_ = name_;
+ if (((from_bitField0_ & 0x00000002) != 0)) {
+ result.id_ = id_;
+ to_bitField0_ |= 0x00000002;
+ }
+ if (((from_bitField0_ & 0x00000004) != 0)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.displayName_ = displayName_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem) {
+ return mergeFrom((org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem other) {
+ if (other == org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.getDefaultInstance()) return this;
+ if (other.hasName()) {
+ bitField0_ |= 0x00000001;
+ name_ = other.name_;
+ onChanged();
+ }
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasDisplayName()) {
+ bitField0_ |= 0x00000004;
+ displayName_ = other.displayName_;
+ onChanged();
+ }
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ private java.lang.Object name_ = "";
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ name_ = s;
+ }
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public Builder setName(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ name_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public Builder clearName() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ name_ = getDefaultInstance().getName();
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ * String name. The most common practice is to set this to a MID or synsets
+ * id. Synset: a set of synonyms that share a common meaning.
+ * https://en.wikipedia.org/wiki/WordNet
+ *
+ *
+ * optional string name = 1;
+ */
+ public Builder setNameBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ name_ = value;
+ onChanged();
+ return this;
+ }
+
+ private int id_ ;
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000002;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ * Integer id that maps to the string name above. Label ids should start
+ * from 1.
+ *
+ *
+ * optional int32 id = 2;
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object displayName_ = "";
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public boolean hasDisplayName() {
+ return ((bitField0_ & 0x00000004) != 0);
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public java.lang.String getDisplayName() {
+ java.lang.Object ref = displayName_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ displayName_ = s;
+ }
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public com.google.protobuf.ByteString
+ getDisplayNameBytes() {
+ java.lang.Object ref = displayName_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ displayName_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public Builder setDisplayName(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ displayName_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public Builder clearDisplayName() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ displayName_ = getDefaultInstance().getDisplayName();
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ * Human readable string label.
+ *
+ *
+ * optional string display_name = 3;
+ */
+ public Builder setDisplayNameBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ displayName_ = value;
+ onChanged();
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem)
+ }
+
+ // @@protoc_insertion_point(class_scope:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem)
+ private static final org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem();
+ }
+
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ @java.lang.Deprecated public static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public StringIntLabelMapItem parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new StringIntLabelMapItem(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ public interface StringIntLabelMapOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ java.util.List
+ getItemList();
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getItem(int index);
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ int getItemCount();
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ java.util.List extends org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder>
+ getItemOrBuilderList();
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder getItemOrBuilder(
+ int index);
+ }
+ /**
+ * Protobuf type {@code org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap}
+ */
+ public static final class StringIntLabelMap extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap)
+ StringIntLabelMapOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use StringIntLabelMap.newBuilder() to construct.
+ private StringIntLabelMap(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private StringIntLabelMap() {
+ item_ = java.util.Collections.emptyList();
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private StringIntLabelMap(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+ item_ = new java.util.ArrayList();
+ mutable_bitField0_ |= 0x00000001;
+ }
+ item_.add(
+ input.readMessage(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.PARSER, extensionRegistry));
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000001) != 0)) {
+ item_ = java.util.Collections.unmodifiableList(item_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.class, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.Builder.class);
+ }
+
+ public static final int ITEM_FIELD_NUMBER = 1;
+ private java.util.List item_;
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public java.util.List getItemList() {
+ return item_;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public java.util.List extends org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder>
+ getItemOrBuilderList() {
+ return item_;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public int getItemCount() {
+ return item_.size();
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getItem(int index) {
+ return item_.get(index);
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder getItemOrBuilder(
+ int index) {
+ return item_.get(index);
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ for (int i = 0; i < item_.size(); i++) {
+ output.writeMessage(1, item_.get(i));
+ }
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (int i = 0; i < item_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, item_.get(i));
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap)) {
+ return super.equals(obj);
+ }
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap other = (org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap) obj;
+
+ if (!getItemList()
+ .equals(other.getItemList())) return false;
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (getItemCount() > 0) {
+ hash = (37 * hash) + ITEM_FIELD_NUMBER;
+ hash = (53 * hash) + getItemList().hashCode();
+ }
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap)
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.class, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.Builder.class);
+ }
+
+ // Construct using org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ getItemFieldBuilder();
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ if (itemBuilder_ == null) {
+ item_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ itemBuilder_.clear();
+ }
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap getDefaultInstanceForType() {
+ return org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap build() {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap buildPartial() {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap result = new org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap(this);
+ int from_bitField0_ = bitField0_;
+ if (itemBuilder_ == null) {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ item_ = java.util.Collections.unmodifiableList(item_);
+ bitField0_ = (bitField0_ & ~0x00000001);
+ }
+ result.item_ = item_;
+ } else {
+ result.item_ = itemBuilder_.build();
+ }
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap) {
+ return mergeFrom((org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap other) {
+ if (other == org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap.getDefaultInstance()) return this;
+ if (itemBuilder_ == null) {
+ if (!other.item_.isEmpty()) {
+ if (item_.isEmpty()) {
+ item_ = other.item_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ ensureItemIsMutable();
+ item_.addAll(other.item_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.item_.isEmpty()) {
+ if (itemBuilder_.isEmpty()) {
+ itemBuilder_.dispose();
+ itemBuilder_ = null;
+ item_ = other.item_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ itemBuilder_ =
+ com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+ getItemFieldBuilder() : null;
+ } else {
+ itemBuilder_.addAllMessages(other.item_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ private java.util.List item_ =
+ java.util.Collections.emptyList();
+ private void ensureItemIsMutable() {
+ if (!((bitField0_ & 0x00000001) != 0)) {
+ item_ = new java.util.ArrayList(item_);
+ bitField0_ |= 0x00000001;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder> itemBuilder_;
+
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public java.util.List getItemList() {
+ if (itemBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(item_);
+ } else {
+ return itemBuilder_.getMessageList();
+ }
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public int getItemCount() {
+ if (itemBuilder_ == null) {
+ return item_.size();
+ } else {
+ return itemBuilder_.getCount();
+ }
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem getItem(int index) {
+ if (itemBuilder_ == null) {
+ return item_.get(index);
+ } else {
+ return itemBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder setItem(
+ int index, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem value) {
+ if (itemBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureItemIsMutable();
+ item_.set(index, value);
+ onChanged();
+ } else {
+ itemBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder setItem(
+ int index, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder builderForValue) {
+ if (itemBuilder_ == null) {
+ ensureItemIsMutable();
+ item_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ itemBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder addItem(org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem value) {
+ if (itemBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureItemIsMutable();
+ item_.add(value);
+ onChanged();
+ } else {
+ itemBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder addItem(
+ int index, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem value) {
+ if (itemBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureItemIsMutable();
+ item_.add(index, value);
+ onChanged();
+ } else {
+ itemBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder addItem(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder builderForValue) {
+ if (itemBuilder_ == null) {
+ ensureItemIsMutable();
+ item_.add(builderForValue.build());
+ onChanged();
+ } else {
+ itemBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder addItem(
+ int index, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder builderForValue) {
+ if (itemBuilder_ == null) {
+ ensureItemIsMutable();
+ item_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ itemBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder addAllItem(
+ java.lang.Iterable extends org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem> values) {
+ if (itemBuilder_ == null) {
+ ensureItemIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(
+ values, item_);
+ onChanged();
+ } else {
+ itemBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder clearItem() {
+ if (itemBuilder_ == null) {
+ item_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ } else {
+ itemBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public Builder removeItem(int index) {
+ if (itemBuilder_ == null) {
+ ensureItemIsMutable();
+ item_.remove(index);
+ onChanged();
+ } else {
+ itemBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder getItemBuilder(
+ int index) {
+ return getItemFieldBuilder().getBuilder(index);
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder getItemOrBuilder(
+ int index) {
+ if (itemBuilder_ == null) {
+ return item_.get(index); } else {
+ return itemBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public java.util.List extends org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder>
+ getItemOrBuilderList() {
+ if (itemBuilder_ != null) {
+ return itemBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(item_);
+ }
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder addItemBuilder() {
+ return getItemFieldBuilder().addBuilder(
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.getDefaultInstance());
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder addItemBuilder(
+ int index) {
+ return getItemFieldBuilder().addBuilder(
+ index, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.getDefaultInstance());
+ }
+ /**
+ * repeated .org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapItem item = 1;
+ */
+ public java.util.List
+ getItemBuilderList() {
+ return getItemFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder>
+ getItemFieldBuilder() {
+ if (itemBuilder_ == null) {
+ itemBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+ org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItem.Builder, org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMapItemOrBuilder>(
+ item_,
+ ((bitField0_ & 0x00000001) != 0),
+ getParentForChildren(),
+ isClean());
+ item_ = null;
+ }
+ return itemBuilder_;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap)
+ }
+
+ // @@protoc_insertion_point(class_scope:org.springframework.cloud.fn.object.detection.protos.StringIntLabelMap)
+ private static final org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap();
+ }
+
+ public static org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ @java.lang.Deprecated public static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public StringIntLabelMap parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new StringIntLabelMap(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public org.springframework.cloud.fn.object.detection.protos.StringIntLabelMapOuterClass.StringIntLabelMap getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\032string_int_label_map.proto\0224org.spring" +
+ "framework.cloud.fn.object.detection.prot" +
+ "os\"G\n\025StringIntLabelMapItem\022\014\n\004name\030\001 \001(" +
+ "\t\022\n\n\002id\030\002 \001(\005\022\024\n\014display_name\030\003 \001(\t\"n\n\021S" +
+ "tringIntLabelMap\022Y\n\004item\030\001 \003(\0132K.org.spr" +
+ "ingframework.cloud.fn.object.detection.p" +
+ "rotos.StringIntLabelMapItem"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMapItem_descriptor,
+ new java.lang.String[] { "Name", "Id", "DisplayName", });
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor =
+ getDescriptor().getMessageTypes().get(1);
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_org_springframework_cloud_fn_object_detection_protos_StringIntLabelMap_descriptor,
+ new java.lang.String[] { "Item", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/function/object-detection-function/src/main/proto/example.proto__ b/function/object-detection-function/src/main/proto/example.proto__
new file mode 100644
index 00000000..fec7562a
--- /dev/null
+++ b/function/object-detection-function/src/main/proto/example.proto__
@@ -0,0 +1,301 @@
+// Protocol messages for describing input data Examples for machine learning
+// model training or inference.
+syntax = "proto3";
+
+import "feature.proto";
+option cc_enable_arenas = true;
+option java_outer_classname = "ExampleProtos";
+option java_multiple_files = true;
+option java_package = "org.tensorflow.example";
+option go_package = "github.com/tensorflow/tensorflow/tensorflow/go/core/example";
+package tensorflow;
+
+// An Example is a mostly-normalized data format for storing data for
+// training and inference. It contains a key-value store (features); where
+// each key (string) maps to a Feature message (which is oneof packed BytesList,
+// FloatList, or Int64List). This flexible and compact format allows the
+// storage of large amounts of typed data, but requires that the data shape
+// and use be determined by the configuration files and parsers that are used to
+// read and write this format. That is, the Example is mostly *not* a
+// self-describing format. In TensorFlow, Examples are read in row-major
+// format, so any configuration that describes data with rank-2 or above
+// should keep this in mind. For example, to store an M x N matrix of Bytes,
+// the BytesList must contain M*N bytes, with M rows of N contiguous values
+// each. That is, the BytesList value must store the matrix as:
+// .... row 0 .... .... row 1 .... // ........... // ... row M-1 ....
+//
+// An Example for a movie recommendation application:
+// features {
+// feature {
+// key: "age"
+// value { float_list {
+// value: 29.0
+// }}
+// }
+// feature {
+// key: "movie"
+// value { bytes_list {
+// value: "The Shawshank Redemption"
+// value: "Fight Club"
+// }}
+// }
+// feature {
+// key: "movie_ratings"
+// value { float_list {
+// value: 9.0
+// value: 9.7
+// }}
+// }
+// feature {
+// key: "suggestion"
+// value { bytes_list {
+// value: "Inception"
+// }}
+// }
+// # Note that this feature exists to be used as a label in training.
+// # E.g., if training a logistic regression model to predict purchase
+// # probability in our learning tool we would set the label feature to
+// # "suggestion_purchased".
+// feature {
+// key: "suggestion_purchased"
+// value { float_list {
+// value: 1.0
+// }}
+// }
+// # Similar to "suggestion_purchased" above this feature exists to be used
+// # as a label in training.
+// # E.g., if training a linear regression model to predict purchase
+// # price in our learning tool we would set the label feature to
+// # "purchase_price".
+// feature {
+// key: "purchase_price"
+// value { float_list {
+// value: 9.99
+// }}
+// }
+// }
+//
+// A conformant Example data set obeys the following conventions:
+// - If a Feature K exists in one example with data type T, it must be of
+// type T in all other examples when present. It may be omitted.
+// - The number of instances of Feature K list data may vary across examples,
+// depending on the requirements of the model.
+// - If a Feature K doesn't exist in an example, a K-specific default will be
+// used, if configured.
+// - If a Feature K exists in an example but contains no items, the intent
+// is considered to be an empty tensor and no default will be used.
+
+message Example {
+ Features features = 1;
+};
+
+// A SequenceExample is an Example representing one or more sequences, and
+// some context. The context contains features which apply to the entire
+// example. The feature_lists contain a key, value map where each key is
+// associated with a repeated set of Features (a FeatureList).
+// A FeatureList thus represents the values of a feature identified by its key
+// over time / frames.
+//
+// Below is a SequenceExample for a movie recommendation application recording a
+// sequence of ratings by a user. The time-independent features ("locale",
+// "age", "favorites") describing the user are part of the context. The sequence
+// of movies the user rated are part of the feature_lists. For each movie in the
+// sequence we have information on its name and actors and the user's rating.
+// This information is recorded in three separate feature_list(s).
+// In the example below there are only two movies. All three feature_list(s),
+// namely "movie_ratings", "movie_names", and "actors" have a feature value for
+// both movies. Note, that "actors" is itself a bytes_list with multiple
+// strings per movie.
+//
+// context: {
+// feature: {
+// key : "locale"
+// value: {
+// bytes_list: {
+// value: [ "pt_BR" ]
+// }
+// }
+// }
+// feature: {
+// key : "age"
+// value: {
+// float_list: {
+// value: [ 19.0 ]
+// }
+// }
+// }
+// feature: {
+// key : "favorites"
+// value: {
+// bytes_list: {
+// value: [ "Majesty Rose", "Savannah Outen", "One Direction" ]
+// }
+// }
+// }
+// }
+// feature_lists: {
+// feature_list: {
+// key : "movie_ratings"
+// value: {
+// feature: {
+// float_list: {
+// value: [ 4.5 ]
+// }
+// }
+// feature: {
+// float_list: {
+// value: [ 5.0 ]
+// }
+// }
+// }
+// }
+// feature_list: {
+// key : "movie_names"
+// value: {
+// feature: {
+// bytes_list: {
+// value: [ "The Shawshank Redemption" ]
+// }
+// }
+// feature: {
+// bytes_list: {
+// value: [ "Fight Club" ]
+// }
+// }
+// }
+// }
+// feature_list: {
+// key : "actors"
+// value: {
+// feature: {
+// bytes_list: {
+// value: [ "Tim Robbins", "Morgan Freeman" ]
+// }
+// }
+// feature: {
+// bytes_list: {
+// value: [ "Brad Pitt", "Edward Norton", "Helena Bonham Carter" ]
+// }
+// }
+// }
+// }
+// }
+//
+// A conformant SequenceExample data set obeys the following conventions:
+//
+// Context:
+// - All conformant context features K must obey the same conventions as
+// a conformant Example's features (see above).
+// Feature lists:
+// - A FeatureList L may be missing in an example; it is up to the
+// parser configuration to determine if this is allowed or considered
+// an empty list (zero length).
+// - If a FeatureList L exists, it may be empty (zero length).
+// - If a FeatureList L is non-empty, all features within the FeatureList
+// must have the same data type T. Even across SequenceExamples, the type T
+// of the FeatureList identified by the same key must be the same. An entry
+// without any values may serve as an empty feature.
+// - If a FeatureList L is non-empty, it is up to the parser configuration
+// to determine if all features within the FeatureList must
+// have the same size. The same holds for this FeatureList across multiple
+// examples.
+// - For sequence modeling, e.g.:
+// http://colah.github.io/posts/2015-08-Understanding-LSTMs/
+// https://github.com/tensorflow/nmt
+// the feature lists represent a sequence of frames.
+// In this scenario, all FeatureLists in a SequenceExample have the same
+// number of Feature messages, so that the ith element in each FeatureList
+// is part of the ith frame (or time step).
+// Examples of conformant and non-conformant examples' FeatureLists:
+//
+// Conformant FeatureLists:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+//
+// Non-conformant FeatureLists (mismatched types):
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { int64_list: { value: [ 5 ] } } }
+// } }
+//
+// Conditionally conformant FeatureLists, the parser configuration determines
+// if the feature sizes must match:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0, 6.0 ] } } }
+// } }
+//
+// Conformant pair of SequenceExample
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+// and:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } }
+// feature: { float_list: { value: [ 2.0 ] } } }
+// } }
+//
+// Conformant pair of SequenceExample
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+// and:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { }
+// } }
+//
+// Conditionally conformant pair of SequenceExample, the parser configuration
+// determines if the second feature_lists is consistent (zero-length) or
+// invalid (missing "movie_ratings"):
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+// and:
+// feature_lists: { }
+//
+// Non-conformant pair of SequenceExample (mismatched types)
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+// and:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { int64_list: { value: [ 4 ] } }
+// feature: { int64_list: { value: [ 5 ] } }
+// feature: { int64_list: { value: [ 2 ] } } }
+// } }
+//
+// Conditionally conformant pair of SequenceExample; the parser configuration
+// determines if the feature sizes must match:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.5 ] } }
+// feature: { float_list: { value: [ 5.0 ] } } }
+// } }
+// and:
+// feature_lists: { feature_list: {
+// key: "movie_ratings"
+// value: { feature: { float_list: { value: [ 4.0 ] } }
+// feature: { float_list: { value: [ 5.0, 3.0 ] } }
+// } }
+
+message SequenceExample {
+ Features context = 1;
+ FeatureLists feature_lists = 2;
+};
diff --git a/function/object-detection-function/src/main/proto/feature.proto__ b/function/object-detection-function/src/main/proto/feature.proto__
new file mode 100644
index 00000000..56f0f05e
--- /dev/null
+++ b/function/object-detection-function/src/main/proto/feature.proto__
@@ -0,0 +1,105 @@
+// Protocol messages for describing features for machine learning model
+// training or inference.
+//
+// There are three base Feature types:
+// - bytes
+// - float
+// - int64
+//
+// A Feature contains Lists which may hold zero or more values. These
+// lists are the base values BytesList, FloatList, Int64List.
+//
+// Features are organized into categories by name. The Features message
+// contains the mapping from name to Feature.
+//
+// Example Features for a movie recommendation application:
+// feature {
+// key: "age"
+// value { float_list {
+// value: 29.0
+// }}
+// }
+// feature {
+// key: "movie"
+// value { bytes_list {
+// value: "The Shawshank Redemption"
+// value: "Fight Club"
+// }}
+// }
+// feature {
+// key: "movie_ratings"
+// value { float_list {
+// value: 9.0
+// value: 9.7
+// }}
+// }
+// feature {
+// key: "suggestion"
+// value { bytes_list {
+// value: "Inception"
+// }}
+// }
+// feature {
+// key: "suggestion_purchased"
+// value { int64_list {
+// value: 1
+// }}
+// }
+// feature {
+// key: "purchase_price"
+// value { float_list {
+// value: 9.99
+// }}
+// }
+//
+
+syntax = "proto3";
+option cc_enable_arenas = true;
+option java_outer_classname = "FeatureProtos";
+option java_multiple_files = true;
+option java_package = "org.tensorflow.example";
+option go_package = "github.com/tensorflow/tensorflow/tensorflow/go/core/example";
+package tensorflow;
+
+// Containers to hold repeated fundamental values.
+message BytesList {
+ repeated bytes value = 1;
+}
+message FloatList {
+ repeated float value = 1 [packed = true];
+}
+message Int64List {
+ repeated int64 value = 1 [packed = true];
+}
+
+// Containers for non-sequential data.
+message Feature {
+ // Each feature can be exactly one kind.
+ oneof kind {
+ BytesList bytes_list = 1;
+ FloatList float_list = 2;
+ Int64List int64_list = 3;
+ }
+};
+
+message Features {
+ // Map from feature name to feature.
+ map feature = 1;
+};
+
+// Containers for sequential data.
+//
+// A FeatureList contains lists of Features. These may hold zero or more
+// Feature values.
+//
+// FeatureLists are organized into categories by name. The FeatureLists message
+// contains the mapping from name to FeatureList.
+//
+message FeatureList {
+ repeated Feature feature = 1;
+};
+
+message FeatureLists {
+ // Map from feature name to feature list.
+ map feature_list = 1;
+};
diff --git a/function/object-detection-function/src/main/proto/string_int_label_map.proto b/function/object-detection-function/src/main/proto/string_int_label_map.proto
new file mode 100644
index 00000000..bc5ccf47
--- /dev/null
+++ b/function/object-detection-function/src/main/proto/string_int_label_map.proto
@@ -0,0 +1,25 @@
+// Message to store the mapping from class label strings to class id. Datasets
+// use string labels to represent classes while the object detection framework
+// works fromMemory class ids. This message maps them so they can be converted back
+// and forth as needed.
+syntax = "proto2";
+
+package org.springframework.cloud.fn.object.detection.protos;
+
+message StringIntLabelMapItem {
+ // String name. The most common practice is to set this to a MID or synsets
+ // id. Synset: a set of synonyms that share a common meaning.
+ // https://en.wikipedia.org/wiki/WordNet
+ optional string name = 1;
+
+ // Integer id that maps to the string name above. Label ids should start
+ // from 1.
+ optional int32 id = 2;
+
+ // Human readable string label.
+ optional string display_name = 3;
+};
+
+message StringIntLabelMap {
+ repeated StringIntLabelMapItem item = 1;
+};
diff --git a/function/object-detection-function/src/main/resources/images/object-detection-augmented.jpg b/function/object-detection-function/src/main/resources/images/object-detection-augmented.jpg
new file mode 100644
index 00000000..f17adfd8
Binary files /dev/null and b/function/object-detection-function/src/main/resources/images/object-detection-augmented.jpg differ
diff --git a/function/object-detection-function/src/main/resources/images/object-detection-segmentation-augmented.jpg b/function/object-detection-function/src/main/resources/images/object-detection-segmentation-augmented.jpg
new file mode 100644
index 00000000..e9466f1e
Binary files /dev/null and b/function/object-detection-function/src/main/resources/images/object-detection-segmentation-augmented.jpg differ
diff --git a/function/object-detection-function/src/main/resources/images/object-detection.jpg b/function/object-detection-function/src/main/resources/images/object-detection.jpg
new file mode 100644
index 00000000..9eb325ac
Binary files /dev/null and b/function/object-detection-function/src/main/resources/images/object-detection.jpg differ
diff --git a/function/object-detection-function/src/main/resources/images/object_detection_1.jpg b/function/object-detection-function/src/main/resources/images/object_detection_1.jpg
new file mode 100644
index 00000000..913b2e6d
Binary files /dev/null and b/function/object-detection-function/src/main/resources/images/object_detection_1.jpg differ
diff --git a/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleInstanceSegmentation.java b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleInstanceSegmentation.java
new file mode 100644
index 00000000..31aa1ecf
--- /dev/null
+++ b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleInstanceSegmentation.java
@@ -0,0 +1,89 @@
+/*
+ * 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.fn.object.detection.examples;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+
+import org.springframework.cloud.fn.common.tensorflow.deprecated.GraphicsUtils;
+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.core.io.DefaultResourceLoader;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * 4 of the pre-trained model in the model zoo (https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md)
+ * can also compute the masks of the detected objects, providing instance segmentation.
+ *
+ * Here are the models that can be used for instance segmentation.
+ *
+ * mask_rcnn_inception_resnet_v2_atrous_coco 771 36 Masks
+ * mask_rcnn_inception_v2_coco 79 25 Masks
+ * mask_rcnn_resnet101_atrous_coco 470 33 Masks
+ * mask_rcnn_resnet50_atrous_coco 343 29 Masks
+ *
+ * @author Christian Tzolov
+ */
+public class ExampleInstanceSegmentation {
+
+ public static void main(String[] args) throws IOException {
+
+ ResourceLoader resourceLoader = new DefaultResourceLoader();
+
+ // You can download pre-trained models directly from the zoo: https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
+ // Just use the notation #
+ // For performance reasons you may consider downloading the model locally and use the file:/ URI instead!
+ String model = "http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz#frozen_inference_graph.pb";
+
+ // All labels for the pre-trained models are available at:
+ // https://github.com/tensorflow/models/tree/master/research/object_detection/data
+ // Use the labels applicable for the model.
+ // Also, for performance reasons you may consider to download the labels and load them from file: instead.
+ String labels = "https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/mscoco_label_map.pbtxt";
+
+ // You can cache the TF model on the local file system to improve the bootstrap performance on consecutive runs!
+ boolean CACHE_TF_MODEL = true;
+
+ // For the pre-trained models fromMemory mask you can set the INSTANCE_SEGMENTATION to enable object instance segmentation as well
+ boolean INSTANCE_SEGMENTATION = true;
+
+ // Only object fromMemory confidence above the threshold are returned
+ float CONFIDENCE_THRESHOLD = 0.4f;
+
+ ObjectDetectionService detectionService =
+ new ObjectDetectionService(model, labels, CONFIDENCE_THRESHOLD, INSTANCE_SEGMENTATION, CACHE_TF_MODEL);
+
+ // You can use file:, http: or classpath: to provide the path to the input image.
+ byte[] image = GraphicsUtils.loadAsByteArray("classpath:/images/object-detection.jpg");
+
+ // Returns a list ObjectDetection domain classes to allow programmatic accesses to the detected objects's metadata
+ List detectedObjects = detectionService.detect(image);
+
+ // Get JSON representation of the detected objects
+ String jsonObjectDetections = new JsonMapperFunction().apply(detectedObjects);
+ System.out.println(jsonObjectDetections);
+
+ // Draw the detected object metadata on top of the original image and store the result
+ byte[] annotatedImage = new ObjectDetectionImageAugmenter(INSTANCE_SEGMENTATION).apply(image, detectedObjects);
+ IOUtils.write(annotatedImage, new FileOutputStream("./object-detection-function/target/object-detection-segmentation-augmented.jpg"));
+ }
+}
diff --git a/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleObjectDetection.java b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleObjectDetection.java
new file mode 100644
index 00000000..f2d3102d
--- /dev/null
+++ b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/ExampleObjectDetection.java
@@ -0,0 +1,84 @@
+/*
+ * 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.fn.object.detection.examples;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+
+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.core.io.DefaultResourceLoader;
+import org.springframework.util.StreamUtils;
+
+/**
+ * @author Christian Tzolov
+ */
+public class ExampleObjectDetection {
+
+ public static void main(String[] args) throws IOException {
+
+ // You can download pre-trained models directly from the zoo: https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
+ // Just use the notation #
+ // For performance reasons you may consider downloading the model locally and use the file:/ URI instead!
+ String model = "http://download.tensorflow.org/models/object_detection/faster_rcnn_nas_coco_2018_01_28.tar.gz#frozen_inference_graph.pb";
+ //Resource model = resourceLoader.getResource("http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet101_fgvc_2018_07_19.tar.gz#frozen_inference_graph.pb");
+ //Resource model = resourceLoader.getResource("http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet50_fgvc_2018_07_19.tar.gz#frozen_inference_graph.pb");
+
+ // All labels for the pre-trained models are available at:
+ // https://github.com/tensorflow/models/tree/master/research/object_detection/data
+ // Use the labels applicable for the model.
+ // Also, for performance reasons you may consider to download the labels and load them from file: instead.
+ String labels = "https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/mscoco_label_map.pbtxt";
+ //Resource labels = resourceLoader.getResource("https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/fgvc_2854_classes_label_map.pbtxt");
+
+ // You can cache the TF model on the local file system to improve the bootstrap performance on consecutive runs!
+ boolean CACHE_TF_MODEL = true;
+
+ // For the pre-trained models fromMemory mask you can set the INSTANCE_SEGMENTATION to enable object instance segmentation as well
+ boolean NO_INSTANCE_SEGMENTATION = false;
+
+ // Only object fromMemory confidence above the threshold are returned
+ float CONFIDENCE_THRESHOLD = 0.4f;
+
+ ObjectDetectionService detectionService =
+ new ObjectDetectionService(model, labels, CONFIDENCE_THRESHOLD, NO_INSTANCE_SEGMENTATION, CACHE_TF_MODEL);
+
+ // You can use file:, http: or classpath: to provide the path to the input image.
+ String inputImageUri = "classpath:/images/object-detection.jpg";
+ try (InputStream is = new DefaultResourceLoader().getResource(inputImageUri).getInputStream()) {
+
+ byte[] image = StreamUtils.copyToByteArray(is);
+
+ // Returns a list ObjectDetection domain classes to allow programmatic accesses to the detected objects's metadata
+ List detectedObjects = detectionService.detect(image);
+
+ // Get JSON representation of the detected objects
+ String jsonObjectDetections = new JsonMapperFunction().apply(detectedObjects);
+ System.out.println(jsonObjectDetections);
+
+ // Draw the detected object metadata on top of the original image and store the result
+ byte[] annotatedImage = new ObjectDetectionImageAugmenter(NO_INSTANCE_SEGMENTATION).apply(image, detectedObjects);
+ IOUtils.write(annotatedImage, new FileOutputStream("./object-detection-function/target/object-detection-augmented.jpg"));
+ }
+ }
+}
diff --git a/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/SimpleExample.java b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/SimpleExample.java
new file mode 100644
index 00000000..b0b60f36
--- /dev/null
+++ b/function/object-detection-function/src/test/java/org/springframework/cloud/fn/object/detection/examples/SimpleExample.java
@@ -0,0 +1,47 @@
+/*
+ * 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.fn.object.detection.examples;
+
+
+import java.util.List;
+
+import org.springframework.cloud.fn.object.detection.ObjectDetectionService;
+import org.springframework.cloud.fn.object.detection.domain.ObjectDetection;
+
+/**
+ * @author Christian Tzolov
+ */
+public class SimpleExample {
+
+ public static void main(String[] args) {
+ // Select a pre-trained model from the model zoo: https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
+ // Just use the notation #
+ String model = "http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_ppn_shared_box_predictor_300x300_coco14_sync_2018_07_03.tar.gz#frozen_inference_graph.pb";
+
+ // All labels for the pre-trained models are available at: https://github.com/tensorflow/models/tree/master/research/object_detection/data
+ String labels = "https://raw.githubusercontent.com/tensorflow/models/master/research/object_detection/data/mscoco_label_map.pbtxt";
+
+ ObjectDetectionService detectionService = new ObjectDetectionService(model, labels,
+ 0.4f, // Only object fromMemory confidence above the threshold are returned. Confidence range is [0, 1].
+ false, // No instance segmentation
+ true); // cache the TF model locally
+
+ // You can use file:, http: or classpath: to provide the path to the input image.
+ List detectedObjects = detectionService.detect("classpath:/images/object-detection.jpg");
+ detectedObjects.stream().map(o -> o.toString()).forEach(System.out::println);
+ }
+}
diff --git a/function/semantic-segmentation-function/README.adoc b/function/semantic-segmentation-function/README.adoc
new file mode 100644
index 00000000..e76f9581
--- /dev/null
+++ b/function/semantic-segmentation-function/README.adoc
@@ -0,0 +1,104 @@
+:images-asciidoc: https://raw.githubusercontent.com/tzolov/stream-applications/tensorflow-redesign/functions/function/semantic-segmentation-function/src/main/resources/images/
+# Semantic Segmentation
+
+[.lead]
+Image Semantic Segmentation based on the state-of-art https://github.com/tensorflow/models/tree/master/research/deeplab[DeepLab] Tensorflow model.
+
+[cols="1,2", frame=none, grid=none]
+|===
+| image:{images-asciidoc}/VikiMaxiAdi-all.png[width=100%]
+|Semantic Segmentation is the process of associating each pixel of an image with a class label, (such as flower, person, road, sky, ocean, or car).
+Unlike the `Instance Segmentation`, which produces instance-aware region masks, the `Semantic Segmentation` produces class-aware masks.
+For implementing `Instance Segmentation` consult the https://github.com/tzolov/stream-applications/tree/tensorflow-redesign/functions/function/object-detection-function[Object Detection Service] instead.
+|===
+
+The https://github.com/tzolov/stream-applications/blob/tensorflow-redesign/functions/common/tensorflow-common/src/main/java/org/springframework/cloud/fn/common/tensorflow/deprecated/JsonMapperFunction.java[JsonMapperFunction] permits
+converting the `List` into JSON objects, and the
+https://github.com/tzolov/stream-applications/blob/tensorflow-redesign/functions/function/object-detection-function/src/main/java/org/springframework/cloud/fn/object/detection/ObjectDetectionImageAugmenter.java[ObjectDetectionImageAugmenter]
+allow to augment the input image with the detected bounding boxes and segmentation masks.
+
+## Usage
+
+Add the `semantic-segmentation` dependency to your pom (_use the latest version available_):
+
+[source,xml]
+----
+
+ org.springframework.cloud.fn
+ semantic-segmentation-function
+ ${spring-cloud-fn.version}
+
+
+
+ org.springframework.cloud.fn
+ object-detection-function
+ ${spring-cloud-fn.version}
+
+----
+
+Following snippet demos how to use the PASCAL VOC model to apply mask to an input image
+
+[source,java,linenums]
+----
+
+SemanticSegmentation segmentationService = new SemanticSegmentation(
+ "http://download.tensorflow.org/models/deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz#frozen_inference_graph.pb", // <1>
+ true); // <2>
+
+byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/VikiMaxiAdi.jpg"); // <3>
+
+byte[] imageMask = segmentationService.masksAsImage(inputImage); // <4>
+BufferedImage bi = ImageIO.read(new ByteArrayInputStream(imageMask));
+ImageIO.write(bi, "png", new FileOutputStream("./semantic-segmentation-function/target/VikiMaxiAdi_masks.png"));
+
+byte[] augmentedImage = segmentationService.augment(inputImage); // <5>
+IOUtils.write(augmentedImage, new FileOutputStream("./semantic-segmentation-function/target/VikiMaxiAdi_augmented.jpg"));
+----
+<1> Download the PASCAL 2012 trained model directly from the web. The `frozen_inference_graph.pb` is the name of the model
+file inside the `tar.gz` archive.
+<2> Cache the downloaded model locally
+<3> Load the input image as byte array
+<4> Read get the segmentation mask as separate image
+<5> Blend the segmentation mask on top of the original image
+
+## Models
+
+Based on the training datasets, three groups of pre-trained models provided:
+
+[cols="1,2", frame=none, grid=none]
+|===
+| image:{images-asciidoc}/VikiMaxiAdi-all.png[width=100%]
+| https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md#deeplab-models-trained-on-pascal-voc-2012[DeepLab models trained on PASCAL VOC 2012]
+
+| image:{images-asciidoc}/cityscape-all-small.png[width=100%]
+| https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md#deeplab-models-trained-on-cityscapes[DeepLab models trained on Cityscapes]
+
+| image:{images-asciidoc}/ADE20K-all-small.png[width=100%]
+| https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md#deeplab-models-trained-on-ade20k[DeepLab models trained on ADE20K]
+|===
+
+Select the model you want to use, copy its archive download Url and add a `#frozen_inference_graph.pb` fragment to it.
+Later fragment is the frozen model's file name inside the archive
+
+TIP: Download the archive and uncompress the `frozen_inference_graph.pb` for required model. Then use the `file://` URI schema.
+
+Also, convenience there are a couple of models, extracted from the archive and uploaded to bintray:
+
+[cols=2*,, frame=none, grid=none]
+|===
+|PASCAL VOC 2012 (default)
+|http://dl.bintray.com/big-data/generic/deeplabv3_mnv2_pascal_train_aug_frozen_inference_graph.pb
+
+|CITYSCAPE
+|http://dl.bintray.com/big-data/generic/deeplabv3_mnv2_cityscapes_train_2018_02_05_frozen_inference_graph.pb
+
+|ADE20K
+|http://dl.bintray.com/big-data/generic/deeplabv3_xception_ade20k_train_2018_05_29_frozen_inference_graph.pb
+|===
+
+## References:
+[.small]
+* https://ai.googleblog.com/2018/03/semantic-image-segmentation-with.html[Semantic Image Segmentation with DeepLab in TensorFlow]
+* https://github.com/tensorflow/models/tree/master/research/deeplab[DeepLab Project]
+* https://medium.freecodecamp.org/how-to-use-deeplab-in-tensorflow-for-object-segmentation-using-deep-learning-a5777290ab6b[How to re-train DeepLab Segmentation models using Transfer Learning]
+
diff --git a/function/semantic-segmentation-function/pom.xml b/function/semantic-segmentation-function/pom.xml
new file mode 100644
index 00000000..95c02c99
--- /dev/null
+++ b/function/semantic-segmentation-function/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+ semantic-segmentation-function
+ 1.0.0-SNAPSHOT
+ semantic-segmentation-function
+ Spring Native Function for Tensorflow semantic-segmentation integration
+
+
+ org.springframework.cloud.fn
+ spring-functions-parent
+ 1.0.0-SNAPSHOT
+ ../../spring-functions-parent
+
+
+
+ 1.3.2
+
+
+
+
+ org.springframework.cloud.fn
+ tensorflow-common
+ ${spring-cloud-fn.version}
+
+
+
+
+
+ tensorflow-snapshots
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+ true
+
+
+
+
diff --git a/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/NativeImageUtils.java b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/NativeImageUtils.java
new file mode 100644
index 00000000..b9ba1eeb
--- /dev/null
+++ b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/NativeImageUtils.java
@@ -0,0 +1,107 @@
+/*
+ * 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.fn.semantic.segmentation;
+
+import java.util.Arrays;
+
+import org.tensorflow.Operand;
+import org.tensorflow.op.Ops;
+import org.tensorflow.op.core.Concat;
+import org.tensorflow.op.core.ExpandDims;
+import org.tensorflow.op.core.Gather;
+import org.tensorflow.op.core.Range;
+import org.tensorflow.op.core.ReduceMax;
+import org.tensorflow.op.core.Tile;
+import org.tensorflow.op.math.Add;
+import org.tensorflow.op.math.Mul;
+import org.tensorflow.op.math.Sub;
+
+/**
+ * @author Christian Tzolov
+ */
+public final class NativeImageUtils {
+
+ private NativeImageUtils() {
+ }
+
+ /**
+ * grayscaleToRgb.
+ * https://github.com/tensorflow/tensorflow/blob/r1.13/tensorflow/python/ops/image_ops_impl.py#L1536
+ */
+ public static Operand grayscaleToRgb(Ops tf, Operand images) {
+ ExpandDims rank_1 = tf.expandDims(
+ tf.math.sub(tf.rank(images), tf.constant(1)),
+ tf.constant(0));
+ // Create once 1D vector of the shape defined by the rank_1.
+ // E.g. for rank [2] will produce matrix [1, 1]. For [3] rank will produce a cube [1, 1, 1]
+ Add ones = tf.math.add(tf.zeros(rank_1, Integer.class), tf.constant(1));
+ // Convert scalar 3 into 1D array [3]
+ ExpandDims channelsAs1D = tf.expandDims(tf.constant(3), tf.constant(0));
+ Concat shapeList = tf.concat(Arrays.asList(ones, channelsAs1D), tf.constant(0));
+ Tile tile = tf.withName("grayscaleToRgb").tile(images, shapeList);
+ return tile;
+ }
+
+ public static Operand normalizeMask(Ops tf, Operand mask, float newValue) {
+ // generate array representing the axis indexes.
+ // For example of tensor of rank K the axisRange is {0, 1, 2 ...K}
+ Range axisRange = tf.range(tf.constant(0), // from
+ tf.dtypes.cast(tf.rank(mask), Integer.class), // to
+ tf.constant(1)); // step
+
+ ReduceMax max = tf.reduceMax(mask, axisRange);
+ //Mul input2Float1 = tf.math.mul(tf.math.div(input2Float, max), tf.constant(1f));
+ Mul normalizedMask = tf.math.mul(tf.math.div(mask, max), tf.constant(newValue));
+
+ return normalizedMask;
+ }
+
+ /**
+ * Alpha Blending .
+ * https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
+ */
+ public static Operand alphaBlending(Ops tf, Operand srcRgb, Operand dstRgb, Operand srcAlpha) {
+ Sub alpha = tf.math.sub(tf.onesLike(srcRgb), srcAlpha);
+ Mul src = tf.math.mul(srcRgb, alpha);
+ Mul dst = tf.math.mul(dstRgb, tf.math.sub(tf.constant(1.0f), alpha));
+ Add out = tf.math.add(dst, src);
+
+ //Mul out = tf.math.mul(srcRgbNormalized, dstRgb);
+ //Squeeze squeeze = tf.withName("squeeze").squeeze(out, Squeeze.axis(Arrays.asList(0L)));
+
+ return out;
+ }
+
+ /**
+ * The mask can contain label values larger than the list of colors provided in the color map.
+ * To avoid out-of-index errors we will "normalize" the label values in the mask to MOD max-color-table-value.
+ * @param tf - tensorflow
+ * @param colorTable Color map of shape [n, 3]. n is the count of label entries and 3 is the RGB color assigned
+ * to that label.
+ * @param mask Mask of shape [h, w] containing label vales.
+ * @return Mask of shape [h, w] fromMemory values normalized between [0, n]
+ */
+ public static Operand normalizeMaskLabels(Ops tf, Operand colorTable, Operand mask) {
+ // The mask can contain label values larger than the list of colors provided in the color map.
+ // To avoid out-of-index errors we will "normalize" the label values in the mask to MOD max-color-table-value.
+ Sub colorTableShape = tf.math.sub(tf.shape(colorTable, Long.class), tf.constant(1L));
+ // Color tables have shape [N, 3], where N is the count of label entries. Therefore the max label id is (N - 1).
+ Gather colorTableSize = tf.gather(colorTableShape, tf.constant(new int[] { 0 }), tf.constant(0));
+ // Normalize the label values in the mask so they don't exceed the max value in the color map.
+ return tf.math.mod(mask, colorTableSize);
+ }
+}
diff --git a/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SegmentationColorMap.java b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SegmentationColorMap.java
new file mode 100644
index 00000000..3a958cf1
--- /dev/null
+++ b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SegmentationColorMap.java
@@ -0,0 +1,306 @@
+/*
+ * 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.fn.semantic.segmentation;
+
+/**
+ *
+ * Visualizes the segmentation results via specified color map.
+ * Color maps helping to visualize the semantic segmentation results for the different datasets.
+ *
+ * Supported colormaps are:
+ * - ADE20K (http://groups.csail.mit.edu/vision/datasets/ADE20K/).
+ * - Cityscapes dataset (https://www.cityscapes-dataset.com).
+ * - Mapillary Vistas (https://research.mapillary.com).
+ * - PASCAL VOC 2012 (http://host.robots.ox.ac.uk/pascal/VOC/).
+ *
+ * Based on: https://github.com/tensorflow/models/blob/master/research/deeplab/utils/get_dataset_colormap.py
+ *
+ * @author Christian Tzolov
+ */
+public final class SegmentationColorMap {
+
+ private SegmentationColorMap() {
+
+ }
+
+ /** MAPILLARY_COLORMAP . */
+ public static final int[][] MAPILLARY_COLORMAP = new int[][] {
+ { 165, 42, 42 },
+ { 0, 192, 0 },
+ { 196, 196, 196 },
+ { 190, 153, 153 },
+ { 180, 165, 180 },
+ { 102, 102, 156 },
+ { 102, 102, 156 },
+ { 128, 64, 255 },
+ { 140, 140, 200 },
+ { 170, 170, 170 },
+ { 250, 170, 160 },
+ { 96, 96, 96 },
+ { 230, 150, 140 },
+ { 128, 64, 128 },
+ { 110, 110, 110 },
+ { 244, 35, 232 },
+ { 150, 100, 100 },
+ { 70, 70, 70 },
+ { 150, 120, 90 },
+ { 220, 20, 60 },
+ { 255, 0, 0 },
+ { 255, 0, 0 },
+ { 255, 0, 0 },
+ { 200, 128, 128 },
+ { 255, 255, 255 },
+ { 64, 170, 64 },
+ { 128, 64, 64 },
+ { 70, 130, 180 },
+ { 255, 255, 255 },
+ { 152, 251, 152 },
+ { 107, 142, 35 },
+ { 0, 170, 30 },
+ { 255, 255, 128 },
+ { 250, 0, 30 },
+ { 0, 0, 0 },
+ { 220, 220, 220 },
+ { 170, 170, 170 },
+ { 222, 40, 40 },
+ { 100, 170, 30 },
+ { 40, 40, 40 },
+ { 33, 33, 33 },
+ { 170, 170, 170 },
+ { 0, 0, 142 },
+ { 170, 170, 170 },
+ { 210, 170, 100 },
+ { 153, 153, 153 },
+ { 128, 128, 128 },
+ { 0, 0, 142 },
+ { 250, 170, 30 },
+ { 192, 192, 192 },
+ { 220, 220, 0 },
+ { 180, 165, 180 },
+ { 119, 11, 32 },
+ { 0, 0, 142 },
+ { 0, 60, 100 },
+ { 0, 0, 142 },
+ { 0, 0, 90 },
+ { 0, 0, 230 },
+ { 0, 80, 100 },
+ { 128, 64, 64 },
+ { 0, 0, 110 },
+ { 0, 0, 70 },
+ { 0, 0, 192 },
+ { 32, 32, 32 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ };
+
+ /**
+ * Label colormap used in ADE20K segmentation benchmark.
+ */
+ public static final int[][] ADE20K_COLORMAP = new int[][] {
+ { 0, 0, 0 },
+ { 120, 120, 120 },
+ { 180, 120, 120 },
+ { 6, 230, 230 },
+ { 80, 50, 50 },
+ { 4, 200, 3 },
+ { 120, 120, 80 },
+ { 140, 140, 140 },
+ { 204, 5, 255 },
+ { 230, 230, 230 },
+ { 4, 250, 7 },
+ { 224, 5, 255 },
+ { 235, 255, 7 },
+ { 150, 5, 61 },
+ { 120, 120, 70 },
+ { 8, 255, 51 },
+ { 255, 6, 82 },
+ { 143, 255, 140 },
+ { 204, 255, 4 },
+ { 255, 51, 7 },
+ { 204, 70, 3 },
+ { 0, 102, 200 },
+ { 61, 230, 250 },
+ { 255, 6, 51 },
+ { 11, 102, 255 },
+ { 255, 7, 71 },
+ { 255, 9, 224 },
+ { 9, 7, 230 },
+ { 220, 220, 220 },
+ { 255, 9, 92 },
+ { 112, 9, 255 },
+ { 8, 255, 214 },
+ { 7, 255, 224 },
+ { 255, 184, 6 },
+ { 10, 255, 71 },
+ { 255, 41, 10 },
+ { 7, 255, 255 },
+ { 224, 255, 8 },
+ { 102, 8, 255 },
+ { 255, 61, 6 },
+ { 255, 194, 7 },
+ { 255, 122, 8 },
+ { 0, 255, 20 },
+ { 255, 8, 41 },
+ { 255, 5, 153 },
+ { 6, 51, 255 },
+ { 235, 12, 255 },
+ { 160, 150, 20 },
+ { 0, 163, 255 },
+ { 140, 140, 140 },
+ { 250, 10, 15 },
+ { 20, 255, 0 },
+ { 31, 255, 0 },
+ { 255, 31, 0 },
+ { 255, 224, 0 },
+ { 153, 255, 0 },
+ { 0, 0, 255 },
+ { 255, 71, 0 },
+ { 0, 235, 255 },
+ { 0, 173, 255 },
+ { 31, 0, 255 },
+ { 11, 200, 200 },
+ { 255, 82, 0 },
+ { 0, 255, 245 },
+ { 0, 61, 255 },
+ { 0, 255, 112 },
+ { 0, 255, 133 },
+ { 255, 0, 0 },
+ { 255, 163, 0 },
+ { 255, 102, 0 },
+ { 194, 255, 0 },
+ { 0, 143, 255 },
+ { 51, 255, 0 },
+ { 0, 82, 255 },
+ { 0, 255, 41 },
+ { 0, 255, 173 },
+ { 10, 0, 255 },
+ { 173, 255, 0 },
+ { 0, 255, 153 },
+ { 255, 92, 0 },
+ { 255, 0, 255 },
+ { 255, 0, 245 },
+ { 255, 0, 102 },
+ { 255, 173, 0 },
+ { 255, 0, 20 },
+ { 255, 184, 184 },
+ { 0, 31, 255 },
+ { 0, 255, 61 },
+ { 0, 71, 255 },
+ { 255, 0, 204 },
+ { 0, 255, 194 },
+ { 0, 255, 82 },
+ { 0, 10, 255 },
+ { 0, 112, 255 },
+ { 51, 0, 255 },
+ { 0, 194, 255 },
+ { 0, 122, 255 },
+ { 0, 255, 163 },
+ { 255, 153, 0 },
+ { 0, 255, 10 },
+ { 255, 112, 0 },
+ { 143, 255, 0 },
+ { 82, 0, 255 },
+ { 163, 255, 0 },
+ { 255, 235, 0 },
+ { 8, 184, 170 },
+ { 133, 0, 255 },
+ { 0, 255, 92 },
+ { 184, 0, 255 },
+ { 255, 0, 31 },
+ { 0, 184, 255 },
+ { 0, 214, 255 },
+ { 255, 0, 112 },
+ { 92, 255, 0 },
+ { 0, 224, 255 },
+ { 112, 224, 255 },
+ { 70, 184, 160 },
+ { 163, 0, 255 },
+ { 153, 0, 255 },
+ { 71, 255, 0 },
+ { 255, 0, 163 },
+ { 255, 204, 0 },
+ { 255, 0, 143 },
+ { 0, 255, 235 },
+ { 133, 255, 0 },
+ { 255, 0, 235 },
+ { 245, 0, 255 },
+ { 255, 0, 122 },
+ { 255, 245, 0 },
+ { 10, 190, 212 },
+ { 214, 255, 0 },
+ { 0, 204, 255 },
+ { 20, 0, 255 },
+ { 255, 255, 0 },
+ { 0, 153, 255 },
+ { 0, 41, 255 },
+ { 0, 255, 204 },
+ { 41, 0, 255 },
+ { 41, 255, 0 },
+ { 173, 0, 255 },
+ { 0, 245, 255 },
+ { 71, 0, 255 },
+ { 122, 0, 255 },
+ { 0, 255, 184 },
+ { 0, 92, 255 },
+ { 184, 255, 0 },
+ { 0, 133, 255 },
+ { 255, 214, 0 },
+ { 25, 194, 194 },
+ { 102, 255, 0 },
+ { 92, 0, 255 },
+ };
+
+ /** BLACK_WHITE_COLORMAP . */
+ public static int[][] BLACK_WHITE_COLORMAP = new int[][] {
+ { 0, 0, 0 },
+ { 127, 127, 127 },
+ { 255, 255, 255 },
+ };
+
+ /** CITYMAP_COLORMAP . */
+ public static final int[][] CITYMAP_COLORMAP = new int[255][3];
+
+ static {
+
+ // Initialize citymap
+ int[][] _CITYMAP_COLORMAP = new int[][] {
+ { 128, 64, 128 },
+ { 244, 35, 232 },
+ { 70, 70, 70 },
+ { 102, 102, 156 },
+ { 190, 153, 153 },
+ { 153, 153, 153 },
+ { 250, 170, 30 },
+ { 220, 220, 0 },
+ { 107, 142, 35 },
+ { 152, 251, 152 },
+ { 70, 130, 180 },
+ { 220, 20, 60 },
+ { 255, 0, 0 },
+ { 0, 0, 142 },
+ { 0, 0, 70 },
+ { 0, 60, 100 },
+ { 0, 80, 100 },
+ { 0, 0, 230 },
+ { 119, 11, 32 }
+ };
+
+ for (int i = 0; i < _CITYMAP_COLORMAP.length; i++) {
+ System.arraycopy(_CITYMAP_COLORMAP[i], 0, CITYMAP_COLORMAP[i], 0, _CITYMAP_COLORMAP[i].length);
+ }
+ }
+}
diff --git a/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SemanticSegmentation.java b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SemanticSegmentation.java
new file mode 100644
index 00000000..bfe5e317
--- /dev/null
+++ b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/SemanticSegmentation.java
@@ -0,0 +1,287 @@
+/*
+ * 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.fn.semantic.segmentation;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+import org.tensorflow.Operand;
+import org.tensorflow.Tensor;
+import org.tensorflow.op.Ops;
+import org.tensorflow.op.core.Gather;
+import org.tensorflow.op.core.Placeholder;
+import org.tensorflow.op.core.Squeeze;
+import org.tensorflow.op.core.ZerosLike;
+import org.tensorflow.op.dtypes.Cast;
+import org.tensorflow.op.image.DecodeJpeg;
+import org.tensorflow.op.image.ExtractJpegShape;
+import org.tensorflow.op.math.Add;
+import org.tensorflow.op.math.Div;
+import org.tensorflow.op.math.Equal;
+import org.tensorflow.types.UInt8;
+
+import org.springframework.cloud.fn.common.tensorflow.Functions;
+import org.springframework.cloud.fn.common.tensorflow.GraphRunner;
+import org.springframework.cloud.fn.common.tensorflow.GraphRunnerMemory;
+import org.springframework.cloud.fn.common.tensorflow.ProtoBufGraphDefinition;
+import org.springframework.cloud.fn.common.tensorflow.deprecated.GraphicsUtils;
+import org.springframework.core.io.DefaultResourceLoader;
+
+/**
+ * @author Christian Tzolov
+ */
+public class SemanticSegmentation implements AutoCloseable {
+
+ private static final long CHANNELS = 3;
+ private static final float REQUIRED_INPUT_IMAGE_SIZE = 513f;
+ private final GraphRunner imageNormalization;
+ private final GraphRunner semanticSegmentation;
+ private final GraphRunner maskImageEncoding;
+ private final GraphRunner alphaBlending;
+ private final Tensor colorMapTensor;
+ private final Tensor maskTransparencyTensor;
+
+ @Override
+ public void close() {
+ this.imageNormalization.close();
+ this.semanticSegmentation.close();
+ this.maskImageEncoding.close();
+ this.alphaBlending.close();
+
+ this.colorMapTensor.close();
+ this.maskTransparencyTensor.close();
+ }
+
+ public SemanticSegmentation(String modelUrl, int[][] colorMap, long[] labelFilter, float maskTransparency) {
+
+ this.imageNormalization = new GraphRunner("input_image", "resized_image")
+ .withGraphDefinition(tf -> {
+ Placeholder input = tf.withName("input_image").placeholder(String.class);
+ ExtractJpegShape imageShapeAndChannel = tf.image.extractJpegShape(input);
+ Gather imageShape = tf.gather(imageShapeAndChannel, tf.constant(new int[] { 0, 1 }), tf.constant(0));
+
+ Cast maxSize = tf.dtypes.cast(tf.max(imageShape, tf.constant(0)), Float.class);
+ Div scale = tf.math.div(tf.constant(REQUIRED_INPUT_IMAGE_SIZE), maxSize);
+ Cast newSize = tf.dtypes.cast(tf.math.mul(scale, tf.dtypes.cast(imageShape, Float.class)), Integer.class);
+
+ final Operand decodedImage =
+ tf.dtypes.cast(tf.image.decodeJpeg(input, DecodeJpeg.channels(CHANNELS)), Float.class);
+
+ final Operand resizedImageFloat =
+ tf.image.resizeBilinear(tf.expandDims(decodedImage, tf.constant(0)), newSize);
+
+ tf.withName("resized_image").dtypes.cast(resizedImageFloat, UInt8.class);
+ });
+
+ this.semanticSegmentation = new GraphRunner("ImageTensor:0", "SemanticPredictions:0")
+ .withGraphDefinition(new ProtoBufGraphDefinition(new DefaultResourceLoader().getResource(modelUrl), true));
+
+ this.colorMapTensor = Tensor.create(colorMap).expect(Integer.class);
+
+ this.maskImageEncoding = new GraphRunner(Arrays.asList("color_map", "mask_pixels"), Arrays.asList("mask_png", "mask_rgb"))
+ .withGraphDefinition(tf -> {
+ Placeholder colorTable = tf.withName("color_map").placeholder(Integer.class);
+
+ Placeholder batchedMask = tf.withName("mask_pixels").placeholder(Long.class);
+ // Remove batch dimension
+ Squeeze mask = tf.squeeze(batchedMask, Squeeze.axis(Arrays.asList(0L)));
+
+ Operand filteredMask = labelFilter(tf, mask, labelFilter);
+
+ // The mask can contain label values larger than the list of colors provided in the color map.
+ // To avoid out-of-index errors we will "normalize" the label values in the mask to MOD max-color-table-value.
+ Operand mask3 = NativeImageUtils.normalizeMaskLabels(tf, colorTable, filteredMask);
+
+ Gather maskRgb = tf.withName("mask_rgb").gather(colorTable, mask3, tf.constant(0));
+
+ Operand png = tf.withName("mask_png").image.encodePng(tf.dtypes.cast(maskRgb, UInt8.class));
+
+ });
+
+ this.maskTransparencyTensor = Tensor.create(maskTransparency).expect(Float.class);
+
+ this.alphaBlending = new GraphRunner(
+ Arrays.asList("input_image", "mask_image", "mask_transparency"), Arrays.asList("blended_png"))
+ .withGraphDefinition(tf -> {
+ // Input image [B, H, W, 3]
+ Cast inputImageRgb = tf.dtypes.cast(tf.withName("input_image").placeholder(UInt8.class), Float.class);
+
+ Placeholder a = tf.withName("mask_image").placeholder(Integer.class);
+ Cast maskRgb = tf.dtypes.cast(a, Float.class);
+
+ Squeeze inputImageRgb2 = tf.squeeze(inputImageRgb, Squeeze.axis(Arrays.asList(0L)));
+
+ Placeholder maskTransparencyHolder = tf.withName("mask_transparency").placeholder(Float.class);
+
+ // Blend the transparent maskImage on top of the input image.
+ Operand blended = NativeImageUtils.alphaBlending(tf, maskRgb, inputImageRgb2, maskTransparencyHolder);
+
+ // Cut
+ //Operand condition = tf.math.equal(a, tf.zerosLike(a));
+ //Operand blended = tf.where3(condition, tf.zerosLike(maskRgb), inputImageRgb2);
+
+ // Encode PNG
+ tf.withName("blended_png").image.encodePng(tf.dtypes.cast(blended, UInt8.class));
+
+ });
+ }
+
+ public byte[] blendMask(byte[] image) {
+ try (Tensor inputTensor = Tensor.create(image); GraphRunnerMemory memory = new GraphRunnerMemory()) {
+
+ Map> blendedTensors =
+ this.imageNormalization.andThen(memory) // (input_image) -> (resized_image) and memorize (resized_image)
+ .andThen(this.semanticSegmentation).andThen(memory) // (ImageTensor:0) -> (SemanticPredictions:0) and memorize (SemanticPredictions:0)
+ .andThen(Functions.rename("SemanticPredictions:0", "mask_pixels")) // (SemanticPredictions:0) -> (mask_pixels)
+ .andThen(Functions.enrichWith("color_map", this.colorMapTensor)) // (mask_pixels) -> (mask_pixels, color_map)
+ .andThen(this.maskImageEncoding).andThen(memory) // (color_map, mask_pixels) -> (mask_png, mask_rgb) and memorize (mask_png, mask_rgb)
+ .andThen(Functions.enrichFromMemory(
+ memory, "resized_image")) // (mask_png, mask_rgb) -> (mask_png, mask_rgb, resized_image), e.g. join the normalizedImageTensor
+ .andThen(Functions.rename(
+ "resized_image", "input_image",
+ "mask_rgb", "mask_image")) // (mask_png, mask_rgb, resized_image) -> (mask_image, input_image)
+ .andThen(Functions.enrichWith("mask_transparency", this.maskTransparencyTensor)) // (mask_image, input_image) -> (mask_image, input_image, mask_transparency)
+ .andThen(this.alphaBlending).andThen(memory) // (mask_image, input_image, mask_transparency) -> (blended_png)
+ .apply(Collections.singletonMap("input_image", inputTensor)); // () -> (input_image)
+
+ byte[] blendedImage = blendedTensors.get("blended_png").bytesValue();
+
+ memory.getTensorMap().entrySet().stream().forEach(e -> System.out.println(e));
+
+ return blendedImage;
+ }
+ }
+
+ public long[][] maskPixels(byte[] image) {
+ try (Tensor inputTensor = Tensor.create(image); GraphRunnerMemory memory = new GraphRunnerMemory()) {
+
+ return this.imageNormalization.andThen(memory) // (input_image) -> (resized_image) and memorize (resized_image)
+ .andThen(this.semanticSegmentation).andThen(memory) // (ImageTensor:0) -> (SemanticPredictions:0) and memorize (SemanticPredictions:0)
+ .andThen(tensorMap -> {
+ Tensor> maskTensor = tensorMap.get("SemanticPredictions:0");
+ int width = (int) maskTensor.shape()[1];
+ int height = (int) maskTensor.shape()[2];
+ return maskTensor.copyTo(new long[1][width][height])[0]; // 1 == batch size
+ })
+ .apply(Collections.singletonMap("input_image", inputTensor)); // () -> (input_image)
+ }
+ }
+
+ public byte[] maskImage(byte[] image) {
+
+ try (Tensor inputTensor = Tensor.create(image); GraphRunnerMemory memory = new GraphRunnerMemory()) {
+
+ return this.imageNormalization.andThen(memory) // (input_image) -> (resized_image) and memorize (resized_image)
+ .andThen(this.semanticSegmentation).andThen(memory) // (ImageTensor:0) -> (SemanticPredictions:0) and memorize (SemanticPredictions:0)
+ .andThen(Functions.rename("SemanticPredictions:0", "mask_pixels")) // (SemanticPredictions:0) -> (mask_pixels)
+ .andThen(Functions.enrichWith("color_map", this.colorMapTensor)) // (mask_pixels) -> (mask_pixels, color_map)
+ .andThen(this.maskImageEncoding).andThen(memory) // (color_map, mask_pixels) -> (mask_png, mask_rgb) and memorize (mask_png, mask_rgb)
+ .andThen(tensorMap -> tensorMap.get("mask_png").bytesValue())
+ .apply(Collections.singletonMap("input_image", inputTensor)); // () -> (input_image)
+ }
+ }
+
+ private Operand labelFilter(Ops tf, Operand mask, long[] labels) {
+
+ if (labels == null || labels.length == 0) {
+ return mask;
+ }
+
+ ZerosLike zeroMask = tf.zerosLike(mask);
+ Operand result = zeroMask;
+ for (long label : labels) {
+ Add labelMask = tf.math.add(tf.zerosLike(mask), tf.constant(label));
+ Equal condition = tf.math.equal(mask, labelMask);
+ result = tf.math.add(result, tf.where3(condition, labelMask, zeroMask));
+ }
+ return result;
+ }
+
+ public static void main(String[] args) throws IOException {
+
+ //String inputImageUri = "file:/Users/ctzolov/Dev/projects/mindmodel/mind-model-services/semantic-segmentation/src/test/resources/images/VikiMaxiAdi.jpg";
+ String outputBlendedImagePath = "./semantic-segmentation/target/blendedImage.png";
+ String outputMaskImagePath = "./semantic-segmentation/target/maskImage.png";
+
+
+ try (SemanticSegmentation segmentationService = new SemanticSegmentation(
+ "http://download.tensorflow.org/models/deeplabv3_mnv2_cityscapes_train_2018_02_05.tar.gz#frozen_inference_graph.pb",
+ SegmentationColorMap.CITYMAP_COLORMAP, null, 0.45f)
+ ) {
+ byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/amsterdam-cityscape1.jpg");
+
+ // 1. Mask pixels
+ long[][] maskPixels = segmentationService.maskPixels(inputImage);
+
+ // 2. Alpha Blending
+ byte[] blended = segmentationService.blendMask(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(blended)), "png", new File(outputBlendedImagePath));
+
+ // 3. Mask Image
+ byte[] maskImage = segmentationService.maskImage(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(maskImage)), "png", new File(outputMaskImagePath));
+ }
+
+
+ try (SemanticSegmentation segmentationService = new SemanticSegmentation(
+ "http://download.tensorflow.org/models/deeplabv3_xception_ade20k_train_2018_05_29.tar.gz#frozen_inference_graph.pb",
+ SegmentationColorMap.ADE20K_COLORMAP, null, 0.45f)
+ ) {
+ byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/interior.jpg");
+
+ // 1. Mask pixels
+ long[][] maskPixels = segmentationService.maskPixels(inputImage);
+
+ // 2. Alpha Blending
+ byte[] blended = segmentationService.blendMask(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(blended)), "png",
+ new File("./semantic-segmentation/target/inventory-blendedImage.png"));
+
+ // 3. Mask Image
+ byte[] maskImage = segmentationService.maskImage(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(maskImage)), "png",
+ new File("./semantic-segmentation/target/inventory-MaskImage.png"));
+ }
+
+ try (SemanticSegmentation segmentationService = new SemanticSegmentation(
+ "http://download.tensorflow.org/models/deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz#frozen_inference_graph.pb",
+ SegmentationColorMap.BLACK_WHITE_COLORMAP, null, 0.45f)
+ ) {
+ byte[] inputImage = GraphicsUtils.loadAsByteArray("classpath:/images/VikiMaxiAdi.jpg");
+
+ // 1. Mask pixels
+ long[][] maskPixels = segmentationService.maskPixels(inputImage);
+
+ // 2. Alpha Blending
+ byte[] blended = segmentationService.blendMask(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(blended)), "png",
+ new File("./semantic-segmentation/target/pascal-blendedImage.png"));
+
+ // 3. Mask Image
+ byte[] maskImage = segmentationService.maskImage(inputImage);
+ ImageIO.write(ImageIO.read(new ByteArrayInputStream(maskImage)), "png",
+ new File("./semantic-segmentation/target/pascal-MaskImage.png"));
+ }
+
+ }
+}
diff --git a/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/attic/SemanticSegmentationUtils.java b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/attic/SemanticSegmentationUtils.java
new file mode 100644
index 00000000..ee6c1ef6
--- /dev/null
+++ b/function/semantic-segmentation-function/src/main/java/org/springframework/cloud/fn/semantic/segmentation/attic/SemanticSegmentationUtils.java
@@ -0,0 +1,289 @@
+/*
+ * 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.fn.semantic.segmentation.attic;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.tensorflow.Tensor;
+import org.tensorflow.types.UInt8;
+
+import org.springframework.cloud.fn.common.tensorflow.deprecated.GraphicsUtils;
+import org.springframework.cloud.fn.common.tensorflow.deprecated.TensorFlowService;
+import org.springframework.core.io.DefaultResourceLoader;
+
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+
+/**
+ *
+ * Semantic image segmentation - the task of assigning a semantic label, such as “road”, “sky”, “person”, “dog”, to
+ * every pixel in an image.
+ *
+ * https://ai.googleblog.com/2018/03/semantic-image-segmentation-with.html
+ * https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md
+ * https://github.com/tensorflow/models/tree/master/research/deeplab
+ * https://github.com/tensorflow/models/blob/master/research/deeplab/deeplab_demo.ipynb
+ * http://presentations.cocodataset.org/Places17-GMRI.pdf
+ *
+ * http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html
+ * https://www.cityscapes-dataset.com/dataset-overview/#class-definitions
+ * http://groups.csail.mit.edu/vision/datasets/ADE20K/
+ *
+ * https://github.com/mapillary/inplace_abn
+ *
+ * @author Christian Tzolov
+ */
+public class SemanticSegmentationUtils {
+
+ /** INPUT_TENSOR_NAME . */
+ public static final String INPUT_TENSOR_NAME = "ImageTensor:0";
+ /** OUTPUT_TENSOR_NAME . */
+ public static final String OUTPUT_TENSOR_NAME = "SemanticPredictions:0";
+
+ private static final int BATCH_SIZE = 1;
+ private static final long CHANNELS = 3;
+ private static final int REQUIRED_INPUT_IMAGE_SIZE = 513;
+
+ public static BufferedImage scaledImage(String imagePath) {
+ try {
+ return scaledImage(ImageIO.read(new DefaultResourceLoader().getResource(imagePath).getInputStream()));
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Failed to load Image from: " + imagePath, e);
+ }
+ }
+
+ public static BufferedImage scaledImage(byte[] image) {
+ try {
+ return scaledImage(ImageIO.read(new ByteArrayInputStream(image)));
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Failed to load Image from byte array", e);
+ }
+ }
+
+ public static BufferedImage scaledImage(BufferedImage image) {
+ double scaleRatio = 1.0 * REQUIRED_INPUT_IMAGE_SIZE / Math.max(image.getWidth(), image.getHeight());
+ return scale(image, scaleRatio);
+ }
+
+ private static BufferedImage scale(BufferedImage originalImage, double scale) {
+ int newWidth = (int) (originalImage.getWidth() * scale);
+ int newHeight = (int) (originalImage.getHeight() * scale);
+
+ Image tmpImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_DEFAULT);
+ //BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, TYPE_INT_BGR);
+ BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, TYPE_3BYTE_BGR);
+ //BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, originalImage.getType());
+
+ Graphics2D g2d = resizedImage.createGraphics();
+ g2d.drawImage(tmpImage, 0, 0, null);
+ g2d.dispose();
+
+ return resizedImage;
+ }
+
+ public static BufferedImage blendMask(BufferedImage mask, BufferedImage background) {
+ GraphicsUtils.overlayImages(background, mask, 0, 0);
+ return background;
+ }
+
+ public static Tensor createInputTensor(BufferedImage scaledImage) {
+ if (scaledImage.getType() != TYPE_3BYTE_BGR) {
+ throw new IllegalArgumentException(
+ String.format("Expected 3-byte BGR encoding in BufferedImage, found %d", scaledImage.getType()));
+ }
+
+ // ImageIO.read produces BGR-encoded images, while the model expects RGB.
+ byte[] data = bgrToRgb(toBytes(scaledImage));
+
+ // Expand dimensions since the model expects images to have shape: [1, None, None, 3]
+ long[] shape = new long[] { BATCH_SIZE, scaledImage.getHeight(), scaledImage.getWidth(), CHANNELS };
+
+ return Tensor.create(UInt8.class, shape, ByteBuffer.wrap(data));
+ }
+
+ private static byte[] bgrToRgb(byte[] brgImage) {
+ byte[] rgbImage = new byte[brgImage.length];
+ for (int i = 0; i < brgImage.length; i += 3) {
+ rgbImage[i] = brgImage[i + 2];
+ rgbImage[i + 1] = brgImage[i + 1];
+ rgbImage[i + 2] = brgImage[i];
+ }
+ return rgbImage;
+ }
+
+ private static byte[] toBytes(BufferedImage bufferedImage) {
+ return ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
+ }
+
+ public static BufferedImage createMaskImage(int[][] maskPixels, int width, int height, double transparency) {
+
+ maskPixels = rotate(maskPixels);
+
+ int maskWidth = maskPixels.length;
+ int maskHeight = maskPixels[0].length;
+
+ int[] maskArray = new int[maskWidth * maskHeight];
+ int k = 0;
+ for (int i = 0; i < maskHeight; i++) {
+ for (int j = 0; j < maskWidth; j++) {
+ Color c = (maskPixels[j][i] == 0) ? Color.BLACK : GraphicsUtils.getClassColor(maskPixels[j][i]);
+ int t = (int) (255 * (1 - transparency));
+ maskArray[k++] = new Color(c.getRed(), c.getGreen(), c.getBlue(), t).getRGB();
+ }
+ }
+
+ // Turn the pixel array into image;
+ BufferedImage maskImage = new BufferedImage(maskWidth, maskHeight, BufferedImage.TYPE_INT_ARGB);
+ maskImage.setRGB(0, 0, maskWidth, maskHeight, maskArray, 0, maskWidth);
+
+ // Stretch the image to fit the target box width and height!
+ return GraphicsUtils.toBufferedImage(maskImage.getScaledInstance(width, height, Image.SCALE_SMOOTH));
+ }
+
+ /**
+ * rotate clockwise in 90 degree.
+ * @param input The 2D matrix to be rotated
+ * @return The input matrix rotated clockwise in 90 degrees
+ */
+ private static int[][] rotate(int[][] input) {
+
+ int w = input.length;
+ int h = input[0].length;
+
+ int[][] output = new int[h][w];
+ for (int y = 0; y < h; y++) {
+ for (int x = w - 1; x >= 0; x--) {
+ output[y][x] = input[x][y];
+ }
+ }
+ return output;
+ }
+
+ public static int[][] toIntArray(long[][] longArray) {
+ int[][] intArray = new int[longArray.length][longArray[0].length];
+ for (int i = 0; i < longArray.length; i++) {
+ for (int j = 0; j < longArray[0].length; j++) {
+ intArray[i][j] = (int) longArray[i][j];
+ }
+ }
+ return intArray;
+ }
+
+ public String serializeToJson(int[][] pixels) {
+ String masksBase64 = Base64.getEncoder().encodeToString(toBytes(pixels));
+ return String.format("{ \"columns\":%d, \"rows\":%d, \"masks\":\"%s\"}", pixels.length, pixels[0].length, masksBase64);
+ }
+
+ public int[][] deserializeToMasks(String json) throws IOException {
+ Map map = new ObjectMapper().readValue(json, Map.class);
+ int cols = (int) map.get("columns");
+ int rows = (int) map.get("rows");
+ String masksBase64 = (String) map.get("masks");
+ byte[] masks = Base64.getDecoder().decode(masksBase64);
+ return toInts(masks, cols, rows);
+ }
+
+ private byte[] toBytes(int[][] pixels) {
+ byte[] b = new byte[pixels.length * pixels[0].length * 4];
+ int bi = 0;
+ for (int i = 0; i < pixels.length; i++) {
+ for (int j = 0; j < pixels[0].length; j++) {
+ b[bi + 0] = (byte) (i >> 24);
+ b[bi + 1] = (byte) (i >> 16);
+ b[bi + 2] = (byte) (i >> 8);
+ b[bi + 3] = (byte) (i /*>> 0*/);
+ bi = bi + 4;
+ }
+ }
+ return b;
+ }
+
+ private int[][] toInts(byte[] b, int ic, int jc) {
+ int[][] intResult = new int[ic][jc];
+ int bi = 0;
+ for (int i = 0; i < ic; i++) {
+ for (int j = 0; j < jc; j++) {
+ intResult[i][j] = (b[bi] << 24) +
+ (b[bi + 1] << 16) +
+ (b[bi + 2] << 8) +
+ b[bi + 3];
+ bi = bi + 4;
+ }
+ }
+ return intResult;
+ }
+
+ public static void main(String[] args) throws IOException {
+
+ // PASCAL VOC 2012
+ //String tensorflowModelLocation = "file:/Users/ctzolov/Downloads/deeplabv3_mnv2_pascal_train_aug/frozen_inference_graph.pb";
+ //String imagePath = "classpath:/images/VikiMaxiAdi.jpg";
+
+ // CITYSCAPE
+ //String tensorflowModelLocation = "file:/Users/ctzolov/Downloads/deeplabv3_mnv2_cityscapes_train/frozen_inference_graph.pb";
+ //String imagePath = "classpath:/images/amsterdam-cityscape1.jpg";
+ //String imagePath = "classpath:/images/amsterdam-channel.jpg";
+ //String imagePath = "classpath:/images/landsmeer.png";
+
+ // ADE20K
+ String tensorflowModelLocation = "file:/Users/ctzolov/Downloads/deeplabv3_xception_ade20k_train/frozen_inference_graph.pb";
+ String imagePath = "classpath:/images/interior.jpg";
+
+ BufferedImage inputImage = ImageIO.read(new DefaultResourceLoader().getResource(imagePath).getInputStream());
+
+ TensorFlowService tf = new TensorFlowService(new DefaultResourceLoader().getResource(tensorflowModelLocation), Arrays.asList(OUTPUT_TENSOR_NAME));
+
+ SemanticSegmentationUtils segmentationService = new SemanticSegmentationUtils();
+
+ BufferedImage scaledImage = segmentationService.scaledImage(inputImage);
+
+ Tensor inTensor = segmentationService.createInputTensor(scaledImage);
+
+ Map> output = tf.apply(Collections.singletonMap(INPUT_TENSOR_NAME, inTensor));
+
+ Tensor> maskPixelsTensor = output.get(OUTPUT_TENSOR_NAME);
+
+ int height = (int) maskPixelsTensor.shape()[1];
+ int width = (int) maskPixelsTensor.shape()[2];
+ long[][] maskPixels = maskPixelsTensor.copyTo(new long[BATCH_SIZE][height][width])[0]; // take 0 because the batch size is 1.
+
+ int[][] maskPixelsInt = segmentationService.toIntArray(maskPixels);
+
+ BufferedImage maskImage = segmentationService.createMaskImage(maskPixelsInt, scaledImage.getWidth(), scaledImage.getHeight(), 0.35);
+
+ BufferedImage blended = segmentationService.blendMask(maskImage, scaledImage);
+
+ ImageIO.write(maskImage, "png", new File("./semantic-segmentation/target/java2Dmask.jpg"));
+ ImageIO.write(blended, "png", new File("./semantic-segmentation/target/java2Dblended.jpg"));
+ }
+}
diff --git a/function/semantic-segmentation-function/src/main/resources/images/ADE20K-all-small.png b/function/semantic-segmentation-function/src/main/resources/images/ADE20K-all-small.png
new file mode 100644
index 00000000..bede9db4
Binary files /dev/null and b/function/semantic-segmentation-function/src/main/resources/images/ADE20K-all-small.png differ
diff --git a/function/semantic-segmentation-function/src/main/resources/images/VikiMaxiAdi-all.png b/function/semantic-segmentation-function/src/main/resources/images/VikiMaxiAdi-all.png
new file mode 100644
index 00000000..719814e1
Binary files /dev/null and b/function/semantic-segmentation-function/src/main/resources/images/VikiMaxiAdi-all.png differ
diff --git a/function/semantic-segmentation-function/src/main/resources/images/cityscape-all-small.png b/function/semantic-segmentation-function/src/main/resources/images/cityscape-all-small.png
new file mode 100644
index 00000000..050a9cbe
Binary files /dev/null and b/function/semantic-segmentation-function/src/main/resources/images/cityscape-all-small.png differ
diff --git a/pom.xml b/pom.xml
index 2849499a..a7d99e4f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@
common/mqtt-common
common/tcp-common
common/twitter-common
-
+ common/tensorflow-common
consumer/cassandra-consumer
consumer/counter-consumer
@@ -79,6 +79,9 @@
function/tasklauncher-function
function/task-launch-request-function
function/twitter-function
+ function/image-recognition-function
+ function/object-detection-function
+ function/semantic-segmentation-function
supplier/file-supplier
supplier/ftp-supplier