/*
* 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.artoolkit.NyARLabelingImage;
import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabelingLabel;
import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabelingLabelStack;
import jp.nyatla.nyartoolkit.core.labeling.artoolkit.NyARLabeling_ARToolKit;
import jp.nyatla.nyartoolkit.core.raster.NyARBinRaster;
import jp.nyatla.nyartoolkit.core.types.NyARIntCoordinates;
import jp.nyatla.nyartoolkit.core.types.NyARIntSize;
/**
* このクラスは、{@link NyARLabeling_ARToolKit}クラスを用いた矩形検出器です。
* 検出した矩形を、自己コールバック関数{@link #onSquareDetect}へ通知します。
* 継承クラスで自己コールバック関数{@link #onSquareDetect}を実装する必要があります。
*/
public abstract class NyARSquareContourDetector_ARToolKit extends NyARSquareContourDetector
{
private static final int AR_AREA_MAX = 100000;// #define AR_AREA_MAX 100000
private static final int AR_AREA_MIN = 70;// #define AR_AREA_MIN 70
private final int _width;
private final int _height;
private final NyARLabeling_ARToolKit _labeling;
private final NyARLabelingImage _limage;
private final NyARLabelOverlapChecker<NyARLabelingLabel> _overlap_checker = new NyARLabelOverlapChecker<NyARLabelingLabel>(32,NyARLabelingLabel.class);
private final NyARContourPickup_ARToolKit _cpickup=new NyARContourPickup_ARToolKit();
private final NyARCoord2SquareVertexIndexes _coord2vertex=new NyARCoord2SquareVertexIndexes();
private final NyARIntCoordinates _coord;
private final int[] __detectMarker_mkvertex = new int[4];
/**
* コンストラクタです。
* 入力画像のサイズを指定して、インスタンスを生成します。
* @param i_size
* 入力画像のサイズ
*/
public NyARSquareContourDetector_ARToolKit(NyARIntSize i_size) throws NyARException
{
this._width = i_size.w;
this._height = i_size.h;
this._labeling = new NyARLabeling_ARToolKit();
this._limage = new NyARLabelingImage(this._width, this._height);
// 輪郭の最大長は画面に映りうる最大の長方形サイズ。
int number_of_coord = (this._width + this._height) * 2;
// 輪郭バッファは頂点変換をするので、輪郭バッファの2倍取る。
this._coord=new NyARIntCoordinates(number_of_coord);
return;
}
/**
* この関数は、ラスタから矩形を検出して、自己コールバック関数{@link #onSquareDetect}で通知します。
* ARToolKitのarDetectMarker2を基にしています。
*/
public final void detectMarker(NyARBinRaster i_raster) throws NyARException
{
final NyARLabelingImage limage = this._limage;
// ラベル数が0ならここまで
final int label_num = this._labeling.labeling(i_raster,this._limage);
if (label_num < 1) {
return;
}
final NyARLabelingLabelStack stack = limage.getLabelStack();
//ラベルをソートしておく
stack.sortByArea();
//
final NyARLabelingLabel[] labels = stack.getArray();
// デカいラベルを読み飛ばし
int i;
for (i = 0; i < label_num; i++) {
// 検査対象内のラベルサイズになるまで無視
if (labels[i].area <= AR_AREA_MAX) {
break;
}
}
final int xsize = this._width;
final int ysize = this._height;
final NyARIntCoordinates coord = this._coord;
final int[] mkvertex =this.__detectMarker_mkvertex;
final NyARLabelOverlapChecker<NyARLabelingLabel> overlap = this._overlap_checker;
//重なりチェッカの最大数を設定
overlap.setMaxLabels(label_num);
for (; i < label_num; i++) {
final NyARLabelingLabel label_pt = labels[i];
final int label_area = label_pt.area;
// 検査対象サイズよりも小さくなったら終了
if (label_area < AR_AREA_MIN) {
break;
}
// クリップ領域が画面の枠に接していれば除外
if (label_pt.clip_l == 1 || label_pt.clip_r == xsize - 2) {// if(wclip[i*4+0] == 1 || wclip[i*4+1] ==xsize-2){
continue;
}
if (label_pt.clip_t == 1 || label_pt.clip_b == ysize - 2) {// if( wclip[i*4+2] == 1 || wclip[i*4+3] ==ysize-2){
continue;
}
// 既に検出された矩形との重なりを確認
if (!overlap.check(label_pt)) {
// 重なっているようだ。
continue;
}
// 輪郭を取得
if(!this._cpickup.getContour(limage,limage.getTopClipTangentX(label_pt),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;
}
}