uiplutils.cpp

来自「微软的基于HMM的人脸识别原代码, 非常经典的说」· C++ 代码 · 共 1,799 行 · 第 1/4 页

CPP
1,799
字号
                {
                    p = ((char*)data)[x*ch];
                }
                else
                {
                    p = ((int*)data)[x*ch]*2 != 0;
                }
                xp = x*p;
                tm0 += p;
                tm1 += xp;
                tm2 += ((int64)x2)*p;
                tm3 += ((int64)x2)*xp;
            }

            m00 += tm0;
            m10 += tm1;
            m01 += tm0*y;
            m20 += tm2;
            m11 += ((int64)tm1)*y;
            m02 += ((int64)tm0)*y2;
            m30 += tm3;
            m21 += tm2*y;
            m12 += ((int64)tm1)*y2;
            m03 += (((int64)tm0)*y2)*y;
        }

        if( m00 != 0 )
        {
            cx = ((double)m10)/m00;
            cy = ((double)m01)/m00;
        }

        s.m00 = (double)m00;
        s.m10 = (double)m10;
        s.m01 = (double)m01;
        s.m20 = (double)m20;
        s.m11 = (double)m11;
        s.m02 = (double)m02;
        s.m30 = (double)m30;
        s.m21 = (double)m21;
        s.m12 = (double)m12;
        s.m03 = (double)m03;
    }
    else /* floating-point spatial moments */
    {
        int x2, y2; /* x^2 & y^2 */
        float* data = (float*)img_data;

        assert( (img_step&3) == 0 );
        img_step /= 4;

        /* calc spatial moments */
        for( y = 0, y2 = 0; y < sz.height; y2 += 2*y + 1, y++, data += img_step )
        {
            double tm0 = 0, tm1 = 0, tm2 = 0, tm3 = 0;

            for( x = 0, x2 = 0; x < sz.width; x2 += 2*x + 1, x++ )
            {
                double p = data[x*ch], xp = x*p;
                tm0 += p;
                tm1 += xp;
                tm2 += x2*p;
                tm3 += x2*xp;
            }

            s.m00 += tm0;
            s.m10 += tm1;
            s.m01 += tm0*y;
            s.m20 += tm2;
            s.m11 += tm1*y;
            s.m02 += tm0*y2;
            s.m30 += tm3;
            s.m21 += tm2*y;
            s.m12 += tm1*y2;
            s.m03 += (tm0*y2)*y;
        }

        if( s.m00 != 0 )
        {
            cx = s.m10/s.m00;
            cy = s.m01/s.m00;
        }
        img_step *= 4;
    }

    /* calc central moments */
    for( y = 0; y < sz.height; y++, img_data += img_step )
    {
        double  tm0 = 0;
        double  tm1 = 0, tm2 = 0, tm3 = 0;
        double  yc = y - cy;
        double  yc2 = yc*yc;

        for( x = 0; x < sz.width; x++ )
        {
            double p;
            double xc = x - cx;
            double xc2 = xc*xc;
            double xcp;

            if( depth == IPL_DEPTH_8U )
            {
                p = binary ? img_data[x*ch] != 0 : img_data[x*ch];
            }
            else if( depth == IPL_DEPTH_8S )
            {
                p = ((char*)img_data)[x*ch];
            }
            else
            {
                p = binary ? ((int*)img_data)[x*ch]*2 != 0 : ((float*)img_data)[x*ch];
            }

            xcp = xc*p;
            tm0 += p;
            tm1 += xcp;
            tm2 += xc2*p;
            tm3 += xc2*xcp;
        }

        s.mu20 += tm2;
        s.mu11 += tm1*yc;
        s.mu02 += tm0*yc2;
        s.mu30 += tm3;
        s.mu21 += tm2*yc;
        s.mu12 += tm1*yc2;
        s.mu03 += tm0*yc2*yc;
    }

    /* calc normalized moments */
    {
        double inv_m00 = s.m00 == 0 ? 0 : 1./s.m00;
        double s2 = inv_m00*inv_m00; /* 1./(m00 ^ (2/2 + 1)) */
        double s3 = s2*sqrt(inv_m00); /* 1./(m00 ^ (3/2 + 1)) */

        s.nu20 = s.mu20 * s2;
        s.nu11 = s.mu11 * s2;
        s.nu02 = s.mu02 * s2;

        s.nu30 = s.mu30 * s3;
        s.nu21 = s.mu21 * s3;
        s.nu12 = s.mu12 * s3;
        s.nu03 = s.mu03 * s3;
    }

    *state = s;
}


/* The function draws line in 8uC1/C3 image */
void  atsDrawLine( IplImage* img, float x1, float y1, float x2, float y2, int color )
{
    float    dx = x2 - x1;
    float    dy = y2 - y1;
    float    adx = (float)fabs(dx);
    float    ady = (float)fabs(dy);
    float    steps = 0;
    uchar*   img_data;
    int      img_step;
    CvSize  sz;
    int      depth = 0, ch = 0, bt_pix = 0;

    uchar    b = (uchar)(color & 0xff);
    uchar    g = (uchar)((color >> 8) & 0xff);
    uchar    r = (uchar)((color >> 16) & 0xff);

    atsGetImageInfo( img, (void**)&img_data, &img_step, &sz, &depth, &ch, &bt_pix );

    assert( depth == IPL_DEPTH_8U );
    assert( ch == 1 || ch == 3);

    if( adx > ady )
    {
        dy /= adx;
        dx = dx > 0 ? 1.f : -1.f;
        steps = adx;
    }
    else if( ady != 0 )
    {
        dx /= ady;
        dy = dy > 0 ? 1.f : -1.f;
        steps = ady;
    }
    else
    {
        dx = dy = 0;
    }

    do
    {
        int x = atsRound(x1);
        int y = atsRound(y1);

        if( (unsigned)x < (unsigned)sz.width &&
            (unsigned)y < (unsigned)sz.height )
        {
            uchar* data = img_data + y*img_step + x*bt_pix;
            data[0] = b;
            if( ch == 3 )
            {
                data[1] = g;
                data[2] = r;
            }
        }

        x1 += dx;
        y1 += dy;
        steps--;
    }
    while( steps >= 0 );
}


/* The function draws ellipse arc in 8uC1/C3 image */
void  atsDrawEllipse( IplImage* img, float xc, float yc, float a, float b,
                      float angle, float arc0, float arc1, int color )
{
    assert( a >= b );
    if( a == 0 ) a = 0.1f;
    if( b == 0 ) b = 0.1f;
    {
    double  ba = b/a;
    double  e = sqrt( 1. - ba*ba);
    double  mag = b*ba;
    double  alpha, beta;
    double  c = a*e;
    double  x, y;
    double  a0 = arc0, a1 = arc1;
    double  ang;
    int     is_pt = arc0 == arc1;

    ang  = IPLsDegToRad(angle);
    alpha = cos(ang);
    beta  = sin(ang);

    if( a0 > a1 )
    {
        double temp = a0;
        a0 = a1;
        a1 = temp;
    }

    if( a1 - a0 >= 360 )
    {
        a0 = a1 = 0;
    }

    a0 = IPL_DegToRad(a0);
    a1 = IPL_DegToRad(a1);

    x = c + a*cos(a0);
    y = b*sin(a0);
    a0 = atan2( y, x )*180/IPL_PI;
    if( a0 < 0 ) a0 += 360.;

    if( is_pt )
        a0 = a1;
    else
    {
        x = c + a*cos(a1);
        y = b*sin(a1);
        a1 = atan2( y, x )*180/IPL_PI;
        if( a1 < 0 ) a1 += 360.f;
        if( a0 > a1 - 0.1 ) a0 -= 360;
    }

    xc = (float)( xc - c*alpha);
    yc = (float)( yc + c*beta);

    atsDrawConic( img, xc, yc, (float)mag, (float)e, angle, (float)a0, (float)a1, color );
    }
}


/* The function draws conic arc in 8uC1/C3 image */
void  atsDrawConic( IplImage* img, float xc, float yc, float mag, float e,
                    float angle, float arc0, float arc1, int color )
{
    int delta = 1;
    double  dang = IPL_PI*delta/180;
    double  alpha, beta;
    double  da = cos(dang), db = sin(dang);
    double  a, b;
    float   x1 = 0.f, y1 = 0.f;
    int     i, n, fl = 0;

    assert( mag > 0 && e >= 0 );

    angle = IPLsDegToRad(angle);
    alpha = cos(angle);
    beta  = sin(angle);

    if( arc0 > arc1 )
    {
        float temp = arc0;
        arc0 = arc1;
        arc1 = temp;
    }

    n = atsRound( arc1 - arc0 );
    if( n > 360 ) n = 360;

    arc0 = IPLsDegToRad(arc0);

    a = cos( arc0 );
    b = sin( arc0 );

    for( i = 0; i < n + delta; i += delta )
    {
        double d;

        if( i > n )
        {
            arc1 = IPLsDegToRad(arc1);
            a = cos(arc1);
            b = sin(arc1);
        }

        d = 1 - e*a;
        if( d != 0 )
        {
            double r = mag/d;
            double x = r*a;
            double y = r*b;
            float  x2 = (float)(xc + x*alpha - y*beta);
            float  y2 = (float)(yc - x*beta - y*alpha);
            if( fl ) atsDrawLine( img, x1, y1, x2, y2, color );
            x1 = x2;
            y1 = y2;
            fl = 1;
        }
        else
        {
            fl = 0;
        }
        d = a*da - b*db;
        b = a*db + b*da;
        a = d;
    }
}


static void _atsCalcConicPoint( double xc, double yc,
                                double mag, double e, double alpha,
                                double beta, double ang, CvPoint* pt )
{
    double a = cos( ang );
    double b = sin( ang );

    double d = 1 - e*a;
    if( d == 0 )
    {
        pt->x = pt->y = -10000;
    }
    else
    {
        d = mag/d;
        a *= d;
        b *= d;
        pt->x = atsRound( xc + alpha*a - beta*b );
        pt->y = atsRound( yc - beta*a - alpha*b );
    }
}


int  atsCalcQuadricCoeffs( double xc, double yc, double mag, double e,
                           double angle, double arc0, double arc1,
                           double* _A, double* _B, double* _C, double* _D, double* _E,
                           CvPoint* pt1, CvPoint* pt2 )
{
    double ang = angle*IPL_PI/180;
    double alpha = cos( ang );
    double beta = sin( ang );
    double alal = alpha*alpha;
    double bebe = beta*beta;
    double albe = alpha*beta;
    double a = 0, c = 0;
    double A = 0, B = 0, C = 0, D = 0, E = 0;
    double dx;
    int    code = 0;
    double cf_max = 0;
    /*double arcm; */
    /*int    oct1, oct2; */
    /*CvPoint ptm; */

    assert( mag > 0 && e >= 0 );

    if( arc0 > arc1 )
    {
        double temp = arc0;
        arc0 = arc1;
        arc1 = temp;
    }

    if( arc1 - arc0 > 360 )
    {
        arc0 = 0;
        arc1 = 360;
    }

    if( e != 1 ) /* non-parabolic case */
    {
        a = mag/fabs(e*e - 1);
        c = sqrt( mag*a );
        dx = a*e;
        a = 1./(a*a);
        c = 1./(c*c);
        D = -2*dx*a;
        if( e > 1 )
        {
            c = -c;
            D = -D;
        }
    }
    else
    {
        c = 1;
        dx = mag*0.5;
        D = -mag*2;
    }

    E = -beta*D;
    D *= alpha;

    /* rotate matrix */
    A = alal*a + bebe*c;
    B = albe*(c - a)*2;
    C = bebe*a + alal*c;

    /* move to (xc, yc) */
    D -= (2*A*xc + B*yc);
    E -= (B*xc + 2*C*yc);

    arc0 *= IPL_PI/180;
    arc1 *= IPL_PI/180;

    _atsCalcConicPoint( xc, yc, mag, e, alpha, beta, arc0, pt1 );
    if( pt1->x == -10000 ) code--;

    _atsCalcConicPoint( xc, yc, mag, e, alpha, beta, arc1, pt2 );
    if( pt2->x == -10000 ) code--;

    if( pt1->x == pt2->x && pt1->y == pt2->y )
    {
        if( arc1 - arc0 < 1.f ) code--;
    }

    if( fabs(A) > cf_max ) cf_max = fabs(A);
    if( fabs(B) > cf_max ) cf_max = fabs(B);
    if( fabs(C) > cf_max ) cf_max = fabs(C);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?