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 private short number_of_fragment; // 現在のフラグメントの数
\r
41 public NyARLabeling_Rle(int i_width)
\r
43 this._rle1 = RleElement.createArray(i_width/2+1);
\r
44 this._rle2 = RleElement.createArray(i_width/2+1);
\r
49 * i_bin_bufのbinイメージをREL圧縮する。
\r
51 * @param i_bin_raster
\r
53 private int toRel(int[] i_bin_buf, int i_st, int i_len, RleElement[] i_out)
\r
59 final int right_edge = i_st + i_len - 1;
\r
60 while (x < right_edge) {
\r
62 if (i_bin_buf[x] != 0) {
\r
67 r = (short) (x - i_st);
\r
68 i_out[current].l = r;
\r
71 while (x < right_edge) {
\r
72 if (i_bin_buf[x] != 0) {
\r
73 // 明点(1)→暗点(0)配列終了>登録
\r
74 i_out[current].r = r;
\r
86 // 最後の1点だけ判定方法が少し違うの。
\r
87 if (i_bin_buf[x] != 0) {
\r
88 // 明点→rカウント中なら暗点配列終了>登録
\r
90 i_out[current].r = r;
\r
94 // 暗点→カウント中でなければl1で追加
\r
96 i_out[current].r = (short) (r + 1);
\r
99 i_out[current].l = (short) (i_st + i_len - 1);
\r
100 i_out[current].r = (short) (i_st + i_len);
\r
108 private void addFragment(RleElement i_rel_img, short i_nof, int i_row_index, int i_rel_index,RleLabelFragmentInfoStack o_stack) throws NyARException
\r
110 i_rel_img.id = i_nof;// REL毎の固有ID
\r
111 RleLabelFragmentInfoStack.RleLabelFragmentInfo v = o_stack.prePush();
\r
113 v.entry_x = i_rel_img.l;
\r
114 v.entry_y = (short) i_row_index;
\r
115 v.area = i_rel_img.r - i_rel_img.l;
\r
120 public void labeling(NyARBinRaster i_bin_raster, int i_top, int i_bottom,RleLabelFragmentInfoStack o_stack) throws NyARException
\r
123 this.number_of_fragment = 0;
\r
126 RleElement[] rle_prev = this._rle1;
\r
127 RleElement[] rle_current = this._rle2;
\r
129 int len_current = 0;
\r
130 final int width = i_bin_raster.getWidth();
\r
131 int[] in_buf = (int[]) i_bin_raster.getBufferReader().getBuffer();
\r
133 short nof = this.number_of_fragment;
\r
136 len_prev = toRel(in_buf, i_top, width, rle_prev);
\r
137 for (int i = 0; i < len_prev; i++) {
\r
138 // フラグメントID=フラグメント初期値、POS=Y値、RELインデクス=行
\r
139 addFragment(rle_prev[i], nof, i_top, i,o_stack);
\r
143 RleLabelFragmentInfoStack.RleLabelFragmentInfo[] f_array = o_stack.getArray();
\r
145 for (int y = i_top + 1; y < i_bottom; y++) {
\r
147 len_current = toRel(in_buf, y * width, width, rle_current);
\r
148 int index_prev = 0;
\r
150 SCAN_CUR: for (int i = 0; i < len_current; i++) {
\r
151 // index_prev,len_prevの位置を調整する
\r
153 // チェックすべきprevがあれば確認
\r
154 SCAN_PREV: while (index_prev < len_prev) {
\r
155 if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング
\r
156 // prevがcurの左方にある→次のフラグメントを探索
\r
159 } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる
\r
160 // prevがcur右方にある→独立フラグメント
\r
161 addFragment(rle_current[i], nof, y, i,o_stack);
\r
166 // 結合対象->prevのIDをコピーして、対象フラグメントの情報を更新
\r
167 id = f_array[rle_prev[index_prev].id].id;
\r
168 RleLabelFragmentInfoStack.RleLabelFragmentInfo prev_ptr;
\r
169 final RleLabelFragmentInfoStack.RleLabelFragmentInfo id_ptr = f_array[id];
\r
170 prev_ptr = f_array[rle_prev[index_prev].id];
\r
171 rle_current[i].id = id;
\r
172 id_ptr.area += (rle_current[i].r - rle_current[i].l);
\r
174 id_ptr.entry_x = prev_ptr.entry_x;
\r
175 id_ptr.entry_y = prev_ptr.entry_y;
\r
179 while (index_prev < len_prev) {
\r
180 if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング
\r
181 // prevがcurの左方にある→prevはcurに連結していない。
\r
183 } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる
\r
184 // prevがcurの右方にある→prevはcurに連結していない。
\r
188 // prevとcurは連結している。
\r
189 final short prev_id = rle_prev[index_prev].id;
\r
190 prev_ptr = f_array[prev_id];
\r
191 if (id != prev_id) {
\r
192 id_ptr.area += prev_ptr.area;
\r
194 // 結合対象->現在のidをインデクスにセット
\r
197 if (id_ptr.entry_y > prev_ptr.entry_y) {
\r
198 // 現在のエントリポイントの方が下にある。(何もしない)
\r
200 if (id_ptr.entry_y < prev_ptr.entry_y) {
\r
201 // 現在のエントリポイントの方が上にある。(エントリポイントの交換)
\r
202 prev_ptr.entry_y = id_ptr.entry_y;
\r
203 prev_ptr.entry_x = id_ptr.entry_x;
\r
205 // 水平方向で小さい方がエントリポイント。
\r
206 if (id_ptr.entry_x < prev_ptr.entry_x) {
\r
207 prev_ptr.entry_y = id_ptr.entry_y;
\r
208 prev_ptr.entry_x = id_ptr.entry_x;
\r
217 // curにidが割り当てられたかを確認
\r
220 addFragment(rle_current[i], nof, y, i,o_stack);
\r
225 RleElement[] tmp = rle_prev;
\r
226 rle_prev = rle_current;
\r
227 len_prev = len_current;
\r
231 this.number_of_fragment = nof;
\r