一、图像的基本知识
图像的本质是是宽w*高h个二维数组,即图像=int[w][h]。在w和h位置的 int 值表示颜色,一般包含 RGB 这 3 个字节 ,图像处理本质就是:对代表图像二维数组中的值进行重新计算。
二、从文件中选择要处理的图像
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.showDialog(new JLabel(), "打开");
File file = chooser.getSelectedFile();
String fName = file.getAbsoluteFile().toString();
System.out.println("己选择文件名 is: "+fName);
三、将选中的图像显示
第 1 步 : 用 ImageIO.read(“图片文件名”)方法,从文件读取图片
BufferedImage
bi=
javax.imageio.ImageIO.read(“
图片文件名
”);
第 2 步 :调用 BufferedImage 对象 bi.getRGB(i,j)方法,得到指定位置的像素值。
创建一个跟图片宽、高相同的二维数组存这些值。
第 3 步 :根据需要,对二维数组中的数据,进行变换后,再画到界面上。
(一)将图像转变为二维数组
public int[][] imageArray(String fName){
File file = new File(fName);
BufferedImage bi = null;
try {
bi = ImageIO.read(file); //读取图片文件名
}catch(Exception e) {
e.printStackTrace();
}
int w = bi.getWidth();
int h = bi.getHeight();
int[][] b = new int[w][h]; //创建一个跟图片宽、高相同的二维数组存像素值。
for(int i = 0;i < w;i++) {
for(int j = 0;j < h;j++) {
int cor = bi.getRGB(i, j); //得到指定位置(i,j)的像素值。
b[i][j] = cor; //存入像素值
}
}
return b;
}
(二)遍历二维数组,显示图像
int[][] a = imageArray(fName);
for(int i = 0;i<a.length;i++) {
for(int j = 0;j<a[i].length;j++) {
int v = a[i][j];
Color c = new Color(v);
g.setColor(c); //g为画笔
g.fillOval(i/2, j/2, 2, 2); //将图片画到界面上
}
}
图像缩放:遍历数组时,步长+4,画的时候,即原图的 1/4
反色:将像素值转为负值即可,即Color c = new Color(-v);
反色可实现医院里的拍片效果。
四、图像的一些基本处理方法
图像处理要切记:色即是数,数即是色!
所有的图像处理都是在图片转换后的二维数组上,进行操作
int rr = c.getRed(); //得到red的分量值
int rb = c.getBlue(); //得到blue的分量值
int rg = c.getGreen(); //得到green的分量值
Color c = new Color(rr,rb,rg); //重构颜色
(一)二值法
二值法就是将图片的颜色变成仅有两种颜色
像素值超过某一数字的用 Red,反之用 Black
if(rr>125) { //设值为125
g.setColor(Color.red); //当红色的值大于125时,画笔的颜色为红色
}else {
g.setColor(Color.black); //当红色的值小于125时,画笔的颜色为黑色
}
g.fillOval(i/2, j/2, 2, 2); //在界面上划出图像
由二值法可以以此类推,运用 if - if else - else 的语句创造出三值法、四值法等,也可实现图像黑白化,即像素值超过某一数字的用 Black,反之用 Whrite 。
(二)单通道图像
单通道图像,指仅用 RGB 中某一个值,另两个置 0
c = new Color(rr,0,0);
g.setColor(c);
g.fillOval(i/2, j/2, 2, 2);
(三)马赛克
马赛克就是图片颜色的稀释,常见的马赛克就是将图片划分成包含多余一个像素点的无数个小矩形,将其中1个像素点的RGB信息作为小矩形中所有点的RGB信息
Random ra = new Random(); //随机数
for(int i=0;i<a.length;i=i+20) { //马赛克在遍历过程中需要跳跃,因此是
// i=i+20,20可变化
for(int j = 0;j<a[i].length;j = j+20) {
int r = ra.nextInt(50); //取随机数,马赛克可不是排列整齐的正方形
int v = a[i][j];
Color c = new Color(v);
g.setColor(c);
g.fillRect(i/2,j/2, r,r);
}
}
(四)灰度处理
灰度图像指 RGB 三个分量都相同,一般可取某平均值,以下将取最大值处理。
图像灰度处理即在rr,rg,rb中取得最大值max,并在new Color(r,g,b)中的三个值都设置成max。
int max = ((rr>rb)?((rr>rg)?rr:rg):((rb>rg)?rb:rg));
c = new Color(max,max,max);
g.setColor(c);
g.fillOval(i/2, j/2, 2, 2);
(五)图像叠加
将两张图片按照一定程度虚化,叠加成一种图片
分别取出两张图片的rr、rg、rb,按一定比例相加成新的rr、rg、rb
int [][]b = imageArray(fName1);
for(int i = 0;i<a.length;i++) {
for(int j = 0;j<a[i].length;j++) {
int v = a[i][j];
Color c = new Color(v);
int v1 = b[i][j];
Color c1 = new Color(v1);
int rr = c.getRed();
int rb = c.getBlue();
int rg = c.getGreen();
int rr1 = c1.getRed();
int rb1 = c1.getBlue();
int rg1 = c1.getGreen();
int rr2 = (int)(rr*0.8) + (int)(rr1*0.2); //0.8和0.2代表两张照片的清晰程度,可改变
int rb2 = (int)(rb*0.8) + (int)(rb1*0.2);
int rg2 = (int)(rg*0.8) + (int)(rg1*0.2);
Color c3 = new Color(rr2,rg2,rb2);
System.out.println("ppp");
bufferG.setColor(c3);
bufferG.fillOval(i/2+100, j/2+100, 2, 2);
}
}
五、从图像到视频
这里的视频是指使用电脑的摄像头功能
需要用到第三方包
可到下方链接下载
https://github.com/sarxos/webcam-capture
public void showUI() {
JFrame jf = new JFrame();
jf.setSize(900, 900);
jf.setTitle("视频");
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
FlowLayout flow = new FlowLayout();
jf.setLayout(flow);
jf.setVisible(true);
Graphics g = jf.getGraphics();
Webcam webcam = Webcam.getDefault(); //用到第三方包里的Webcam类
webcam.open();
while(true) {
Image image = webcam.getImage();
g.drawImage(image,100,100,500,300,null);
}
}