Untitled
unknown
plain_text
a year ago
31 kB
6
Indexable
package com.example.multimediadata;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.*;
import javafx.stage.FileChooser;
import javafx.scene.paint.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.*;
public class HelloController implements Initializable {
@FXML
private ComboBox<String> categoryComboBox;
@FXML
private ComboBox<String> subMethodComboBox;
@FXML
private ImageView beforeImageView;
@FXML
private ImageView afterImageView;
@FXML
private Slider powerSlider;
@FXML
private Label laplacianLabel;
@FXML
private CheckBox laplacianCheckBox;
@FXML
private Label histogramLabel;
@FXML
private CheckBox histogramCheckBox;
@FXML
private ImageView originalHistogramView;
@FXML
private ImageView modifiedHistogramView;
@FXML
private Slider thresholdSlider;
@FXML
private Label thresholdLabel;
@FXML
private Label otsuThresholdLabel;
private WritableImage laplacianImage;
private File selectedFile;
private String selectedCategory = "Ничего";
private String selectedSubMethod = "";
@Override
public void initialize(URL location, ResourceBundle resources) {
categoryComboBox.setValue("Ничего");
subMethodComboBox.setVisible(false);
subMethodComboBox.setItems(FXCollections.observableArrayList());
subMethodComboBox.setValue(null);
powerSlider.setVisible(false);
laplacianLabel.setVisible(false);
laplacianCheckBox.setVisible(false);
thresholdSlider.setVisible(false);
thresholdLabel.setVisible(false);
otsuThresholdLabel.setVisible(false);
}
@FXML
public void onSelectPhoto() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Выберите изображение");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.jpeg")
);
selectedFile = fileChooser.showOpenDialog(null);
if (selectedFile != null) {
try {
Image image = new Image(new FileInputStream(selectedFile));
beforeImageView.setImage(image);
beforeImageView.setPreserveRatio(true);
applyChanges();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
@FXML
public void onCategoryChange() {
selectedCategory = categoryComboBox.getValue();
selectedSubMethod = "";
subMethodComboBox.getItems().clear();
subMethodComboBox.setValue(null);
powerSlider.setVisible(false);
laplacianLabel.setVisible(false);
laplacianCheckBox.setVisible(false);
thresholdSlider.setVisible(false);
thresholdLabel.setVisible(false);
otsuThresholdLabel.setVisible(false);
subMethodComboBox.setVisible(false);
if (selectedCategory.equals("Градиент")) {
subMethodComboBox.setItems(FXCollections.observableArrayList("Робертса", "Собеля"));
subMethodComboBox.setVisible(true);
} else if (selectedCategory.equals("Пороговый фильтр")) {
subMethodComboBox.setItems(FXCollections.observableArrayList("Глобальный порог", "Метод Оцу"));
subMethodComboBox.setVisible(true);
}
applyChanges();
}
@FXML
public void onSubMethodChange() {
selectedSubMethod = subMethodComboBox.getValue();
applyChanges();
}
@FXML
public void onSliderChange() {
applyChanges();
}
@FXML
public void onThresholdSliderChange() {
applyChanges();
}
@FXML
public void onLaplacianCheckBoxChange() {
applyChanges();
}
@FXML
public void onHistogramCheckBoxChange() {
if (histogramCheckBox.isSelected()) {
generateAndDisplayHistograms();
} else {
originalHistogramView.setVisible(false);
modifiedHistogramView.setVisible(false);
}
}
private void applyChanges() {
if (selectedFile != null) {
powerSlider.setVisible(false);
laplacianLabel.setVisible(false);
laplacianCheckBox.setVisible(false);
thresholdSlider.setVisible(false);
thresholdLabel.setVisible(false);
otsuThresholdLabel.setVisible(false);
switch (selectedCategory) {
case "Ничего":
applyNoEffect();
break;
case "Негатив":
applyNegativeEffect();
break;
case "Степенное преобразование":
powerSlider.setVisible(true);
applyPowerTransformation();
break;
case "Лапласиан":
laplacianLabel.setVisible(true);
laplacianCheckBox.setVisible(true);
applyLaplacian();
break;
case "Градиент":
if (selectedSubMethod != null) {
switch (selectedSubMethod) {
case "Робертса":
applyRobertsGradient();
break;
case "Собеля":
applySobelGradient();
break;
}
}
break;
case "Пороговый фильтр":
if (selectedSubMethod != null) {
switch (selectedSubMethod) {
case "Глобальный порог":
thresholdSlider.setVisible(true);
thresholdLabel.setVisible(true);
applyGlobalThreshold();
break;
case "Метод Оцу":
otsuThresholdLabel.setVisible(true);
applyOtsuThreshold();
break;
}
}
break;
case "Линейный сглаживающий (усредняющий) фильтр":
applyAverageFilter();
break;
case "Медианный фильтр":
applyMedianFilter();
break;
case "Эквализация гистограммы":
applyHistogramEqualization();
break;
default:
applyNoEffect();
break;
}
if (histogramCheckBox.isSelected()) {
generateAndDisplayHistograms();
}
}
}
private void applyNoEffect() {
Image originalImage = beforeImageView.getImage();
afterImageView.setImage(originalImage);
}
private void applyNegativeEffect() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
WritableImage afterImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = afterImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int alpha = (argb >> 24) & 0xff;
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int negRed = 255 - red;
int negGreen = 255 - green;
int negBlue = 255 - blue;
int negativeArgb = (alpha << 24) | (negRed << 16) | (negGreen << 8) | negBlue;
writer.setArgb(x, y, negativeArgb);
}
}
afterImageView.setImage(afterImage);
}
}
private void applyPowerTransformation() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
double gamma = powerSlider.getValue();
WritableImage afterImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = afterImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int alpha = (argb >> 24) & 0xff;
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int newRed = clamp((int) (255 * Math.pow((red / 255.0), gamma)));
int newGreen = clamp((int) (255 * Math.pow((green / 255.0), gamma)));
int newBlue = clamp((int) (255 * Math.pow((blue / 255.0), gamma)));
int powerArgb = (alpha << 24) | (newRed << 16) | (newGreen << 8) | newBlue;
writer.setArgb(x, y, powerArgb);
}
}
afterImageView.setImage(afterImage);
}
}
private void applyRobertsGradient() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
WritableImage afterImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = afterImage.getPixelWriter();
for (int y = 0; y < height - 1; y++) {
for (int x = 0; x < width - 1; x++) {
int argb1 = reader.getArgb(x, y);
int argb2 = reader.getArgb(x + 1, y + 1);
int argb3 = reader.getArgb(x + 1, y);
int argb4 = reader.getArgb(x, y + 1);
int redX = ((argb1 >> 16) & 0xff) - ((argb2 >> 16) & 0xff);
int redY = ((argb3 >> 16) & 0xff) - ((argb4 >> 16) & 0xff);
int gradientRed = clamp((int) Math.sqrt(redX * redX + redY * redY));
int greenX = ((argb1 >> 8) & 0xff) - ((argb2 >> 8) & 0xff);
int greenY = ((argb3 >> 8) & 0xff) - ((argb4 >> 8) & 0xff);
int gradientGreen = clamp((int) Math.sqrt(greenX * greenX + greenY * greenY));
int blueX = (argb1 & 0xff) - (argb2 & 0xff);
int blueY = (argb3 & 0xff) - (argb4 & 0xff);
int gradientBlue = clamp((int) Math.sqrt(blueX * blueX + blueY * blueY));
int alpha = (argb1 >> 24) & 0xff;
int gradientArgb = (alpha << 24) | (gradientRed << 16) | (gradientGreen << 8) | gradientBlue;
writer.setArgb(x, y, gradientArgb);
}
}
afterImageView.setImage(afterImage);
}
}
private void applySobelGradient() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int[][] sobelX = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int[][] sobelY = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
WritableImage afterImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = afterImage.getPixelWriter();
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int gradientRedX = 0, gradientGreenX = 0, gradientBlueX = 0;
int gradientRedY = 0, gradientGreenY = 0, gradientBlueY = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int argb = reader.getArgb(x + j, y + i);
gradientRedX += ((argb >> 16) & 0xff) * sobelX[i + 1][j + 1];
gradientGreenX += ((argb >> 8) & 0xff) * sobelX[i + 1][j + 1];
gradientBlueX += (argb & 0xff) * sobelX[i + 1][j + 1];
gradientRedY += ((argb >> 16) & 0xff) * sobelY[i + 1][j + 1];
gradientGreenY += ((argb >> 8) & 0xff) * sobelY[i + 1][j + 1];
gradientBlueY += (argb & 0xff) * sobelY[i + 1][j + 1];
}
}
int gradientRed = clamp((int) Math.sqrt(gradientRedX * gradientRedX + gradientRedY * gradientRedY));
int gradientGreen = clamp((int) Math.sqrt(gradientGreenX * gradientGreenX + gradientGreenY * gradientGreenY));
int gradientBlue = clamp((int) Math.sqrt(gradientBlueX * gradientBlueX + gradientBlueY * gradientBlueY));
int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
int sobelArgb = (alpha << 24) | (gradientRed << 16) | (gradientGreen << 8) | gradientBlue;
writer.setArgb(x, y, sobelArgb);
}
}
afterImageView.setImage(afterImage);
}
}
private void applyLaplacian() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int[][] laplacianMask = {
{0, 1, 0},
{1, -4, 1},
{0, 1, 0}
};
WritableImage laplacianResult = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = laplacianResult.getPixelWriter();
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int sumRed = 0, sumGreen = 0, sumBlue = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int argb = reader.getArgb(x + j, y + i);
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
sumRed += red * laplacianMask[i + 1][j + 1];
sumGreen += green * laplacianMask[i + 1][j + 1];
sumBlue += blue * laplacianMask[i + 1][j + 1];
}
}
sumRed = clamp(Math.abs(sumRed));
sumGreen = clamp(Math.abs(sumGreen));
sumBlue = clamp(Math.abs(sumBlue));
int argbCenter = reader.getArgb(x, y);
int alpha = (argbCenter >> 24) & 0xff;
int laplacianArgb = (alpha << 24) | (sumRed << 16) | (sumGreen << 8) | sumBlue;
writer.setArgb(x, y, laplacianArgb);
}
}
if (laplacianCheckBox.isSelected()) {
laplacianImage = laplacianResult;
combineImagesWithLaplacian();
} else {
afterImageView.setImage(laplacianResult);
}
}
}
private void combineImagesWithLaplacian() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null && laplacianImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
WritableImage combinedImage = new WritableImage(width, height);
PixelReader originalReader = beforeImage.getPixelReader();
PixelReader laplacianReader = laplacianImage.getPixelReader();
PixelWriter writer = combinedImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int originalArgb = originalReader.getArgb(x, y);
int laplacianArgb = laplacianReader.getArgb(x, y);
int alpha = (originalArgb >> 24) & 0xff;
int originalRed = (originalArgb >> 16) & 0xff;
int originalGreen = (originalArgb >> 8) & 0xff;
int originalBlue = originalArgb & 0xff;
int laplacianRed = (laplacianArgb >> 16) & 0xff;
int laplacianGreen = (laplacianArgb >> 8) & 0xff;
int laplacianBlue = laplacianArgb & 0xff;
int combinedRed = clamp(originalRed + laplacianRed);
int combinedGreen = clamp(originalGreen + laplacianGreen);
int combinedBlue = clamp(originalBlue + laplacianBlue);
int combinedArgb = (alpha << 24) | (combinedRed << 16) | (combinedGreen << 8) | combinedBlue;
writer.setArgb(x, y, combinedArgb);
}
}
afterImageView.setImage(combinedImage);
}
}
private void applyGlobalThreshold() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int threshold = (int) thresholdSlider.getValue();
WritableImage thresholdImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = thresholdImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int alpha = (argb >> 24) & 0xff;
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
int binary = (luminance >= threshold) ? 255 : 0;
int binaryArgb = (alpha << 24) | (binary << 16) | (binary << 8) | binary;
writer.setArgb(x, y, binaryArgb);
}
}
afterImageView.setImage(thresholdImage);
}
}
private void applyOtsuThreshold() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int totalPixels = width * height;
int[] histogram = new int[256];
PixelReader reader = beforeImage.getPixelReader();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
histogram[luminance]++;
}
}
double sum = 0;
for (int t = 0; t < 256; t++) {
sum += t * histogram[t];
}
double sumB = 0;
int wB = 0;
int wF = 0;
double maxVariance = 0;
int threshold = 0;
for (int t = 0; t < 256; t++) {
wB += histogram[t];
if (wB == 0) continue;
wF = totalPixels - wB;
if (wF == 0) break;
sumB += t * histogram[t];
double mB = sumB / wB;
double mF = (sum - sumB) / wF;
double varianceBetween = (double) wB * (double) wF * (mB - mF) * (mB - mF);
if (varianceBetween > maxVariance) {
maxVariance = varianceBetween;
threshold = t;
}
}
otsuThresholdLabel.setText("Порог Оцу: " + threshold);
otsuThresholdLabel.setVisible(true);
WritableImage thresholdImage = new WritableImage(width, height);
PixelWriter writer = thresholdImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int alpha = (argb >> 24) & 0xff;
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
int binary = (luminance >= threshold) ? 255 : 0;
int binaryArgb = (alpha << 24) | (binary << 16) | (binary << 8) | binary;
writer.setArgb(x, y, binaryArgb);
}
}
afterImageView.setImage(thresholdImage);
}
}
private void generateAndDisplayHistograms() {
Image originalImage = beforeImageView.getImage();
Image modifiedImage = afterImageView.getImage();
if (originalImage != null && modifiedImage != null) {
Image originalHistogram = generateHistogram(originalImage);
Image modifiedHistogram = generateHistogram(modifiedImage);
originalHistogramView.setImage(originalHistogram);
modifiedHistogramView.setImage(modifiedHistogram);
originalHistogramView.setVisible(true);
modifiedHistogramView.setVisible(true);
}
}
private Image generateHistogram(Image image) {
int width = 256;
int height = 100;
int[] histogram = new int[256];
PixelReader reader = image.getPixelReader();
int imgWidth = (int) image.getWidth();
int imgHeight = (int) image.getHeight();
for (int y = 0; y < imgHeight; y++) {
for (int x = 0; x < imgWidth; x++) {
int argb = reader.getArgb(x, y);
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
histogram[luminance]++;
}
}
int max = 0;
for (int value : histogram) {
if (value > max) {
max = value;
}
}
WritableImage histogramImage = new WritableImage(width, height);
PixelWriter writer = histogramImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
writer.setColor(x, y, Color.WHITE);
}
}
for (int i = 0; i < width; i++) {
double ratio = (double) histogram[i] / max;
int barHeight = (int) Math.round(ratio * height);
for (int y = height - barHeight; y < height; y++) {
writer.setColor(i, y, Color.BLACK);
}
}
return histogramImage;
}
private void applyMedianFilter() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
WritableImage medianImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = medianImage.getPixelWriter();
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
List<Integer> reds = new ArrayList<>();
List<Integer> greens = new ArrayList<>();
List<Integer> blues = new ArrayList<>();
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int argb = reader.getArgb(x + j, y + i);
reds.add((argb >> 16) & 0xff);
greens.add((argb >> 8) & 0xff);
blues.add(argb & 0xff);
}
}
Collections.sort(reds);
Collections.sort(greens);
Collections.sort(blues);
int medianRed = reds.get(4);
int medianGreen = greens.get(4);
int medianBlue = blues.get(4);
int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
int medianArgb = (alpha << 24) | (medianRed << 16) | (medianGreen << 8) | medianBlue;
writer.setArgb(x, y, medianArgb);
}
}
afterImageView.setImage(medianImage);
}
}
private void applyHistogramEqualization() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int totalPixels = width * height;
int L = 256;
int[] histogram = new int[L];
PixelReader reader = beforeImage.getPixelReader();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
histogram[luminance]++;
}
}
double[] cdf = new double[L];
cdf[0] = (double) histogram[0] / totalPixels;
for (int k = 1; k < L; k++) {
cdf[k] = cdf[k - 1] + ((double) histogram[k] / totalPixels);
}
int[] s = new int[L];
for (int k = 0; k < L; k++) {
s[k] = clamp((int) Math.round((L - 1) * cdf[k]));
}
WritableImage equalizedImage = new WritableImage(width, height);
PixelWriter writer = equalizedImage.getPixelWriter();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = reader.getArgb(x, y);
int alpha = (argb >> 24) & 0xff;
int red = (argb >> 16) & 0xff;
int green = (argb >> 8) & 0xff;
int blue = argb & 0xff;
int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
int equalizedLuminance = s[luminance];
int equalizedArgb = (alpha << 24) | (equalizedLuminance << 16) | (equalizedLuminance << 8) | equalizedLuminance;
writer.setArgb(x, y, equalizedArgb);
}
}
afterImageView.setImage(equalizedImage);
}
}
private void applyAverageFilter() {
Image beforeImage = beforeImageView.getImage();
if (beforeImage != null) {
int width = (int) beforeImage.getWidth();
int height = (int) beforeImage.getHeight();
int[][] averageMask = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
WritableImage afterImage = new WritableImage(width, height);
PixelReader reader = beforeImage.getPixelReader();
PixelWriter writer = afterImage.getPixelWriter();
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
int sumRed = 0, sumGreen = 0, sumBlue = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int argb = reader.getArgb(x + j, y + i);
sumRed += (argb >> 16) & 0xff;
sumGreen += (argb >> 8) & 0xff;
sumBlue += argb & 0xff;
}
}
int averageRed = clamp(sumRed / 9);
int averageGreen = clamp(sumGreen / 9);
int averageBlue = clamp(sumBlue / 9);
int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
int averageArgb = (alpha << 24) | (averageRed << 16) | (averageGreen << 8) | averageBlue;
writer.setArgb(x, y, averageArgb);
}
}
afterImageView.setImage(afterImage);
}
}
private int clamp(int value) {
return Math.max(0, Math.min(255, value));
}
}
Editor is loading...
Leave a Comment