实现内容:
- 通过美颜相机,我们可以为图片添加滤镜,以及,对图片进行灰度和二值化,实现对图像的处理
- 为了实现一个具体的功能,我们可以建立一个美颜相机界面,在界面上添加功能按钮,来对图像进行处理
方法:
1.在界面类中,创建一个流式布局,并且添加流式布局以及多个按钮,给所有按钮添加动作监听器
2.在监听器类中,实现动作监听器接口,实现点击按钮,直接绘制图像的功能
3.在图像处理类中,读取图片像素,完成所有的图像功能
一、界面类
注意:在可视化之前加按钮,在可视化之后获取画笔
import javax.swing.*;
import java.awt.*;
public class ImageUI {
//创建监听器对象
ImageListener imgl=new ImageListener();
public void showUI(){//写界面的代码
JFrame jf=new JFrame();
jf.setTitle("图像处理v1.0");
jf.setSize(1200,800);
jf.setLocationRelativeTo(null);//居中显示
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//默认关闭
//设置流式布局
FlowLayout layout=new FlowLayout();
jf.setLayout(layout);
String[] btnTexts={"加载图片","原图","灰度化","二值化","马赛克","圆点马赛克","轮廓化","怀旧","图片融合"};
//创建按钮,用循环
for (int i = 0; i < btnTexts.length; i++) {
JButton btn=new JButton(btnTexts[i]);
btn.setBackground(Color.WHITE);
jf.add(btn);
btn.addActionListener(imgl);//给按钮添加动作监听器
}
//可视化
jf.setVisible(true);
//获取画笔
Graphics g=jf.getGraphics();
//传给监听器imgl中的imageutils 的g imgl.imageUtils.addGraphics(g);
imgl.imageUtils.addGraphics(g);
}
public static void main(String[] args) {//程序启动的入口
ImageUI imageUI=new ImageUI();
imageUI.showUI();
}
}
二、监听器类
使用动作监听器
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ImageListener implements ActionListener {
ImageUtils imageUtils=new ImageUtils();
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("点击了按钮");
//获取文本用于判断调用哪种功能
String opStr=e.getActionCommand();
System.out.println("图像操作:"+opStr);
if(opStr.equals("加载图片")){
imageUtils.getImageArray("C:\\Users\\小绿\\Desktop\\abc.png");
}else if(opStr.equals("原图")){
imageUtils.drawImage(50,100);
}else if(opStr.equals("灰度化")){
imageUtils.gray(600,100);
}else if(opStr.equals("二值化")){
imageUtils.binary(1000,100);
}else if(opStr.equals("马赛克")){
imageUtils.mosaic(50,600);
}else if(opStr.equals("圆点马赛克")) {
imageUtils.roundMasaic(600,600);
}else if(opStr.equals("轮廓化")){
imageUtils.outline(50,500);
} else if (opStr.equals("怀旧")) {
imageUtils.old(1000,600);
}else{
imageUtils.fusion(570,500);
}
}
}
三、图像处理类
完成各种功能
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageUtils {
//存储当前图片像素的二维数组
int[][] imgArray;
Graphics g;
public void addGraphics(Graphics g){
this.g=g;
}
}
1.加载图片:
可以在遍历完像素之后输出一句话,方便观察是否有问题
//获取图片的数组
public void getImageArray(String path){
File file=new File(path);
try{
BufferedImage img= ImageIO.read(file);//读取图片
//将图片的像素存入数组中
int w=img.getWidth();
int h=img.getHeight();
//根据宽高 创建数组
imgArray=new int[w][h];
//遍历图片获取像素,存入数组中
for (int i = 0; i <w ; i++) {
for (int j = 0; j <h; j++) {
imgArray[i][j]=img.getRGB(i,j);
}
}
System.out.println("加载完成");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
2.原图:
public void drawImage(int x,int y){
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
g.setColor(color);
g.fillRect(i+x,j+y,1,1);
}
}
}
3.灰度化:
颜色中取出红绿蓝,并求平均值
public void gray(int x,int y){
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();
int gray=(red+green+blue)/3;
//用灰度值创建一个新的颜色
Color graycolor =new Color(gray,gray,gray);
g.setColor(graycolor);
g.fillRect(i+x,j+y,1,1);
}
}
}
4.二值化:
在灰度值的基础上,做判断,如果灰度值小于某个数,则画成黑色,大于某个数时,则画成白色
public void binary(int x,int y){
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();
int gray=(red+green+blue)/3;
//根据灰度值判断哪
if(gray<70){
g.setColor(Color.BLACK);
}else{
g.setColor(Color.WHITE);
}
g.fillRect(i+x,j+y,1,1);
}
}
}
5.马赛克,圆点马赛克:
只需改变遍历数组之间的间距,绘制的间距
public void mosaic(int x,int y){//马赛克
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j+=10) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
g.setColor(color);
g.fillRect(i+x,j+y,10,10);
}
}
}
public void roundMasaic(int x,int y){//圆点马赛克
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j+=10) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
g.setColor(color);
g.fillOval(i+x,j+y,10,10);
}
}
}
6.怀旧:如果想让蓝色少一点,最好使用除法,避免减法减到负数;
如果要让红色和绿色多一点,应该做一个判断,避免加法过后超出255
red=color.getRed();
green=color.getGreen();
red+=20;
if(red>255){
red=255;
}
if(green>255){
green=255;
}
Color color1=new Color(red,green,blue/3);
g.setColor(color1);
g.fillRect(i+x,j+y,1,1);
7.轮廓化:通过比较两个像素之间的灰度值,如果超过某一限度,则判定为边框,画出黑色的线条
如果想要画出来的线条更多,则应该在判断时减小两个之间的差值
public void outline(int x,int y){
int w= imgArray.length;
int h= imgArray[0].length;
for (int i = 0; i < w-2; i++) {
for (int j = 0; j < h-2; j++) {
int pixNum=imgArray[i][j];//获取像素值
Color color=new Color(pixNum);
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();
int gray=(red+green+blue)/3;
int otPixNum=imgArray[i+2][j+2];
Color otcolor =new Color(otPixNum);
int otred=otcolor.getRed();
int otgreen=otcolor.getGreen();
int otblue= otcolor.getBlue();
int otgray=(otred+otgreen+otblue)/3;
if(Math.abs(gray=otgray)>=20){
g.setColor(Color.BLACK);
}else{
g.setColor(Color.WHITE);
}
if(gray<70){
g.setColor(Color.BLACK);
}else{
g.setColor(Color.WHITE);
}
g.fillRect(i+x,j+y,1,1);
}
}
}
8.图片融合:再创建一个像素数组,存另一张照片;
在绘制时取两张照片最小的宽和高,取出各自图片的颜色后,合成一个新的颜色(两数相加除以2);