Build a Traffic Sign Recognition System with Spring Boot & Deeplearning4j
This tutorial explains how to create a traffic sign recognition application using Spring Boot and Java Deeplearning4j, covering CNN selection, dataset organization, Maven dependencies, data loading, model construction, training, prediction, unit testing, and expected results.
Technical Overview
This guide demonstrates how to build a traffic‑sign recognition system using Spring Boot and Java Deeplearning4j. A convolutional neural network (CNN) is employed to classify images of traffic signs.
1. Neural‑Network Choice
A CNN is selected because it extracts local visual features via weight sharing, reduces the number of parameters, and builds hierarchical representations that are well‑suited for image classification.
2. Dataset Format
The dataset should have an images directory containing JPEG/PNG files and a matching labels directory with a plain‑text file per image that stores the class index (e.g., 0 for speed‑limit, 1 for prohibition).
traffic_sign_dataset/
├── images/
│ ├── sign1.jpg
│ ├── sign2.jpg
│ └── ...
├── labels/
│ ├── sign1.txt
│ ├── sign2.txt
│ └── ...3. Technology Stack
Spring Boot – rapid development and auto‑configuration for Java web applications.
Deeplearning4j – Java deep‑learning library that supports CNNs and other architectures.
Maven Dependencies
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-core</artifactId>
<version>1.0.0-beta7</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-nn</artifactId>
<version>1.0.0-beta7</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-ui</artifactId>
<version>1.0.0-beta7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>Code Examples
1. Data Loading and Pre‑processing
import org.datavec.image.loader.NativeImageLoader;
import org.deeplearning4j.datasets.iterator.impl.ListDataSetIterator;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.dataset.DataSet;
import org.nd4j.linalg.dataset.api.preprocessor.DataNormalization;
import org.nd4j.linalg.dataset.api.preprocessor.ImagePreProcessingScaler;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class DataLoader {
public static ListDataSetIterator<DataSet> loadData(String dataDirectory) {
// Load images
File imageDir = new File(dataDirectory + "/images");
NativeImageLoader loader = new NativeImageLoader(32, 32, 3);
List<INDArray> images = new ArrayList<>();
for (File imgFile : imageDir.listFiles()) {
images.add(loader.asMatrix(imgFile));
}
// Load labels (one integer per file)
File labelDir = new File(dataDirectory + "/labels");
List<Integer> labels = new ArrayList<>();
for (File lblFile : labelDir.listFiles()) {
int label = Integer.parseInt(org.apache.commons.io.FileUtils.readFileToString(lblFile, "UTF-8"));
labels.add(label);
}
// Build DataSet
DataSet ds = new DataSet(
images.toArray(new INDArray[0]),
labels.stream().mapToDouble(i -> i).toArray()
);
// Normalize to [0,1]
DataNormalization scaler = new ImagePreProcessingScaler(0, 1);
scaler.fit(ds);
scaler.transform(ds);
return new ListDataSetIterator<>(ds, 32);
}
}2. Model Construction and Training
import org.deeplearning4j.nn.conf.ConvolutionMode;
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
import org.deeplearning4j.nn.conf.layers.ConvolutionLayer;
import org.deeplearning4j.nn.conf.layers.DenseLayer;
import org.deeplearning4j.nn.conf.layers.OutputLayer;
import org.deeplearning4j.nn.conf.layers.SubsamplingLayer;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.deeplearning4j.nn.weights.WeightInit;
import org.nd4j.linalg.activations.Activation;
import org.nd4j.linalg.lossfunctions.LossFunctions;
public class TrafficSignRecognitionModel {
public static MultiLayerNetwork buildModel() {
NeuralNetConfiguration.ListBuilder builder = new NeuralNetConfiguration.Builder()
.seed(12345)
.weightInit(WeightInit.XAVIER)
.l2(0.0005)
.list();
// Conv + pool
builder.layer(0, new ConvolutionLayer.Builder(5,5)
.nIn(3).stride(1,1).nOut(32)
.activation(Activation.RELU)
.convolutionMode(ConvolutionMode.Same)
.build());
builder.layer(1, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
.kernelSize(2,2).stride(2,2).build());
// Second conv + pool
builder.layer(2, new ConvolutionLayer.Builder(5,5)
.nOut(64)
.activation(Activation.RELU)
.convolutionMode(ConvolutionMode.Same)
.build());
builder.layer(3, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
.kernelSize(2,2).stride(2,2).build());
// Fully connected
builder.layer(4, new DenseLayer.Builder().nOut(1024).activation(Activation.RELU).build());
// Output (assume 10 classes)
builder.layer(5, new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
.nOut(10)
.activation(Activation.SOFTMAX)
.build());
MultiLayerNetwork net = new MultiLayerNetwork(builder.build());
return net;
}
public static void trainModel(MultiLayerNetwork model, ListDataSetIterator<DataSet> iterator) {
model.init();
for (int epoch = 0; epoch < 10; epoch++) {
model.fit(iterator);
iterator.reset();
}
}
}3. Prediction
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.datavec.image.loader.NativeImageLoader;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.dataset.api.preprocessor.DataNormalization;
import org.nd4j.linalg.dataset.api.preprocessor.ImagePreProcessingScaler;
import org.nd4j.linalg.factory.Nd4j;
import java.io.File;
public class Prediction {
public static int predict(MultiLayerNetwork model, File imageFile) throws Exception {
NativeImageLoader loader = new NativeImageLoader(32, 32, 3);
INDArray image = loader.asMatrix(imageFile);
DataNormalization scaler = new ImagePreProcessingScaler(0, 1);
scaler.transform(image);
INDArray output = model.output(image);
return Nd4j.argMax(output, 1).getInt(0);
}
}4. Unit Tests
import org.deeplearning4j.datasets.iterator.impl.ListDataSetIterator;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class TrafficSignRecognitionTest {
private MultiLayerNetwork model;
@BeforeEach
public void setup() {
model = TrafficSignRecognitionModel.buildModel();
}
@Test
public void testLoadData() {
String dataDir = "path/to/your/dataset";
ListDataSetIterator<?> iterator = DataLoader.loadData(dataDir);
assertNotNull(iterator);
}
@Test
public void testTrainModel() {
String dataDir = "path/to/your/dataset";
ListDataSetIterator<?> iterator = DataLoader.loadData(dataDir);
TrafficSignRecognitionModel.trainModel(model, iterator);
assertNotNull(model);
}
}Expected Output
Running the system should return the correct class index for a supplied traffic‑sign image (e.g., the index representing a speed‑limit sign).
References
Deeplearning4j official documentation
Spring Boot official documentation
"Deep Learning" by Ian Goodfellow, Yoshua Bengio, and Aaron Courville
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
