java 图像灰度化与二值化
转载:http://www.chinasb.org/archives/2013/01/5053.shtml
1: package org.chinasb.client;
2:
3: import java.awt.Color;
4: import java.awt.image.BufferedImage;
5: import java.io.File;
6: import java.io.IOException;
7:
8: import javax.imageio.ImageIO;
9:
10: public class BinaryTest {
11:
12: public static void main(String[] args) throws IOException {
13: BufferedImage bufferedImage = ImageIO.read(new File("D:/passCodeAction.jpg"));
14: int h = bufferedImage.getHeight();
15: int w = bufferedImage.getWidth();
16:
17: // 灰度化
18: int[][] gray = new int[w][h];
19: for (int x = 0; x < w; x++) {
20: for (int y = 0; y < h; y++) {
21: int argb = bufferedImage.getRGB(x, y);
22: int r = (argb >> 16) & 0xFF;
23: int g = (argb >> 8) & 0xFF;
24: int b = (argb >> 0) & 0xFF;
25: int grayPixel = (int) ((b * 29 + g * 150 + r * 77 + 128) >> 8);
26: gray[x][y] = grayPixel;
27: }
28: }
29:
30: // 二值化
31: int threshold = ostu(gray, w, h);
32: BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
33: for (int x = 0; x < w; x++) {
34: for (int y = 0; y < h; y++) {
35: if (gray[x][y] > threshold) {
36: gray[x][y] |= 0x00FFFF;
37: } else {
38: gray[x][y] &= 0xFF0000;
39: }
40: binaryBufferedImage.setRGB(x, y, gray[x][y]);
41: }
42: }
43:
44: // 矩阵打印
45: for (int y = 0; y < h; y++) {
46: for (int x = 0; x < w; x++) {
47: if (isBlack(binaryBufferedImage.getRGB(x, y))) {
48: System.out.print("*");
49: } else {
50: System.out.print(" ");
51: }
52: }
53: System.out.println();
54: }
55:
56: ImageIO.write(binaryBufferedImage, "jpg", new File("D:/code.jpg"));
57: }
58:
59: public static boolean isBlack(int colorInt) {
60: Color color = new Color(colorInt);
61: if (color.getRed() + color.getGreen() + color.getBlue() <= 300) {
62: return true;
63: }
64: return false;
65: }
66:
67: public static boolean isWhite(int colorInt) {
68: Color color = new Color(colorInt);
69: if (color.getRed() + color.getGreen() + color.getBlue() > 300) {
70: return true;
71: }
72: return false;
73: }
74:
75: public static int isBlackOrWhite(int colorInt) {
76: if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730) {
77: return 1;
78: }
79: return 0;
80: }
81:
82: public static int getColorBright(int colorInt) {
83: Color color = new Color(colorInt);
84: return color.getRed() + color.getGreen() + color.getBlue();
85: }
86:
87: public static int ostu(int[][] gray, int w, int h) {
88: int[] histData = new int[w * h];
89: // Calculate histogram
90: for (int x = 0; x < w; x++) {
91: for (int y = 0; y < h; y++) {
92: int red = 0xFF & gray[x][y];
93: histData[red]++;
94: }
95: }
96:
97: // Total number of pixels
98: int total = w * h;
99:
100: float sum = 0;
101: for (int t = 0; t < 256; t++)
102: sum += t * histData[t];
103:
104: float sumB = 0;
105: int wB = 0;
106: int wF = 0;
107:
108: float varMax = 0;
109: int threshold = 0;
110:
111: for (int t = 0; t < 256; t++) {
112: wB += histData[t]; // Weight Background
113: if (wB == 0)
114: continue;
115:
116: wF = total - wB; // Weight Foreground
117: if (wF == 0)
118: break;
119:
120: sumB += (float) (t * histData[t]);
121:
122: float mB = sumB / wB; // Mean Background
123: float mF = (sum - sumB) / wF; // Mean Foreground
124:
125: // Calculate Between Class Variance
126: float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
127:
128: // Check if new maximum found
129: if (varBetween > varMax) {
130: varMax = varBetween;
131: threshold = t;
132: }
133: }
134:
135: return threshold;
136: }
137: }
效果