OSDN Git Service

[更新]NyARToolkit
[nyartoolkit-and/nyartoolkit-and.git] / src / jp / nyatla / nyartoolkit / core2 / rasteranalyzer / threshold / NyARRasterThresholdAnalyzer_SlidePTile.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 /**\r
41  * 明点と暗点をPタイル法で検出して、その中央値を閾値とする。\r
42  * \r
43  * \r
44  */\r
45 public class NyARRasterThresholdAnalyzer_SlidePTile implements INyARRasterThresholdAnalyzer\r
46 {\r
47         private int _persentage;\r
48 \r
49         private int _threshold;\r
50 \r
51         /**\r
52          * @param i_persentage\r
53          * 0<=50であること。白/黒マーカーの場合は10~20を推奨 正の場合、黒点を基準にします。 負の場合、白点を基準にします。\r
54          * (CMOSカメラの場合、基準点は白点の方が良い)\r
55          */\r
56         public NyARRasterThresholdAnalyzer_SlidePTile(int i_persentage)\r
57         {\r
58                 assert (0 <= i_persentage && i_persentage <= 50);\r
59                 this._persentage = i_persentage;\r
60         }\r
61 \r
62         private int createHistgram(INyARBufferReader i_reader,NyARIntSize i_size, int[] o_histgram) throws NyARException\r
63         {\r
64                 int[] in_buf = (int[]) i_reader.getBuffer();\r
65                 int[] histgram = o_histgram;\r
66 \r
67                 // ヒストグラムを作成\r
68                 for (int i = 0; i < 256; i++) {\r
69                         histgram[i] = 0;\r
70                 }\r
71                 int sum = 0;\r
72                 for (int y = 0; y < i_size.h; y++) {\r
73                         int sum2 = 0;\r
74                         for (int x = 0; x < i_size.w; x++) {\r
75                                 int v = in_buf[y* i_size.w+x];\r
76                                 histgram[v]++;\r
77                                 sum2 += v;\r
78                         }\r
79                         sum = sum + sum2 / i_size.w;\r
80                 }\r
81                 // 閾値ピクセル数確定\r
82                 int th_pixcels = i_size.w * i_size.h * this._persentage / 100;\r
83                 int th_wk;\r
84                 int th_w, th_b;\r
85 \r
86                 // 黒点基準\r
87                 th_wk = th_pixcels;\r
88                 for (th_b = 0; th_b < 254; th_b++) {\r
89                         th_wk -= histgram[th_b];\r
90                         if (th_wk <= 0) {\r
91                                 break;\r
92                         }\r
93                 }\r
94                 // 白点基準\r
95                 th_wk = th_pixcels;\r
96                 for (th_w = 255; th_w > 1; th_w--) {\r
97                         th_wk -= histgram[th_w];\r
98                         if (th_wk <= 0) {\r
99                                 break;\r
100                         }\r
101                 }\r
102                 // 閾値の保存\r
103                 return (th_w + th_b) / 2;\r
104         }\r
105 \r
106         public void analyzeRaster(INyARRaster i_input) throws NyARException\r
107         {\r
108                 final INyARBufferReader buffer_reader=i_input.getBufferReader();        \r
109                 assert (buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GLAY_8));\r
110 \r
111                 int[] histgram = new int[256];\r
112                 // 閾値の基準値を出す。\r
113                 this._threshold = createHistgram(buffer_reader,i_input.getSize(), histgram);\r
114                 return;\r
115         }\r
116 \r
117         /**\r
118          * ヒストグラムをラスタに書き出す。\r
119          * \r
120          * @param i_output\r
121          */\r
122         public void debugDrawHistgramMap(INyARRaster i_input, INyARRaster i_output) throws NyARException\r
123         {\r
124                 INyARBufferReader in_buffer_reader=i_input.getBufferReader();   \r
125                 INyARBufferReader out_buffer_reader=i_output.getBufferReader(); \r
126                 assert (in_buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GLAY_8));\r
127                 assert (out_buffer_reader.isEqualBufferType(INyARBufferReader.BUFFERFORMAT_INT1D_GLAY_8));\r
128 \r
129                 NyARIntSize size = i_output.getSize();\r
130 \r
131                 int[] out_buf = (int[]) out_buffer_reader.getBuffer();\r
132                 // 0で塗りつぶし\r
133                 for (int y = 0; y < size.h; y++) {\r
134                         for (int x = 0; x < size.w; x++) {\r
135                                 out_buf[y* size.w+x] = 0;\r
136                         }\r
137                 }\r
138                 // ヒストグラムを計算\r
139                 int[] histgram = new int[256];\r
140                 int threshold = createHistgram(in_buffer_reader,i_input.getSize(), histgram);\r
141                 for (int i = 255; i > 0; i--) {\r
142                         histgram[i] = Math.abs(histgram[i]);\r
143                 }\r
144 \r
145                 // ヒストグラムの最大値を出す\r
146                 int max_v = 0;\r
147                 for (int i = 0; i < 255; i++) {\r
148                         if (max_v < histgram[i]) {\r
149                                 max_v = histgram[i];\r
150                         }\r
151                 }\r
152                 // 目盛り\r
153                 for (int i = 0; i < size.h; i++) {\r
154                         out_buf[i* size.w+0] = 128;\r
155                         out_buf[i* size.w+128] = 128;\r
156                         out_buf[i* size.w+255] = 128;\r
157                 }\r
158                 // スケーリングしながら描画\r
159                 for (int i = 0; i < 255; i++) {\r
160                         out_buf[(histgram[i] * (size.h - 1) / max_v)* size.w+i] = 255;\r
161                 }\r
162                 // 値\r
163                 for (int i = 0; i < size.h; i++) {\r
164                         out_buf[i* size.w+threshold] = 255;\r
165                 }\r
166                 return;\r
167         }\r
168 \r
169         public int getThreshold()\r
170         {\r
171                 return this._threshold;\r
172         }\r
173 \r
174         public int getThreshold(int i_x, int i_y)\r
175         {\r
176                 return this._threshold;\r
177         }\r
178 }\r