java图像滤镜处理(基于像素处理)


前言

Java中的图像滤镜算法可以分为两类:基于像素的滤镜和基于卷积核的滤镜。

基于像素的滤镜 这种滤镜是通过像素的颜色值对图像进行处理的。常用的像素滤镜有:灰度化、二值化、反色、美白、马赛克等。

基于卷积核的滤镜 这种滤镜是根据卷积核的权重进行像素处理的。常用的卷积核滤镜有:高斯模糊、锐化、浮雕、膨胀、腐蚀等。

对于Java开发者而言,可以使用Java提供的图像处理工具包Java Advanced Imaging (JAI) 来实现上述滤镜算法。例如,可以使用JAI中的 ConvolveDescriptor 类实现基于卷积核的滤镜算法。同时,也可以使用JAI中的其他类来实现像素级别的滤镜算法。

本文将以基于像素的滤镜为主来介绍如何实现简单的图像处理

一、基于像素的滤镜是什么?

Java基于像素的图像滤镜处理技术是一种图像处理方法,它通过对图像中的每个像素进行操作来实现各种效果,比如模糊、二值化、颜色增强等。这些效果通常是通过修改每个像素的颜色值或者像素周围的邻近像素来实现的。

实现基于像素的图像滤镜处理通常需要以下步骤:

  1. 像素访问:图像被加载后,可以通过像素级别的访问来获取图像中的每个像素的颜色值。在Java中,可以使用像素访问方法来获得图像的每个像素。
  2. 滤镜处理:一旦获取了图像中的每个像素,就可以根据所需的滤镜效果对像素进行处理。例如,对于模糊效果,可以使用像素周围的邻近像素的颜色值来计算当前像素的新颜色值;对于颜色增强,可以通过调整每个像素的颜色分量来增强图像的饱和度或对比度等。

值得注意的是,基于像素的图像滤镜处理通常会涉及大量的像素操作,因此在处理大图像时,可能需要考虑性能优化,以确保处理速度和效率。

二、使用步骤

1.图像读取

将一张图片转换为一个二维数组可以实现像素级别的访问和处理。在Java中,可以使用Java内置的图像处理类库java.awt.image.BufferedImage来实现这个过程。以下是简单的步骤:

  1. 导入必要的类库:
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
  1. 加载图片并获取像素数据:
try {
    // 加载图片文件
    File imageFile = new File("path/to/your/image.jpg");
    BufferedImage image = ImageIO.read(imageFile);

    // 获取图像的宽度和高度
    int width = image.getWidth();
    int height = image.getHeight();

    // 创建一个二维数组,用于存储像素数据
    int[][] pixelArray = new int[height][width];

    // 将图像像素数据存储到二维数组中
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            // 获取当前像素的颜色值
            int pixel = image.getRGB(x, y);

            // 将颜色值存储到二维数组中
            pixelArray[y][x] = pixel;
        }
    }
    System.out.println("read Image file successfully----width:" + width + " height:" + height);
} catch (Exception e) {
    e.printStackTrace();
}

在上述代码中,我们首先加载了一张图片并创建了一个BufferedImage对象。然后,通过调用getWidth()getHeight()方法获取图像的宽度和高度。接下来,我们创建一个与图像尺寸相同的二维数组pixelArray,用于存储图像的像素数据。

通过嵌套的循环,我们遍历图像的每个像素,并使用getRGB(x, y)方法获取每个像素的颜色值,并将颜色值存储到二维数组中。这样,我们就可以通过访问pixelArray[y][x]来获取图像中坐标为(x, y)的像素颜色值。

这样,我们就成功地将一张图片转换为了一个二维数组,可以在这个数组上进行像素级别的处理和操作。


2.滤镜处理

(1).二值化

二值化是一种简单的图像处理技术,它将图像中的像素颜色值转换为只有两种取值(通常是黑色和白色)。这样的处理使得图像中的颜色信息变得非常简单,更易于处理和分析。

以下是逐行解释这段代码:

public void BlackAndWhiteImage(int[][] bwi) {
    // 遍历图像的每一行(根据OutputSpeed参数来跳过一定的行数,以加快处理速度)
    for (int i = 0; i < bwi.length; i += OutputSpeed) {
        // 遍历图像的每一列(根据OutputSpeed参数来跳过一定的列数,以加快处理速度)
        for (int j = 0; j < bwi[0].length; j += OutputSpeed) {
            // 获取当前像素的颜色值
            int v = bwi[i][j];
            Color color = new Color(v);
            // 判断颜色值的亮度(这里以红色分量为例,通常RGB三个分量是相近的)
            if (color.getRed() > 155) {
                // 如果颜色较亮,则将像素设置为白色,利用Graphics g作为画笔
                g.setColor(Color.WHITE);
                g.fillRect(i / 8, j / 8, 1, 1);
            } else {
                // 如果颜色较暗,则将像素设置为黑色
                g.setColor(Color.BLACK);
                g.fillRect(i / 8, j / 8, 1, 1);
            }
        }
    }
}

在这段代码中,bwi是一个二维数组,表示图像的像素数据。这里的OutputSpeed是一个控制处理速度的参数,它决定了每次跳过的行和列数,以减少处理时间,但可能会降低处理精度。

接着,代码通过嵌套的循环遍历图像的每个像素,获取像素的颜色值,并通过Color类的getRed()方法获取该像素的红色分量(在RGB颜色空间中,红色分量代表像素的亮度)。然后,通过一个阈值(155)来判断像素的亮度是较亮还是较暗。

如果像素的红色分量值大于155,表示像素较亮,将其设置为白色;否则,将其设置为黑色。这样,就实现了简单的图像二值化滤镜算法,将图像转换为黑白两种颜色的像素表示。

(2).马赛克

public void Mosaic(int[][] ms) {
    // 遍历图像的每一行(根据OutputSpeed参数来跳过一定的行数,以加快处理速度)
    for (int i = 0; i < ms.length; i += OutputSpeed * 6) {
        // 遍历图像的每一列(根据OutputSpeed参数来跳过一定的列数,以加快处理速度)
        for (int j = 0; j < ms[0].length; j += OutputSpeed * 6) {
            // 获取当前像素的颜色值
            int v = ms[i][j];
            Color color = new Color(v);
            // 将小块内的像素颜色设置为当前像素的颜色
            g.setColor(color);
            g.fillRect((X + i) / 8, (Y + j) / 8, 10, 10);
        }
    }
}

(3).反色

public void OppositeImage(int[][] oi) {
    // 遍历图像的每一行(根据OutputSpeed参数来跳过一定的行数,以加快处理速度)
    for (int i = 0; i < oi.length; i += OutputSpeed) {
        // 遍历图像的每一列(根据OutputSpeed参数来跳过一定的列数,以加快处理速度)
        for (int j = 0; j < oi[0].length; j += OutputSpeed) {
            // 获取当前像素的颜色值
            int v = oi[i][j];
            Color color = new Color(v);
            // 获取当前像素的红色、绿色和蓝色分量值
            int red = color.getRed();
            int green = color.getGreen();
            int blue = color.getBlue();
            // 计算颜色的反色,将RGB分量值取反
            Color ocolor = new Color(255 - red, 255 - green, 255 - blue);
            // 将反色应用到画布上
            g.setColor(ocolor);
            g.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
        }
    }
}

(4).脸部提亮

public void FaceBrightening(int[][] fb) {
        for (int i = 0; i < fb.length; i += OutputSpeed) {
            for (int j = 0; j < fb[0].length; j += OutputSpeed) {
                int v = fb[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int Bred = red > 220 ? 250 : red + 30;
                int Bgreen = green > 220 ? 250 : green + 30;
                int Bblue = blue > 220 ? 250 : blue + 30;
                int gray = (red + green + blue) / 3;
                Color Bcolor = new Color(Bred, Bgreen, Bblue);
                if (gray < 60) {
                    g.setColor(color);
                } else {
                    g.setColor(Bcolor);
                }
                g.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

(5).黑白照片

public void GrayscaleImage(int[][] gi) {
        for (int i = 0; i < gi.length; i += OutputSpeed) {
            for (int j = 0; j < gi[0].length; j += OutputSpeed) {
                int v = gi[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);
                Color Gcolor = new Color(gray, gray, gray);
                g.setColor(Gcolor);
                g.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

(6)油画效果

public void PaintingImage(int[][] pi) {
        for (int i = 0; i < pi.length; i += OutputSpeed) {
            for (int j = 0; j < pi[0].length; j += OutputSpeed) {
                int v = pi[i][j];
                Color color = new Color(v);
                //利用Random随机数就可以实现油画效果
                Random random = new Random();
                int r = random.nextInt(15) + 5;
                g.setColor(color);
                g.fillOval((X + i) / 8, (Y + j) / 8, r, r);
            }
        }
    }

(7)融合特效

public void FusionImage(String Path1, String Path2) {
    // 读取图像1和图像2,转换为二维整数数组
    int[][] imga = toArry(Path1);
    int[][] imgb = toArry(Path2);
    
    // 计算混合图像的宽度和高度,选择较小的图像尺寸作为混合图像的尺寸
    int w = Math.min(imga.length, imgb.length);
    int h = Math.min(imga[0].length, imgb[0].length);
    
    // 以OutputSpeed / 2的步长遍历混合图像的像素
    for (int i = 0; i < w; i += (OutputSpeed / 2)) {
        for (int j = 0; j < h; j += (OutputSpeed / 2)) {
            // 获取图像1和图像2当前位置(i, j)处的颜色
            Color ca = new Color(imga[i][j]);
            Color cb = new Color(imgb[i][j]);
            
            // 计算混合后的红色、绿色和蓝色值,按照0.4和0.6的比例混合两个颜色
            int red = (int) (ca.getRed() * 0.4 + cb.getRed() * 0.6);
            int green = (int) (ca.getGreen() * 0.4 + cb.getGreen() * 0.6);
            int blue = (int) (ca.getBlue() * 0.4 + cb.getBlue() * 0.6);
            
            // 创建新的颜色对象,表示混合后的颜色
            Color cn = new Color(red, green, blue);
            
            // 设置画布的颜色为混合后的颜色,并在缩放后的位置(X + i) / 4, (Y + j) / 4绘制一个1x1像素的矩形
            g.setColor(cn);
            g.fillRect((X + i) / 4, (Y + j) / 4, 1, 1);
        }
    }
}

(8)轮廓提取

public void ContourExtraction(int[][] ce) {
        for (int i = 0; i < ce.length; i += OutputSpeed) {
            for (int j = 0; j < ce[0].length; j += OutputSpeed) {
                int v = ce[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);
                //取出右下斜方向的像素值 灰度化 作比较
                if (((i + 2) < ce.length) && ((j + 2) < ce[0].length)) {
                    int nv = ce[i + 2][j + 2];
                    Color ncolor = new Color(nv);
                    int nred = ncolor.getRed();
                    int ngreen = ncolor.getGreen();
                    int nblue = ncolor.getBlue();
                    int ngray = (int) (nred * 0.41 + ngreen * 0.36 + nblue * 0.23);
                    if (Math.abs(ngray - gray) > 15) {
                        g.setColor(Color.BLACK);
                    } else {
                        g.setColor(Color.WHITE);
                    }
                }
                g.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

3.界面美化

  1. CustomButton类继承了JButton类,这意味着它会拥有按钮的基本功能。
  2. BORDER_RADIUS是一个私有的静态常量,它定义了按钮的圆角弧度,这将影响按钮的外观。
  3. 在构造函数中,首先调用了JButton的构造函数,传递了一个字符串参数text,用于设置按钮的文本。
  4. 接下来,通过一系列设置方法来定制按钮的外观和行为:
    • setFocusPainted(false):禁止绘制焦点框,当按钮获得焦点时不会出现虚线框。
    • setContentAreaFilled(false):取消绘制内容区域,使按钮的内容透明,从而显示自定义的背景。
    • setBorderPainted(false):取消绘制边框,使按钮没有标准的边框样式。
    • setOpaque(false):设置按钮为透明,这样才能显示自定义的背景。
  5. 设置按钮的字体和文本颜色:
    • setFont(new Font("Arial", Font.BOLD, 30)):设置按钮文本的字体为Arial,加粗,大小为30。
    • setForeground(Color.WHITE):设置按钮文本的颜色为白色。
  6. 设置按钮的背景:
    • setBackground(new Color(40, 130, 220)):设置按钮的默认背景颜色为一种蓝色(RGB值为40, 130, 220)。
    • setPreferredSize(new Dimension(120, 40)):设置按钮的首选大小为宽120像素,高40像素。
  7. 重写paintComponent方法:这是一个绘制方法,它用于绘制按钮的外观。在这个方法中,首先通过create()方法创建了一个Graphics2D对象,用于绘制2D图形。然后获取按钮的宽度和高度。
  8. 创建按钮的背景渐变效果:
    • 使用GradientPaint创建了一个渐变色对象gradientPaint,从上到下从一种蓝色(RGB值为40, 130, 220)渐变到另一种蓝色(RGB值为30, 100, 180)。
    • g2d.setPaint(gradientPaint):将绘图上下文的绘制颜色设置为渐变色。
  9. 绘制圆角矩形的按钮:
    • g2d.fillRoundRect(0, 0, width, height, BORDER_RADIUS, BORDER_RADIUS):使用渐变色绘制一个圆角矩形,该矩形覆盖整个按钮区域。
  10. 最后,调用super.paintComponent(g)方法来保留JButton的默认绘制行为,确保按钮的文本和其他交互元素仍然能正常显示。
class CustomButton extends JButton {
    private static final int BORDER_RADIUS = 15;

    public CustomButton(String text) {
        super(text);
        setFocusPainted(false);
        setContentAreaFilled(false);
        setBorderPainted(false);
        setOpaque(false);

        // Set the font and text color
        setFont(new Font("Arial", Font.BOLD, 30));
        setForeground(Color.WHITE);

        // Set the button gradient background
        setBackground(new Color(40, 130, 220));
        setPreferredSize(new Dimension(120, 40));
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        int width = getWidth();
        int height = getHeight();

        // Create the gradient for the background
        GradientPaint gradientPaint = new GradientPaint(0, 0, new Color(40, 130, 220), 0, height, new Color(30, 100, 180));
        g2d.setPaint(gradientPaint);

        // Create a rounded rectangle for the button
        g2d.fillRoundRect(0, 0, width, height, BORDER_RADIUS, BORDER_RADIUS);
        g2d.dispose();

        super.paintComponent(g);
    }
}

4.加入双缓冲

双缓冲效果,用于在图像输出时减少闪烁和画面的不连续性。
首先,通过BufferedImage类创建了一个名为offScreenBuffer的离屏图像缓冲区。该缓冲区的尺寸为10,000 x 10,000像素,并使用ARGB色彩模式存储像素数据。
接下来,通过offScreenBuffer对象的getGraphics()方法获取到一个Graphics对象offScreenGraphics,用于在离屏缓冲区上进行绘制操作。
最后,定义了一个新的方法drawOffScreenBuffer(Graphics g),该方法接受一个Graphics对象作为参数,在主屏幕上绘制离屏缓冲区的内容。它使用参数gdrawImage()方法将offScreenBuffer绘制在主屏幕上的坐标(0, 0)处。
这个双缓冲效果的原理是,首先将图像输出绘制到离屏缓冲区,然后再将整个离屏缓冲区一次性地绘制到主屏幕上。这样可以避免在绘制过程中出现的闪烁和画面不连续的问题。
通过使用双缓冲技术,可以提高图像输出的质量和流畅度,使得视觉效果更加平滑和稳定。

private final BufferedImage offScreenBuffer = new BufferedImage(10000, 10000, BufferedImage.TYPE_INT_ARGB);
private final Graphics offScreenGraphics = offScreenBuffer.getGraphics();
// Add a new method to draw the off-screen buffer onto the main screen
public void drawOffScreenBuffer(Graphics g) {
	g.drawImage(offScreenBuffer, 0, 0, null);
}

加入双缓冲之后,以上代码的所有画笔g就都可以换成offScreenGraphics


三、完整代码

import javax.swing.*;
import java.awt.*;

public class DrawImage extends JFrame {
    actionListener acl = new actionListener();

    public void createUI() {
        this.setTitle("图像滤镜");
        this.setSize(1200, 800);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel contentPane = new JPanel(new BorderLayout());
        contentPane.setBackground(Color.BLACK);

        JPanel buttonPanel = new JPanel(new GridLayout(2, 6, 2, 2)); // 使用GridLayout以网格形式排列按钮
        addButton(buttonPanel);
        JScrollPane scrollPane = new JScrollPane(buttonPanel); // 添加滚动面板
        contentPane.add(scrollPane, BorderLayout.NORTH);

        JPanel imagePanel = new JPanel() {
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                // 在此处绘制图片
            }
        };
        imagePanel.setPreferredSize(new Dimension(800, 500));
        imagePanel.setBackground(Color.WHITE);
        contentPane.add(imagePanel, BorderLayout.CENTER);

        this.setContentPane(contentPane);
        this.setVisible(true);

        actionListener.g = imagePanel.getGraphics(); // 将图形上下文g指向imagePanel的Graphics对象
    }

    public void addButton(JPanel buttonPanel) {
        String[] btnstrs = {"原图", "二值化", "马赛克", "反色", "脸部提亮", "普通黑白", "油画", "融合特效", "轮廓提取", "清空"};
        for (String btnstr : btnstrs) {
            CustomButton button = new CustomButton(btnstr);
            button.setFont(new Font("宋体", Font.PLAIN, 20)); // 设置按钮字体为宋体
            buttonPanel.add(button);
            button.addActionListener(acl);
        }
    }

    public static void main(String[] args) {
        DrawImage drawImage = new DrawImage();
        drawImage.createUI();
    }
}

class CustomButton extends JButton {
    private static final int BORDER_RADIUS = 15;

    public CustomButton(String text) {
        super(text);
        setFocusPainted(false);
        setContentAreaFilled(false);
        setBorderPainted(false);
        setOpaque(false);

        // Set the font and text color
        setFont(new Font("Arial", Font.BOLD, 30));
        setForeground(Color.WHITE);

        // Set the button gradient background
        setBackground(new Color(40, 130, 220));
        setPreferredSize(new Dimension(120, 40));
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        int width = getWidth();
        int height = getHeight();

        // Create the gradient for the background
        GradientPaint gradientPaint = new GradientPaint(0, 0, new Color(40, 130, 220), 0, height, new Color(30, 100, 180));
        g2d.setPaint(gradientPaint);

        // Create a rounded rectangle for the button
        g2d.fillRoundRect(0, 0, width, height, BORDER_RADIUS, BORDER_RADIUS);
        g2d.dispose();

        super.paintComponent(g);
    }
}
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Random;
import java.util.Scanner;

public class actionListener implements ActionListener {

    //图像地址
    String ImagePath = "path.jpg";
    String ImagePath1 = "path1.jpg";
    String ImagePath2 = "path2.jpg";
    static Graphics g;
    //1图片转二维数组; 2图像处理滤镜绘制方法
    int[][] ict;
    private String msg = String.valueOf(0);
    private final byte[] msgByte = msg.getBytes();
    //图片初始绘制坐标参数
    final int X = 0;
    final int Y = 0;
    int OutputSpeed = 5;  //清晰度,输出速度
    private final BufferedImage offScreenBuffer = new BufferedImage(10000, 10000, BufferedImage.TYPE_INT_ARGB);
    private final Graphics offScreenGraphics = offScreenBuffer.getGraphics();

    // Add a new method to draw the off-screen buffer onto the main screen
    public void drawOffScreenBuffer(Graphics g) {
        g.drawImage(offScreenBuffer, 0, 0, null);
    }

    //构造方法调用图像
    public actionListener() {
        try {
            ict = toArry(ImagePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //重写,图像绘制方式选择
    public void actionPerformed(ActionEvent e) {
        String btnstr = e.getActionCommand();
        System.out.println("点击了" + btnstr);
        switch (btnstr) {
            case "二值化" -> BlackAndWhiteImage(ict);
            case "原图" -> OriginalImage(ict);
            case "马赛克" -> Mosaic(ict);
            case "反色" -> OppositeImage(ict);
            case "脸部提亮" -> FaceBrightening(ict);
            case "普通黑白" -> GrayscaleImage(ict);
            case "油画" -> PaintingImage(ict);
            case "融合特效" -> FusionImage(ImagePath1, ImagePath2);
            case "轮廓提取" -> ContourExtraction(ict);
            case "清空" -> {
                Empty();
                System.out.println("已清空");
            }
        }
        drawOffScreenBuffer(g);
    }
    
    //储存图像为二维数组
    public int[][] toArry(String path) {
        //取得照片
        File f = new File(path);
        //提取照片信息
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(f);
        } catch (Exception ef) {
            ef.printStackTrace();
        }

        int w = 0, h = 0;
        if (bi != null) {
            w = bi.getWidth();
            h = bi.getHeight();
        }
        int[][] data = new int[w][h];
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                int v = bi.getRGB(i, j);
                data[i][j] = v;
            }
        }
        System.out.println("read Image file successfully----w:" + w + " h:" + h);
        return data;
    }

    //原图
    public void OriginalImage(int[][] ori) {
        // Use off-screen graphics instead of 'g'
        for (int i = 0; i < ori.length; i += OutputSpeed) {
            for (int j = 0; j < ori[i].length; j += OutputSpeed) {
                int rgb = ori[i][j];
                Color color = new Color(rgb);
                offScreenGraphics.setColor(color);
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

    //二值化
    public void BlackAndWhiteImage(int[][] bwi) {
        for (int i = 0; i < bwi.length; i += OutputSpeed) {
            for (int j = 0; j < bwi[0].length; j += OutputSpeed) {
                int v = bwi[i][j];
                Color color = new Color(v);
                //g.setColor(color);
                if (color.getRed() > 155) {
                    offScreenGraphics.setColor(Color.WHITE);
                    offScreenGraphics.fillRect(i / 8, j / 8, 1, 1);
                } else {
                    offScreenGraphics.setColor(Color.BLACK);
                    offScreenGraphics.fillRect(i / 8, j / 8, 1, 1);
                }
            }
        }
    }

    //马赛克
    public void Mosaic(int[][] ms) {
        for (int i = 0; i < ms.length; i += OutputSpeed * 6) {
            for (int j = 0; j < ms[0].length; j += OutputSpeed * 6) {
                int v = ms[i][j];
                Color color = new Color(v);
                offScreenGraphics.setColor(color);
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 10, 10);
            }
        }
    }

    //反色
    public void OppositeImage(int[][] oi) {
        for (int i = 0; i < oi.length; i += OutputSpeed) {
            for (int j = 0; j < oi[0].length; j += OutputSpeed) {
                int v = oi[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                Color ocolor = new Color(255 - red, 255 - green, 255 - blue);
                offScreenGraphics.setColor(ocolor);
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

    //脸部提亮
    public void FaceBrightening(int[][] fb) {
        for (int i = 0; i < fb.length; i += OutputSpeed) {
            for (int j = 0; j < fb[0].length; j += OutputSpeed) {
                int v = fb[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int Bred = red > 220 ? 250 : red + 30;
                int Bgreen = green > 220 ? 250 : green + 30;
                int Bblue = blue > 220 ? 250 : blue + 30;
                int gray = (red + green + blue) / 3;
                Color Bcolor = new Color(Bred, Bgreen, Bblue);
                if (gray < 60) {
                    offScreenGraphics.setColor(color);
                } else {
                    offScreenGraphics.setColor(Bcolor);
                }
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

    //普通黑白
    public void GrayscaleImage(int[][] gi) {
        for (int i = 0; i < gi.length; i += OutputSpeed) {
            for (int j = 0; j < gi[0].length; j += OutputSpeed) {
                int v = gi[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);
                Color Gcolor = new Color(gray, gray, gray);
                offScreenGraphics.setColor(Gcolor);
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

    //油画
    public void PaintingImage(int[][] pi) {
        for (int i = 0; i < pi.length; i += OutputSpeed) {
            for (int j = 0; j < pi[0].length; j += OutputSpeed) {
                int v = pi[i][j];
                Color color = new Color(v);
                Random random = new Random();
                int r = random.nextInt(15) + 5;
                offScreenGraphics.setColor(color);
                offScreenGraphics.fillOval((X + i) / 8, (Y + j) / 8, r, r);
            }
        }
    }

    //融合特效
    public void FusionImage(String Path1, String Path2) {
        int[][] imga = toArry(Path1);
        int[][] imgb = toArry(Path2);
        int w = Math.min(imga.length, imgb.length);
        int h = Math.min(imga[0].length, imgb[0].length);
        for (int i = 0; i < w; i += (OutputSpeed / 2)) {
            for (int j = 0; j < h; j += (OutputSpeed / 2)) {
                Color ca = new Color(imga[i][j]);
                Color cb = new Color(imgb[i][j]);
                int red = (int) (ca.getRed() * 0.4 + cb.getRed() * 0.6);
                int green = (int) (ca.getGreen() * 0.4 + cb.getGreen() * 0.6);
                int blue = (int) (ca.getBlue() * 0.4 + cb.getBlue() * 0.6);
                Color cn = new Color(red, green, blue);
                offScreenGraphics.setColor(cn);
                offScreenGraphics.fillRect((X + i) / 4, (Y + j) / 4, 1, 1);
            }
        }
    }

    //轮廓提取
    public void ContourExtraction(int[][] ce) {
        for (int i = 0; i < ce.length; i += OutputSpeed) {
            for (int j = 0; j < ce[0].length; j += OutputSpeed) {
                int v = ce[i][j];
                Color color = new Color(v);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);
                //取出右下斜方向的像素值 灰度化 作比较
                if (((i + 2) < ce.length) && ((j + 2) < ce[0].length)) {
                    int nv = ce[i + 2][j + 2];
                    Color ncolor = new Color(nv);
                    int nred = ncolor.getRed();
                    int ngreen = ncolor.getGreen();
                    int nblue = ncolor.getBlue();
                    int ngray = (int) (nred * 0.41 + ngreen * 0.36 + nblue * 0.23);
                    if (Math.abs(ngray - gray) > 15) {
                        offScreenGraphics.setColor(Color.BLACK);
                    } else {
                        offScreenGraphics.setColor(Color.WHITE);
                    }
                }
                offScreenGraphics.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
            }
        }
    }

    //清空
    public void Empty() {
        offScreenGraphics.setColor(Color.WHITE);
        offScreenGraphics.fillRect(0, 0, 10000, 10000);
        flag = true;
    }

总结

以上就是一个简单的基于像素的图像滤镜处理,实现了几种常见的滤镜处理方法,每一种处理方法都可以根据实际情况来修改对应颜色数据和输出速度。。首先介绍了Java图像处理的基本知识,包括图像的像素和RGB颜色模式等;然后详细讲解了Java实现图像滤镜处理的步骤,包括读取图像、处理像素、修改像素等;接着介绍了常见的图像滤镜处理算法,包括灰度化、反色、二值化、油画效果、马赛克等,通过代码实现了这些算法;最后介绍了如何将多种滤镜组合起来实现复杂的图像处理效果。对于想要了解Java图像处理的开发者来说是一篇不错的参考资料。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钻石程序的金锄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值