Add convolution and mean filtering
This commit is contained in:
@@ -6,18 +6,17 @@ import com.google.common.eventbus.EventBus;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Scopes;
|
||||
import presenters.doubleMatrix.DoubleMatrixPresenter;
|
||||
import presenters.filtering.FilteringPresenter;
|
||||
import presenters.filtering.global.GlobalFilteringPresenter;
|
||||
import presenters.MainPresenter;
|
||||
import presenters.NavPresenter;
|
||||
import presenters.filtering.local.LocalFilteringPresenter;
|
||||
import services.ImageService;
|
||||
import ui.abstractions.*;
|
||||
import ui.implementation.components.nav.NavBar;
|
||||
import ui.implementation.views.DoubleMatrix;
|
||||
import ui.implementation.views.IdealFilteringView;
|
||||
import ui.implementation.views.fitering.global.IdealFilteringView;
|
||||
import ui.implementation.views.MainView;
|
||||
import ui.abstractions.IDoubleMatrix;
|
||||
import ui.abstractions.IFilteringView;
|
||||
import ui.abstractions.IMainView;
|
||||
import ui.abstractions.INavBar;
|
||||
import ui.implementation.views.fitering.local.LocalFilteringView;
|
||||
|
||||
/**
|
||||
* Gathers some configurations in order to set the dependency injection container up
|
||||
@@ -40,13 +39,15 @@ public class AppModule extends AbstractModule {
|
||||
bind(INavBar.class).to(NavBar.class);
|
||||
bind(IMainView.class).to(MainView.class);
|
||||
bind(IDoubleMatrix.class).to(DoubleMatrix.class);
|
||||
bind(IFilteringView.class).to(IdealFilteringView.class);
|
||||
bind(IGlobalFilteringView.class).to(IdealFilteringView.class);
|
||||
bind(ILocalFilteringView.class).to(LocalFilteringView.class);
|
||||
|
||||
//--- Presentation layer ---
|
||||
bind(MainPresenter.class);
|
||||
bind(NavPresenter.class);
|
||||
bind(DoubleMatrixPresenter.class);
|
||||
bind(FilteringPresenter.class);
|
||||
bind(GlobalFilteringPresenter.class);
|
||||
bind(LocalFilteringPresenter.class);
|
||||
|
||||
//--- Service layer layer ---
|
||||
bind(ImageService.class);
|
||||
|
||||
@@ -10,6 +10,7 @@ public interface INavigator {
|
||||
* Displays Fourier view
|
||||
*/
|
||||
void showFourier();
|
||||
void showFiltering();
|
||||
void showIdealFiltering();
|
||||
void showButterworth();
|
||||
void showConvolutionFiltering();
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@ package app;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import ui.implementation.views.DoubleMatrix;
|
||||
import ui.implementation.views.IdealFilteringView;
|
||||
import ui.implementation.views.NonIdealFilteringView;
|
||||
import ui.implementation.views.fitering.global.IdealFilteringView;
|
||||
import ui.implementation.views.fitering.global.NonIdealFilteringView;
|
||||
import ui.implementation.views.ViewInitializer;
|
||||
import ui.implementation.views.fitering.local.LocalFilteringView;
|
||||
|
||||
/**
|
||||
* Concrete implement of the INavigator interface.
|
||||
@@ -17,16 +18,19 @@ public class SwingNavigator implements INavigator {
|
||||
private final Provider<DoubleMatrix> doubleMatrixProvider;
|
||||
private final Provider<IdealFilteringView> filteringProvider;
|
||||
private final Provider<NonIdealFilteringView> nonIdealFilteringProvider;
|
||||
private final Provider<LocalFilteringView> convolutionFilteringProvider;
|
||||
|
||||
@Inject
|
||||
public SwingNavigator(
|
||||
Provider<DoubleMatrix> doubleMatrixProvider,
|
||||
Provider<IdealFilteringView> filteringProvider,
|
||||
Provider<NonIdealFilteringView> nonIdealFilteringProvider
|
||||
Provider<NonIdealFilteringView> nonIdealFilteringProvider,
|
||||
Provider<LocalFilteringView> convolutionFilterProvider
|
||||
) {
|
||||
this.doubleMatrixProvider = doubleMatrixProvider;
|
||||
this.filteringProvider = filteringProvider;
|
||||
this.nonIdealFilteringProvider = nonIdealFilteringProvider;
|
||||
this.convolutionFilteringProvider = convolutionFilterProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,7 +41,7 @@ public class SwingNavigator implements INavigator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFiltering() {
|
||||
public void showIdealFiltering() {
|
||||
IdealFilteringView view = filteringProvider.get();
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
@@ -49,4 +53,12 @@ public class SwingNavigator implements INavigator {
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showConvolutionFiltering() {
|
||||
LocalFilteringView view = convolutionFilteringProvider.get();
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,27 +2,27 @@ package app.state;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.Image;
|
||||
import presenters.filtering.FilteringListener;
|
||||
import presenters.filtering.global.GlobalFilteringListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FilteringState extends State {
|
||||
public class GlobalFilteringState extends State {
|
||||
private Image lowPass;
|
||||
private Image highPass;
|
||||
private Image butterworthLowPass;
|
||||
private Image butterworthHighPass;
|
||||
|
||||
private final List<FilteringListener> listeners = new ArrayList<>();
|
||||
private final List<GlobalFilteringListener> listeners = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
public FilteringState() {}
|
||||
public GlobalFilteringState() {}
|
||||
|
||||
public void subscribe(FilteringListener listener) {
|
||||
public void subscribe(GlobalFilteringListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void unsubscribe(FilteringListener listener) {
|
||||
public void unsubscribe(GlobalFilteringListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
45
src/main/java/app/state/LocalFilteringState.java
Normal file
45
src/main/java/app/state/LocalFilteringState.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package app.state;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.Image;
|
||||
import presenters.filtering.global.GlobalFilteringListener;
|
||||
import presenters.filtering.local.LocalFilteringListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LocalFilteringState extends State {
|
||||
private Image convolution;
|
||||
private Image mean;
|
||||
|
||||
private final List<LocalFilteringListener> listeners = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
public LocalFilteringState() {}
|
||||
|
||||
public void subscribe(LocalFilteringListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void unsubscribe(LocalFilteringListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setConvolution(Image image) {
|
||||
convolution = image;
|
||||
listeners.forEach(listener -> listener.onConvolutionChanged(image));
|
||||
}
|
||||
|
||||
public void setMean(Image image) {
|
||||
mean = image;
|
||||
listeners.forEach(listener -> listener.onMeanChanged(image));
|
||||
}
|
||||
|
||||
public Image getConvolution() {
|
||||
return convolution;
|
||||
}
|
||||
|
||||
public Image getMean() {
|
||||
return mean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package domain.image.processing.filtering;
|
||||
|
||||
import domain.image.GrayScaleMatrix;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
public class LocalLinearFiltering {
|
||||
|
||||
public static GrayScaleMatrix convolutionMask(GrayScaleMatrix matrix, double[][] mask) {
|
||||
validateMask(mask);
|
||||
return applyMask(matrix, mask);
|
||||
}
|
||||
|
||||
public static GrayScaleMatrix meanFilter(GrayScaleMatrix matrix, int maskSize) {
|
||||
validateMaskSize(maskSize);
|
||||
|
||||
double coefficient = 1.0 / (maskSize * maskSize);
|
||||
double[][] mask = new double[maskSize][maskSize];
|
||||
|
||||
for (int y = 0; y < maskSize; y++) {
|
||||
for (int x = 0; x < maskSize; x++) {
|
||||
mask[y][x] = coefficient;
|
||||
}
|
||||
}
|
||||
|
||||
return applyMask(matrix, mask);
|
||||
}
|
||||
|
||||
private static GrayScaleMatrix applyMask(GrayScaleMatrix matrix, double[][] mask) {
|
||||
Mat source = toMat(matrix);
|
||||
int maskSize = mask.length;
|
||||
|
||||
Mat kernel = new Mat(maskSize, maskSize, CvType.CV_64F);
|
||||
|
||||
for (int y = 0; y < maskSize; y++) {
|
||||
for (int x = 0; x < maskSize; x++) {
|
||||
kernel.put(y, x, mask[y][x]);
|
||||
}
|
||||
}
|
||||
|
||||
Mat destination = new Mat();
|
||||
|
||||
Imgproc.filter2D(
|
||||
source,
|
||||
destination,
|
||||
CvType.CV_64F,
|
||||
kernel,
|
||||
new Point(-1, -1),
|
||||
0,
|
||||
Core.BORDER_REPLICATE
|
||||
);
|
||||
|
||||
GrayScaleMatrix result = fromMat(destination);
|
||||
|
||||
source.release();
|
||||
kernel.release();
|
||||
destination.release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void validateMask(double[][] mask) {
|
||||
if (mask == null || mask.length == 0 || mask.length % 2 == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Le masque doit être une matrice carrée de dimension impaire."
|
||||
);
|
||||
}
|
||||
|
||||
int size = mask.length;
|
||||
|
||||
for (double[] row : mask) {
|
||||
if (row == null || row.length != size) {
|
||||
throw new IllegalArgumentException(
|
||||
"Le masque doit être une matrice carrée."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateMaskSize(int maskSize) {
|
||||
if (maskSize <= 0 || maskSize % 2 == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"La taille du masque doit être un entier positif impair."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static Mat toMat(GrayScaleMatrix matrix) {
|
||||
double[][] image = matrix.getRawData();
|
||||
int height = image.length;
|
||||
int width = image[0].length;
|
||||
|
||||
Mat mat = new Mat(height, width, CvType.CV_64F);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
mat.put(y, x, image[y][x]);
|
||||
}
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
private static GrayScaleMatrix fromMat(Mat mat) {
|
||||
int height = mat.rows();
|
||||
int width = mat.cols();
|
||||
double[][] result = new double[height][width];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
result[y][x] = Math.clamp(mat.get(y, x)[0], 0.0, 255.0);
|
||||
}
|
||||
}
|
||||
|
||||
return new GrayScaleMatrix(result);
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,12 @@ public class NavPresenter {
|
||||
}
|
||||
|
||||
public void goToFiltering() {
|
||||
navigator.showFiltering();
|
||||
navigator.showIdealFiltering();
|
||||
}
|
||||
|
||||
public void goToConvolution() {
|
||||
navigator.showConvolutionFiltering();
|
||||
}
|
||||
|
||||
public void gotToButterworth() {
|
||||
navigator.showButterworth();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package presenters.filtering;
|
||||
package presenters.filtering.global;
|
||||
|
||||
import domain.events.listeners.Listener;
|
||||
import domain.image.Image;
|
||||
|
||||
public interface FilteringListener extends Listener {
|
||||
public interface GlobalFilteringListener extends Listener {
|
||||
void onLowPassChanged(Image image);
|
||||
void onHighPassChanged(Image image);
|
||||
void onButterworthLowPassChanged(Image image);
|
||||
@@ -1,23 +1,23 @@
|
||||
package presenters.filtering;
|
||||
package presenters.filtering.global;
|
||||
|
||||
import app.state.AppState;
|
||||
import app.state.FilteringState;
|
||||
import app.state.GlobalFilteringState;
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.GrayScaleMatrix;
|
||||
import domain.image.Image;
|
||||
import services.FilteringService;
|
||||
import services.GlobalFilteringService;
|
||||
import services.ImageService;
|
||||
import ui.abstractions.IFilteringView;
|
||||
import ui.abstractions.IGlobalFilteringView;
|
||||
|
||||
public class FilteringPresenter implements FilteringListener {
|
||||
public class GlobalFilteringPresenter implements GlobalFilteringListener {
|
||||
private final AppState appState;
|
||||
private final FilteringState state;
|
||||
private final GlobalFilteringState state;
|
||||
private final ImageService imageService;
|
||||
private final FilteringService filteringService;
|
||||
private IFilteringView view;
|
||||
private final GlobalFilteringService filteringService;
|
||||
private IGlobalFilteringView view;
|
||||
|
||||
@Inject
|
||||
public FilteringPresenter(AppState appState, FilteringState state, ImageService imageService, FilteringService filteringService) {
|
||||
public GlobalFilteringPresenter(AppState appState, GlobalFilteringState state, ImageService imageService, GlobalFilteringService filteringService) {
|
||||
this.appState = appState;
|
||||
this.state = state;
|
||||
this.imageService = imageService;
|
||||
@@ -25,7 +25,7 @@ public class FilteringPresenter implements FilteringListener {
|
||||
this.state.subscribe(this);
|
||||
}
|
||||
|
||||
public void setView(IFilteringView view) {
|
||||
public void setView(IGlobalFilteringView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package presenters.filtering.local;
|
||||
|
||||
import domain.image.Image;
|
||||
|
||||
public interface LocalFilteringListener {
|
||||
|
||||
void onConvolutionChanged(Image image);
|
||||
void onMeanChanged(Image image);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package presenters.filtering.local;
|
||||
|
||||
import app.state.AppState;
|
||||
import app.state.LocalFilteringState;
|
||||
import domain.image.Image;
|
||||
import jakarta.inject.Inject;
|
||||
import services.ImageService;
|
||||
import services.LocalFilteringService;
|
||||
import ui.abstractions.ILocalFilteringView;
|
||||
|
||||
public class LocalFilteringPresenter implements LocalFilteringListener {
|
||||
|
||||
private final AppState appState;
|
||||
private final LocalFilteringState state;
|
||||
private final ImageService imageService;
|
||||
private final LocalFilteringService filteringService;
|
||||
|
||||
private ILocalFilteringView view;
|
||||
|
||||
@Inject
|
||||
public LocalFilteringPresenter(
|
||||
AppState appState,
|
||||
LocalFilteringState state,
|
||||
ImageService imageService,
|
||||
LocalFilteringService filteringService
|
||||
) {
|
||||
this.appState = appState;
|
||||
this.state = state;
|
||||
this.imageService = imageService;
|
||||
this.filteringService = filteringService;
|
||||
|
||||
this.state.subscribe(this);
|
||||
}
|
||||
|
||||
public void setView(ILocalFilteringView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public void computeConvolutionFiltering(double[][] mask) {
|
||||
Image image = filteringService.applyConvolutionMask(appState.getImage(), mask);
|
||||
state.setConvolution(image);
|
||||
}
|
||||
|
||||
public void computeMeanFiltering(int value) {
|
||||
Image image = filteringService.applyMeanFilter(appState.getImage(),value);
|
||||
state.setMean(image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConvolutionChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateConvolutionFiltering(image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeanChanged(Image image) {
|
||||
if (view != null) {
|
||||
view.updateMeanFiltering(image);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
state.unsubscribe(this);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import domain.image.GrayScaleMatrix;
|
||||
import domain.image.Image;
|
||||
import domain.image.processing.filtering.GlobalLinearFiltering;
|
||||
|
||||
public class FilteringService {
|
||||
public class GlobalFilteringService {
|
||||
|
||||
public Image lowPassFiltering(GrayScaleMatrix matrix, double percentage) {
|
||||
double cutoff = percentage * getMaxCutoff(matrix.getWidth(), matrix.getHeight());
|
||||
23
src/main/java/services/LocalFilteringService.java
Normal file
23
src/main/java/services/LocalFilteringService.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package services;
|
||||
|
||||
import domain.image.GrayScaleMatrix;
|
||||
import domain.image.Image;
|
||||
import domain.image.processing.filtering.LocalLinearFiltering;
|
||||
|
||||
public class LocalFilteringService {
|
||||
|
||||
public Image applyConvolutionMask(Image image, double[][] mask) {
|
||||
GrayScaleMatrix result = LocalLinearFiltering.convolutionMask(getGrayScale(image), mask);
|
||||
return result.toImage();
|
||||
}
|
||||
|
||||
public Image applyMeanFilter(Image image, int maskSize) {
|
||||
GrayScaleMatrix result = LocalLinearFiltering.meanFilter(getGrayScale(image), maskSize);
|
||||
return result.toImage();
|
||||
}
|
||||
|
||||
private GrayScaleMatrix getGrayScale(Image image) {
|
||||
return image.toGrayScale();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package ui.abstractions;
|
||||
|
||||
import domain.image.Image;
|
||||
|
||||
public interface IFilteringView {
|
||||
public interface IGlobalFilteringView {
|
||||
void updateLowPassFiltering(Image image);
|
||||
void updateHighPassFiltering(Image image);
|
||||
void updateButterworthHighPassFiltering(Image image);
|
||||
10
src/main/java/ui/abstractions/ILocalFilteringView.java
Normal file
10
src/main/java/ui/abstractions/ILocalFilteringView.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ui.abstractions;
|
||||
|
||||
import domain.image.Image;
|
||||
|
||||
public interface ILocalFilteringView {
|
||||
|
||||
void updateConvolutionFiltering(Image image);
|
||||
|
||||
void updateMeanFiltering(Image image);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
new MenuItem("Butterworth", this::displayButterworth)
|
||||
),
|
||||
new Menu("Local",
|
||||
new MenuItem("Masque de convolution", this::displayIdealFilter),
|
||||
new MenuItem("Masque de convolution", this::displayConvolution),
|
||||
new MenuItem("Filtre moyenneur", this::displayButterworth)
|
||||
)
|
||||
);
|
||||
@@ -107,6 +107,7 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
histogramMenu.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
//####################################################
|
||||
|
||||
private File chooseFile(){
|
||||
@@ -229,6 +230,10 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
presenter.gotToButterworth();
|
||||
}
|
||||
|
||||
private void displayConvolution(ActionEvent actionEvent) {
|
||||
presenter.goToConvolution();
|
||||
}
|
||||
|
||||
private void displayErrorMessage(String title, String message) {
|
||||
JOptionPane.showMessageDialog(
|
||||
this,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package ui.implementation.views;
|
||||
package ui.implementation.views.fitering.global;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.Image;
|
||||
import presenters.filtering.FilteringPresenter;
|
||||
import presenters.filtering.global.GlobalFilteringPresenter;
|
||||
import ui.abstractions.AbstractView;
|
||||
import ui.implementation.components.controls.IntensitySlider;
|
||||
import ui.implementation.components.controls.SaveButton;
|
||||
import ui.abstractions.IFilteringView;
|
||||
import ui.abstractions.IGlobalFilteringView;
|
||||
import ui.implementation.components.image.TabbedImagePanel;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
|
||||
public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
public class IdealFilteringView extends AbstractView implements IGlobalFilteringView {
|
||||
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-haut";
|
||||
@@ -20,35 +20,14 @@ public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
private TabbedImagePanel modeTab;
|
||||
private IntensitySlider intensitySlider;
|
||||
private JLabel intensityLabel;
|
||||
private final FilteringPresenter presenter;
|
||||
private final GlobalFilteringPresenter presenter;
|
||||
private boolean isUpdating;
|
||||
|
||||
@Inject
|
||||
public IdealFilteringView(FilteringPresenter presenter) {
|
||||
public IdealFilteringView(GlobalFilteringPresenter presenter) {
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents(){
|
||||
this.intensityLabel = new JLabel();
|
||||
this.intensitySlider = new IntensitySlider(0, 1000);
|
||||
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||
|
||||
this.modeTab = new TabbedImagePanel();
|
||||
this.modeTab.addPreviewTab(LOW_PASS_TAB_TITLE);
|
||||
this.modeTab.addPreviewTab(HIGH_PASS_TAB_TITLE);
|
||||
|
||||
JButton saveButton = new SaveButton();
|
||||
|
||||
saveButton.addActionListener(e -> {});
|
||||
|
||||
buildLayout(modeTab, intensityLabel, intensitySlider, saveButton);
|
||||
setTitle("Filtre idéal");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void buildLayout(JTabbedPane modeTab,
|
||||
JLabel valueTextField,
|
||||
@@ -165,6 +144,27 @@ public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents(){
|
||||
this.intensityLabel = new JLabel();
|
||||
this.intensitySlider = new IntensitySlider(0, 1000);
|
||||
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||
|
||||
this.modeTab = new TabbedImagePanel();
|
||||
this.modeTab.addPreviewTab(LOW_PASS_TAB_TITLE);
|
||||
this.modeTab.addPreviewTab(HIGH_PASS_TAB_TITLE);
|
||||
|
||||
JButton saveButton = new SaveButton();
|
||||
|
||||
saveButton.addActionListener(e -> {});
|
||||
|
||||
buildLayout(modeTab, intensityLabel, intensitySlider, saveButton);
|
||||
setTitle("Filtre idéal");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initValues(){
|
||||
this.presenter.setView(this);
|
||||
@@ -1,10 +1,10 @@
|
||||
package ui.implementation.views;
|
||||
package ui.implementation.views.fitering.global;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import domain.image.Image;
|
||||
import presenters.filtering.FilteringPresenter;
|
||||
import presenters.filtering.global.GlobalFilteringPresenter;
|
||||
import ui.abstractions.AbstractView;
|
||||
import ui.abstractions.IFilteringView;
|
||||
import ui.abstractions.IGlobalFilteringView;
|
||||
import ui.implementation.components.controls.IntensitySlider;
|
||||
import ui.implementation.components.controls.SaveButton;
|
||||
import ui.implementation.components.image.TabbedImagePanel;
|
||||
@@ -12,7 +12,7 @@ import ui.implementation.components.image.TabbedImagePanel;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
|
||||
public class NonIdealFilteringView extends AbstractView implements IFilteringView {
|
||||
public class NonIdealFilteringView extends AbstractView implements IGlobalFilteringView {
|
||||
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-haut";
|
||||
@@ -22,11 +22,11 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
private IntensitySlider orderSlider;
|
||||
private JLabel intensityLabel;
|
||||
private JLabel orderLabel;
|
||||
private final FilteringPresenter presenter;
|
||||
private final GlobalFilteringPresenter presenter;
|
||||
private boolean isUpdating;
|
||||
|
||||
@Inject
|
||||
public NonIdealFilteringView(FilteringPresenter presenter) {
|
||||
public NonIdealFilteringView(GlobalFilteringPresenter presenter) {
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
package ui.implementation.views.fitering.local;
|
||||
|
||||
import domain.image.Image;
|
||||
import jakarta.inject.Inject;
|
||||
import presenters.filtering.local.LocalFilteringPresenter;
|
||||
import ui.abstractions.AbstractView;
|
||||
import ui.abstractions.ILocalFilteringView;
|
||||
import ui.implementation.components.controls.SaveButton;
|
||||
import ui.implementation.components.image.TabbedImagePanel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class LocalFilteringView extends AbstractView implements ILocalFilteringView {
|
||||
private static final String CONVOLUTION_TAB_TITLE = "Convolution";
|
||||
private static final String MEAN_TAB_TITLE = "Moyenneur";
|
||||
|
||||
private final LocalFilteringPresenter presenter;
|
||||
|
||||
private TabbedImagePanel modeTab;
|
||||
|
||||
private JTextField convolutionSizeField;
|
||||
private JPanel convolutionMaskPanel;
|
||||
private JTextField[][] convolutionMaskFields;
|
||||
|
||||
private JTextField meanSizeField;
|
||||
|
||||
@Inject
|
||||
public LocalFilteringView(LocalFilteringPresenter presenter) {
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents() {
|
||||
modeTab = new TabbedImagePanel();
|
||||
modeTab.addPreviewTab(CONVOLUTION_TAB_TITLE);
|
||||
modeTab.addPreviewTab(MEAN_TAB_TITLE);
|
||||
|
||||
convolutionSizeField = new JTextField("3", 5);
|
||||
JButton createMaskButton = new JButton("Créer le masque");
|
||||
createMaskButton.addActionListener(e -> createConvolutionMask());
|
||||
|
||||
convolutionMaskPanel = new JPanel();
|
||||
|
||||
JButton applyConvolutionButton = new JButton("Appliquer convolution");
|
||||
applyConvolutionButton.addActionListener(e -> applyConvolution());
|
||||
|
||||
meanSizeField = new JTextField("3", 5);
|
||||
|
||||
JButton applyMeanButton = new JButton("Appliquer moyenneur");
|
||||
applyMeanButton.addActionListener(e -> applyMean());
|
||||
|
||||
JButton saveButton = new SaveButton();
|
||||
|
||||
buildLayout(
|
||||
modeTab,
|
||||
convolutionSizeField,
|
||||
createMaskButton,
|
||||
convolutionMaskPanel,
|
||||
applyConvolutionButton,
|
||||
meanSizeField,
|
||||
applyMeanButton,
|
||||
saveButton
|
||||
);
|
||||
|
||||
setTitle("Filtrage linéaire local");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initValues() {
|
||||
presenter.setView(this);
|
||||
createConvolutionMask();
|
||||
}
|
||||
|
||||
private void createConvolutionMask() {
|
||||
try {
|
||||
int size = Integer.parseInt(convolutionSizeField.getText());
|
||||
|
||||
if (size <= 0 || size % 2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
convolutionMaskPanel.removeAll();
|
||||
convolutionMaskPanel.setLayout(new GridLayout(size, size, 3, 3));
|
||||
convolutionMaskFields = new JTextField[size][size];
|
||||
|
||||
for (int y = 0; y < size; y++) {
|
||||
for (int x = 0; x < size; x++) {
|
||||
JTextField field = new JTextField("0");
|
||||
field.setHorizontalAlignment(JTextField.CENTER);
|
||||
convolutionMaskFields[y][x] = field;
|
||||
convolutionMaskPanel.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
convolutionMaskPanel.revalidate();
|
||||
convolutionMaskPanel.repaint();
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyConvolution() {
|
||||
try {
|
||||
double[][] mask = new double[convolutionMaskFields.length][convolutionMaskFields.length];
|
||||
|
||||
for (int y = 0; y < mask.length; y++) {
|
||||
for (int x = 0; x < mask.length; x++) {
|
||||
mask[y][x] = Double.parseDouble(convolutionMaskFields[y][x].getText());
|
||||
}
|
||||
}
|
||||
|
||||
presenter.computeConvolutionFiltering(mask);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyMean() {
|
||||
try {
|
||||
int maskSize = Integer.parseInt(meanSizeField.getText());
|
||||
|
||||
if (maskSize <= 0 || maskSize % 2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
presenter.computeMeanFiltering(maskSize);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateConvolutionFiltering(Image image) {
|
||||
modeTab.loadImage(CONVOLUTION_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
public void updateMeanFiltering(Image image) {
|
||||
modeTab.loadImage(MEAN_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeCore() {
|
||||
presenter.setView(null);
|
||||
presenter.dispose();
|
||||
}
|
||||
|
||||
private void buildLayout(
|
||||
JComponent imagePanel,
|
||||
JTextField convolutionSizeField,
|
||||
JButton createMaskButton,
|
||||
JPanel convolutionMaskPanel,
|
||||
JButton applyConvolutionButton,
|
||||
JTextField meanSizeField,
|
||||
JButton applyMeanButton,
|
||||
JButton saveButton
|
||||
) {
|
||||
JPanel convolutionPanel = new JPanel();
|
||||
GroupLayout convolutionLayout = new GroupLayout(convolutionPanel);
|
||||
convolutionPanel.setLayout(convolutionLayout);
|
||||
convolutionLayout.setAutoCreateGaps(true);
|
||||
convolutionLayout.setAutoCreateContainerGaps(true);
|
||||
|
||||
convolutionLayout.setHorizontalGroup(
|
||||
convolutionLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(convolutionSizeField, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(createMaskButton)
|
||||
.addComponent(convolutionMaskPanel)
|
||||
.addComponent(applyConvolutionButton)
|
||||
);
|
||||
|
||||
convolutionLayout.setVerticalGroup(
|
||||
convolutionLayout.createSequentialGroup()
|
||||
.addComponent(convolutionSizeField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(createMaskButton)
|
||||
.addComponent(convolutionMaskPanel)
|
||||
.addComponent(applyConvolutionButton)
|
||||
);
|
||||
|
||||
JPanel meanPanel = new JPanel();
|
||||
GroupLayout meanLayout = new GroupLayout(meanPanel);
|
||||
meanPanel.setLayout(meanLayout);
|
||||
meanLayout.setAutoCreateGaps(true);
|
||||
meanLayout.setAutoCreateContainerGaps(true);
|
||||
|
||||
meanLayout.setHorizontalGroup(
|
||||
meanLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(meanSizeField, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(applyMeanButton)
|
||||
);
|
||||
|
||||
meanLayout.setVerticalGroup(
|
||||
meanLayout.createSequentialGroup()
|
||||
.addComponent(meanSizeField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(applyMeanButton)
|
||||
);
|
||||
|
||||
JPanel rightPanel = new JPanel();
|
||||
JTabbedPane operationTabs = new JTabbedPane();
|
||||
operationTabs.addTab("Convolution", convolutionPanel);
|
||||
operationTabs.addTab("Moyenneur", meanPanel);
|
||||
|
||||
GroupLayout rightLayout = new GroupLayout(rightPanel);
|
||||
rightPanel.setLayout(rightLayout);
|
||||
rightLayout.setAutoCreateGaps(true);
|
||||
rightLayout.setAutoCreateContainerGaps(true);
|
||||
|
||||
rightLayout.setHorizontalGroup(
|
||||
rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(operationTabs)
|
||||
.addComponent(saveButton)
|
||||
);
|
||||
|
||||
rightLayout.setVerticalGroup(
|
||||
rightLayout.createSequentialGroup()
|
||||
.addComponent(operationTabs)
|
||||
.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(imagePanel)
|
||||
.addComponent(rightPanel)
|
||||
);
|
||||
|
||||
mainLayout.setVerticalGroup(
|
||||
mainLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(imagePanel)
|
||||
.addComponent(rightPanel)
|
||||
);
|
||||
|
||||
setContentPane(mainPanel);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user