/*
* PROJECT: NyARToolkit
* --------------------------------------------------------------------------------
* This work is based on the original ARToolKit developed by
* Hirokazu Kato
* Mark Billinghurst
* HITLab, University of Washington, Seattle
* http://www.hitl.washington.edu/artoolkit/
*
* The NyARToolkit is Java edition ARToolKit class library.
* Copyright (C)2008-2009 Ryo Iizuka
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For further information please contact.
* http://nyatla.jp/nyatoolkit/
* <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
*
*/
package jp.nyatla.nyartoolkit.core.squaredetect;
import jp.nyatla.nyartoolkit.NyARException;
import jp.nyatla.nyartoolkit.core.labeling.NyARLabelOverlapChecker;
import jp.nyatla.nyartoolkit.core.labeling.rlelabeling.*;
import jp.nyatla.nyartoolkit.core.raster.NyARBinRaster;
import jp.nyatla.nyartoolkit.core.raster.NyARGrayscaleRaster;
import jp.nyatla.nyartoolkit.core.types.*;
/**
* このクラスは、{@link NyARLabeling_Rle}クラスを用いた矩形検出器です。
* 検出した矩形を、自己コールバック関数{@link #onSquareDetect}へ通知します。
* 継承クラスで自己コールバック関数{@link #onSquareDetect}を実装する必要があります。
*/
public abstract class NyARSquareContourDetector_Rle extends NyARSquareContourDetector
{
/** label_stackにソート後の結果を蓄積するクラス*/
private class Labeling extends NyARLabeling_Rle
{
public NyARRleLabelFragmentInfoPtrStack label_stack;
int _right;
int _bottom;
public Labeling(int i_width,int i_height) throws NyARException
{
super(i_width,i_height);
this.label_stack=new NyARRleLabelFragmentInfoPtrStack(i_width*i_height*2048/(320*240)+32);//検出可能な最大ラベル数
this._bottom=i_height-1;
this._right=i_width-1;
return;
}
public void labeling(NyARGrayscaleRaster i_raster,NyARIntRect i_area,int i_th) throws NyARException
{
//配列初期化
this.label_stack.clear();
//ラベルの検出
super.labeling(i_raster, i_area, i_th);
//ソート
this.label_stack.sortByArea();
}
public void labeling(NyARBinRaster i_bin_raster) throws NyARException
{
//配列初期化
this.label_stack.clear();
//ラベルの検出
super.labeling(i_bin_raster);
//ソート
this.label_stack.sortByArea();
}
protected void onLabelFound(NyARRleLabelFragmentInfo i_label)
{
// クリップ領域が画面の枠に接していれば除外
if (i_label.clip_l == 0 || i_label.clip_r == this._right){
return;
}
if (i_label.clip_t == 0 || i_label.clip_b == this._bottom){
return;
}
this.label_stack.push(i_label);
}
}
private final int _width;
private final int _height;
private final Labeling _labeling;
private final NyARLabelOverlapChecker<NyARRleLabelFragmentInfo> _overlap_checker = new NyARLabelOverlapChecker<NyARRleLabelFragmentInfo>(32,NyARRleLabelFragmentInfo.class);
private final NyARContourPickup _cpickup=new NyARContourPickup();
private final NyARCoord2SquareVertexIndexes _coord2vertex=new NyARCoord2SquareVertexIndexes();
private final NyARIntCoordinates _coord;
/**
* コンストラクタです。
* 入力画像のサイズを指定して、インスタンスを生成します。
* @param i_size
* 入力画像のサイズ
*/
public NyARSquareContourDetector_Rle(NyARIntSize i_size) throws NyARException
{
//特性確認
assert(NyARLabeling_Rle._sf_label_array_safe_reference);
this._width = i_size.w;
this._height = i_size.h;
//ラベリングのサイズを指定したいときはsetAreaRangeを使ってね。
this._labeling = new Labeling(this._width,this._height);
// 輪郭の最大長は画面に映りうる最大の長方形サイズ。
int number_of_coord = (this._width + this._height) * 2;
// 輪郭バッファ
this._coord = new NyARIntCoordinates(number_of_coord);
return;
}
private final int[] __detectMarker_mkvertex = new int[4];
/**
* この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
* @param i_raster
* 検出元のラスタ画像
* 入力できるラスタの画素形式は、{@link NyARLabeling_Rle#labeling(NyARGrayscaleRaster, int)}と同じです。
* @param i_area
* 検出する範囲。検出元のラスタの内側である必要があります。
* @param i_th
* ラベルと判定する敷居値
* @throws NyARException
*/
public void detectMarker(NyARGrayscaleRaster i_raster,NyARIntRect i_area,int i_th) throws NyARException
{
assert(i_area.w*i_area.h>0);
final NyARRleLabelFragmentInfoPtrStack flagment=this._labeling.label_stack;
final NyARLabelOverlapChecker<NyARRleLabelFragmentInfo> overlap = this._overlap_checker;
// ラベル数が0ならここまで
this._labeling.labeling(i_raster, i_area, i_th);
final int label_num=flagment.getLength();
if (label_num < 1) {
return;
}
//ラベルリストを取得
NyARRleLabelFragmentInfo[] labels=flagment.getArray();
NyARIntCoordinates coord = this._coord;
final int[] mkvertex =this.__detectMarker_mkvertex;
//重なりチェッカの最大数を設定
overlap.setMaxLabels(label_num);
for (int i=0; i < label_num; i++) {
NyARRleLabelFragmentInfo label_pt=labels[i];
// 既に検出された矩形との重なりを確認
if (!overlap.check(label_pt)) {
// 重なっているようだ。
continue;
}
//輪郭を取得
if(!this._cpickup.getContour(i_raster,i_area, i_th,label_pt.entry_x,label_pt.clip_t,coord))
{
continue;
}
int label_area = label_pt.area;
//輪郭線をチェックして、矩形かどうかを判定。矩形ならばmkvertexに取得
if (!this._coord2vertex.getVertexIndexes(coord,label_area,mkvertex)){
// 頂点の取得が出来なかった
continue;
}
//矩形を発見したことをコールバック関数で通知
this.onSquareDetect(coord,mkvertex);
// 検出済の矩形の属したラベルを重なりチェックに追加する。
overlap.push(label_pt);
}
return;
}
/**
* この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
* ARToolKitのarDetectMarker2を基にしています。
*/
public void detectMarker(NyARBinRaster i_raster) throws NyARException
{
final NyARRleLabelFragmentInfoPtrStack flagment=this._labeling.label_stack;
final NyARLabelOverlapChecker<NyARRleLabelFragmentInfo> overlap = this._overlap_checker;
// ラベル数が0ならここまで
flagment.clear();
this._labeling.labeling(i_raster);
final int label_num=flagment.getLength();
if (label_num < 1) {
return;
}
//ラベルをソートしておく
flagment.sortByArea();
//ラベルリストを取得
NyARRleLabelFragmentInfo[] labels=flagment.getArray();
NyARIntCoordinates coord = this._coord;
final int[] mkvertex =this.__detectMarker_mkvertex;
//重なりチェッカの最大数を設定
overlap.setMaxLabels(label_num);
for (int i=0; i < label_num; i++) {
final NyARRleLabelFragmentInfo label_pt=labels[i];
int label_area = label_pt.area;
// 既に検出された矩形との重なりを確認
if (!overlap.check(label_pt)) {
// 重なっているようだ。
continue;
}
//輪郭を取得
if(!this._cpickup.getContour(i_raster,label_pt.entry_x,label_pt.clip_t,coord)){
continue;
}
//輪郭線をチェックして、矩形かどうかを判定。矩形ならばmkvertexに取得
if (!this._coord2vertex.getVertexIndexes(coord,label_area, mkvertex)) {
// 頂点の取得が出来なかった
continue;
}
//矩形を発見したことをコールバック関数で通知
this.onSquareDetect(coord,mkvertex);
// 検出済の矩形の属したラベルを重なりチェックに追加する。
overlap.push(label_pt);
}
return;
}
/**
* デバック用API
* @return
* オブジェクト配列
*/
public Object[] _probe()
{
Object[] ret=new Object[10];
return ret;
}
}