java之實現圖片二值化
阿新 • • 發佈:2019-01-28
閒著沒事突然看到一部落格實現的圖片二值化 覺得intresting 就寫了個玩玩,所謂二值化 就是彩色照片變成黑白吧。。
影象的二值化,就是將影象上的畫素點的灰度值設定為0或255,也就是將整個影象呈現出明顯的只有黑和白的視覺效果
具體程式碼實現:
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class ImageTest {
public static void main(String[] args) throws Exception {
//File.separator 而File.separator是系統預設的檔案分割符號,遮蔽了這些系統的區別。
//用File.separator保證了在任何系統下不會出錯。
String filename="D:"+ File.separator+"binaryzation"+File.separator+"wuyanzu.jpg";
File file = new File(filename);
BufferedImage bufferedImage = ImageIO.read(file);
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
int rgb = bufferedImage.getRGB(0,0);
int arr[][] =new int[width][height];//存放圖片每個畫素點的灰度值
//
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
arr[i][j] = getImageRgb(bufferedImage.getRGB(i,j));
}
}
// 構造一個型別為預定義影象型別之一的 BufferedImage,TYPE_BYTE_BINARY(表示一個不透明的以位元組打包的 1、2 或 4 點陣圖像。)
BufferedImage newBufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_BINARY);
int threshold = 130;//閾值 關於閥值,網上有許多演算法,有興趣的朋友可以自己研究下,這裡我隨機給出了一箇中間數130。
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
// 大於閥值則設為黑色,小於則為白色
if (getGray(arr,i,j,width,height)>threshold){
int black = new Color(255,255,255).getRGB();
newBufferedImage.setRGB(i,j,black);
}else {
int white = new Color(0,0,0).getRGB();
newBufferedImage.setRGB(i,j,white);
}
}
}
ImageIO.write(newBufferedImage,"jpg",new File("D:"+File.separator+"binaryzation"+File.separator+"binaryzation-wuyanzu.jpg"));
System.out.println("圖片二值化成功");
//下面這段主要是實現加水印的功能 可忽略
int fontStyle=1;
int fontSize=20;//字型大小
File pressFile =new File("D:/QRCodetest/pressText.txt");
String pressText = ReadFromFile.readFromFile(pressFile);
String newImg="D:"+File.separator+"newPicWithPressText.jpg";
String targetImg="D:"+File.separator+"binaryzation"+File.separator+"binaryzation-wuyanzu.jpg";
QRCodeUtils.pressText(pressText,newImg,targetImg,fontStyle, Color.green,fontSize,width,height);
}
/**
* //自己加周圍8個灰度值再除以9,算出其相對灰度值
* @param gray
* @param x
* @param y
* @param width
* @param height
* @return
*/
private static int getGray(int[][] gray, int x, int y, int width, int height) {
int rs = gray[x][y]
+(x==0 ? 255 : gray[x-1][y])
+(x==0 || y==0 ? 255 : gray[x-1][y-1])
+(x==0 || y==height-1 ? 255 : gray[x-1][y+1])
+(y==0 ? 255 : gray[x][y-1])
+(y==height-1 ? 255 : gray[x][y+1])
+(x==width-1 ? 255 : gray[x+1][y])
+(x==width-1 || y==0 ?255: gray[x+1][y-1])
+(x==width-1 || y==height-1 ? 255 : gray[x+1][y+1]);
return rs/9;
}
/**
* 得到圖片灰度值
* @param rgb
* @return
*/
private static int getImageRgb(int rgb) {
//關於圖片的灰度值,這裡使用簡單的(R+G+B)/3
String argb = Integer.toHexString(rgb);//十進位制轉十六進位制
int r = Integer.parseInt(argb.substring(2,4),16);//16代表16進位制
int g = Integer.parseInt(argb.substring(4,6),16);
int b = Integer.parseInt(argb.substring(6,8),16);
int result = (int)((r+g+b)/3);
return result;
}
}
效果如下:
檔案結構:
原圖:
二值化後:
加水印: