5 package jp.nyatla.nyartoolkit.core.labeling.rlelabeling;
\r
7 import jp.nyatla.nyartoolkit.NyARException;
\r
8 import jp.nyatla.nyartoolkit.core.raster.*;
\r
22 public static RleElement[] createArray(int i_length)
\r
24 RleElement[] ret = new RleElement[i_length];
\r
25 for (int i = 0; i < i_length; i++) {
\r
26 ret[i] = new RleElement();
\r
32 // RleImageをラベリングする。
\r
33 public class NyARLabeling_Rle
\r
35 private RleElement[] _rle1;
\r
37 private RleElement[] _rle2;
\r
39 public NyARLabeling_Rle(int i_width)
\r
41 this._rle1 = RleElement.createArray(i_width/2+1);
\r
42 this._rle2 = RleElement.createArray(i_width/2+1);
\r
47 * i_bin_bufのbinイメージをREL圧縮する。
\r
49 * @param i_bin_raster
\r
51 private int toRel(int[] i_bin_buf, int i_st, int i_len, RleElement[] i_out)
\r
57 final int right_edge = i_st + i_len - 1;
\r
58 while (x < right_edge) {
\r
60 if (i_bin_buf[x] != 0) {
\r
66 i_out[current].l = r;
\r
69 while (x < right_edge) {
\r
70 if (i_bin_buf[x] != 0) {
\r
71 // 明点(1)→暗点(0)配列終了>登録
\r
72 i_out[current].r = r;
\r
84 // 最後の1点だけ判定方法が少し違うの。
\r
85 if (i_bin_buf[x] != 0) {
\r
86 // 明点→rカウント中なら暗点配列終了>登録
\r
88 i_out[current].r = r;
\r
92 // 暗点→カウント中でなければl1で追加
\r
94 i_out[current].r = (r + 1);
\r
97 i_out[current].l = (i_len - 1);
\r
98 i_out[current].r = (i_len);
\r
106 private void addFragment(RleElement i_rel_img, int i_nof, int i_row_index, int i_rel_index,RleLabelFragmentInfoStack o_stack) throws NyARException
\r
109 final int len=i_rel_img.r - l;
\r
110 i_rel_img.fid = i_nof;// REL毎の固有ID
\r
111 RleLabelFragmentInfoStack.RleLabelFragmentInfo v = o_stack.prePush();
\r
115 v.clip_r=i_rel_img.r-1;
\r
116 v.clip_t=i_row_index;
\r
117 v.clip_b=i_row_index;
\r
118 v.pos_x+=(len*(2*l+(len-1)))/2;
\r
119 v.pos_y+=i_row_index*len;
\r
125 public int labeling(NyARBinRaster i_bin_raster, int i_top, int i_bottom,RleLabelFragmentInfoStack o_stack) throws NyARException
\r
130 RleElement[] rle_prev = this._rle1;
\r
131 RleElement[] rle_current = this._rle2;
\r
133 int len_current = 0;
\r
134 final int width = i_bin_raster.getWidth();
\r
135 int[] in_buf = (int[]) i_bin_raster.getBufferReader().getBuffer();
\r
141 len_prev = toRel(in_buf, i_top, width, rle_prev);
\r
142 for (int i = 0; i < len_prev; i++) {
\r
143 // フラグメントID=フラグメント初期値、POS=Y値、RELインデクス=行
\r
144 addFragment(rle_prev[i], id_max, i_top, i,o_stack);
\r
149 RleLabelFragmentInfoStack.RleLabelFragmentInfo[] f_array = o_stack.getArray();
\r
151 for (int y = i_top + 1; y < i_bottom; y++) {
\r
153 len_current = toRel(in_buf, y * width, width, rle_current);
\r
154 int index_prev = 0;
\r
156 SCAN_CUR: for (int i = 0; i < len_current; i++) {
\r
157 // index_prev,len_prevの位置を調整する
\r
159 // チェックすべきprevがあれば確認
\r
160 SCAN_PREV: while (index_prev < len_prev) {
\r
161 if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング
\r
162 // prevがcurの左方にある→次のフラグメントを探索
\r
165 } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる
\r
166 // prevがcur右方にある→独立フラグメント
\r
167 addFragment(rle_current[i], id_max, y, i,o_stack);
\r
173 id=rle_prev[index_prev].fid;//ルートフラグメントid
\r
174 RleLabelFragmentInfoStack.RleLabelFragmentInfo id_ptr = f_array[id];
\r
175 //結合対象(初回)->prevのIDをコピーして、ルートフラグメントの情報を更新
\r
176 rle_current[i].fid = id;//フラグメントIDを保存
\r
178 final int l= rle_current[i].l;
\r
179 final int r= rle_current[i].r;
\r
181 //結合先フラグメントの情報を更新する。
\r
182 id_ptr.area += len;
\r
183 //tとentry_xは、結合先のを使うので更新しない。
\r
184 id_ptr.clip_l=l<id_ptr.clip_l?l:id_ptr.clip_l;
\r
185 id_ptr.clip_r=r>id_ptr.clip_r?r-1:id_ptr.clip_r;
\r
187 id_ptr.pos_x+=(len*(2*l+(len-1)))/2;
\r
188 id_ptr.pos_y+=y*len;
\r
191 while (index_prev < len_prev) {
\r
192 if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング
\r
193 // prevがcurの左方にある→prevはcurに連結していない。
\r
195 } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる
\r
196 // prevがcurの右方にある→prevはcurに連結していない。
\r
200 // prevとcurは連結している→ルートフラグメントの統合
\r
203 final int prev_id =rle_prev[index_prev].fid;
\r
204 RleLabelFragmentInfoStack.RleLabelFragmentInfo prev_ptr = f_array[prev_id];
\r
205 if (id != prev_id){
\r
206 if(prev_ptr.area==0){
\r
207 System.out.println("ERRRR");
\r
210 //prevとcurrentのフラグメントidを書き換える。
\r
211 for(int i2=index_prev;i2<len_prev;i2++){
\r
213 if(rle_prev[i2].fid==prev_id){
\r
214 rle_prev[i2].fid=id;
\r
217 for(int i2=0;i2<i;i2++){
\r
218 //currentは0から現在-1まで
\r
219 if(rle_current[i2].fid==prev_id){
\r
220 rle_current[i2].fid=id;
\r
224 //現在のルートフラグメントに情報を集約
\r
225 id_ptr.area +=prev_ptr.area;
\r
226 id_ptr.pos_x+=prev_ptr.pos_x;
\r
227 id_ptr.pos_y+=prev_ptr.pos_y;
\r
229 if (id_ptr.clip_t > prev_ptr.clip_t) {
\r
231 id_ptr.clip_t = prev_ptr.clip_t;
\r
232 id_ptr.entry_x = prev_ptr.entry_x;
\r
233 }else if (id_ptr.clip_t < prev_ptr.clip_t) {
\r
234 // 現在の方が上にある。prevにフィードバック
\r
236 // 水平方向で小さい方がエントリポイント。
\r
237 if (id_ptr.entry_x > prev_ptr.entry_x) {
\r
238 id_ptr.entry_x = prev_ptr.entry_x;
\r
243 if (id_ptr.clip_l > prev_ptr.clip_l) {
\r
244 id_ptr.clip_l=prev_ptr.clip_l;
\r
248 if (id_ptr.clip_r < prev_ptr.clip_r) {
\r
249 id_ptr.clip_r=prev_ptr.clip_r;
\r
254 //結合済のルートフラグメントを無効化する。
\r
264 // curにidが割り当てられたかを確認
\r
267 addFragment(rle_current[i], id_max, y, i,o_stack);
\r
273 RleElement[] tmp = rle_prev;
\r
274 rle_prev = rle_current;
\r
275 len_prev = len_current;
\r
279 o_stack.sortByArea();
\r
281 o_stack.reserv(label_count);
\r
283 for(int i=0;i<label_count;i++){
\r
284 final RleLabelFragmentInfoStack.RleLabelFragmentInfo tmp=f_array[i];
\r
285 tmp.pos_x/=tmp.area;
\r
286 tmp.pos_y/=tmp.area;
\r
289 return label_count;
\r