ARToolKit源码阅读 摄像头标定 calib_dist

本文详细介绍了calib_dist程序的源码,该程序主要用于测量图像中心点坐标和镜头畸变参数。文中深入分析了calib_dist.c、calib_dist.h等核心文件,并解释了关键函数如arVideoOpen()、arglDispImage()的功能与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

calib_dist用于测量图像中心点坐标和镜头畸变参数,而程序calib_cparam用于测量摄像机实际焦距。
本文主要介绍 calib_dist 程序的源码
主要文件有 calib_dist.c、calib_dist.h、check_dist.c

calib_dist.c

Part1 参数

static ARUint8      *gARTImage = NULL;
// 处理的图像
static ARParam      gARTCparam; 
// 给 gsub_lite.c 提供的 AR参数
static ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
//设置 setting

//GL的相关设置 
static int             gWin;        //gl窗口
static int             gXsize = 0;  //窗大小
static int             gYsize = 0;
static int             gThresh = THRESH;  
//keyboard 和 motion 中用到
static unsigned char   *gClipImage = NULL;

static int             gStatus;   //状态变量  0等待抓取图像,1绘制包围盒,2放置经线。


//------------------------------------------------待定----
static CALIB_PATT_T    gPatt;          
static double          dist_factor[4];
static int             point_num;
static int             gDragStartX = -1, gDragStartY = -1, gDragEndX = -1, gDragEndY = -1;  
static int             check_num;

PART2 Main函数

int main(int argc, char *argv[])
{
//glut初始化
    glutInit(&argc, argv);
//init()函数
    if (!init(argc, argv)) exit(-1);
//glut窗口名称、大小、模式设置
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowSize(gXsize, gYsize);
    glutInitWindowPosition(100,100);
    gWin = glutCreateWindow("Calibrate distortion");


/* arglSetupForCurrentContext()函数
    主要包括arglDrawModeSet()、arTextmapModeSet()、argTexRectangleModeSet()
    这三个函数分别进行如下操作:
        gArglSettings->arglDrawMode =AR_DRAW_BY_TEXTURE
        gArglSettings->arTextmapMode =AR_DRAW_TEXTURE_FULL_IMAGE
        gArglSettings->arglTexRectangle =TRUE
*/
    if ((gArglSettings = arglSetupForCurrentContext()) == NULL) {
        fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
        exit(-1);
    }
//arglDistortionCompensationSet()函数 
//主要是将 gArglSettings->disableDistortionCompensation=TRUE
    arglDistortionCompensationSet(gArglSettings, FALSE);

    gARTCparam.xsize = gXsize;
    gARTCparam.ysize = gYsize;

//glut对应的事件设置
    glutDisplayFunc(Display);//用于注册一个绘图函数
    glutReshapeFunc(Reshape);//当你改变窗口大小时的回调(CallBack)函数 
    glutVisibilityFunc(Visibility);//设置当前窗口的可视回调函数
    glutKeyboardFunc(Keyboard);//注册当前窗口的键盘回调函数
    glutMouseFunc(Mouse);//注册当前窗口的鼠标回调函数
    glutMotionFunc(Motion);
//arVideoCapStart()函数 对init()函数中的vid->graphManger,调用run()函数
//arVideoCapStart():打开相机线程,与arVideoCapStop对应,合理运用可减少CPU负载。 
    if (arVideoCapStart() != 0) {
        fprintf(stderr, "init(): Unable to begin camera data capture.\n");
        return (FALSE);     
    }

    point_num = 0;
    gStatus = 0;
    print_comment(0);
//进入GLUT事件处理循环,让所有的与“事件”有关的函数调用无限循环。在一个GLUT程序中,这个例程被调用一次 。一旦被调用,这个程序将永远不会返回 。它将调用必要的任何已注册的回调。
    glutMainLoop();

    return (0);
}

PART3 init()函数

static int init(int argc, char *argv[])
{
    char    line[512];
    int     i;
    gPatt.h_num    = H_NUM;
    gPatt.v_num    = V_NUM;
    gPatt.loop_num = 0;
    if (gPatt.h_num < 3 || gPatt.v_num < 3) exit(0);
    strcpy_s(line, vconf);
    for (i = 1; i < argc; i++) {
        strcat_s(line, " ");
        strcat_s(line, argv[i]);
    }
//本程序中 line =vconf
//char *vconf = "Data\\WDM_camera_flipV.xml";
    if (arVideoOpen(line) < 0) {
        //arVideoOpen()函数的源码 下面具体讲
        fprintf(stderr, "init(): Unable to open connection to camera.\n");
        return (FALSE);
    }
//获取arVideo的width 和height
//vid->graphManager->GetCurrentMediaFormat(&frame_width, &frame_height,null,null)
    if (arVideoInqSize(&gXsize, &gYsize) < 0) return (FALSE);
    fprintf(stdout, "Camera image size (x,y) = (%d,%d)\n", gXsize, gYsize);
//arMalloc ar的空间分配函数
    arMalloc(gClipImage, unsigned char, gXsize * gYsize);
    return (TRUE);
}

arVideoOpen()函数 与 ar2VideoOpen(char *config)函数

arVideoOpen()

int arVideoOpen(char *config)
{
    if (gVid != NULL) {
        fprintf(stderr, "arVideoOpen(): Error, device is already open.\n");
        return (-1);
    }
    gVid = ar2VideoOpen(config);
    if (gVid == NULL) return (-1);
    return (0);
}

ar2VideoOpen()

AR2VideoParamT *ar2VideoOpen(char *config)
{
    AR2VideoParamT *vid = NULL;
    char config_default[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><dsvl_input><camera show_format_dialog=\"true\" friendly_name=\"\"><pixel_format><RGB32 flip_h=\"false\" flip_v=\"true\"/></pixel_format></camera></dsvl_input>";
//分配参数空间并将其填充。
    arMalloc(vid, AR2VideoParamT, 1);
    memset(vid, 0, sizeof(AR2VideoParamT));
// win函数 以单线程的方式创建com对象
    CoInitialize(NULL);
//新建 vid->graphManager  用DSVL new的对象
    vid->graphManager = new DSVL_VideoSource();
//用config 参数 也就是上文的line 对vid->graphManger 赋值
//如果config不存在 就用config_default;如果存在 则有 fromXMLString 和fromXMLFile 两种不同的方式
    if (!config) {
        if (FAILED(vid->graphManager->BuildGraphFromXMLString(config_default))) return(NULL);
    } else {
        if (strncmp(config, "<?xml", 5) == 0) {
            if (FAILED(vid->graphManager->BuildGraphFromXMLString(config))) return(NULL);
        } else {
            if (FAILED(vid->graphManager->BuildGraphFromXMLFile(config))) return(NULL);
        }
    }
//内存缓冲区
    if (FAILED(vid->graphManager->EnableMemoryBuffer())) return(NULL);

    return (vid);
}

PART4 Display()函数

static void Display(void)
{
    double         x, y;
    int            ssx, eex, ssy, eey;
    int            i;

    // GL buffer set
    glDrawBuffer(GL_BACK);
    glClear(GL_COLOR_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    beginOrtho2D(); // beginOrtho2D() 一些gl的操作

    if (gStatus == 0) {
        arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);  
        arVideoCapNext();//接着将获取下一帧图像
        gARTImage = NULL;

    }


    else if (gStatus == 1) {
    //在mouse事件后 gStatus 0->1 gARTImage 通过 grabImage()函数 赋值给gPatt.savedImage
        arglDispImage(gPatt.savedImage[gPatt.loop_num - 1], &gARTCparam, 1.0, gPatt.arglSettings[gPatt.loop_num - 1]);
        for (i = 0; i < point_num; i++) {
            x = gPatt.point[gPatt.loop_num - 1][i].x_coord;
            y = gPatt.point[gPatt.loop_num - 1][i].y_coord;
            //在鼠标点击位置 画一个红色的“十”字
            glColor3f(1.0f, 0.0f, 0.0f);
            glBegin(GL_LINES);
            glVertex2d(x - 10.0, (GLdouble)(gYsize - 1) - y);
            glVertex2d(x + 10.0, (GLdouble)(gYsize - 1) - y);
            glVertex2d(x, (GLdouble)(gYsize - 1) - (y - 10.0));
            glVertex2d(x, (GLdouble)(gYsize - 1) - (y + 10.0));
            glEnd();
        }

        // 绘制当前鼠标拖动剪辑区域。
        if (gDragStartX != -1 && gDragStartY != -1
            && gDragEndX != -1 && gDragEndY != -1) {
            if (gDragStartX < gDragEndX) { ssx = gDragStartX; eex = gDragEndX; }
            else { ssx = gDragEndX; eex = gDragStartX; }
            if (gDragStartY < gDragEndY) { ssy = gDragStartY; eey = gDragEndY; }
            else { ssy = gDragEndY; eey = gDragStartY; }
            if (gClipImage) {
                glPixelZoom(1.0f, -1.0f);   // ARToolKit bitmap 0.0 is at upper-left, OpenGL bitmap 0.0 is at lower-left.
                glRasterPos2f((GLfloat)(ssx), (GLfloat)(gYsize - 1 - ssy));
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                //框选位置的图片 画成GL_LUMINANCE
                glDrawPixels(eex - ssx + 1, eey - ssy + 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, gClipImage);
            }
        }

    }
    else if (gStatus == 2) {
        glDispImage(gPatt.savedImage[check_num], &gARTCparam, 1.0, gPatt.arglSettings[check_num]);
        for (i = 0; i < gPatt.h_num*gPatt.v_num; i++) {
            x = gPatt.point[check_num][i].x_coord;
            y = gPatt.point[check_num][i].y_coord;
            glColor3f(1.0f, 0.0f, 0.0f);
            glBegin(GL_LINES);
            glVertex2d(x - 10.0, (GLdouble)(gYsize - 1) - y);
            glVertex2d(x + 10.0, (GLdouble)(gYsize - 1) - y);
            glVertex2d(x, (GLdouble)(gYsize - 1) - (y - 10.0));
            glVertex2d(x, (GLdouble)(gYsize - 1) - (y + 10.0));
            glEnd();
        }
        draw_line();

    }

    endOrtho2D();
    glutSwapBuffers();
}

arglDispImage()函数

void arglDispImage(ARUint8 *image, const ARParam *cparam, const double zoom, ARGL_CONTEXT_SETTINGS_REF contextSettings)
{
    GLint texEnvModeSave;   
    GLboolean lightingSave;
    GLboolean depthTestSave;
    if (!image) return;

// Prepare an orthographic projection, set camera position for 2D drawing, and save GL state.
// Save GL texture environment mode.    
    glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &texEnvModeSave); 
    if (texEnvModeSave != GL_REPLACE) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// Save enabled state of lighting.  
    lightingSave = glIsEnabled(GL_LIGHTING);        
    if (lightingSave == GL_TRUE) glDisable(GL_LIGHTING);
// Save enabled state of depth test.
    depthTestSave = glIsEnabled(GL_DEPTH_TEST);     
    if (depthTestSave == GL_TRUE) glDisable(GL_DEPTH_TEST);
//GL操作:将当前矩阵指定为 投影矩阵
    glMatrixMode(GL_PROJECTION);
//GL操作:将当前矩阵存入堆栈
    glPushMatrix();
//GL操作:重置当前指定矩阵为 单位矩阵
    glLoadIdentity();
//GL操作:通过正交投影,把景物1:1绘制到一个剪切面
    gluOrtho2D(0, cparam->xsize, 0, cparam->ysize);
//GL操作:将当前矩阵指定为 模型视景的操作
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    // Restore previous projection, camera position, and GL state.
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
// Restore enabled state of depth test.
    if (depthTestSave == GL_TRUE) glEnable(GL_DEPTH_TEST);  
// Restore enabled state of lighting.
    if (lightingSave == GL_TRUE) glEnable(GL_LIGHTING); 
// Restore GL texture environment mode.
    if (texEnvModeSave != GL_REPLACE) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texEnvModeSave); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值