ARToolKit编程框架研究

一. ARToolKit SDK中基于多标示的识别例程:

 

    ART是基于OPENGL和DSVL的增强现实软件包,它遵循OPENGL的运行模式,基于帧循环实现3D图像的渲染,
在每次进入帧循环后做标识物的检测和摄像机的重定位。

 

    当然这里使用DSVL的视频处理和基于OPENGL的图像处理,都可以用其他方式来代替。比如可以用OSG图形
引擎来完成较为复杂的图像处理,效果会更好,它也是基于OPENGL的接口,也需要在帧循环中处理。

 

下面的步骤必须在应用程序中采取的主要代码:

 

 

Initialization 1. 初始化视频捕获和读取文件的标记模式和相机参数.
Main Loop 2. 获取一帧输入视频.
3. 在输入视频图像中检测标识和注册的模版.
4. 计算摄像机相对于检测到的模版的位置.
5. 绘制虚拟模型到检测到的模板上.
Shutdown 6. 关闭视频捕获,回收资源.

 

#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef __APPLE__
#include <GL/gl.h>
#include <GL/glut.h>
#else
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#endif
#include <AR/gsub.h>
#include <AR/video.h>
#include <AR/param.h>
#include <AR/ar.h>
#include <AR/arMulti.h>

/* set up the video format globals */

#ifdef _WIN32
char   *vconf = "Data//WDM_camera_flipV.xml";      //摄像机默认参数
#else
char   *vconf = "";
#endif

int             xsize, ysize;
int             thresh = 100;
int             count = 0;

char           *cparam_name    = "Data/camera_para.dat";    //摄像机特征参数
ARParam         cparam;

char                *config_name = "Data/multi/marker.dat"; //标识信息
ARMultiMarkerInfoT  *config;

static void   init(void);
static void   cleanup(void);
static void   keyEvent( unsigned char key, int x, int y);
static void   mainLoop(void);
static void   draw( double trans1[3][4], double trans2[3][4], int mode );

//程序入口
int main(int argc, char **argv)
{
 //初始化OPENGL
 glutInit(&argc, argv);

 //初始化摄像机参数和显示窗口
    init();

 //启动摄像机
    arVideoCapStart();

 //注册响应事件函数(分别是鼠标事件、键盘事件、帧循环) 
    //实际是用OPENGL的内部事件处理机制,这里只是传递函数指针
    argMainLoop( NULL, keyEvent, mainLoop );
 return (0);
}

//键盘事件响应函数
static void   keyEvent( unsigned char key, int x, int y)
{
    /* quit if the ESC key is pressed */
 /* 点击ESC退出 */
    if( key == 0x1b ) {
        printf("*** %f (frame/sec)/n", (double)count/arUtilTimer());

  //释放资源
        cleanup();
        exit(0);
    }

 //调整二值化闸值 
    if( key == 't' ) {
        printf("*** %f (frame/sec)/n", (double)count/arUtilTimer());
        printf("Enter new threshold value (current = %d): ", thresh);
        scanf("%d",&thresh); while( getchar()!='/n' );
        printf("/n");
        count = 0;
    }

    /* turn on and off the debug mode with right mouse */
 /* 调试模式开关,显示二值化图像*/
    if( key == 'd' ) {
        printf("*** %f (frame/sec)/n", (double)count/arUtilTimer());
        arDebug = 1 - arDebug;
        if( arDebug == 0 ) {
            glClearColor( 0.0, 0.0, 0.0, 0.0 );
            glClear(GL_COLOR_BUFFER_BIT);

   //交换缓冲区
            argSwapBuffers();
            glClear(GL_COLOR_BUFFER_BIT);
            argSwapBuffers();
        }
        count = 0;
    }

}

/* main loop */
/* 主循环:完成标示物的检测和位置的重定位,并渲染模型。 */
static void mainLoop(void)
{
    ARUint8         *dataPtr;
    ARMarkerInfo    *marker_info; //标志信息结构
    int             marker_num;
    double          err;
    int             i;

    /* grab a vide frame */
 /* 获取一帧图像 */
    if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
  
  //调用延时
        arUtilSleep(2);
        return;
    }
 
 //计时复位
    if( count == 0 ) arUtilTimerReset();
    count++;

    /* detect the markers in the video frame */
 /* 检测标识 */
    if( arDetectMarkerLite(
            dataPtr, //帧数据
             thresh, //二值化闸值
          &marker_info, //标识特征信息
          &marker_num   // 标识数量
  ) < 0 ) {
        cleanup();
        exit(0);
    }

 //为渲染2D或3D对象更新当前摄像机参数
    argDrawMode2D();
    if( !arDebug ) {
        argDispImage( dataPtr, 0,0 );
    }
    else {
        argDispImage( dataPtr, 1, 1 );//调试模式下不显示摄像机图像作为背景
        if( arImageProcMode == AR_IMAGE_PROC_IN_HALF )
            argDispHalfImage( arImage, 0, 0 );
        else
            argDispImage( arImage, 0, 0);

        glColor3f( 1.0, 0.0, 0.0 );
        glLineWidth( 1.0 );
        for( i = 0; i < marker_num; i++ ) {
            argDrawSquare( marker_info[i].vertex, 0, 0 );
        }
        glLineWidth( 1.0 );
    }

 //每帧必须调用这个函数,完成诸多功能的支持...
    arVideoCapNext();

 //获取摄像机位置
    if( (err=arMultiGetTransMat(marker_info, marker_num, config)) < 0 ) {
        argSwapBuffers();
        return;
    }
    printf("err = %f/n", err);
    if(err > 100.0 ) {
        argSwapBuffers();
        return;
    }
/*
    for(i=0;i<3;i++) {
        for(j=0;j<4;j++) printf("%10.5f ", config->trans[i][j]);
        printf("/n");
    }
    printf("/n");
*/
    argDrawMode3D();
    argDraw3dCamera( 0, 0 );//3D模式开关
    glClearDepth( 1.0 );
    glClear(GL_DEPTH_BUFFER_BIT);

 //将模型绘制到对应位置
    for( i = 0; i < config->marker_num; i++ ) {
        if( config->marker[i].visible >= 0 ) draw( config->trans, config->marker[i].trans, 0 );
        else                                 draw( config->trans, config->marker[i].trans, 1 );
    }
    argSwapBuffers();
}

//初始化函数
static void init( void )
{
    ARParam  wparam;

    /* open the video path */
 /* 打开摄像机参数文件 */
    if( arVideoOpen( vconf ) < 0 ) exit(0);
    /* find the size of the window */
 /* 获取视频窗口大小 */
    if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0);
    printf("Image size (x,y) = (%d,%d)/n", xsize, ysize);

    /* set the initial camera parameters */
 /* 设置摄像机特征参数,这里的参数与摄像机安装和内部参数相关,主要是为了能更好的识别标识物。
 该参数文件可用用标准模版程序得到。 */
    if( arParamLoad(cparam_name, 1, &wparam) < 0 ) {
        printf("Camera parameter load error !!/n");
        exit(0);
    }
    arParamChangeSize( &wparam, xsize, ysize, &cparam );

 //初始化摄像机
    arInitCparam( &cparam );
    printf("*** Camera Parameter ***/n");
    arParamDisp( &cparam );

 //读取多标识的定义文件,该文件中记录有各个标识的特征信息和序号。
    if( (config = arMultiReadConfigFile(config_name)) == NULL ) {
        printf("config data load error !!/n");
        exit(0);
    }

    /* open the graphics window */
 /* 打开图像窗口 */
    argInit( &cparam, 1.0, 0, 2, 1, 0 );
    arFittingMode   = AR_FITTING_TO_IDEAL;
    arImageProcMode = AR_IMAGE_PROC_IN_HALF;
    argDrawMode     = AR_DRAW_BY_TEXTURE_MAPPING;
    argTexmapMode   = AR_DRAW_TEXTURE_HALF_IMAGE;
}

/* cleanup function called when program exits */
/* 当退出程序时回收资源 */
static void cleanup(void)
{
    arVideoCapStop();
    arVideoClose();
    argCleanup();
}

//绘制3D模型,这部分完全属于OPENGL的内容
static void draw( double trans1[3][4], double trans2[3][4], int mode )
{
    double    gl_para[16];
    GLfloat   mat_ambient[]     = {0.0, 0.0, 1.0, 1.0};
    GLfloat   mat_ambient1[]    = {1.0, 0.0, 0.0, 1.0};
    GLfloat   mat_flash[]       = {0.0, 0.0, 1.0, 1.0};
    GLfloat   mat_flash1[]      = {1.0, 0.0, 0.0, 1.0};
    GLfloat   mat_flash_shiny[] = {50.0};
    GLfloat   mat_flash_shiny1[]= {50.0};
    GLfloat   light_position[]  = {100.0,-200.0,200.0,0.0};
    GLfloat   ambi[]            = {0.1, 0.1, 0.1, 0.1};
    GLfloat   lightZeroColor[]  = {0.9, 0.9, 0.9, 0.1};
   
 //进入3D绘图模式
    argDrawMode3D();
    argDraw3dCamera( 0, 0 );
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
   
    /* load the camera transformation matrix */
 /* 加载摄像机转换矩阵 */
    glMatrixMode(GL_MODELVIEW);
    argConvGlpara(trans1, gl_para);
    glLoadMatrixd( gl_para );
    argConvGlpara(trans2, gl_para);
    glMultMatrixd( gl_para );

    if( mode == 0 ) {
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);
        glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny); 
        glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    }
    else {
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glLightfv(GL_LIGHT0, GL_POSITION, light_position);
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash1);
        glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny1); 
        glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
    }
    glMatrixMode(GL_MODELVIEW);
    glTranslatef( 0.0, 0.0, 25.0 );
    if( !arDebug ) glutSolidCube(50.0);
     else          glutWireCube(50.0);
    glDisable( GL_LIGHTING );

    glDisable( GL_DEPTH_TEST );
}

二 这个程序使用的标示图像如下:

 

    其中包括了六个标示,这些标示的特征被记录在六个独体的PATT文件中。加载时不需要一一说明,只需要加载这六个文件
的总说明文件即“marker.dat”即可。

 

 

三 标示特征文件“marker.dat”的内部结构:

 

    这个文件中并没有标示物的具体特征参数,而是他们加载后的识别顺序和对应的特征文件名。

 

 

四 程序运行的效果:

 

 

五 如果对这个说明还有任何疑问,可以留言。我会尽量补充!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值