Java 高斯模糊半径越大,图像越暗

Java 高斯模糊半径越大,图像越暗,java,gaussian,gaussianblur,Java,Gaussian,Gaussianblur,我用Java实现,它似乎适用于较小的半径,但不适用于较大的半径。我不确定为什么在较大的半径上图像变暗,我遵循相同的公式和步骤应用模糊。生成模糊矩阵并将其应用于原始图像,并且将像素值设置为图像矩阵与模糊矩阵相乘的结果之和。我在下面添加了我编写的代码: public class GaussianBlur extends ImageFilter { private int radius; private double sigma; public GaussianBlur(St

我用Java实现,它似乎适用于较小的半径,但不适用于较大的半径。我不确定为什么在较大的半径上图像变暗,我遵循相同的公式和步骤应用模糊。生成模糊矩阵并将其应用于原始图像,并且将像素值设置为图像矩阵与模糊矩阵相乘的结果之和。我在下面添加了我编写的代码:

public class GaussianBlur extends ImageFilter {
    private int radius;
    private double sigma;

    public GaussianBlur(String imageFilename, int radius) {
        super(imageFilename);
        this.radius = radius;
        this.sigma = ((2.0 * radius) + 1.0) / 2.0;
    }

    @Override
    public void applyFilter() throws IOException {
        init();

        Matrix<Double> gaussianMatrix = getGaussianMatrix();

        Matrix<Color> imageMatrix, weightedImageMatrix;
        Color weightedPixelSum;
        for(int i = 0; i < getWidth(); i++) {
            for(int j = 0; j < getHeight(); j++) {
                imageMatrix = getImageMatrix(i, j);
                weightedImageMatrix = multiplyImageMatrixWithWeight(imageMatrix, gaussianMatrix);
                weightedPixelSum = getWeightedGaussianBlurValue(weightedImageMatrix);

                getFilter().setRGB(i, j, weightedPixelSum.getRGB());
            }
        }
    }

    private Matrix<Double> getGaussianMatrix() {
        Matrix<Double> gaussianMatrix = new Matrix<>(Double.class, radius);
        double weightedSum = 0.0;

        int matrixI = 0, matrixJ;
        double gaussianValue;
        for(int i = -radius; i <= radius; i++) {
            matrixJ = 0;

            for(int j = -radius; j <= radius; j++) {
                gaussianValue = getGaussianValue(i, j);
                weightedSum += gaussianValue;
                gaussianMatrix.setValue(matrixI, matrixJ, gaussianValue);
                matrixJ++;
            }

            matrixI++;
        }

        for(int i = 0; i < gaussianMatrix.getMatrix().length; i++) {
            for(int j = 0; j < gaussianMatrix.getMatrix()[i].length; j++) {
                gaussianMatrix.setValue(i, j, gaussianMatrix.getValue(i, j) / weightedSum);
            }
        }

        return gaussianMatrix;
    }

    private double getGaussianValue(int x, int y) {
        return 1.0 / (2.0 * Math.PI * sigma * sigma) * Math.pow(Math.E, -((x * x) + (y * y)) / (2.0 * (sigma * sigma)));
    }

    private Color getWeightedGaussianBlurValue(Matrix<Color> weightedImageMatrix) {
        int r = 0, g = 0, b = 0;

        for(int i = 0; i < weightedImageMatrix.getMatrix().length; i++) {
            for(int j = 0; j < weightedImageMatrix.getMatrix()[i].length; j++) {
                if(weightedImageMatrix.getValue(i, j) != null) {
                    r += weightedImageMatrix.getValue(i, j).getRed();
                    g += weightedImageMatrix.getValue(i, j).getGreen();
                    b += weightedImageMatrix.getValue(i, j).getBlue();
                }
            }
        }

        return new Color(r, g, b);
    }

    /*
     * Multiply each image pixel with its matrix value to get a new matrix with the weighted pixel values.
     */
    private Matrix<Color> multiplyImageMatrixWithWeight(Matrix<Color> imageMatrix, Matrix<Double> gaussianMatrix) {
        Matrix<Color> weightedImageMatrix = new Matrix<>(Color.class, this.radius);

        Color weightedValue;
        for(int i = 0; i < weightedImageMatrix.getMatrix().length; i++) {
            for(int j = 0; j < weightedImageMatrix.getMatrix()[i].length; j++) {
                if(imageMatrix.getValue(i, j) != null) {
                    weightedValue = new Color(
                        (int) ((double) imageMatrix.getValue(i, j).getRed() * gaussianMatrix.getValue(i, j)),
                        (int) ((double) imageMatrix.getValue(i, j).getGreen() * gaussianMatrix.getValue(i, j)),
                        (int) ((double) imageMatrix.getValue(i, j).getBlue() * gaussianMatrix.getValue(i, j))
                    );

                    weightedImageMatrix.setValue(i, j, weightedValue);
                } else {
                    weightedImageMatrix.setValue(i, j, null);
                }
            }
        }

        return weightedImageMatrix;
    }

    /*
     * Given the center points (i, j), construct a matrix from the image to blur.
     */
    private Matrix<Color> getImageMatrix(int i, int j) {
        Matrix<Color> imageMatrix = new Matrix<>(Color.class, radius);

        int matrixI = 0, matrixJ;
        for(int x = i - radius; x <= i + radius; x++) {
            matrixJ = 0;

            for(int y = j - radius; y <= j + radius; y++) {
                if(x > -1 && y > -1 && x < getOriginal().getWidth() && y < getOriginal().getHeight()) {
                    imageMatrix.setValue(matrixI, matrixJ, new Color(getOriginal().getRGB(x, y)));
                } else {
                    imageMatrix.setValue(matrixI, matrixJ, null);
                }

                matrixJ++;
            }

            matrixI++;
        }

        return imageMatrix;
    }

    private class Color {
        private int r, g, b;

        public Color(int r, int g, int b) {
            this.r = r;
            this.g = g;
            this.b = b;
        }

        public Color(int rgb) {
            this((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff);
        }

        public int getRed() {
            return r;
        }

        public int getGreen() {
            return g;
        }

        public int getBlue() {
            return b;
        }

        public int getRGB() {
            return (r << 16) | (g << 8) | b;
        }

        @Override
        public String toString() {
            return "(" + r + "," + g + "," + b + ")";
        }
    }

    private class Matrix<T> {
        private T[][] matrix;

        public Matrix(Class<T> clazz, int radius) {
            int length = (2 * radius) + 1;
            matrix = (T[][]) Array.newInstance(clazz, length, length);
        }

        public T getValue(int i, int j) {
            return matrix[i][j];
        }

        public void setValue(int i, int j, T value) {
            matrix[i][j] = value;
        }

        public T[][] getMatrix() {
            return matrix;
        }
    }
}
下面是生成的图像

原始图像:

以半径2模糊:

以半径7模糊:


为什么用半径7模糊它会使图像变暗?公式中是否有遗漏或我遗漏了什么?

“半径2模糊”似乎也有点暗!如果是这样的话,你的算法通常会变暗。你是从图像边界之外读取“黑色度”吗?@AndyTurner如果我在边界(例如端点或边界),我只是将像素设置为null,以便在计算权重时不使用它们。我不确定你所说的“黑色”是什么意思?@Hakumanatata看看半径2图像周围的黑色边框:“黑色”来自某个地方。看起来
getGaussianMatrix
的元素加起来不等于1,所以图像整体会更暗。一个更大的问题是,在
getWeightedGaussianBlurValue
public static void main(String[] args) throws IOException {
    String filename = "res" + File.separator + "TajMahal.jpeg";

    GaussianBlur gaussianBlur = new GaussianBlur(filename, 2);
    gaussianBlur.applyFilter();
    gaussianBlur.displayImage();
}