Untitled
unknown
plain_text
5 months ago
31 kB
3
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