Implement Butterworth filters
This commit is contained in:
@@ -11,5 +11,5 @@ public interface INavigator {
|
||||
*/
|
||||
void showFourier();
|
||||
void showFiltering();
|
||||
|
||||
void showButterworth();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.ViewInitializer;
|
||||
|
||||
/**
|
||||
@@ -15,27 +16,37 @@ public class SwingNavigator implements INavigator {
|
||||
|
||||
private final Provider<DoubleMatrix> doubleMatrixProvider;
|
||||
private final Provider<IdealFilteringView> filteringProvider;
|
||||
private final Provider<NonIdealFilteringView> nonIdealFilteringProvider;
|
||||
|
||||
@Inject
|
||||
public SwingNavigator(
|
||||
Provider<DoubleMatrix> doubleMatrixProvider,
|
||||
Provider<IdealFilteringView> filteringProvider
|
||||
Provider<IdealFilteringView> filteringProvider,
|
||||
Provider<NonIdealFilteringView> nonIdealFilteringProvider
|
||||
) {
|
||||
this.doubleMatrixProvider = doubleMatrixProvider;
|
||||
this.filteringProvider = filteringProvider;
|
||||
this.nonIdealFilteringProvider = nonIdealFilteringProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFourier() {
|
||||
DoubleMatrix doubleMatrix = doubleMatrixProvider.get();
|
||||
ViewInitializer.Initialize(doubleMatrix);
|
||||
doubleMatrix.setVisible(true);
|
||||
DoubleMatrix view = doubleMatrixProvider.get();
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFiltering() {
|
||||
IdealFilteringView filteringView = filteringProvider.get();
|
||||
ViewInitializer.Initialize(filteringView);
|
||||
filteringView.setVisible(true);
|
||||
IdealFilteringView view = filteringProvider.get();
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showButterworth() {
|
||||
NonIdealFilteringView view = nonIdealFilteringProvider.get();
|
||||
ViewInitializer.Initialize(view);
|
||||
view.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ public class NavPresenter {
|
||||
navigator.showFiltering();
|
||||
}
|
||||
|
||||
|
||||
public void gotToButterworth() {
|
||||
navigator.showButterworth();
|
||||
}
|
||||
|
||||
public GrayScaleMatrix getImageGrayMatrix() {
|
||||
return appState.getImage().toGrayScale();
|
||||
}
|
||||
@@ -57,4 +62,5 @@ public class NavPresenter {
|
||||
public void setMode(Mode mode) {
|
||||
modeService.setMode(mode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,15 +41,15 @@ public class FilteringPresenter implements FilteringListener {
|
||||
state.setHighPass(image);
|
||||
}
|
||||
|
||||
public void computeButterworthLowPassFiltering(float percentage) {
|
||||
public void computeButterworthLowPassFiltering(float percentage, int order) {
|
||||
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||
Image image = filteringService.butterworthLowPassFiltering(matrix, percentage / 100);
|
||||
Image image = filteringService.butterworthLowPassFiltering(matrix, percentage / 100, order);
|
||||
state.setButterworthLowPass(image);
|
||||
}
|
||||
|
||||
public void computeButterworthHighPassFiltering(float percentage) {
|
||||
public void computeButterworthHighPassFiltering(float percentage, int order) {
|
||||
GrayScaleMatrix matrix = imageService.getGrayScale(appState.getImage());
|
||||
Image image = filteringService.butterworthHighPassFiltering(matrix, percentage / 100);
|
||||
Image image = filteringService.butterworthHighPassFiltering(matrix, percentage / 100, order);
|
||||
state.setButterworthHighPass(image);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,20 @@ public class FilteringService {
|
||||
return filteredMatrix.toImage();
|
||||
}
|
||||
|
||||
public Image butterworthLowPassFiltering(GrayScaleMatrix matrix, float percentage, int order) {
|
||||
double cutoff = percentage * getMaxCutoff(matrix.getWidth(), matrix.getHeight());
|
||||
GrayScaleMatrix filteredMatrix = GlobalLinearFiltering.butterworthLowPassFiltering(matrix, cutoff, order);
|
||||
return filteredMatrix.toImage();
|
||||
}
|
||||
|
||||
public Image butterworthHighPassFiltering(GrayScaleMatrix matrix, float percentage, int order) {
|
||||
double cutoff = percentage * getMaxCutoff(matrix.getWidth(), matrix.getHeight());
|
||||
GrayScaleMatrix filteredMatrix = GlobalLinearFiltering.butterworthHighPassFiltering(matrix, cutoff, order);
|
||||
return filteredMatrix.toImage();
|
||||
}
|
||||
|
||||
private double getMaxCutoff(int width, int height) {
|
||||
return Math.sqrt(Math.pow(width / 2.0, 2) + Math.pow(height / 2.0, 2));
|
||||
}
|
||||
|
||||
public Image butterworthLowPassFiltering(GrayScaleMatrix matrix, float v) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Image butterworthHighPassFiltering(GrayScaleMatrix matrix, float v) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import java.awt.event.ActionListener;
|
||||
|
||||
public class IntensitySlider extends JSlider {
|
||||
|
||||
public IntensitySlider() {
|
||||
public IntensitySlider(int min, int max) {
|
||||
super();
|
||||
setMinimum(0);
|
||||
setMaximum(1000);
|
||||
setMinimum(min);
|
||||
setMaximum(max);
|
||||
}
|
||||
|
||||
public float getPercentage(){
|
||||
|
||||
@@ -73,7 +73,7 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
new MenuItem("NG", e -> {
|
||||
displayErrorMessage("Oups !", "Not implemented.");
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
fourierMenu = new Menu("Fourier","/cp_51_p1.jpg",
|
||||
@@ -82,13 +82,12 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
|
||||
linearMenu = new Menu("Linéaire","/cp_51_p1.jpg",
|
||||
new Menu("Global",
|
||||
new Menu("Ideal",
|
||||
new MenuItem("Passe-bas", this::displayFilter),
|
||||
new MenuItem("Passe-haut", this::displayFilter)),
|
||||
new Menu("Butterworth",
|
||||
new MenuItem("Passe-bas", this::displayFilter),
|
||||
new MenuItem("Passe-haut", this::displayFilter)
|
||||
)
|
||||
new MenuItem("Ideal", this::displayIdealFilter),
|
||||
new MenuItem("Butterworth", this::displayButterworth)
|
||||
),
|
||||
new Menu("Local",
|
||||
new MenuItem("Masque de convolution", this::displayIdealFilter),
|
||||
new MenuItem("Filtre moyenneur", this::displayButterworth)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -222,10 +221,14 @@ public class NavBar extends JMenuBar implements INavBar {
|
||||
}
|
||||
}
|
||||
|
||||
private void displayFilter(ActionEvent e) {
|
||||
private void displayIdealFilter(ActionEvent e) {
|
||||
presenter.goToFiltering();
|
||||
}
|
||||
|
||||
private void displayButterworth(ActionEvent e) {
|
||||
presenter.gotToButterworth();
|
||||
}
|
||||
|
||||
private void displayErrorMessage(String title, String message) {
|
||||
JOptionPane.showMessageDialog(
|
||||
this,
|
||||
|
||||
@@ -14,8 +14,8 @@ import javax.swing.event.ChangeEvent;
|
||||
|
||||
public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-haut";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-haut";
|
||||
|
||||
private TabbedImagePanel modeTab;
|
||||
private IntensitySlider intensitySlider;
|
||||
@@ -31,7 +31,7 @@ public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
@Override
|
||||
public void initComponents(){
|
||||
this.intensityLabel = new JLabel();
|
||||
this.intensitySlider = new IntensitySlider();
|
||||
this.intensitySlider = new IntensitySlider(0, 1000);
|
||||
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||
|
||||
this.modeTab = new TabbedImagePanel();
|
||||
@@ -43,7 +43,7 @@ public class IdealFilteringView extends AbstractView implements IFilteringView {
|
||||
saveButton.addActionListener(e -> {});
|
||||
|
||||
buildLayout(modeTab, intensityLabel, intensitySlider, saveButton);
|
||||
setTitle("Filtering");
|
||||
setTitle("Filtre idéal");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
|
||||
@@ -14,12 +14,14 @@ import javax.swing.event.ChangeEvent;
|
||||
|
||||
public class NonIdealFilteringView extends AbstractView implements IFilteringView {
|
||||
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-haut";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String LOW_PASS_TAB_TITLE = "Passe-bas";
|
||||
private final static String HIGH_PASS_TAB_TITLE = "Passe-haut";
|
||||
|
||||
private TabbedImagePanel modeTab;
|
||||
private IntensitySlider intensitySlider;
|
||||
private IntensitySlider orderSlider;
|
||||
private JLabel intensityLabel;
|
||||
private JLabel orderLabel;
|
||||
private final FilteringPresenter presenter;
|
||||
private boolean isUpdating;
|
||||
|
||||
@@ -28,35 +30,36 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void buildLayout(JTabbedPane modeTab,
|
||||
JLabel valueTextField,
|
||||
JSlider intensitySlider,
|
||||
JButton saveButton) {
|
||||
private void buildLayout(JTabbedPane modeTab, JButton saveButton) {
|
||||
|
||||
JPanel rightPanel = new JPanel();
|
||||
GroupLayout rightLayout = new GroupLayout(rightPanel);
|
||||
rightPanel.setLayout(rightLayout);
|
||||
|
||||
rightLayout.setHorizontalGroup(
|
||||
rightLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(valueTextField, GroupLayout.PREFERRED_SIZE, 90, GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(rightLayout.createSequentialGroup()
|
||||
rightLayout.createSequentialGroup()
|
||||
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(intensityLabel)
|
||||
.addComponent(intensitySlider)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(orderLabel)
|
||||
.addComponent(orderSlider)
|
||||
)
|
||||
);
|
||||
|
||||
rightLayout.setVerticalGroup(
|
||||
rightLayout.createSequentialGroup()
|
||||
.addComponent(valueTextField, GroupLayout.PREFERRED_SIZE,
|
||||
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(intensityLabel)
|
||||
.addComponent(orderLabel)
|
||||
)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(rightLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(intensitySlider)
|
||||
.addComponent(orderSlider)
|
||||
)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
);
|
||||
|
||||
// -------------------------
|
||||
@@ -72,10 +75,8 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
//.addComponent(valeurMin)
|
||||
.addGap(50)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
//.addComponent(valeurMax)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED,
|
||||
GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(saveButton)
|
||||
@@ -117,8 +118,22 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
try {
|
||||
this.intensityLabel.setText(String.valueOf(intensitySlider.getPercentage()));
|
||||
switch (modeTab.getSelectedIndex()) {
|
||||
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||
case 0 -> presenter.computeButterworthLowPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
case 1 -> presenter.computeButterworthHighPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
}
|
||||
} finally {
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void onOrderUpdate(ChangeEvent e) {
|
||||
if (isUpdating) return;
|
||||
isUpdating = true;
|
||||
try {
|
||||
this.orderLabel.setText(String.valueOf(orderSlider.getValue()));
|
||||
switch (modeTab.getSelectedIndex()) {
|
||||
case 0 -> presenter.computeButterworthLowPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
case 1 -> presenter.computeButterworthHighPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
}
|
||||
} finally {
|
||||
isUpdating = false;
|
||||
@@ -136,21 +151,26 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButterworthHighPassFiltering(Image image) {
|
||||
public void updateButterworthLowPassFiltering(Image image) {
|
||||
modeTab.loadImage(LOW_PASS_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButterworthLowPassFiltering(Image image) {
|
||||
public void updateButterworthHighPassFiltering(Image image) {
|
||||
modeTab.loadImage(HIGH_PASS_TAB_TITLE, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents(){
|
||||
this.intensityLabel = new JLabel();
|
||||
this.intensitySlider = new IntensitySlider();
|
||||
this.orderLabel = new JLabel();
|
||||
|
||||
this.intensitySlider = new IntensitySlider(0, 1000);
|
||||
this.intensitySlider.setOrientation(JSlider.VERTICAL);
|
||||
|
||||
this.orderSlider = new IntensitySlider(0, 10);
|
||||
this.orderSlider.setOrientation(JSlider.VERTICAL);
|
||||
|
||||
this.modeTab = new TabbedImagePanel();
|
||||
this.modeTab.addPreviewTab(LOW_PASS_TAB_TITLE);
|
||||
this.modeTab.addPreviewTab(HIGH_PASS_TAB_TITLE);
|
||||
@@ -159,8 +179,8 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
|
||||
saveButton.addActionListener(e -> {});
|
||||
|
||||
buildLayout(modeTab, intensityLabel, intensitySlider, saveButton);
|
||||
setTitle("Filtering");
|
||||
buildLayout(modeTab, saveButton);
|
||||
setTitle("Filtre non-idéal");
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
pack();
|
||||
}
|
||||
@@ -172,14 +192,17 @@ public class NonIdealFilteringView extends AbstractView implements IFilteringVie
|
||||
this.intensitySlider.addChangeListener(this::onCutoffUpdate);
|
||||
this.intensityLabel.setText(String.valueOf(intensitySlider.getValue()));
|
||||
|
||||
this.orderSlider.addChangeListener(this::onOrderUpdate);
|
||||
this.orderLabel.setText(String.valueOf(orderSlider.getValue()));
|
||||
|
||||
this.modeTab.addChangeListener(e -> {
|
||||
switch (modeTab.getSelectedIndex()) {
|
||||
case 0 -> presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||
case 1 -> presenter.computeHighPassFiltering(intensitySlider.getPercentage());
|
||||
case 0 -> presenter.computeButterworthLowPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
case 1 -> presenter.computeButterworthHighPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
this.presenter.computeLowPassFiltering(intensitySlider.getPercentage());
|
||||
this.presenter.computeButterworthLowPassFiltering(intensitySlider.getPercentage(), orderSlider.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user