OSDN Git Service

5f563bb6188a0393d106b62c81ab9aa724783ace
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core2 / rasteranalyzer / threshold / NyARRasterThresholdAnalyzer_PTile.java
1 /* \r
2  * PROJECT: NyARToolkit(Extension)\r
3  * --------------------------------------------------------------------------------\r
4  * The NyARToolkit is Java edition ARToolKit class library.\r
5  * Copyright (C)2008-2009 Ryo Iizuka\r
6  *\r
7  * This program is free software: you can redistribute it and/or modify\r
8  * it under the terms of the GNU General Public License as published by\r
9  * the Free Software Foundation, either version 3 of the License, or\r
10  * (at your option) any later version.\r
11  * \r
12  * This program is distributed in the hope that it will be useful,\r
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15  * GNU General Public License for more details.\r
16  *\r
17  * You should have received a copy of the GNU General Public License\r
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
19  * \r
20  * For further information please contact.\r
21  *      http://nyatla.jp/nyatoolkit/\r
22  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
23  * \r
24  */\r
25 package jp.nyatla.nyartoolkit.core2.rasteranalyzer.threshold;\r
26 \r
27 import jp.nyatla.nyartoolkit.NyARException;\r
28 import jp.nyatla.nyartoolkit.core.raster.*;\r
29 import jp.nyatla.nyartoolkit.core.rasterreader.INyARBufferReader;\r
30 import jp.nyatla.nyartoolkit.core.types.*;\r
31 \r
32 /**\r
33  * Pタイル法による閾値検出\r
34  * \r
35  */\r
36 public class NyARRasterThresholdAnalyzer_PTile implements INyARRasterThresholdAnalyzer\r
37 {\r
38         private int _persentage;\r
39 \r
40         private int _threshold;\r
41 \r
42         /**\r
43          * @param i_persentage\r
44          * -100<=0<=100であること。 正の場合、黒点を基準にします。 負の場合、白点を基準にします。\r
45          * (CMOSカメラの場合、基準点は白点の方が良い)\r
46          */\r
47         public NyARRasterThresholdAnalyzer_PTile(int i_persentage)\r
48         {\r
49                 assert (-100 <= i_persentage && i_persentage <= 100);\r
50                 this._persentage = i_persentage;\r
51         }\r
52 \r
53         private int createHistgram(INyARBufferReader i_reader,NyARIntSize i_size, int[] o_histgram) throws NyARException\r
54         {\r
55                 int[] in_buf = (int[]) i_reader.getBuffer();\r
56                 int[] histgram = o_histgram;\r
57 \r
58                 // ヒストグラムを作成\r
59                 for (int i = 0; i < 256; i++) {\r
60                         histgram[i] = 0;\r
61                 }\r
62                 int sum = 0;\r
63                 for (int y = 0; y < i_size.h; y++) {\r
64                         int sum2 = 0;\r
65                         for (int x = 0; x < i_size.w; x++) {\r
66                                 int v = in_buf[y* i_size.w+x];\r
67                                 histgram[v]++;\r
68                                 sum2 += v;\r
69                         }\r
70                         sum = sum + sum2 / i_size.w;\r
71                 }\r
72                 // 閾値ピクセル数確定\r
73                 int th_pixcels = i_size.w * i_size.h * this._persentage / 100;\r
74 \r
75                 // 閾値判定\r
76                 int i;\r
77                 if (th_pixcels > 0) {\r
78                         // 黒点基準\r
79                         for (i = 0; i < 254; i++) {\r
80                                 th_pixcels -= histgram[i];\r
81                                 if (th_pixcels <= 0) {\r
82                                         break;\r
83                                 }\r
84                         }\r
85                 } else {\r
86                         // 白点基準\r
87                         for (i = 255; i > 1; i--) {\r
88                                 th_pixcels += histgram[i];\r
89                                 if (th_pixcels >= 0) {\r
90                                         break;\r
91                                 }\r
92                         }\r
93                 }\r
94                 // 閾値の保存\r
95                 return i;\r
96         }\r
97 \r
98         public void analyzeRaster(INyARRaster i_input) throws NyARException\r
99         {\r
100                 final INyARBufferReader buffer_reader=i_input.getBufferReader();        \r
101                 assert (buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GRAY_8));\r
102                 int[] histgram = new int[256];\r
103                 this._threshold = createHistgram(buffer_reader,i_input.getSize(), histgram);\r
104         }\r
105 \r
106         /**\r
107          * デバック用の関数です。 ヒストグラムをラスタに書き出します。\r
108          * \r
109          * @param i_output\r
110          * 書き出し先のラスタオブジェクト 256ピクセル以上の幅があること。\r
111          */\r
112         public void debugDrawHistgramMap(INyARRaster i_input, INyARRaster i_output) throws NyARException\r
113         {\r
114                 INyARBufferReader in_buffer_reader=i_input.getBufferReader();   \r
115                 INyARBufferReader out_buffer_reader=i_output.getBufferReader(); \r
116                 assert (in_buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GRAY_8));\r
117                 assert (out_buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GRAY_8));\r
118                 NyARIntSize size = i_output.getSize();\r
119 \r
120                 int[] out_buf = (int[]) out_buffer_reader.getBuffer();\r
121                 // 0で塗りつぶし\r
122                 for (int y = 0; y < size.h; y++) {\r
123                         for (int x = 0; x < size.w; x++) {\r
124                                 out_buf[y* size.w+x] = 0;\r
125                         }\r
126                 }\r
127                 // ヒストグラムを計算\r
128                 int[] histgram = new int[256];\r
129                 int threshold = createHistgram(in_buffer_reader,i_input.getSize(), histgram);\r
130 \r
131                 // ヒストグラムの最大値を出す\r
132                 int max_v = 0;\r
133                 for (int i = 0; i < 255; i++) {\r
134                         if (max_v < histgram[i]) {\r
135                                 max_v = histgram[i];\r
136                         }\r
137                 }\r
138                 // 目盛り\r
139                 for (int i = 0; i < size.h; i++) {\r
140                         out_buf[i* size.w+0] = 128;\r
141                         out_buf[i* size.w+128] = 128;\r
142                         out_buf[i* size.w+255] = 128;\r
143                 }\r
144                 // スケーリングしながら描画\r
145                 for (int i = 0; i < 255; i++) {\r
146                         out_buf[(histgram[i] * (size.h - 1) / max_v)* size.w+i] = 255;\r
147                 }\r
148                 // 値\r
149                 for (int i = 0; i < size.h; i++) {\r
150                         out_buf[i* size.w+threshold] = 255;\r
151                 }\r
152                 return;\r
153         }\r
154 \r
155         public int getThreshold()\r
156         {\r
157                 return this._threshold;\r
158         }\r
159 }\r