文章目录
- 前言
- 一.基于像素的滤镜是什么?
- 二.项目完备过程:
- (1).创建窗体和各类面板
- (2).图像的读取
- (3).双缓冲处理和拉杆设置
- (4).图像的滤镜处理
- 三.完整代码
- (一)主函数
- (二) 监听器
- 四.总结
- 五.实际效果
前言
Java中的图像滤镜算法可以分为两类:基于像素的滤镜和基于卷积核的滤镜。
基于像素的滤镜 这种滤镜是通过像素的颜色值对图像进行处理的。常用的像素滤镜有:灰度化、二值化、反色、美白、马赛克等。
基于卷积核的滤镜 这种滤镜是根据卷积核的权重进行像素处理的。常用的卷积核滤镜有:高斯模糊、锐化、浮雕、膨胀、腐蚀等。
对于Java开发者而言,可以使用Java提供的图像处理工具包Java Advanced Imaging (JAI) 来实现上述滤镜算法。例如,可以使用JAI中的 ConvolveDescriptor 类实现基于卷积核的滤镜算法。同时,也可以使用JAI中的其他类来实现像素级别的滤镜算法。
本文将以基于像素的滤镜为主来介绍如何实现简单的图像处理。
一.基于像素的滤镜是什么?
基于像素的滤镜(Pixel-based filters)是一种图像处理技术,它是对图像的每个像素进行操作或转换,而不考虑像素周围的上下文。这种滤镜通常是在图像上应用一些数学运算或变换,以改变像素的颜色、亮度、对比度或其他属性,从而达到图像增强、特效添加或艺术效果等目的。
基于像素的滤镜的工作方式是遍历图像的每个像素,并根据某种算法或函数来修改该像素的值。这些滤镜通常是局部操作,因为它们只依赖于单个像素的信息,而不考虑像素的上下文。由于只考虑了像素本身的属性,因此基于像素的滤镜处理速度较快,并且可以轻松应用于实时图像处理和交互式图像编辑。
一些常见的基于像素的滤镜包括:
灰度化滤镜: 将彩色图像转换为黑白图像,通常通过将RGB颜色分量加权平均来实现。
反转滤镜: 反转图像的颜色,即将亮的像素变暗,暗的像素变亮。
亮度/对比度调整滤镜: 调整图像的亮度和对比度,以增强或减弱图像的视觉效果。
色彩平衡滤镜: 调整图像中红、绿、蓝三个颜色通道的平衡,改变图像的色调。
伽马校正滤镜: 通过伽马变换调整图像的亮度曲线,影响图像的亮暗细节。
阈值化滤镜: 将图像转换为二值图像,像素值高于阈值的设为白色,低于阈值的设为黑色。
模糊滤镜: 平均或加权平均周围像素的值,从而减少图像的细节和噪声。
锐化滤镜: 增强图像的边缘和细节,使图像看起来更加清晰。
这些基于像素的滤镜通常是图像处理软件和编辑器中常见的功能,也可以作为计算机视觉和图像处理中的基本操作来处理图像数据。
二.项目完备过程:
(1).创建窗体和各类面板
窗体提供了应用程序的主要框架,用于展示整个GUI界面,并处理与窗体本身相关的事件。而面板则用于组织和布局窗体上的各种GUI组件,帮助构建应用程序的用户界面。
1.创建窗体
//窗体的创建
this.setTitle("PC版美颜相机--by zyx");
this.setSize(1000, 600);
this.getContentPane().setBackground(Color.WHITE);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
2.创建各类面板
//按钮面板 对象JPanel 默认是流式布局
JPanel eastPanel = new JPanel();
eastPanel.setBackground(new Color(220,226,248));
eastPanel.setPreferredSize(new Dimension(200,0));
this.add(eastPanel,BorderLayout.EAST);
//图画面板
JPanel drawPanel = new JPanel();
drawPanel.setBackground(Color.WHITE);
drawPanel.setPreferredSize(new Dimension(800,500));
this.add(drawPanel,BorderLayout.CENTER);
this.setVisible(true);
Graphics g=drawPanel.getGraphics();
3 .加入功能按钮
String[] strs={"原图","二值化","灰度","马赛克","放大","缩小","油画","哈哈镜","旋转","加密"};
Color primaryColor = new Color(137, 190, 178);
Color textColor = Color.WHITE;
// 应用颜色方案到按钮
Font buttonFont = new Font("宋体", Font.PLAIN, 16); // 设置按钮字体和字号
for(int i=0;i< strs.length;i++) {
JButton buDraw = new JButton(strs[i]);
buDraw.setPreferredSize(new Dimension(80,30));
buDraw.setBackground(primaryColor);
buDraw.setForeground(textColor);
buDraw.setFont(buttonFont);
buDraw.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
//创建一个空白边框,为按钮的内容留出一些空间,使其看起来更加整洁和美观。
eastPanel.add(buDraw);
buDraw.addActionListener(mouse);
}
JLabel j1 = new JLabel("大小/程度选择:");
j1.setFont(new Font("黑体",1,15));
eastPanel.add(j1);
(2).图像的读取
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();
}
实现了一个简单的图片加载和像素数据处理的过程。它为我们提供了一个基本的框架,可以在后续的代码中进一步处理这些像素数据,比如进行图像处理、分析图像特征等操作。
(3).双缓冲处理和拉杆设置
1.双缓存处理
Java中的双缓冲处理是一种图形渲染技术,用于避免图像闪烁和提高绘制效率。Java中的双缓冲处理是一种图形渲染技术,用于避免图像闪烁和提高绘制效率。
public void bufferZone() {
int[][] data = image(fn);
bufferedImage = new BufferedImage( data.length, data[0].length,BufferedImage.TYPE_INT_RGB);
bg = bufferedImage.getGraphics();
bg.setColor(Color.WHITE);
bg.fillRect(0,0,bufferedImage.getWidth(),bufferedImage.getHeight());
}
2.拉杆设置
在Java中,JSlider是Swing组件库中的一个类,用于创建滑动条控件。JSlider允许用户在指定的范围内拖动滑块来选择一个值,这个值可以是整数、浮点数或其他数据类型。JSlider通常用于用户界面中需要选择范围值的情况,比如音量调节、亮度控制、时间选择等。
//拉杆
JSlider js1 = new JSlider(1,10);
js1.setMajorTickSpacing(1);
js1.setMinorTickSpacing(1);
js1.setPreferredSize(new Dimension(200,80));
js1.setFont (new Font ("黑体",1,15));
js1.setPaintLabels(true);
js1.setPaintTicks(true);
js1.setSnapToTicks(true);
js1.setOpaque(false);
js1.setValue(1);
eastPanel.add(js1);
js1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
g.setColor(Color.WHITE);
g.fillRect(0,100,1000,1000);
if(e != null){
int x =js1.getValue();
mouse.s = x;
}
}
});
}
(4).图像的滤镜处理
1.灰度滤镜
灰度处理是将彩色图像转换为灰度图像的过程,也就是将每个像素点的颜色值从RGB(红、绿、蓝)表示转换为灰度亮度表示。有平均值法,加权平均法,最大(小)值法,加权平均法。本代码采用平均值法
public void grey(){
bufferZone();
int[][] data = image(fn);
for (int i = 0; i < data.length; i++){
for (int j = 0; j < data[i].length; j++){
Color color = new Color(data[i][j]);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int sum = (red+green+blue)/3;
Color newColor = new Color(sum,sum,sum);
bg.setColor(newColor);
bg.drawOval(i/2,j/2,1,1);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
2.二值化处理
采取阈值处理:选择一个合适的阈值(Threshold),通常是一个介于0到255之间的值。然后,对灰度图像中的每个像素进行处理,将像素灰度值与阈值进行比较,大于阈值的像素设为255(白色),小于等于阈值的像素设为0(黑色),从而生成二值图像。
public void binarization() {
bufferZone();
int x = s;
int[][] data = image(fn);
int h = data.length;
int w = data[0].length;
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
int p = data[i][j];
Color color = new Color(p);
int blue = color.getBlue();
if (blue >(70+2*x)){
bg.setColor(Color.BLACK);
}else{
bg.setColor(Color.WHITE);
}
bg.drawOval(i/2,j/2,1,1);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
3.马赛克滤镜
马赛克处理的主要步骤如下:
---------1.将图像划分为若干个区域:首先,将图像划分为若干个大小相等的小区域。
---------2.计算每个区域的平均颜色:对于每个小区域,计算该区域内所有像素点的颜色的平均值。
---------3.用平均颜色替换区域内的像素:将该区域内所有像素点的颜色值都替换为计算得到的平均颜色。
public void mosaic() {
bufferZone();
int x = s;
int[][] data = image(fn);
for (int i = 0; i < data.length; i += (15+1.6*x)) {
for (int j = 0; j < data[i].length; j += (15+1.6*x)) {
Color color = new Color(data[i][j]);
bg.setColor(color);
bg.fillRect(i / 2, j/ 2, 15, 15);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
4.油画效果
实现油画效果的基本步骤如下:
---------1.将图像分割为若干个小区域。
---------2.对于每个小区域,计算其周围像素的平均颜色值。
---------3.将当前小区域的所有像素值替换为计算得到的平均颜色值。
---------4.重复上述步骤,直到对整个图像都进行了处理。
通过这种方式,图像的细节会逐渐被模糊化,形成油画效果。
需要注意的是,实现油画效果有很多不同的算法和参数选择,不同的实现方式可能会产生不同的效果。这种效果的复杂性和处理时间也取决于图像的大小和算法的复杂性。
public void oil(){
bufferZone();
int x = s;
int[][] data = image(fn);
for (int i =0; i < data.length-5; i +=5){
for (int j =0; j < data[i].length-5; j +=5) {
Color color = new Color(data[i][j]);
bg.setColor(color);
Random ran=new Random();
int r1 = ran.nextInt(20)*x+5;
int r2 = ran.nextInt(40)*x+5;
bg.fillOval((i+x)/2, (j+x)/2,Math.max(r1,r2), Math.min(r1,r2));
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
5.哈哈镜效果
实现哈哈镜效果的基本步骤如下:
1.将图像分割为若干个小区域。
2.对于每个小区域,根据一定的规则或算法对像素进行扭曲或变形。
3.将扭曲后的像素重新组合,生成哈哈镜效果的图像。
在具体的实现中,可以使用不同的变形算法和参数来得到不同的效果。常见的哈哈镜效果包括鱼眼效果、凸透镜效果和凹透镜效果等。
public void funhouseMirror() {
bufferZone();
int x = s;
int[][] data = image(fn);
int h=data.length;
int w=data[0].length;
int maxDist = (int) Math.sqrt((w/2 - a) * (w/2 - a) + (h/2 - b) * (h/2 - b));
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
int deltaX = i - b;
int deltaY = j - a;
double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
int newX = (int) (i + deltaX * x * maxDist / distance*0.1);
int newY = (int) (j + deltaY * x * maxDist / distance*0.1);
if (newX >= 0 && newX < data.length && newY >= 0 && newY < data[i].length) {
Color color = new Color(data[newX][newY]);
bg.setColor(color);
bg.drawOval(i/2, j/2, 1, 1);
}
}
}
// 把缓冲区显示在窗体;
g.drawImage(bufferedImage, 0, 22, j1);
}
6.轮廓提取
这里提供一个基于Sobel算子的简单边缘检测方法。Sobel算子是一种常用的边缘检测算子,它可以用于轮廓提取。
---------1.将彩色图像转换为灰度图像,以简化处理。我们使用加权平均法将RGB彩色值转换为单一的灰度值。通常使用以下公式:Gray = 0.3 * Red + 0.59 * Green + 0.11 * Blue。
---------2.对灰度图像应用Sobel算子进行边缘检测。Sobel算子是一个离散差分算子,用于计算图像中每个像素点的梯度幅值和方向。通过计算图像在水平和垂直方向上的梯度,我们可以找到图像中的边缘。
---------3.对梯度幅值进行阈值处理,以筛选出边缘点。通常使用双阈值处理,将梯度幅值分为高阈值和低阈值区间。高于高阈值的像素被视为强边缘,低于低阈值的像素被视为弱边缘,介于两个阈值之间的像素可以根据其是否与强边缘相连来决定是否保留。
---------1.可选:应用边缘连接算法,将弱边缘与强边缘连接起来,形成完整的边缘线。
public void ContourExtraction() {
for (int i = 0; i < ce.length; i +=1) {
for (int j = 0; j < ce[0].length; j += 1) {
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) {
bg.setColor(Color.BLACK);
} else {
bg.setColor(Color.WHITE);
}
}
bg.fillRect((X + i) / 8, (Y + j) / 8, 1, 1);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
三.完整代码
(一)主函数
package CamaddLSBzyx0722;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
public class ImageBoard extends JFrame {
//private DrawMouse dl=null;
String fName;
DrawMouse mouse = new DrawMouse();
public void initUI() {
//窗体的创建
this.setTitle("PC版美颜相机--by zyx");
this.setSize(1000, 600);
this.getContentPane().setBackground(Color.WHITE);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
//按钮面板 对象JPanel 默认是流式布局
JPanel eastPanel = new JPanel();
eastPanel.setBackground(new Color(220,226,248));
eastPanel.setPreferredSize(new Dimension(200,0));
this.add(eastPanel,BorderLayout.EAST);
//图画面板
JPanel drawPanel = new JPanel();
drawPanel.setBackground(Color.WHITE);
drawPanel.setPreferredSize(new Dimension(800,500));
this.add(drawPanel,BorderLayout.CENTER);
mouse.j1=drawPanel;
drawPanel.addMouseListener(mouse);
this.setVisible(true);
Graphics g=drawPanel.getGraphics();
mouse.g = g;
String[] strs={"原图","二值化","灰度","马赛克","放大","缩小","油画","哈哈镜","旋转","加密"};
Color primaryColor = new Color(137, 190, 178);
Color textColor = Color.WHITE;
// 应用颜色方案到按钮
Font buttonFont = new Font("宋体", Font.PLAIN, 16); // 设置按钮字体和字号
for(int i=0;i< strs.length;i++) {
JButton buDraw = new JButton(strs[i]);
buDraw.setPreferredSize(new Dimension(80,30));
buDraw.setBackground(primaryColor);
buDraw.setForeground(textColor);
buDraw.setFont(buttonFont);
buDraw.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
//创建一个空白边框,为按钮的内容留出一些空间,使其看起来更加整洁和美观。
eastPanel.add(buDraw);
buDraw.addActionListener(mouse);
}
JLabel j1 = new JLabel("大小/程度选择:");
j1.setFont(new Font("黑体",1,15));
eastPanel.add(j1);
JMenuBar jmb = new JMenuBar();
JMenu jm = new JMenu();
jm.setText("文件");
jmb.add(jm);
this.setJMenuBar(jmb);
JMenuItem open = new JMenuItem();
open.setText("Open");
jm.add(open);
//按钮键->按钮功能(动作监听器)
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e != null){
JFileChooser jfc =new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
jfc.showDialog(new Label(),"选中");
File file = jfc.getSelectedFile();
fName = file.getPath();
mouse.fn = fName;
}
}
});
//拉杆
JSlider js1 = new JSlider(1,10);
js1.setMajorTickSpacing(1);
js1.setMinorTickSpacing(1);
js1.setPreferredSize(new Dimension(200,80));
js1.setFont (new Font ("黑体",1,15));
js1.setPaintLabels(true);
js1.setPaintTicks(true);
js1.setSnapToTicks(true);
js1.setOpaque(false);
js1.setValue(1);
eastPanel.add(js1);
js1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
g.setColor(Color.WHITE);
g.fillRect(0,100,1000,1000);
if(e != null){
int x =js1.getValue();
mouse.s = x;
}
}
});
}
public void paint(Graphics g) {
super.paint(g);
if (mouse.fn != null){
switch (mouse.str){
case "原图":
mouse.oripic();
break;
case "灰度":
mouse.grey();
break;
case "二值化":
mouse.binarization();
break;
case "马赛克":
mouse.mosaic();
break;
case "放大":
mouse.Todouble();
break;
case "缩小":
mouse.narrow();
break;
case "油画":
mouse.oil();
break;
case"哈哈镜":
mouse.funhouseMirror();
break;
case"旋转":
mouse.spin();
break;
case"加密":
mouse.encrypt();
break;
default:
break;
}
}
}
public static void main(String[] args) {
new ImageBoard().initUI();
}
}
(二) 监听器
package CamaddLSBzyx0722;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;
public class DrawMouse implements ActionListener,MouseListener {
public Graphics g;
private Graphics bg;
private BufferedImage bufferedImage;
public String fn;//= "D:\\JAVAproject\\idea\\BeautyCam\\src\\Cam3zyx0711\\flower.jpg";
public String str;
public JPanel j1=null;
public int s=1 ;
public int a,b;
public void mouseClicked(MouseEvent e){
int x =a= e.getX();
int y =b= e.getY();
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void actionPerformed(ActionEvent e) {
String btnStr = e.getActionCommand();
str = btnStr;
System.out.println("用户点击了" + btnStr+"按钮......");
System.out.println("稍等一会,图片效果马上呈现");
// 使用SwingWorker来执行异步图像处理
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
protected Void doInBackground() {
// 根据按钮选择的效果处理图像
//根据字符串绘制相关图片
switch (btnStr) {
case "原图":
oripic();
break;
case "灰度"://取rgb平均值,则画成灰度图
grey();
break;
case "二值化":
binarization();
break;
case "马赛克":
mosaic();
break;
case"放大":
Todouble();
break;
case"缩小":
narrow();
break;
case"油画":
oil();
break;
case"哈哈镜":
funhouseMirror();
break;
case "旋转":
spin();
break;
case "加密":
encrypt();
break;
}
return null;
}
protected void done() {
// 图像处理完成后的操作,更新UI等
g.drawImage(bufferedImage, 0, 22, j1);
}
};
// 执行SwingWorker中的异步图像处理
worker.execute();
}
//程序的执行过程:代码 > jvm > os > 总线 > 显示器
//创建缓冲区 把所有的像素点显示在缓存去上
public void bufferZone() {
int[][] data = image(fn);
bufferedImage = new BufferedImage( data.length, data[0].length,BufferedImage.TYPE_INT_RGB);
bg = bufferedImage.getGraphics();
bg.setColor(Color.WHITE);
bg.fillRect(0,0,bufferedImage.getWidth(),bufferedImage.getHeight());
}
public void oripic(){
bufferZone();
int[][] data = image(fn);//图片放在项目目录下
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
//得到颜色值,画出每一个点
Color c = new Color(data[i][j]);
bg.setColor(c);//g.setColor(new Color(data[i][j]));
bg.fillOval(i / 2, j /2, 2, 2);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
public void grey(){
bufferZone();
int[][] data = image(fn);
for (int i = 0; i < data.length; i++){
for (int j = 0; j < data[i].length; j++){
Color color = new Color(data[i][j]);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int sum = (red+green+blue)/3;
Color newColor = new Color(sum,sum,sum);
bg.setColor(newColor);
bg.drawOval(i/2,j/2,1,1);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
public void mosaic() {
bufferZone();
int x = s;
int[][] data = image(fn);
for (int i = 0; i < data.length; i += (15+1.6*x)) {
for (int j = 0; j < data[i].length; j += (15+1.6*x)) {
Color color = new Color(data[i][j]);
bg.setColor(color);
bg.fillRect(i / 2, j/ 2, 15, 15);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
public void binarization() {
bufferZone();
int x = s;
int[][] data = image(fn);
int h = data.length;
int w = data[0].length;
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
int p = data[i][j];
Color color = new Color(p);
int blue = color.getBlue();
if (blue >(70+2*x)){
bg.setColor(Color.BLACK);
}else{
bg.setColor(Color.WHITE);
}
bg.drawOval(i/2,j/2,1,1);
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
public void narrow(){
bufferZone();
int x = s;
int[][] data = image(fn);//图片放在项目目录下
int w= data.length;
int h=data[0].length;
for (int i = 0; i < w; i+=2) {
for (int j = 0; j < h; j+=2) {
//得到颜色值,画出每一个点
Color c = new Color(data[i][j]);
bg.setColor(c);//g.setColor(new Color(data[i][j]));
bg.fillRect(i/(2*x) , j/(2*x), x, x);
}
}
g.drawImage(bufferedImage, 0, 22, j1);
}
public void Todouble(){
bufferZone();
int x = s;
int[][] data = image(fn);//图片放在项目目录下
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
//得到颜色值,画出每一个点
Color c = new Color(data[i][j]);
bg.setColor(c);//g.setColor(new Color(data[i][j]));
bg.fillRect(i*(x/2)/2, j *(x/2)/2, x, x);
}
}
g.drawImage(bufferedImage, 0, 22, j1);
}
public void oil(){
bufferZone();
int x = s;
int[][] data = image(fn);
for (int i =0; i < data.length-5; i +=5){
for (int j =0; j < data[i].length-5; j +=5) {
Color color = new Color(data[i][j]);
bg.setColor(color);
Random ran=new Random();
int r1 = ran.nextInt(20)*x+5;
int r2 = ran.nextInt(40)*x+5;
bg.fillOval((i+x)/2, (j+x)/2,Math.max(r1,r2), Math.min(r1,r2));
}
}
//把缓冲区显示在窗体;
g.drawImage(bufferedImage,0,22,j1);
}
public void funhouseMirror() {
bufferZone();
int x = s;
int[][] data = image(fn);
int h=data.length;
int w=data[0].length;
int maxDist = (int) Math.sqrt((w/2 - a) * (w/2 - a) + (h/2 - b) * (h/2 - b));
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
int deltaX = i - b;
int deltaY = j - a;
double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
int newX = (int) (i + deltaX * x * maxDist / distance*0.1);
int newY = (int) (j + deltaY * x * maxDist / distance*0.1);
if (newX >= 0 && newX < data.length && newY >= 0 && newY < data[i].length) {
Color color = new Color(data[newX][newY]);
bg.setColor(color);
bg.drawOval(i/2, j/2, 1, 1);
}
}
}
// 把缓冲区显示在窗体;
g.drawImage(bufferedImage, 0, 22, j1);
}
public void encrypt(){
bufferZone();
int[][] data = image(fn);
System.out.println("请输入所要加入图像里的信息:");
Scanner scanner = new Scanner(System.in);
String messageToEncrypt = scanner.nextLine();
scanner.close();
int messageIndex = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (messageIndex < messageToEncrypt.length()) {
Color color = new Color(data[i][j]);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
char charToHide = messageToEncrypt.charAt(messageIndex);
int asciiValue = (int) charToHide;
// 将ASCII码值存储到蓝色通道的最低2位
blue = (blue & 0xFC) | ((asciiValue >> 6) & 0x03);
Color newColor = new Color(red, green, blue);
bg.setColor(newColor);
bg.drawOval(i / 2, j / 2, 1, 1);
messageIndex++;
} else {
// 如果已经加密完整个信息,则将原图像像素写入缓冲区
Color color = new Color(data[i][j]);
bg.setColor(color);
bg.drawOval(i / 2, j / 2, 1, 1);
}
}
}
// 把缓冲区显示在窗体;
g.drawImage(bufferedImage, 0, 22, j1);
try {
File outputImageFile = new File("encrypted_image.jpg"); // 新文件的路径
ImageIO.write(bufferedImage, "jpg", outputImageFile);
System.out.println("加密后的图像已保存到文件 'encrypted_image.jpg'");
} catch (IOException e) {
System.out.println("保存图像文件时出现错误: " + e.getMessage());
}
}
public void spin(){
bufferZone();
int x = s;
int[][] data = image(fn);
}
//将一张图片转化一个int型的二维数组
private int[][] image(String imageName) {
File file = new File(fn);
BufferedImage bi = null;
try {
bi = ImageIO.read(file); //从文件到图片对象
} catch (Exception e) {
e.printStackTrace();
}
int w = bi.getWidth(); //图片的宽
int h = bi.getHeight(); //图片的高
int[][] imIndex = new int[w][h];//存像素值的二维数组
//System.out.println("w=" + w + " h=" + h );
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
imIndex[i][j] = bi.getRGB(i, j); //i,j 位置的 Color 值,每个像素点的 color 存入数组
}
}
return imIndex;
}
}
四.总结
以上就是一个简单的基于像素的图像滤镜处理,实现了几种常见的滤镜处理方法,每一种处理方法都可以根据实际情况来修改对应颜色数据和输出速度。。首先介绍了Java图像处理的基本知识,包括图像的像素和RGB颜色模式等;然后详细讲解了Java实现图像滤镜处理的步骤,包括读取图像、处理像素、修改像素等;接着介绍了常见的图像滤镜处理算法,包括灰度化、反色、二值化、油画效果、马赛克等,通过代码实现了这些算法;最后介绍了如何将多种滤镜组合起来实现复杂的图像处理效果。对于想要了解Java图像处理的开发者来说是一篇不错的参考资料。