OSDN Git Service

[backup]NyARToolkit
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core / analyzer / histgram / NyARHistgramAnalyzer_DiscriminantThreshold.java
1 package jp.nyatla.nyartoolkit.core.analyzer.histgram;\r
2 \r
3 import jp.nyatla.nyartoolkit.core.types.NyARHistgram;\r
4 \r
5 /**\r
6  * 判別法で閾値を求めます。\r
7  * 画素数が2048^2に満たない場合は、fixedint(24-8)で計算できます。\r
8  * @param i_histgram\r
9  * @param o_value\r
10  * @return\r
11  */\r
12 public class NyARHistgramAnalyzer_DiscriminantThreshold implements INyARHistgramAnalyzer_Threshold\r
13 {\r
14         private double _score;\r
15 \r
16 \r
17         public int getThreshold(NyARHistgram i_histgram)\r
18         {\r
19                 int[] hist=i_histgram.data;\r
20                 int n=i_histgram.length;\r
21                 int da,sa,db,sb,dt,pt,st;\r
22                 int i;          \r
23                 int th=0;\r
24                 //後で使う\r
25                 dt=pt=0;\r
26                 for(i=0;i<n;i++){\r
27                         int h=hist[i];\r
28                         dt+=h*i;\r
29                         pt+=h*i*i;//正規化の時に使う定数\r
30                 }\r
31                 st=i_histgram.total_of_data;\r
32                 //Low側(0<=i<=n-2)\r
33                 da=dt;\r
34                 sa=st;\r
35                 //High側(i=n-1)\r
36                 db=sb=0;                \r
37                 \r
38                 double max=-1;\r
39                 double max_mt=0;\r
40                 //各ヒストグラムの分離度を計算する(1<=i<=n-1の範囲で評価)\r
41                 for(i=n-1;i>0;i--){\r
42                         //次のヒストグラムを計算\r
43                         int hist_count=hist[i];\r
44                         int hist_val=hist_count*i;\r
45                         da-=hist_val;\r
46                         sa-=hist_count;\r
47                         db+=hist_val;\r
48                         sb+=hist_count;\r
49                         \r
50                         //クラス間分散を計算\r
51                         double dv=(sa+sb);\r
52                         double mt=(double)(da+db)/dv;\r
53                         double ma=(sa!=0?((double)da/(double)sa):0)-mt;\r
54                         double mb=(sb!=0?((double)db/(double)sb):0)-mt;\r
55                         double kai=((double)(sa*(ma*ma)+sb*(mb*mb)))/dv;\r
56                         if(max<kai){\r
57                                 max_mt=mt;\r
58                                 max=kai;\r
59                                 th=i;\r
60                         }\r
61                         //System.out.println(kai);\r
62                 }\r
63                 //max_mtを元に正規化\r
64                 this._score=max/((double)(pt+max_mt*max_mt*st-2*max_mt*dt)/st);//129,0.8888888888888887\r
65                 return th;\r
66         }\r
67         /**\r
68          * 最後に実行したgetThresholdのスコアを返します。\r
69          * スコアは正規化された分離度。1.0-0.0の範囲を取る。0.7以上なら概ね双峰的です。\r
70          * @return\r
71          */\r
72         public final double getLastScore()\r
73         {\r
74                 return this._score;\r
75         }\r
76         /**\r
77          * Debug\r
78          */\r
79         public static void main(String[] args)\r
80         {\r
81                 NyARHistgram data=new NyARHistgram(256);\r
82                 for(int i=0;i<256;i++){\r
83                         data.data[i]=128-i>0?128-i:i-128;\r
84                 }\r
85                 data.total_of_data=data.getTotal(0,255);\r
86                 NyARHistgramAnalyzer_DiscriminantThreshold an=new NyARHistgramAnalyzer_DiscriminantThreshold();\r
87                 int th=an.getThreshold(data);\r
88                 System.out.print(th);\r
89                 return;\r
90         }\r
91 }\r