OSDN Git Service

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