2018-11-29
你拼命的样子或许很狼狈,但你努力的样子真的很美……
**
【零基础学习ARToolkit系列之二】ARToolkit开发第一个程序第一部分
**
要使用 ARToolKit 开发应用有两个部分(开发原则):1.编写应用程序(其实就是敲代码啦),2.训练对增强现实应用中所用到的真实世界标志的图像处理例程。
本次我们将通过对例程simple的解读来详细地示范怎么样开发一个 ARToolKit 的应用,可以在目录 examples/simple/里找到这个程序。
一. 一个应用程序的主代码必须包含以下步骤:
初始化
- 初始化视频捕获,读取标识文件和相机参数
主循环 - 抓取一帧输入视频的图像
- 探测标识以及识别这帧输入视频中的模板
- 计算摄像头相对于探测到的标识的转换矩阵
- 在探测到的标识上叠加虚拟物体
关闭 - 关闭视频捕捉
二.相应于 ARToolKit 应用程序步骤的函数调用和代码
ARToolKit 步骤和对应的函数
1、应用程序初始化 init
2、抓取一帧输入视频 arVideoGetImage (在主循环中调用)
3、探测标识卡 arDetectMarker(在主循环中调用)
4、计算摄像头的转移矩阵 arGetTransMat(在主循环中调用)
5、画上虚拟物体 draw(在主循环中调用)
6、关闭视频捕捉 cleanup
主要的函数:main(主函数),init(初始化),mainloop(主循环,步骤2-5),drawcleanup(关闭视频捕捉)
Main
例程simple中的mian函数如下
int main(int argc, char **argv)
{
glutInit(&argc, argv);
init();//初始化
arVideoCapStart();//视频开始函数
argMainLoop( NULL, keyEvent, mainLoop );//主循环
return (0);
}
init
static void init( void )
{
ARParam wparam;
//1.视频通道打开,确定视频图像大小
/* 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);
//2.要初始化 ARToolKit 应用程序的参数。
/ set the initial camera parameters /
//2.1可能被用来进行模板模式匹配的模板信息,以及这些模板锁对应的虚拟物体
//摄像机的参数信息通过默认的摄像机参数文件名 Data/camera_para.dat 被读入
if( arParamLoad(cparam_name, 1, &wparam) < 0 ) {
printf(“Camera parameter load error !!\n”);
exit(0);
}
//2.2所用的视频摄像机的相机特性参数
//3.接下来,这些参数根据现有的图像大小被转换,
arParamChangeSize( &wparam, xsize, ysize, &cparam );
//4.摄像机的参数被读入它的程序设置,摄像机的参数被输出显示到屏幕上
arInitCparam( &cparam );
printf("** Camera Parameter **\n");
arParamDisp( &cparam );
//5.之后我们通过默认的模板文件 Data/patt.hiro 读入模板的定义信息
if( (patt_id=arLoadPatt(patt_name)) < 0 ) {
printf(“pattern load error !!\n”);
exit(0);
}
/ open the graphics window /
//6.最终打开图像窗口
argInit( &cparam, 1.0, 0, 0, 0, 0 );
}
mainloop
/ main loop */
static void mainLoop(void)
{
ARUint8 *dataPtr;
ARMarkerInfo *marker_info;
int marker_num;
int j, k;
/* grab a vide frame */
//1.通过函数 arVideoGetImage 来捕捉一个输入视频帧
if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
arUtilSleep(2);
return;
}
if( count == 0 ) arUtilTimerReset();
count++;
argDrawMode2D();
argDispImage( dataPtr, 0,0 );
/* detect the markers in the video frame */
//2. 函数 arDetectMarker 被使用以搜索整个图像来寻找含有正确的标识模板的方块:
if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) {
cleanup();
exit(0);
}
arVideoCapNext();
//3.接下来,所有的已经探测到的标识的可信度信息被加以比较,最终确定正确的标识鉴定信息为可信度最高的标识的鉴定信息
/* check for object visibility */
k = -1;
for( j = 0; j < marker_num; j++ ) {
if( patt_id == marker_info[j].id ) {
if( k == -1 ) k = j;
else if( marker_info[k].cf < marker_info[j].cf ) k = j;
}
}
//如果没有标识被找到(k==-1),应用程序会做一个简单的优化步骤,我们可以交换缓冲器而不需要调用函数 draw,然后返回
if( k == -1 ) {
argSwapBuffers();
return;
}
/* get the transformation between the marker and the real camera */
//4.标识卡和摄像机之间的转移信息可以通过使用函数 arGetTransMat 来获取
arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);
//5.使用绘图函数,虚拟物体可以被叠加在标识卡上
draw();
argSwapBuffers();
}
draw
static void draw( void )
{
//1.显示环境初始化
double gl_para[16];
GLfloat mat_ambient[] = {0.0, 0.0, 1.0, 1.0};
GLfloat mat_flash[] = {0.0, 0.0, 1.0, 1.0};
GLfloat mat_flash_shiny[] = {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};
argDrawMode3D();
argDraw3dCamera( 0, 0 );
glClearDepth( 1.0 );
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//2.设置矩阵
/* load the camera transformation matrix */
argConvGlpara(patt_trans, gl_para);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd( gl_para );
//虚拟世界的摄像机的位置是用函数 glLoadMatrixd(gl_para)来设置的。代码的最后是三维物体的显示。在这个例子中,显示的是白色光束下是一个蓝色立方体
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);
glMatrixMode(GL_MODELVIEW);
glTranslatef( 0.0, 0.0, 25.0 );
glutSolidCube(50.0);
//在最后,要重置某些 OpenGL 的参数为默认值.显示物体
glDisable( GL_LIGHTING );
glDisable( GL_DEPTH_TEST );
}
Cleanup
//停止视频处理以及关闭视频路径并释放它使其他的应用可以使用
/* cleanup function called when program exits */
static void cleanup(void)
{
arVideoCapStop();
arVideoClose();
argCleanup();
}
这个程序的一个限制是它只使用模板 Hiro,我们在下一节介绍怎么样使用其他模板。啾咪~