Add non-linear outline
This commit is contained in:
@@ -12,6 +12,8 @@ import presenters.filtering.local.LocalFilteringPresenter;
|
||||
import presenters.morphology.BasicMorphologyPresenter;
|
||||
import presenters.morphology.ComplexMorphologyPresenter;
|
||||
import presenters.outline.LinearOutlinePresenter;
|
||||
import presenters.outline.NonLinearOutlineListener;
|
||||
import presenters.outline.NonLinearOutlinePresenter;
|
||||
import services.GlobalFilteringService;
|
||||
import services.ImageService;
|
||||
import services.MorphologyService;
|
||||
@@ -25,6 +27,7 @@ import ui.implementation.views.fitering.local.LocalFilteringView;
|
||||
import ui.implementation.views.morphology.BasicMorphologyView;
|
||||
import ui.implementation.views.morphology.ComplexMorphologyView;
|
||||
import ui.implementation.views.outline.LinearOutlineView;
|
||||
import ui.implementation.views.outline.NonLinearOutlineView;
|
||||
|
||||
/**
|
||||
* Gathers some configurations in order to set the dependency injection container up
|
||||
@@ -43,6 +46,7 @@ public class AppModule extends AbstractModule {
|
||||
bind(BasicMorphologyState.class);
|
||||
bind(ComplexMorphologyState.class);
|
||||
bind(LinearOutlineState.class);
|
||||
bind(NonLinearOutlineState.class);
|
||||
|
||||
//--- Application layer ---
|
||||
bind(EventBus.class).in(Scopes.SINGLETON);
|
||||
@@ -57,6 +61,7 @@ public class AppModule extends AbstractModule {
|
||||
bind(IBasicMorphologyView.class).to(BasicMorphologyView.class);
|
||||
bind(IComplexMorphologyView.class).to(ComplexMorphologyView.class);
|
||||
bind(ILinearOutlineView.class).to(LinearOutlineView.class);
|
||||
bind(INonLinearOutlineView.class).to(NonLinearOutlineView.class);
|
||||
|
||||
//--- Presentation layer ---
|
||||
bind(MainPresenter.class);
|
||||
@@ -67,6 +72,7 @@ public class AppModule extends AbstractModule {
|
||||
bind(BasicMorphologyPresenter.class);
|
||||
bind(ComplexMorphologyPresenter.class);
|
||||
bind(LinearOutlinePresenter.class);
|
||||
bind(NonLinearOutlinePresenter.class);
|
||||
|
||||
//--- Service layer layer ---
|
||||
bind(ImageService.class);
|
||||
|
||||
@@ -12,6 +12,7 @@ import ui.implementation.views.fitering.local.LocalFilteringView;
|
||||
import ui.implementation.views.morphology.BasicMorphologyView;
|
||||
import ui.implementation.views.morphology.ComplexMorphologyView;
|
||||
import ui.implementation.views.outline.LinearOutlineView;
|
||||
import ui.implementation.views.outline.NonLinearOutlineView;
|
||||
|
||||
/**
|
||||
* Concrete implement of the INavigator interface.
|
||||
@@ -26,7 +27,8 @@ public class SwingNavigator implements INavigator {
|
||||
private final Provider<LocalFilteringView> convolutionFilteringProvider;
|
||||
private final Provider<BasicMorphologyView> basicMorphologyProvider;
|
||||
private final Provider<ComplexMorphologyView> complexMorphologyProvider;
|
||||
private Provider<LinearOutlineView> linearOutlineProvider;
|
||||
private final Provider<LinearOutlineView> linearOutlineProvider;
|
||||
private final Provider<NonLinearOutlineView> nonLinearOutlineProvider;
|
||||
|
||||
@Inject
|
||||
public SwingNavigator(
|
||||
@@ -36,7 +38,8 @@ public class SwingNavigator implements INavigator {
|
||||
Provider<LocalFilteringView> convolutionFilterProvider,
|
||||
Provider<BasicMorphologyView> basicMorphologyProvider,
|
||||
Provider<ComplexMorphologyView> complexMorphologyProvider,
|
||||
Provider<LinearOutlineView> linearOutlineProvider
|
||||
Provider<LinearOutlineView> linearOutlineProvider,
|
||||
Provider<NonLinearOutlineView> nonLinearOutlineProvider
|
||||
) {
|
||||
this.doubleMatrixProvider = doubleMatrixProvider;
|
||||
this.filteringProvider = filteringProvider;
|
||||
@@ -45,6 +48,7 @@ public class SwingNavigator implements INavigator {
|
||||
this.basicMorphologyProvider = basicMorphologyProvider;
|
||||
this.complexMorphologyProvider = complexMorphologyProvider;
|
||||
this.linearOutlineProvider = linearOutlineProvider;
|
||||
this.nonLinearOutlineProvider = nonLinearOutlineProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,6 +95,8 @@ public class SwingNavigator implements INavigator {
|
||||
|
||||
@Override
|
||||
public void showNonLinearOutline() {
|
||||
NonLinearOutlineView view = nonLinearOutlineProvider.get();
|
||||
runView(view);
|
||||
}
|
||||
|
||||
private void runView(AbstractView view) {
|
||||
|
||||
74
src/main/java/app/state/NonLinearOutlineState.java
Normal file
74
src/main/java/app/state/NonLinearOutlineState.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package app.state;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.Image;
|
||||
import presenters.outline.NonLinearOutlineListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NonLinearOutlineState extends State {
|
||||
|
||||
private Image erosionGradient;
|
||||
private Image dilationGradient;
|
||||
private Image beucherGradient;
|
||||
private Image nonLinearLaplacian;
|
||||
|
||||
private final List<NonLinearOutlineListener> listeners = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
public NonLinearOutlineState() {
|
||||
}
|
||||
|
||||
public void subscribe(NonLinearOutlineListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void unsubscribe(NonLinearOutlineListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setErosionGradient(Image image) {
|
||||
erosionGradient = image;
|
||||
listeners.forEach(listener ->
|
||||
listener.onErosionGradientChanged(image)
|
||||
);
|
||||
}
|
||||
|
||||
public void setDilationGradient(Image image) {
|
||||
dilationGradient = image;
|
||||
listeners.forEach(listener ->
|
||||
listener.onDilationGradientChanged(image)
|
||||
);
|
||||
}
|
||||
|
||||
public void setBeucherGradient(Image image) {
|
||||
beucherGradient = image;
|
||||
listeners.forEach(listener ->
|
||||
listener.onBeucherGradientChanged(image)
|
||||
);
|
||||
}
|
||||
|
||||
public void setNonLinearLaplacian(Image image) {
|
||||
nonLinearLaplacian = image;
|
||||
listeners.forEach(listener ->
|
||||
listener.onNonLinearLaplacianChanged(image)
|
||||
);
|
||||
}
|
||||
|
||||
public Image getErosionGradient() {
|
||||
return erosionGradient;
|
||||
}
|
||||
|
||||
public Image getDilationGradient() {
|
||||
return dilationGradient;
|
||||
}
|
||||
|
||||
public Image getBeucherGradient() {
|
||||
return beucherGradient;
|
||||
}
|
||||
|
||||
public Image getNonLinearLaplacian() {
|
||||
return nonLinearLaplacian;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package domain.image.processing.outline;
|
||||
|
||||
import domain.image.GrayScaleMatrix;
|
||||
import domain.image.Image;
|
||||
import domain.image.processing.morphology.BasicMorphology;
|
||||
|
||||
public class NonLinearOutline {
|
||||
|
||||
public static GrayScaleMatrix gradientErosion(Image image) {
|
||||
GrayScaleMatrix original = image.toGrayScale();
|
||||
GrayScaleMatrix erosion = BasicMorphology.erosion(image, 3);
|
||||
|
||||
return subtract(original, erosion);
|
||||
}
|
||||
|
||||
public static GrayScaleMatrix gradientDilation(Image image) {
|
||||
GrayScaleMatrix original = image.toGrayScale();
|
||||
GrayScaleMatrix dilation = BasicMorphology.dilation(image, 3);
|
||||
|
||||
return subtract(dilation, original);
|
||||
}
|
||||
|
||||
public static GrayScaleMatrix beucherGradient(Image image) {
|
||||
GrayScaleMatrix erosion = BasicMorphology.erosion(image, 3);
|
||||
GrayScaleMatrix dilation = BasicMorphology.dilation(image, 3);
|
||||
|
||||
return subtract(dilation, erosion);
|
||||
}
|
||||
|
||||
public static GrayScaleMatrix nonLinearLaplacian(Image image) {
|
||||
GrayScaleMatrix original = image.toGrayScale();
|
||||
GrayScaleMatrix erosion = BasicMorphology.erosion(image, 3);
|
||||
GrayScaleMatrix dilation = BasicMorphology.dilation(image, 3);
|
||||
|
||||
int height = original.getHeight();
|
||||
int width = original.getWidth();
|
||||
|
||||
double[][] result = new double[height][width];
|
||||
|
||||
double[][] originalData = original.getRawData();
|
||||
double[][] erosionData = erosion.getRawData();
|
||||
double[][] dilationData = dilation.getRawData();
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
result[y][x] =
|
||||
dilationData[y][x]
|
||||
+ erosionData[y][x]
|
||||
- 2 * originalData[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
return new GrayScaleMatrix(result);
|
||||
}
|
||||
|
||||
private static GrayScaleMatrix subtract(GrayScaleMatrix first, GrayScaleMatrix second) {
|
||||
int height = first.getHeight();
|
||||
int width = first.getWidth();
|
||||
|
||||
double[][] firstData = first.getRawData();
|
||||
double[][] secondData = second.getRawData();
|
||||
|
||||
double[][] result = new double[height][width];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
result[y][x] =
|
||||
firstData[y][x] - secondData[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
return new GrayScaleMatrix(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package presenters.outline;
|
||||
|
||||
import domain.image.Image;
|
||||
|
||||
public interface NonLinearOutlineListener {
|
||||
|
||||
void onErosionGradientChanged(Image image);
|
||||
|
||||
void onDilationGradientChanged(Image image);
|
||||
|
||||
void onBeucherGradientChanged(Image image);
|
||||
|
||||
void onNonLinearLaplacianChanged(Image image);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package presenters.outline;
|
||||
|
||||
import app.state.AppState;
|
||||
import app.state.NonLinearOutlineState;
|
||||
import domain.image.Image;
|
||||
import jakarta.inject.Inject;
|
||||
import services.OutlineService;
|
||||
import ui.abstractions.INonLinearOutlineView;
|
||||
|
||||
public class NonLinearOutlinePresenter implements NonLinearOutlineListener {
|
||||
|
||||
private final AppState appState;
|
||||
private final NonLinearOutlineState outlineState;
|
||||
private final OutlineService outlineService;
|
||||
|
||||
private INonLinearOutlineView view;
|
||||
|
||||
@Inject
|
||||
public NonLinearOutlinePresenter(
|
||||
AppState appState,
|
||||
NonLinearOutlineState outlineState,
|
||||
OutlineService outlineService
|
||||
) {
|
||||
this.appState = appState;
|
||||
this.outlineState = outlineState;
|
||||
this.outlineService = outlineService;
|
||||
|
||||
outlineState.subscribe(this);
|
||||
}
|
||||
|
||||
public void setView(INonLinearOutlineView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
view = null;
|
||||
outlineState.unsubscribe(this);
|
||||
}
|
||||
|
||||
public void computeErosionGradient() {
|
||||
Image image = appState.getImage();
|
||||
|
||||
Image result = outlineService.gradientErosion(image);
|
||||
|
||||
outlineState.setErosionGradient(result);
|
||||
}
|
||||
|
||||
public void computeDilationGradient() {
|
||||
Image image = appState.getImage();
|
||||
|
||||
Image result = outlineService.gradientDilation(image);
|
||||
|
||||
outlineState.setDilationGradient(result);
|
||||
}
|
||||
|
||||
public void computeBeucherGradient() {
|
||||
Image image = appState.getImage();
|
||||
|
||||
Image result = outlineService.beucherGradient(image);
|
||||
|
||||
outlineState.setBeucherGradient(result);
|
||||
}
|
||||
|
||||
public void computeNonLinearLaplacian() {
|
||||
Image image = appState.getImage();
|
||||
|
||||
Image result = outlineService.nonLinearLaplacian(image);
|
||||
|
||||
outlineState.setNonLinearLaplacian(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErosionGradientChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateErosionGradient(image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDilationGradientChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateDilationGradient(image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeucherGradientChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateBeucherGradient(image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNonLinearLaplacianChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateNonLinearLaplacian(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package services;
|
||||
|
||||
import domain.image.Image;
|
||||
import domain.image.processing.outline.LinearOutline;
|
||||
import domain.image.processing.outline.NonLinearOutline;
|
||||
|
||||
public class OutlineService {
|
||||
|
||||
@@ -29,4 +30,31 @@ public class OutlineService {
|
||||
.toImage();
|
||||
}
|
||||
|
||||
public Image gradientErosion(Image image) {
|
||||
return NonLinearOutline
|
||||
.gradientErosion(image)
|
||||
.toImage();
|
||||
}
|
||||
|
||||
public Image gradientDilation(Image image) {
|
||||
return NonLinearOutline
|
||||
.gradientDilation(image)
|
||||
.toImage();
|
||||
}
|
||||
|
||||
public Image beucherGradient(Image image) {
|
||||
return NonLinearOutline
|
||||
.beucherGradient(image)
|
||||
.toImage();
|
||||
}
|
||||
|
||||
public Image nonLinearLaplacian(Image image) {
|
||||
return NonLinearOutline
|
||||
.nonLinearLaplacian(image)
|
||||
.toImage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
14
src/main/java/ui/abstractions/INonLinearOutlineView.java
Normal file
14
src/main/java/ui/abstractions/INonLinearOutlineView.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package ui.abstractions;
|
||||
|
||||
import domain.image.Image;
|
||||
|
||||
public interface INonLinearOutlineView {
|
||||
|
||||
void updateErosionGradient(Image image);
|
||||
|
||||
void updateDilationGradient(Image image);
|
||||
|
||||
void updateBeucherGradient(Image image);
|
||||
|
||||
void updateNonLinearLaplacian(Image image);
|
||||
}
|
||||
@@ -99,11 +99,10 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
);
|
||||
|
||||
outlineMenu = new Menu("Contours","/cp_51_p1.jpg",
|
||||
new MenuItem("Linéair", this::displayLinearOutline),
|
||||
new MenuItem("Non-linéair", this::displayNonLinearOutline)
|
||||
new MenuItem("Linéaire", this::displayLinearOutline),
|
||||
new MenuItem("Non-linéaire", this::displayNonLinearOutline)
|
||||
);
|
||||
|
||||
|
||||
histogramMenu = new Menu("Histogramme","/report_48_hot.jpg",
|
||||
new MenuItem("Afficher", "/report_32_hot.jpg",this::displayHistogram)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package ui.implementation.views.outline;
|
||||
|
||||
import domain.image.Image;
|
||||
import jakarta.inject.Inject;
|
||||
import presenters.outline.NonLinearOutlinePresenter;
|
||||
import ui.abstractions.AbstractView;
|
||||
import ui.abstractions.INonLinearOutlineView;
|
||||
import ui.implementation.components.controls.SaveButton;
|
||||
import ui.implementation.components.image.TabbedImagePanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class NonLinearOutlineView extends AbstractView implements INonLinearOutlineView {
|
||||
|
||||
private static final String EROSION_GRADIENT_TAB_TITLE = "Gradient d'érosion";
|
||||
private static final String DILATION_GRADIENT_TAB_TITLE = "Gradient de dilatation";
|
||||
private static final String BEUCHER_GRADIENT_TAB_TITLE = "Gradient de Beucher";
|
||||
private static final String NON_LINEAR_LAPLACIAN_TAB_TITLE = "Laplacien non-linéaire";
|
||||
|
||||
private final NonLinearOutlinePresenter presenter;
|
||||
|
||||
private TabbedImagePanel modeTab;
|
||||
|
||||
@Inject
|
||||
public NonLinearOutlineView(NonLinearOutlinePresenter presenter) {
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents() {
|
||||
modeTab = new TabbedImagePanel();
|
||||
|
||||
modeTab.addPreviewTab(EROSION_GRADIENT_TAB_TITLE);
|
||||
modeTab.addPreviewTab(DILATION_GRADIENT_TAB_TITLE);
|
||||
modeTab.addPreviewTab(BEUCHER_GRADIENT_TAB_TITLE);
|
||||
modeTab.addPreviewTab(NON_LINEAR_LAPLACIAN_TAB_TITLE);
|
||||
|
||||
JButton applyButton = new JButton("Appliquer");
|
||||
applyButton.addActionListener(e -> applyOutline());
|
||||
|
||||
JButton saveButton = new SaveButton();
|
||||
|
||||
JPanel controlPanel = createControlPanel(applyButton);
|
||||
|
||||
JPanel rightPanel = new JPanel();
|
||||
|
||||
GroupLayout rightLayout = new GroupLayout(rightPanel);
|
||||
rightPanel.setLayout(rightLayout);
|
||||
rightLayout.setAutoCreateGaps(true);
|
||||
rightLayout.setAutoCreateContainerGaps(true);
|
||||
|
||||
rightLayout.setHorizontalGroup(
|
||||
rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(controlPanel)
|
||||
.addComponent(saveButton)
|
||||
);
|
||||
|
||||
rightLayout.setVerticalGroup(
|
||||
rightLayout.createSequentialGroup()
|
||||
.addComponent(controlPanel)
|
||||
.addComponent(saveButton)
|
||||
);
|
||||
|
||||
JPanel mainPanel = new JPanel();
|
||||
|
||||
GroupLayout mainLayout = new GroupLayout(mainPanel);
|
||||
mainPanel.setLayout(mainLayout);
|
||||
mainLayout.setAutoCreateGaps(true);
|
||||
mainLayout.setAutoCreateContainerGaps(true);
|
||||
|
||||
mainLayout.setHorizontalGroup(
|
||||
mainLayout.createSequentialGroup()
|
||||
.addComponent(modeTab)
|
||||
.addComponent(rightPanel)
|
||||
);
|
||||
|
||||
mainLayout.setVerticalGroup(
|
||||
mainLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(modeTab)
|
||||
.addComponent(rightPanel)
|
||||
);
|
||||
|
||||
setContentPane(mainPanel);
|
||||
|
||||
setTitle("Contours non-linéaires");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
|
||||
private JPanel createControlPanel(JButton applyButton) {
|
||||
JPanel panel = new JPanel();
|
||||
|
||||
GroupLayout layout = new GroupLayout(panel);
|
||||
panel.setLayout(layout);
|
||||
layout.setAutoCreateGaps(true);
|
||||
layout.setAutoCreateContainerGaps(true);
|
||||
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(applyButton)
|
||||
);
|
||||
|
||||
layout.setVerticalGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addComponent(applyButton)
|
||||
);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initValues() {
|
||||
presenter.setView(this);
|
||||
|
||||
applyOutline();
|
||||
}
|
||||
|
||||
private void applyOutline() {
|
||||
int operation = modeTab.getSelectedIndex();
|
||||
|
||||
switch (operation) {
|
||||
case 0 -> presenter.computeErosionGradient();
|
||||
case 1 -> presenter.computeDilationGradient();
|
||||
case 2 -> presenter.computeBeucherGradient();
|
||||
case 3 -> presenter.computeNonLinearLaplacian();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateErosionGradient(Image image) {
|
||||
modeTab.loadImage(EROSION_GRADIENT_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDilationGradient(Image image) {
|
||||
modeTab.loadImage(DILATION_GRADIENT_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBeucherGradient(Image image) {
|
||||
modeTab.loadImage(BEUCHER_GRADIENT_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNonLinearLaplacian(Image image) {
|
||||
modeTab.loadImage(NON_LINEAR_LAPLACIAN_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeCore() {
|
||||
presenter.setView(null);
|
||||
presenter.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user