Skip to content

Commit

Permalink
Merge pull request #113 from Samyssmile/augmentation
Browse files Browse the repository at this point in the history
Augmentation Baseline Implemented
  • Loading branch information
Samyssmile authored Nov 9, 2023
2 parents 2e43d6f + 3b3b341 commit 90055e0
Show file tree
Hide file tree
Showing 38 changed files with 1,040 additions and 10 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ bin/
gradle.properties
!gradle.properties
!**/src/main/**/gradle.properties

### Images
*.jpg
*.jpeg
*.png
/benchmark-data/augmentation-benchmark-images/*
1 change: 1 addition & 0 deletions benchmark-data/placeholder.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.jvmargs=-Xmx32g -Xms8g
org.gradle.jvmargs=-Xmx8g
7 changes: 7 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'java-library'
id 'maven-publish'
id 'signing'
id "me.champeau.jmh" version "0.7.2"
}

group = 'io.github.samyssmile'
Expand Down Expand Up @@ -42,6 +43,10 @@ dependencies {
implementation "org.ejml:${lib}:0.43.1"
}

// JMH dependencies
implementation 'org.openjdk.jmh:jmh-core:1.37'
implementation 'org.openjdk.jmh:jmh-generator-annprocess:1.37'

// Other dependencies
implementation 'com.opencsv:opencsv:5.8'
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
Expand Down Expand Up @@ -124,6 +129,7 @@ javadoc {
}
}


static String getOsString() {
String vendor = System.getProperty("java.vendor");
if ("The Android Project" == vendor) {
Expand Down Expand Up @@ -170,3 +176,4 @@ static String getArchString() {
}
return "unknown";
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.edux.benchmark.augmentation.io;

import de.edux.augmentation.io.AugmentationImageReader;
import de.edux.augmentation.io.IAugmentationImageReader;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.SECONDS)
@Timeout(time = 25, timeUnit = TimeUnit.SECONDS)
@Warmup(iterations = 1)
public class AugmentatioIOBenchmark {

IAugmentationImageReader reader;

public AugmentatioIOBenchmark() {}

public static void main(String[] args) throws Exception {

org.openjdk.jmh.Main.main(args);
}

@Benchmark
@Fork(value = 1, warmups = 1)
@BenchmarkMode({Mode.All})
public void readBatchOfImages() throws Exception {
Path benchmarkDataDir =
Paths.get(
".."
+ File.separator
+ "benchmark-data"
+ File.separator
+ "augmentation-benchmark-images");
reader = new AugmentationImageReader();

var imageStream = reader.readBatchOfImages(benchmarkDataDir.toString(), 100, 100);
}
}
24 changes: 24 additions & 0 deletions lib/src/main/java/de/edux/augmentation/AbstractAugmentation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.edux.augmentation;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import javax.imageio.ImageIO;

/**
* Abstract class for augmentation operations. All specific augmentation classes should extend this.
*/
public abstract class AbstractAugmentation {

public static BufferedImage readImage(Path imagePath) throws IOException {
return ImageIO.read(imagePath.toFile());
}

/**
* Applies the augmentation to an image.
*
* @param image The image to augment.
* @return The augmented image.
*/
public abstract BufferedImage apply(BufferedImage image);
}
34 changes: 34 additions & 0 deletions lib/src/main/java/de/edux/augmentation/AugmentationBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.edux.augmentation;

import de.edux.augmentation.composite.CompositeAugmentationSequence;
import java.util.ArrayList;
import java.util.List;

/** Builder class for creating an augmentation sequence. */
public class AugmentationBuilder {
private List<AbstractAugmentation> augmentations;

public AugmentationBuilder() {
this.augmentations = new ArrayList<>();
}

/**
* Adds an augmentation to the sequence.
*
* @param augmentation The augmentation operation to add.
* @return The builder instance for chaining.
*/
public AugmentationBuilder addAugmentation(AbstractAugmentation augmentation) {
this.augmentations.add(augmentation);
return this;
}

/**
* Builds the final Augmentation sequence from the added operations.
*
* @return The composite Augmentation object containing all added operations.
*/
public AugmentationSequence build() {
return new CompositeAugmentationSequence(augmentations);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.edux.augmentation;

import java.awt.image.BufferedImage;

public interface AugmentationSequence {

BufferedImage applyTo(BufferedImage image);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package de.edux.augmentation.composite;

import de.edux.augmentation.AbstractAugmentation;
import de.edux.augmentation.AugmentationSequence;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;

/** Composite augmentation that applies a sequence of augmentations. */
public class CompositeAugmentationSequence implements AugmentationSequence {
private final List<AbstractAugmentation> augmentations;

public CompositeAugmentationSequence(List<AbstractAugmentation> augmentations) {
this.augmentations = augmentations;
}

@Override
public BufferedImage applyTo(BufferedImage image) {
BufferedImage currentImage = image;
for (AbstractAugmentation augmentation : augmentations) {
currentImage = augmentation.apply(currentImage);
}
return currentImage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package de.edux.augmentation.effects;

import de.edux.augmentation.AbstractAugmentation;

import java.awt.image.BufferedImage;
import java.awt.image.Kernel;
import java.awt.image.ConvolveOp;

/** This class provides an augmentation that applies a Gaussian blur to an image. */
public class BlurAugmentation extends AbstractAugmentation {

private final float radius;

/**
* Initializes a new instance of the BlurAugmentation class with the specified blur radius.
*
* @param radius The radius of the Gaussian blur. Higher values result in a more pronounced blur
* effect.
*/
public BlurAugmentation(float radius) {
this.radius = radius;
}

/**
* Applies a Gaussian blur augmentation to the provided image.
*
* @param image The BufferedImage to which the blur augmentation will be applied.
* @return A new BufferedImage with the blur augmentation applied.
*/
@Override
public BufferedImage apply(BufferedImage image) {
int radius = (int) this.radius;
int size = radius * 2 + 1;
float[] data = new float[size * size];

float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;

for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
float distance = x * x + y * y;
int index = (y + radius) * size + x + radius;
data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}
}

for (int i = 0; i < data.length; i++) {
data[i] /= total;
}

Kernel kernel = new Kernel(size, size, data);
ConvolveOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
return op.filter(image, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package de.edux.augmentation.effects;

import de.edux.augmentation.AbstractAugmentation;
import java.awt.Color;
import java.awt.image.BufferedImage;

/** This class enhances the contrast of an image. */
public class ContrastAugmentation extends AbstractAugmentation {

private final float scaleFactor;

/**
* Initializes a new instance of the ContrastAugmentation class with the specified contrast
* factor.
*
* @param contrast A value between 0 and 1, where higher values indicate a higher level of
* contrast.
*/
public ContrastAugmentation(float contrast) {
if (contrast < 0 || contrast > 1) {
throw new IllegalArgumentException("Contrast must be between 0 and 1.");
}
this.scaleFactor = 1 + (contrast - 0.5f) * 2;
}

/**
* Applies contrast enhancement to the provided image.
*
* @param image The BufferedImage to which the contrast enhancement will be applied.
* @return A new BufferedImage with the contrast enhancement applied.
*/
@Override
public BufferedImage apply(BufferedImage image) {
BufferedImage contrastedImage =
new BufferedImage(image.getWidth(), image.getHeight(), image.getType());

for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
int rgba = image.getRGB(x, y);
Color col = new Color(rgba, true);
int r = (int) bound((int) (col.getRed() * scaleFactor));
int g = (int) bound((int) (col.getGreen() * scaleFactor));
int b = (int) bound((int) (col.getBlue() * scaleFactor));

Color newColor = new Color(bound(r), bound(g), bound(b), col.getAlpha());
contrastedImage.setRGB(x, y, newColor.getRGB());
}
}

return contrastedImage;
}

private int bound(int colorValue) {
return Math.min(Math.max(colorValue, 0), 255);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package de.edux.augmentation.effects;

import de.edux.augmentation.AbstractAugmentation;
import java.awt.image.BufferedImage;

/** This class provides an augmentation that crops an image based on a specified factor. */
public class CroppingAugmentation extends AbstractAugmentation {

private final float cropFactor;

/**
* Constructs a CroppingAugmentation with a specified crop factor. The crop factor should be
* between 0 and 1, where 1 would result in no crop and 0.5 would crop half of the width and
* height.
*
* @param cropFactor The factor by which the image should be cropped.
*/
public CroppingAugmentation(float cropFactor) {
if (cropFactor <= 0 || cropFactor > 1) {
throw new IllegalArgumentException("Crop factor must be between 0 and 1.");
}
this.cropFactor = cropFactor;
}

/**
* Applies a cropping augmentation to the provided image.
*
* @param image The BufferedImage to which the cropping augmentation will be applied.
* @return A new BufferedImage with the cropping augmentation applied.
*/
@Override
public BufferedImage apply(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int newWidth = (int) (width * cropFactor);
int newHeight = (int) (height * cropFactor);

int x0 = (width - newWidth) / 2;
int y0 = (height - newHeight) / 2;

return image.getSubimage(x0, y0, newWidth, newHeight);
}
}
Loading

0 comments on commit 90055e0

Please sign in to comment.