打开一个图片文件
BufferedImage bi_src = ImageIO.read(new File(filepath_image + System.getProperty("file.separator") + filename_image));
filepath_image 图片文件路径
filename_image 图片文件名
System.getProperty("file.separator") 取系统分隔符
保存图片文件
ImageIO.write(bi, "jpg", new File(new File(filepath_image + System.getProperty("file.separator") + filename_image)));
创建一个图片内存文件
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
width 图片文件的宽
height 图片文件的高
BufferedImage.TYPE_3BYTE_BGR 参数类型,详情请查询说明
获取和赋值给像数点操作
像数点的颜色数值为ARGB 4个分量,可以利用位移操作取得对应的数值,详见下面例子
如下例子给出遍历所有的像素点将图片转换为灰度数组.
int w = bi.getWidth(); //取得图片的宽
int h = bi.getHeight(); //取得图片的高
int[][] result = new int[w][h]; //结果数组
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int rgb = bi.getRGB(i, j); //获取像数点的颜色数据
int r = ((rgb >> 16) & 0xFF); // 红色通道数据
int g = ((rgb >> 8) & 0xFF); //绿色通道数据
int b = ((rgb >> 0) & 0xFF); // 蓝色通道数据
result[i][j] = (int) ((b * 29 + g * 150 + r * 77) >> 8);
// 按照人们接受的数据参数转换为灰度数值
}
}
也可以直接将颜色转换为数值,BLUE颜色根据自己的需要设定
int data = Color.BLUE.getRGB()
将ARGB的设定数值转换为颜色数据,反向操作取颜色的过程
int data= 0;
data+= alpha;
data= newPixel << 8;
data+= red;
data= newPixel << 8;
data+= green;
data= newPixel << 8;
data+= blue;
return data;
图像Loading操作
我们常见的彩色图,灰度图,二值化图。可以图像知识进行转换处理。
下面给出实例:
public static void open_image() {
try {
//设置Mointor区域的数值
monitor_bar.setPicture_path(filepath_image);
monitor_bar.setPicture_name(filename_image);
//打开需要打开的文件,获取彩色的图像
BufferedImage bi_src = ImageIO.read(new File(filepath_image + System.getProperty("file.separator") + filename_image));
//利用函数工具进行灰度转换
bi_gray=ImageTool.ThreeColorToGray(bi_src); //函数Code见下面
//利用函数将灰度图转换为二值化图 函数Code见下面
BufferedImage bi_binary = ImageTool.GrayArrayToBinaryArray(bi_gray, "OSTU",255,0);
//设置Mointor区域的数值
monitor_bar.setOrg_width(bi_src.getWidth());
monitor_bar.setOrg_height(bi_src.getHeight());
//记录操作记录
operation_record.tf.insert(
"Select file Name : " + filepath_image + System.getProperty("file.separator") + filename_image, 0);
//显示在客户端上
reload_image(bi_src);
//显示导航小图片
load_thumbnail();
} catch (IOException e) {
e.printStackTrace();
System.out.println("打开图片发生错误!");
}
}
彩色图像转换为灰度图
public static BufferedImage ThreeColorToGray(BufferedImage bi) {
if (bi == null) {
return null;
}
int w = bi.getWidth();
int h = bi.getHeight();
BufferedImage result = new BufferedImage(w,h,BufferedImage.TYPE_BYTE_GRAY);
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int rgb = bi.getRGB(i, j);
int r = ((rgb >> 16) & 0xFF);
int g = ((rgb >> 8) & 0xFF);
int b = ((rgb >> 0) & 0xFF);
int gray_value = (int) ((b * 29 + g * 150 + r * 77) >> 8);
//给灰度图赋值
result.setRGB(i, j, new Color(gray_value,gray_value,gray_value).getRGB());
}
}
return result;
}
灰度图转为二值化图
public static BufferedImage GrayArrayToBinaryArray(BufferedImage bi, String Threshold_Type,int max,int min) {
if (bi == null) {
return null;
}
int[][] gray=GrayToArray(bi); //Code参见 下面
int white=new Color(255,255,255).getRGB(); //取得 白色的数值
int black=new Color(0,0,0).getRGB(); //取得黑色的数值
int width = gray.length; //图像的宽
int height = gray[0].length; //图像的长
int low_limit=0; //双值法的下限值
int[] HistGram = new int[256];
int threshold = 0; // 阀值 ,二值图好坏的重要参数
//根据 客户端 设置不同的参数类型调用相应的threshold方法
//共有5种方法
if (Threshold_Type.toUpperCase().equals("OSTU")) {
threshold = ostu(gray, width, height); //Code参见 下面
} else if (Threshold_Type.toUpperCase().equals("GETMINIMUM")) {
HistGram = getHistGram(gray); //Code参见 下面
threshold = GetMinimum(HistGram); //Code参见 下面
} else if(Threshold_Type.toUpperCase().equals("AVG")){
//取平均值方法
HistGram = getHistGram(gray);
int sum = 0;
for (int i = 0; i < HistGram.length; i++) {
sum = sum + i * HistGram[i];
}
threshold = sum / width / height;
} else if(Threshold_Type.toUpperCase().equals("MAX_MIN")){
//人工设置上下限值
threshold=max;
low_limit=min;
}else if(Threshold_Type.toUpperCase().equals("FIX")){
// 人工设置固定值
threshold=max;
}else{
return bi;
}
BufferedImage binary_bi=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_BINARY);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (gray[x][y] > threshold|gray[x][y]<low_limit) {
//设置像数点为白色
binary_bi.setRGB(x, y, white);
} else {
//设置像数点为黑色
binary_bi.setRGB(x, y, black);
}
}
}
return binary_bi;
}
//这种算法假设一副图像由前景色和背景色组成,通过统计学的方法来选取一个阈值,使得这个阈值可以将前景色和背景色尽可能的分开
public static int ostu(int[][] gray, int w, int h) {
int[] histData = new int[w * h];
// Calculate histogram
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int red = 0xFF & gray[x][y];
histData[red]++;
}
}
// Total number of pixels
int total = w * h;
float sum = 0;
for (int t = 0; t < 256; t++)
sum += t * histData[t];
float sumB = 0;
int wB = 0;
int wF = 0;
float varMax = 0;
int threshold = 0;
for (int t = 0; t < 256; t++) {
wB += histData[t]; // Weight Background
if (wB == 0)
continue;
wF = total - wB; // Weight Foreground
if (wF == 0)
break;
sumB += (float) (t * histData[t]);
float mB = sumB / wB; // Mean Background
float mF = (sum - sumB) / wF; // Mean Foreground
// Calculate Between Class Variance
float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
// Check if new maximum found
if (varBetween > varMax) {
varMax = varBetween;
threshold = t;
}
}
return threshold;
}
//取得灰度值方图
public static int[] getHistGram(int[][] gray) {
int[] histgram = new int[256];
int w = gray.length;
int h = gray[0].length;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
histgram[gray[i][j]]++;
}
}
return histgram;
}
// 双峰法 取得 阀值 ,灰度直方图中 前后元素差异 前后的灰度存在差异
public static int GetMinimum(int[] HistGram) {
int iter = 0;
double[] HistGramC = new double[256];
double[] HistGramCC = new double[256];
for (int y = 0; y < 256; y++) {
HistGramC[y] = HistGram[y];
HistGramCC[y] = HistGram[y];
}
while (IsDimodal(HistGramCC) == false) {
HistGramCC[0] = (HistGramC[0] + HistGramC[0] + HistGramC[1]) / 3;
for (int i = 1; i < 255; i++) {
HistGramCC[i] = (HistGramC[i - 1] + HistGramC[i] + HistGramC[i + 1]) / 3;
}
HistGramCC[255] = (HistGramC[254] + HistGramC[255] + HistGramC[255]) / 3;
for (int i = 0; i < 256; i++) {
HistGramC[i] = HistGramCC[i];
}
iter++;
if (iter >= 500)
return -1;
}
boolean peakfound = false;
for (int j = 1; j < 255; j++) {
if (HistGramCC[j - 1] < HistGramCC[j] && HistGramCC[j + 1] < HistGramCC[j]) {
peakfound = true;
}
if (peakfound == true && HistGramCC[j - 1] >= HistGramCC[j] && HistGramCC[j + 1] >= HistGramCC[j]) {
return j - 1;
}
}
return -1;
}
private static boolean IsDimodal(double[] HistGram) {
int count = 0;
for (int y = 1; y < 255; y++) {
if (HistGram[y - 1] < HistGram[y] && HistGram[y + 1] < HistGram[y]) {
count++;
if (count > 2) {
return false;
}
}
}
if (count == 2) {
return true;
} else {
return false;
}
}
效果图如下:
//也可以利用JAVA提供的工具进行灰度转换
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
BufferedImage bi_gray = op.filter(bi_src, null);