基於Java對圖片進行二值化處理


一直以來對Java的圖形處理能力表無力,但好像又不是那么一回事,之前用PHP做過一些應用,涉及到驗證碼的識別,其中有個圖片二值化的步驟,今天換成Java來實現下

在java的擴展包javax.imageio中為我們提供了一個類叫ImageIO,這個類提供了一些執行簡單編碼和解碼的靜態便捷方法,具體說明大家可以翻下API看看

 

下面來說下關於圖片二值化的原理:

1、首先要獲取每個像素點的灰度值。

2、定義一個閥值。

3、將每個像素點的灰度值和它周圍的8個像素點的灰度值相疊加再除以9,然后和閥值進行比較。

4、大於閥值則設為黑色,小雨則為白色。

 

下面貼下具體代碼,注釋很全

  • separator是File類的一個常量,因年代久遠的關系,那時候的代碼規范沒有和現在一樣,常量必須大寫,屬於歷史遺留問題,不必太糾結(建議使用separator而不是"/",便於跨平台) 。
  • BufferedImage里的getRGB得到的是一個ARGB,A代表透明,R代表紅色,G代表綠色,B代表藍色。
  • 包裝類Integer里的parseInt方法,第二個可選參數為"要處理幾進制的數"。
  • 關於閥值,網上有許多算法,有興趣的朋友可以自己研究下,這里我隨機給出了一個中間數130。
  • 關於圖片的灰度值,這里使用簡單的(R+G+B)/3。
 1 import java.awt.Color;
 2 import java.awt.image.BufferedImage;
 3 import java.io.File;
 4 import java.io.IOException;
 5 
 6 import javax.imageio.ImageIO;
 7 
 8 public class ImageTest {
 9 
10     public static void main(String[] args) throws IOException {
11         String filename = "D:" + File.separator + "/123.jpg";// separator是File里的一個常量,由於java歷史遺留問題故為小寫
12         File file = new File(filename);
13         BufferedImage bi = ImageIO.read(file);
14         // 獲取當前圖片的高,寬,ARGB
15         int h = bi.getHeight();
16         int w = bi.getWidth();
17         int rgb = bi.getRGB(0, 0);
18         int arr[][] = new int[w][h];
19 
20         // 獲取圖片每一像素點的灰度值
21         for (int i = 0; i < w; i++) {
22             for (int j = 0; j < h; j++) {
23                 // getRGB()返回默認的RGB顏色模型(十進制)
24                 arr[i][j] = getImageRgb(bi.getRGB(i, j));//該點的灰度值
25             }
26 
27         }
28         
29         BufferedImage bufferedImage=new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);//  構造一個類型為預定義圖像類型之一的 BufferedImage,TYPE_BYTE_BINARY(表示一個不透明的以字節打包的 1、2 或 4 位圖像。)
30         int FZ=130;
31         for (int i = 0; i < w; i++) {
32             for (int j = 0; j < h; j++) {
33                 if(getGray(arr,i,j,w,h)>FZ){
34                     int black=new Color(255,255,255).getRGB();
35                     bufferedImage.setRGB(i, j, black);
36                 }else{
37                     int white=new Color(0,0,0).getRGB();
38                     bufferedImage.setRGB(i, j, white);
39                 }
40             }
41             
42         }
43          ImageIO.write(bufferedImage, "jpg", new File("D:"+File.separator+"new123.jpg"));
44     }
45 
46     private static int getImageRgb(int i) {
47         String argb = Integer.toHexString(i);// 將十進制的顏色值轉為十六進制
48         // argb分別代表透明,紅,綠,藍 分別占16進制2位
49         int r = Integer.parseInt(argb.substring(2, 4),16);//后面參數為使用進制
50         int g = Integer.parseInt(argb.substring(4, 6),16);
51         int b = Integer.parseInt(argb.substring(6, 8),16);
52         int result=(int)((r+g+b)/3);
53         return result;
54     }
55     
56     
57     
58     //自己加周圍8個灰度值再除以9,算出其相對灰度值 
59      public static int  getGray(int gray[][], int x, int y, int w, int h)  
60         {  
61             int rs = gray[x][y]  
62                             + (x == 0 ? 255 : gray[x - 1][y])  
63                             + (x == 0 || y == 0 ? 255 : gray[x - 1][y - 1])  
64                             + (x == 0 || y == h - 1 ? 255 : gray[x - 1][y + 1])  
65                             + (y == 0 ? 255 : gray[x][y - 1])  
66                             + (y == h - 1 ? 255 : gray[x][y + 1])  
67                             + (x == w - 1 ? 255 : gray[x + 1][ y])  
68                             + (x == w - 1 || y == 0 ? 255 : gray[x + 1][y - 1])  
69                             + (x == w - 1 || y == h - 1 ? 255 : gray[x + 1][y + 1]);  
70             return rs / 9;  
71         }  
72 }

看下效果吧:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM