This is an automated email from the ASF dual-hosted git repository.

tsato pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-kamelets.git


The following commit(s) were added to refs/heads/main by this push:
     new 2ad4d453 Create an Image-to-Text action kamelet (#2171)
2ad4d453 is described below

commit 2ad4d45359e8086a172a0fa062815d0a4ce557e6
Author: Tadayoshi Sato <[email protected]>
AuthorDate: Thu Aug 29 18:01:50 2024 +0900

    Create an Image-to-Text action kamelet (#2171)
    
    * Switch to Camel 4.8.0-SNAPSHOT
    
    * Create an Image-to-Text action kamelet
---
 docs/modules/ROOT/nav.adoc                         |  1 +
 kamelets/djl-image-to-text-action.kamelet.yaml     | 75 ++++++++++++++++++++++
 .../kamelets/catalog/KameletsCatalogTest.java      |  2 +-
 library/camel-kamelets-utils/pom.xml               | 18 ++++++
 .../camel/kamelets/utils/djl/ImageNetUtil.java     | 58 +++++++++++++++++
 .../kamelets/djl-image-to-text-action.kamelet.yaml | 75 ++++++++++++++++++++++
 pom.xml                                            |  4 +-
 7 files changed, 230 insertions(+), 3 deletions(-)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 35629fc9..162a9a63 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -62,6 +62,7 @@
 * xref:cron-source.adoc[]
 * xref:data-type-action.adoc[]
 * xref:delay-action.adoc[]
+* xref:djl-image-to-text-action.adoc[]
 * xref:dns-dig-action.adoc[]
 * xref:dns-ip-action.adoc[]
 * xref:dns-lookup-action.adoc[]
diff --git a/kamelets/djl-image-to-text-action.kamelet.yaml 
b/kamelets/djl-image-to-text-action.kamelet.yaml
new file mode 100644
index 00000000..7031d9f7
--- /dev/null
+++ b/kamelets/djl-image-to-text-action.kamelet.yaml
@@ -0,0 +1,75 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#      http://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.
+# ---------------------------------------------------------------------------
+apiVersion: camel.apache.org/v1
+kind: Kamelet
+metadata:
+  name: djl-image-to-text-action
+  annotations:
+    camel.apache.org/kamelet.support.level: "Preview"
+    camel.apache.org/catalog.version: "4.8.0-SNAPSHOT"
+    camel.apache.org/kamelet.icon: 
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAArCAYAAACO7C3tAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAXEgAAFxIBZ5/SUgAAD7ZJREFUeAHtW1tsXMUZnplz21178SWxg01uTRNKbJVLmjSlhcaBVGoLkVpVG7WhaqW2UiSqICoR+oKUzSMvNHJUJCIUtS8Exby0RYmggjioIkBxY9LGkARMTGATx/Flbe/l3Gb6/WcvWdtxvL7EBsxIZ8/ZOXP9v/82M//hrLzE88UK9/JqMabijPEzsRhva2tTqFS4yq0/63LxuBLjG4nHuRyfd53/PI6x4xqfyqk7vk7Z/8si8JEjR7TBwUFx6dKlssoXeu/v7+dL7r9fsa4u1tDQoA4fPqxa2ttlfL6AUSBo1xmjiTXlhkS3LsbqrrTLrVu3eoVxXu9Oc+7q6t
 [...]
+    camel.apache.org/provider: "Apache Software Foundation"
+    camel.apache.org/kamelet.group: "Actions"
+    camel.apache.org/kamelet.namespace: "AI"
+  labels:
+    camel.apache.org/kamelet.type: "action"
+spec:
+  definition:
+    title: "Image-to-Text Action"
+    description: Detect and classify objects in an image into texts using the 
SSD and ResNet models and the ImageNet dataset.
+    type: object
+  types:
+    out:
+      mediaType: application/json
+  dependencies:
+    - "mvn:ai.djl.pytorch:pytorch-engine:0.29.0"
+    - "mvn:ai.djl.pytorch:pytorch-model-zoo:0.29.0"
+    - "mvn:net.sf.extjwnl:extjwnl:2.0.5"
+    - "mvn:net.sf.extjwnl:extjwnl-data-wn31:1.2"
+    - "mvn:org.apache.camel.kamelets:camel-kamelets-utils:4.8.0-SNAPSHOT"
+    - "camel:core"
+    - "camel:kamelet"
+    - "camel:jackson"
+    - "camel:djl"
+  template:
+    beans:
+      - name: imageNetUtil
+        type: "#class:org.apache.camel.kamelets.utils.djl.ImageNetUtil"
+    from:
+      uri: "kamelet:source"
+      steps:
+        - to: "djl:cv/object_detection?artifactId=ssd"
+        - convertBodyTo: "ai.djl.modality.cv.Image[]"
+        - split:
+            expression:
+              simple: "${body}"
+            aggregationStrategy: 
"#class:org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy"
+            steps:
+              - to: "djl:cv/image_classification?artifactId=resnet"
+              # The output from the image classification model is classified
+              # as one of 1000 labels from WordNet.
+              # Since it's too fine-grained, we want to find the higher-level
+              # group (= hypernym) for the classification using the WordNet
+              # dictionary.
+              - bean:
+                  ref: "{{imageNetUtil}}"
+                  method: extractClassName
+              - bean:
+                  ref: "{{imageNetUtil}}"
+                  method: addHypernym
+        - marshal:
+            json: {}
diff --git 
a/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
 
b/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
index 5056592c..8307e227 100644
--- 
a/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
+++ 
b/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
@@ -155,7 +155,7 @@ public class KameletsCatalogTest {
     @Test
     void testSupportedHeaders() throws Exception {
         verifyHeaders("aws-s3-source", 20);
-        verifyHeaders("aws-s3-sink", 27);
+        verifyHeaders("aws-s3-sink", 29);
         verifyHeaders("aws-cloudtrail-source", 4);
         verifyHeaders("aws-redshift-source", 0);
         verifyHeaders("aws-not-exists", 0);
diff --git a/library/camel-kamelets-utils/pom.xml 
b/library/camel-kamelets-utils/pom.xml
index 704d05a9..e217210a 100644
--- a/library/camel-kamelets-utils/pom.xml
+++ b/library/camel-kamelets-utils/pom.xml
@@ -92,6 +92,24 @@
             <scope>provided</scope>
         </dependency>
 
+        <!-- Dependencies for DJL and ImageNet util classes -->
+        <dependency>
+          <groupId>org.apache.camel</groupId>
+          <artifactId>camel-djl</artifactId>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>net.sf.extjwnl</groupId>
+          <artifactId>extjwnl</artifactId>
+          <version>2.0.5</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>net.sf.extjwnl</groupId>
+          <artifactId>extjwnl-data-wn31</artifactId>
+          <version>1.2</version>
+          <scope>provided</scope>
+        </dependency>
 
         <!-- Test scoped dependencies -->
         <dependency>
diff --git 
a/library/camel-kamelets-utils/src/main/java/org/apache/camel/kamelets/utils/djl/ImageNetUtil.java
 
b/library/camel-kamelets-utils/src/main/java/org/apache/camel/kamelets/utils/djl/ImageNetUtil.java
new file mode 100644
index 00000000..26dad880
--- /dev/null
+++ 
b/library/camel-kamelets-utils/src/main/java/org/apache/camel/kamelets/utils/djl/ImageNetUtil.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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.apache.camel.kamelets.utils.djl;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+
+import ai.djl.modality.Classifications;
+import net.sf.extjwnl.data.IndexWord;
+import net.sf.extjwnl.data.POS;
+import net.sf.extjwnl.data.PointerUtils;
+import net.sf.extjwnl.data.list.PointerTargetNodeList;
+import net.sf.extjwnl.dictionary.Dictionary;
+
+/**
+ * A utility bean class for handling ImageNet (https://image-net.org/) 
classifications.
+ */
+public class ImageNetUtil {
+
+    public ImageNetUtil() {
+    }
+
+    public void extractClassName(Exchange exchange) {
+        Classifications body = 
exchange.getMessage().getBody(Classifications.class);
+        String className = body.best().getClassName().split(",")[0].split(" ", 
2)[1];
+        exchange.getMessage().setBody(className);
+    }
+
+    public void addHypernym(Exchange exchange) throws Exception {
+        String className = exchange.getMessage().getBody(String.class);
+        Dictionary dic = Dictionary.getDefaultResourceInstance();
+        IndexWord word = dic.getIndexWord(POS.NOUN, className);
+        if (word == null) {
+            throw new RuntimeCamelException("Word not found: " + className);
+        }
+        PointerTargetNodeList hypernyms = 
PointerUtils.getDirectHypernyms(word.getSenses().get(0));
+        String hypernym = hypernyms.stream()
+                .map(h -> h.getSynset().getWords().get(0).getLemma())
+                .findFirst().orElse(className);
+        exchange.getMessage().setBody(List.of(className, hypernym));
+    }
+}
diff --git 
a/library/camel-kamelets/src/main/resources/kamelets/djl-image-to-text-action.kamelet.yaml
 
b/library/camel-kamelets/src/main/resources/kamelets/djl-image-to-text-action.kamelet.yaml
new file mode 100644
index 00000000..7031d9f7
--- /dev/null
+++ 
b/library/camel-kamelets/src/main/resources/kamelets/djl-image-to-text-action.kamelet.yaml
@@ -0,0 +1,75 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#      http://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.
+# ---------------------------------------------------------------------------
+apiVersion: camel.apache.org/v1
+kind: Kamelet
+metadata:
+  name: djl-image-to-text-action
+  annotations:
+    camel.apache.org/kamelet.support.level: "Preview"
+    camel.apache.org/catalog.version: "4.8.0-SNAPSHOT"
+    camel.apache.org/kamelet.icon: 
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAArCAYAAACO7C3tAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAXEgAAFxIBZ5/SUgAAD7ZJREFUeAHtW1tsXMUZnplz21178SWxg01uTRNKbJVLmjSlhcaBVGoLkVpVG7WhaqW2UiSqICoR+oKUzSMvNHJUJCIUtS8Exby0RYmggjioIkBxY9LGkARMTGATx/Flbe/l3Gb6/WcvWdtxvL7EBsxIZ8/ZOXP9v/82M//hrLzE88UK9/JqMabijPEzsRhva2tTqFS4yq0/63LxuBLjG4nHuRyfd53/PI6x4xqfyqk7vk7Z/8si8JEjR7TBwUFx6dKlssoXeu/v7+dL7r9fsa4u1tDQoA4fPqxa2ttlfL6AUSBo1xmjiTXlhkS3LsbqrrTLrVu3eoVxXu9Oc+7q6t
 [...]
+    camel.apache.org/provider: "Apache Software Foundation"
+    camel.apache.org/kamelet.group: "Actions"
+    camel.apache.org/kamelet.namespace: "AI"
+  labels:
+    camel.apache.org/kamelet.type: "action"
+spec:
+  definition:
+    title: "Image-to-Text Action"
+    description: Detect and classify objects in an image into texts using the 
SSD and ResNet models and the ImageNet dataset.
+    type: object
+  types:
+    out:
+      mediaType: application/json
+  dependencies:
+    - "mvn:ai.djl.pytorch:pytorch-engine:0.29.0"
+    - "mvn:ai.djl.pytorch:pytorch-model-zoo:0.29.0"
+    - "mvn:net.sf.extjwnl:extjwnl:2.0.5"
+    - "mvn:net.sf.extjwnl:extjwnl-data-wn31:1.2"
+    - "mvn:org.apache.camel.kamelets:camel-kamelets-utils:4.8.0-SNAPSHOT"
+    - "camel:core"
+    - "camel:kamelet"
+    - "camel:jackson"
+    - "camel:djl"
+  template:
+    beans:
+      - name: imageNetUtil
+        type: "#class:org.apache.camel.kamelets.utils.djl.ImageNetUtil"
+    from:
+      uri: "kamelet:source"
+      steps:
+        - to: "djl:cv/object_detection?artifactId=ssd"
+        - convertBodyTo: "ai.djl.modality.cv.Image[]"
+        - split:
+            expression:
+              simple: "${body}"
+            aggregationStrategy: 
"#class:org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy"
+            steps:
+              - to: "djl:cv/image_classification?artifactId=resnet"
+              # The output from the image classification model is classified
+              # as one of 1000 labels from WordNet.
+              # Since it's too fine-grained, we want to find the higher-level
+              # group (= hypernym) for the classification using the WordNet
+              # dictionary.
+              - bean:
+                  ref: "{{imageNetUtil}}"
+                  method: extractClassName
+              - bean:
+                  ref: "{{imageNetUtil}}"
+                  method: addHypernym
+        - marshal:
+            json: {}
diff --git a/pom.xml b/pom.xml
index 218db32e..925171b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-dependencies</artifactId>
-        <version>4.7.0</version>
+        <version>4.8.0-SNAPSHOT</version>
     </parent>
 
     <groupId>org.apache.camel.kamelets</groupId>
@@ -62,7 +62,7 @@
         <apache-rat-plugin.version>0.16.1</apache-rat-plugin.version>
         <cyclonedx-maven-plugin-version>2.8.1</cyclonedx-maven-plugin-version>
 
-        <camel.version>4.7.0</camel.version>
+        <camel.version>4.8.0-SNAPSHOT</camel.version>
         <camel.k.crds.version>2.4.0</camel.k.crds.version>
 
         <citrus.version>4.2.0</citrus.version>

Reply via email to