Thanks to visit codestin.com
Credit goes to github.com

Skip to content

vigneshjd/camel-tensorflow-image-classification

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TensorFlow Serving + Apache Camel Image Classification

End-to-end image classification system using:

  • TensorFlow Serving (gRPC) for model serving
  • Apache Camel 4.x for orchestration
  • ResNet50 pretrained model (ImageNet)
  • Java 21 and Gradle multi-module project

Architecture Overview

┌─────────────────┐
│  input-images/  │  ──┐
│   (*.jpg, *.png)│    │
└─────────────────┘    │
                       │ (1) File component reads images
                       │
                       ▼
              ┌────────────────────┐
              │  Camel Client      │
              │  (Java 21)         │
              │                    │
              │  - Read image bytes│
              │  - Build Request   │  (2) Build PredictRequest (protobuf)
              │  - Parse Response  │      containing raw JPEG bytes
              └────────┬───────────┘
                       │
                       │ (3) gRPC call (localhost:8500)
                       ▼
              ┌────────────────────┐
              │ TensorFlow Serving │
              │  (Docker)          │
              │                    │
              │  - Decode JPEG     │  (4) Model processes:
              │  - Resize 224x224  │      - Decoding
              │  - Preprocess      │      - Resizing
              │  - ResNet50        │      - Preprocessing
              │  - Inference       │      - Inference
              └────────┬───────────┘
                       │
                       │ (5) PredictResponse (1000 class probs)
                       ▼
              ┌────────────────────┐
              │  Camel Client      │
              │                    │
              │  - Parse response  │  (6) Log results:
              │  - Map to labels   │      - Top-5 predictions
              │  - Log results     │      - Cat detection
              │  - Move file       │      - Move to .done/
              └────────────────────┘

Key Design Decisions

Why TensorFlow Serving (not DJL)?

  • TensorFlow Serving is the official TF model serving framework
  • Production-ready with gRPC support
  • Handles model versioning, batching, and optimization
  • DJL is NOT used - all inference happens in TensorFlow Serving

Why gRPC (not REST)?

  • gRPC is more efficient for binary data (protobufs)
  • Lower latency and bandwidth compared to JSON/REST
  • Better type safety with protocol buffers
  • Camel's camel-tensorflow-serving component uses gRPC

Why preprocessing in the model?

  • SavedModel includes preprocessing (decode, resize, normalize)
  • Java client sends raw JPEG bytes (no preprocessing in Java)
  • Simpler client code, less error-prone
  • Model is self-contained and portable

Project Structure

camel-tensorflow-image-classification/
├── tools/                              # Python scripts
│   ├── export_resnet50_savedmodel.py   # Export model with custom signature
│   └── download_imagenet_labels.py     # Download ImageNet labels
├── models/
│   └── resnet50/1/                     # SavedModel directory
│       ├── saved_model.pb              # Model graph
│       ├── variables/                  # Model weights
│       └── assets/                     # (empty)
├── input-images/                       # Image input directory
│   └── .done/                          # Processed images
├── docker-compose.yml                  # TensorFlow Serving container
├── settings.gradle                     # Gradle multi-module config
├── build.gradle                        # Root build file
└── camel-client/                       # Camel application
    ├── build.gradle
    └── src/main/
        ├── java/com/example/camel/tensorflow/
        │   ├── ImageClassificationApp.java           # Main entry point
        │   ├── ImageClassificationRoute.java         # Camel route
        │   ├── TensorFlowServingHelper.java         # Protobuf utilities
        │   └── ImageNetLabels.java                  # Label mapping
        └── resources/
            ├── application.properties               # Configuration
            ├── logback.xml                         # Logging config
            └── imagenet_class_index.json           # ImageNet labels

Quick Start

Prerequisites

  • Java 21
  • Python 3.8+ with TensorFlow 2.x
  • Docker and Docker Compose
  • Gradle (or use gradlew.bat)

Step 1: Export the Model (Python)

# Install TensorFlow
pip install tensorflow

# Export ResNet50 model with custom serving signature
python tools/export_resnet50_savedmodel.py

# Download ImageNet labels
python tools/download_imagenet_labels.py

This creates:

  • models/resnet50/1/ - SavedModel with preprocessing
  • camel-client/src/main/resources/imagenet_class_index.json - Labels

Step 2: Start TensorFlow Serving (Docker)

# Start TensorFlow Serving container
docker-compose up -d

# Check logs to verify model is loaded
docker-compose logs -f tensorflow-serving

# Look for: "Successfully loaded servable version"

TensorFlow Serving now listens on:

  • gRPC: localhost:8500 (used by Camel)
  • REST: localhost:8501 (not used in this project)

Step 3: Build and Run the Camel Client

# Build the project
gradlew.bat build

# Run the application
gradlew.bat :camel-client:run

Step 4: Test with Images

# Copy test images to input directory
copy path\to\cat.jpg input-images\
copy path\to\dog.jpg input-images\

# Watch the console for classification results

Technical Details

SavedModel Signature

The exported model has the following signature:

signature_name: "serving_default"

inputs:
  image_bytes: TensorSpec(shape=(), dtype=tf.string)
    # Raw JPEG bytes (no preprocessing in client)

outputs:
  predictions: TensorSpec(shape=(1, 1000), dtype=tf.float32)
    # Class probabilities for 1000 ImageNet classes

gRPC Communication Flow

  1. Client builds PredictRequest:

    PredictRequest request = PredictRequest.newBuilder()
        .setModelSpec(ModelSpec.newBuilder()
            .setName("resnet50")
            .setSignatureName("serving_default"))
        .putInputs("image_bytes", imageTensorProto)
        .build();
  2. TensorFlow Serving processes:

    • Receives gRPC request
    • Extracts image_bytes tensor
    • Runs SavedModel inference (decode, resize, ResNet50)
    • Returns predictions tensor
  3. Client parses PredictResponse:

    TensorProto predictionsTensor = response.getOutputsOrThrow("predictions");
    List<Float> probabilities = predictionsTensor.getFloatValList();

Cat Detection Logic

The application logs whether an image is a cat:

boolean isCat = topPredictions.stream()
    .anyMatch(p -> labels.getLabel(p.classIndex()).toLowerCase().contains("cat"));

ImageNet has multiple cat-related classes:

  • tabby cat
  • tiger cat
  • Persian cat
  • Siamese cat
  • Egyptian cat
  • etc.

Configuration

Edit camel-client/src/main/resources/application.properties:

# TensorFlow Serving endpoint
tensorflow.serving.host=localhost
tensorflow.serving.port=8500
tensorflow.serving.model.name=resnet50

# Input directory
camel.component.file.input.directory=input-images

# Number of top predictions to log
classification.top.predictions=5

Troubleshooting

Model not loaded

Error: Model not found: resnet50

Solution: Run python tools/export_resnet50_savedmodel.py first

gRPC connection failed

Error: UNAVAILABLE: io exception

Solution: Ensure TensorFlow Serving is running: docker-compose up -d

Labels not found

Error: imagenet_class_index.json not found

Solution: Run python tools/download_imagenet_labels.py

Java version mismatch

Error: Unsupported class file major version

Solution: Ensure Java 21 is installed and JAVA_HOME is set

Performance Notes

  • First inference is slow (~2-3 seconds) - model loading
  • Subsequent inferences are fast (~50-200ms)
  • gRPC is faster than REST for binary data
  • Batching is not implemented in this demo (processes one image at a time)

Dependencies

Python

  • tensorflow>=2.13.0 - Model export and SavedModel API

Java

  • apache-camel:4.4.0 - Routing and orchestration
  • camel-tensorflow-serving - gRPC client for TensorFlow Serving
  • tensorflow-core-platform:0.5.0 - TensorFlow Java API (protobufs)
  • jackson-databind:2.16.0 - JSON parsing for labels

Docker

  • tensorflow/serving:latest - Official TensorFlow Serving image

License

This is a demonstration project for educational purposes.

Author

Created as an example of TensorFlow Serving integration with Apache Camel 4.x.

About

A complete, production-ready TensorFlow Serving + Apache Camel 4.x integration project for image classification.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors