图像处理方法java(一)
目录
1.引言
初学java,想做一个简易的美颜相机,对图像处理的一些方法进行了相应的学习。主要包括图像的原理、图像的数据处理、位运算、滤镜效果、图片读写等。
2.基本原理
2.1图像的基本原理
每一张图像,其实都是由一个个的带有颜色的点组成的矩阵,也就是我们常说的像素点矩阵,同时横纵坐标像素点的个数乘积就是图像的分辨率。
每一个像素点的颜色,都是有相应的编号的,一般的存储格式是RGB和ARGB格式。RGB格式:RGB其实就是三原色,Red、Green、Blue,每一种原色的编号范围是0-255,也就是存储在一个字节(8位2进制)中。Red从0到255颜色会越来越“红”,红的程度会加深。
举个例子来说,对于RGB: 123, 200,13 来说,这个颜色是由Red123,Green200,Blue13这三种颜色合成的。
所以我们很容易知道,RGB是占三个字节,可以存储在整型变量(四个字节)中,并且存储在低24位,那么就会出现高8位没有使用的情况。ARGB格式就是把高8位也利用起来,用来存其他的信息例如照片拍摄日期等等。
2.2图像数据的处理
初始化生成一个窗体,然后通过随机数随机生成一张RGB格式的图片。通过位移运算计算RGB格式里red、green、blue的值(位移运算在2.3会讲解)。对于滤镜等操作,就可以通过调节red、green、blue的值来实现,比如说red=red/2,就能实现图片红色降度,也就是照片的红色不会太鲜艳。
我们常常也会听说灰度图片,就是照片会变成灰色,这种照片的每一个像素点的RGB值均满足red=green=blue,我们可以调整三原色的占比来确定灰阶(详见代码)。
二维码:有了灰阶,也就是对每一个像素值都有唯一标准了。我们可以确定一个分界值a,当算出的灰度值大于a,就用白色来表示;若小于a,就用黑色来表示,并且使用fiilRect方法的时候,把像素点的宽和高调大一点,我们就可以得到这张图片的二维码了,也就是说,这个二维码储存了我这张图片的数据。
import javax.swing.*;
import java.awt.*;
import java.util.Random;
import javax.swing.JFrame;
public class ImageUI extends JFrame {
//初始化一个窗体
public void initUI(){
setTitle("图像编程");
setSize(1000,1000);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
/*
* 窗体出现在屏幕上时调用
* 绘制窗体本身
* 在窗体上绘制像素点
* @param g :图形对象 可以来绘制图形
* Graphics 图形
* g.fillRect(x,y,w,h);
*/
public void paint(Graphics g){
super.paint(g);
//g.fillRect(100,100,10,10);
int[][] imgarr=new int[300][300];
// 随机创建颜色矩阵
Random random = new Random();
for (int i = 0; i < 300; i++) {
for (int j = 0; j < 300; j++) {
int colorValue = random.nextInt(256*256*256);
imgarr[i][j]=colorValue;
Color color = new Color(colorValue);
g.setColor(color);
g.fillRect(50+i,50+j,1,1);
}
}
for (int i = 0; i <imgarr.length; i+=10) {
for (int j = 0; j < imgarr[i].length; j+=10) {
int value = imgarr[i][j];
int red =(value>>16)&0xFF;
int green =(value>>8)&0xFF;
int blue =(value>>0)&0xFF;
// 灰度 r=g=b
// 有了灰阶 一张照片所有的像素值都具有同样的标准了
int gray =(int)(red*0.36+green*0.29+blue*0.35);
if(gray>128){
g.setColor(Color.white);
}
else{
g.setColor(Color.black);
}
g.fillRect(400+i,50+j,10,10);
}
}
}
// 启动程序
public static void main(String[] args) {
ImageUI img = new ImageUI();
img.initUI();
}
}
运行图片
2.3位运算
这里主要讲如何通过存储RGB的整型int得到red、green、blue的值;以及red、green、blue如何合成为一个int。
我们了解了RGB的存储原理,很容易知道:17-24位存red,9-16位存green,1-8位存blue,用除法和减法可以提取出red、green、blue,但是这样运算速度会慢一些,可以用位移运算,运算速度会快一些。
假设RGB的值存储在int value中,通过位移运算有:
int red =(value>>16)&0xFF;
int green =(value>>8)&0xFF;
int blue =(value>>0)&0xFF;
为什么要位移之后与0xFF求与运算呢? 仔细分析后,我们知道,与0xFF做与运算后,可以将除低8位以外的所有位的数字变为0。
所以我们以此类推,我们发现把red、green、blue合成一个RGB时,可以通过位移加上或运算来实现:
int rgb= (red<<16)|(green<<8)|blue;
3.图片读写与滤镜效果
3.1图片读写