Add some use cases

This commit is contained in:
2026-10-04 15:20:25 +02:00
parent 6373978aac
commit 541a1440a3
3 changed files with 127 additions and 84 deletions

View File

@@ -10,6 +10,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.function.Supplier;
public class UseCasePresenter {
@@ -38,7 +39,12 @@ public class UseCasePresenter {
public void computeNoiseReduction() {
Image image1 = loadImage(NOISE_1_IMAGE);
Image image2 = loadImage(NOISE_2_IMAGE);
Image[] results = {service.reduceNoise(image1), service.reduceNoise(image2)};
Image reduced1 = measureTime("Reduction 1", () -> service.reduceNoise(image1, 0.5f, 7));
Image reduced2 = measureTime("Reduction 2", () -> service.reduceNoise(image2, 1f, 5));
Image[] results = { reduced1, reduced2 };
view.updateNoiseReduction(results[0], results[1]);
}
@@ -50,13 +56,13 @@ public class UseCasePresenter {
public void computePeasSegmentation() {
Image image = loadImage(PEAS_IMAGE);
Image[] results = service.segmentPeas(image);
Image[] results = measureTime("Peas segmentation", () -> service.segmentPeas(image));
view.updatePeasSegmentation(results[0], results[1]);
}
public void computeBarnacleSegmentation() {
Image image = loadImage(BARNACLES_IMAGE);
Image[] results = service.segmentBarnacles(image);
Image[] results =measureTime("Barnacle segmentation", () -> service.segmentBarnacles(image));
view.updateBarnacleSegmentation(results[0], results[1]);
}
@@ -95,4 +101,16 @@ public class UseCasePresenter {
public void dispose() {
view = null;
}
public <T> T measureTime(String name, Supplier<T> operation) {
long start = System.nanoTime();
T result = operation.get();
long elapsed = (System.nanoTime() - start) / 1_000_000;
System.out.println(name + " took " + elapsed + " ms");
return result;
}
}

View File

@@ -2,23 +2,26 @@ package services;
import domain.image.GrayScaleMatrix;
import domain.image.Image;
import domain.image.Pixel;
import domain.image.processing.filtering.GlobalLinearFiltering;
import domain.image.processing.morphology.BasicMorphology;
import domain.image.processing.morphology.ComplexMorphology;
import domain.image.processing.threshold.Thresholding;
import java.util.function.Supplier;
public class UseCaseService {
public Image reduceNoise(Image i0) {
public Image reduceNoise(Image i0, float cutOffPercentage, int maskSize) {
double cutoff = 0.7 * getMaxCutoff(i0.getWidth(), i0.getHeight());
double cutoff = cutOffPercentage * getMaxCutoff(i0.getWidth(), i0.getHeight());
GrayScaleMatrix m0 = i0.toGrayScale();
GrayScaleMatrix m1 = measureTime("Butterworth low pass", () -> GlobalLinearFiltering.butterworthLowPassFiltering(m0, cutoff, 1));
GrayScaleMatrix m1 = GlobalLinearFiltering.butterworthLowPassFiltering(m0, cutoff, 1);
Image i1 = m1.toImage();
return measureTime("Median filter", () -> ComplexMorphology.medianFilter(i1, 5).toImage());
return ComplexMorphology.medianFilter(i1, maskSize).toImage();
}
public Image[] equalizeHistogram(Image image) {
@@ -28,15 +31,81 @@ public class UseCaseService {
}
public Image[] segmentPeas(Image image) {
Image bluePeas = extractBluePeas(image);
Image redPeas = extractRedPeas(image);
return new Image[]{bluePeas, redPeas};
int width = image.getWidth();
int height = image.getHeight();
Pixel[][] bluePixels = new Pixel[height][width];
Pixel[][] redPixels = new Pixel[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Pixel pixel = image.getPixel(x, y);
int red = pixel.getRed();
int green = pixel.getGreen();
int blue = pixel.getBlue();
boolean isBlue = blue > red * 1.2 && blue > green * 1.2;
boolean isRed = red > blue * 1.2 && red > green * 1.2;
bluePixels[y][x] = isBlue ? new Pixel(255, 255, 255) : new Pixel(0, 0, 0);
redPixels[y][x] = isRed ? new Pixel(255, 255, 255) : new Pixel(0, 0, 0);
}
}
return new Image[]{
new Image(bluePixels),
new Image(redPixels)
};
}
public Image[] segmentBarnacles(Image image) {
Image largeBarnacles = extractLargeBarnacles(image);
Image smallBarnacles = extractSmallBarnacles(image);
return new Image[]{largeBarnacles, smallBarnacles};
GrayScaleMatrix base = image.toGrayScale();
Image largeThreshold = Thresholding.simpleThreshold(image, 128).toImage();
Image largeClosing = BasicMorphology.closing(largeThreshold, 7).toImage();
Image largeOpening = BasicMorphology.opening(largeClosing, 31).toImage();
GrayScaleMatrix largeMask = BasicMorphology.dilation(largeOpening, 11);
double[][] baseData = base.getRawData();
double[][] largeMaskData = largeMask.getRawData();
double[][] largeResult = new double[base.getHeight()][base.getWidth()];
for (int y = 0; y < base.getHeight(); y++) {
for (int x = 0; x < base.getWidth(); x++) {
largeResult[y][x] = largeMaskData[y][x] > 0 ? baseData[y][x] : 0;
}
}
// Small barnacles
GrayScaleMatrix small = Thresholding.simpleThreshold(image, 198);
GrayScaleMatrix smallMask = BasicMorphology.closing(small.toImage(), 9);
double[][] smallMaskData = smallMask.getRawData();
for (int y = 0; y < base.getHeight(); y++) {
for (int x = 0; x < base.getWidth(); x++) {
if (largeMaskData[y][x] > 0) {
smallMaskData[y][x] = 0;
}
}
}
smallMask = new GrayScaleMatrix(smallMaskData);
Image smallMaskImage = smallMask.toImage();
Image smallOpening = BasicMorphology.opening(smallMaskImage, 5).toImage();
smallMask =BasicMorphology.dilation(smallOpening, 5);
smallMaskData = smallMask.getRawData();
double[][] smallResult = new double[base.getHeight()][base.getWidth()];
for (int y = 0; y < base.getHeight(); y++) {
for (int x = 0; x < base.getWidth(); x++) {
smallResult[y][x] = smallMaskData[y][x] > 0 ? baseData[y][x] : 0;
}
}
return new Image[]{
new GrayScaleMatrix(largeResult).toImage(),
new GrayScaleMatrix(smallResult).toImage()
};
}
public Image segmentTools(Image image) {
@@ -93,17 +162,6 @@ public class UseCaseService {
return image;
}
public <T> T measureTime(String name, Supplier<T> operation) {
long start = System.nanoTime();
T result = operation.get();
long elapsed = (System.nanoTime() - start) / 1_000_000;
System.out.println(name + " took " + elapsed + " ms");
return result;
}
private double getMaxCutoff(int width, int height) {
return Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
}

View File

@@ -12,39 +12,23 @@ import javax.swing.*;
import java.awt.*;
public class UseCaseView extends AbstractView implements IUseCaseView {
private static final String NOISE_1_TAB_TITLE = "Bruit 1";
private static final String NOISE_2_TAB_TITLE = "Bruit 2";
private static final String HISTOGRAM_RGB_TAB_TITLE = "Égalisation RGB";
private static final String HISTOGRAM_LUMINANCE_TAB_TITLE = "Égalisation luminance";
private static final String PEAS_BLUE_TAB_TITLE = "Pois bleus";
private static final String PEAS_RED_TAB_TITLE = "Pois rouges";
private static final String BARNACLE_LARGE_TAB_TITLE = "Balanes grandes";
private static final String BARNACLE_SMALL_TAB_TITLE = "Balanes petites";
private static final String TOOLS_TAB_TITLE = "Outils";
private static final String SPACECRAFT_TAB_TITLE = "Synthèse";
private static final String SPACECRAFT_CONTOUR_TAB_TITLE = "Synthèse contour";
private static final String TOAST_TAB_TITLE = "Tartines";
private static final String NOISE_1_TAB_TITLE = "1. Bruit 1";
private static final String NOISE_2_TAB_TITLE = "1. Bruit 2";
private static final String HISTOGRAM_RGB_TAB_TITLE = "2. Égalisation RGB";
private static final String HISTOGRAM_LUMINANCE_TAB_TITLE = "2. Égalisation luminance";
private static final String PEAS_BLUE_TAB_TITLE = "3. Pois bleus";
private static final String PEAS_RED_TAB_TITLE = "3. Pois rouges";
private static final String BARNACLE_LARGE_TAB_TITLE = "4. Balanes grandes";
private static final String BARNACLE_SMALL_TAB_TITLE = "4. Balanes petites";
private static final String TOOLS_TAB_TITLE = "5. Outils";
private static final String SPACECRAFT_TAB_TITLE = "6. Synthèse";
private static final String SPACECRAFT_CONTOUR_TAB_TITLE = "6. Synthèse contour";
private static final String TOAST_TAB_TITLE = "7. Tartines";
private final UseCasePresenter presenter;
private final TabbedPanelFactory tabbedPanelFactory;
private TabbedImagePanel resultPanel;
private JButton noiseButton;
private JButton histogramButton;
private JButton peasButton;
private JButton barnacleButton;
private JButton toolsButton;
private JButton spacecraftButton;
private JButton toastButton;
@Inject
public UseCaseView(UseCasePresenter presenter, TabbedPanelFactory tabbedPanelFactory) {
this.presenter = presenter;
@@ -68,54 +52,37 @@ public class UseCaseView extends AbstractView implements IUseCaseView {
TOAST_TAB_TITLE
);
noiseButton = new JButton("Bruit");
histogramButton = new JButton("Histogramme");
peasButton = new JButton("Petits pois");
barnacleButton = new JButton("Balanes");
toolsButton = new JButton("Outils");
spacecraftButton = new JButton("Vaisseau");
toastButton = new JButton("Tartines");
resultPanel.addChangeListener(e -> computeSelectedExercise());
noiseButton.addActionListener(e -> presenter.computeNoiseReduction());
histogramButton.addActionListener(e -> presenter.computeHistogramEqualization());
peasButton.addActionListener(e -> presenter.computePeasSegmentation());
barnacleButton.addActionListener(e -> presenter.computeBarnacleSegmentation());
toolsButton.addActionListener(e -> presenter.computeToolsSegmentation());
spacecraftButton.addActionListener(e -> presenter.computeSpacecraftExtraction());
toastButton.addActionListener(e -> presenter.computeToastOutline());
JPanel controlPanel = createControlPanel();
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPanel.add(resultPanel, BorderLayout.CENTER);
mainPanel.add(controlPanel, BorderLayout.SOUTH);
setContentPane(mainPanel);
setTitle("Applications");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setSize(1200, 800);
setLocationRelativeTo(null);
}
private JPanel createControlPanel() {
JPanel panel = new JPanel(new GridLayout(1, 7, 5, 5));
private void computeSelectedExercise() {
int index = resultPanel.getSelectedIndex();
panel.add(noiseButton);
panel.add(histogramButton);
panel.add(peasButton);
panel.add(barnacleButton);
panel.add(toolsButton);
panel.add(spacecraftButton);
panel.add(toastButton);
return panel;
switch (index) {
case 0, 1 -> presenter.computeNoiseReduction();
case 2, 3 -> presenter.computeHistogramEqualization();
case 4, 5 -> presenter.computePeasSegmentation();
case 6, 7 -> presenter.computeBarnacleSegmentation();
case 8 -> presenter.computeToolsSegmentation();
case 9, 10 -> presenter.computeSpacecraftExtraction();
case 11 -> presenter.computeToastOutline();
}
}
@Override
public void initValues() {
presenter.setView(this);
presenter.computeNoiseReduction();
}
@Override