linefit.cpp 19 KB
Newer Older
wester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"

static const double eps = 1e-6;

wester committed
45 46
static CvStatus
icvFitLine2D_wods( CvPoint2D32f * points, int _count, float *weights, float *line )
wester committed
47 48 49 50
{
    double x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0;
    double dx2, dy2, dxy;
    int i;
wester committed
51
    int count = _count;
wester committed
52 53
    float t;

wester committed
54 55
    /* Calculating the average of x and y... */

wester committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    if( weights == 0 )
    {
        for( i = 0; i < count; i += 1 )
        {
            x += points[i].x;
            y += points[i].y;
            x2 += points[i].x * points[i].x;
            y2 += points[i].y * points[i].y;
            xy += points[i].x * points[i].y;
        }
        w = (float) count;
    }
    else
    {
        for( i = 0; i < count; i += 1 )
        {
            x += weights[i] * points[i].x;
            y += weights[i] * points[i].y;
            x2 += weights[i] * points[i].x * points[i].x;
            y2 += weights[i] * points[i].y * points[i].y;
            xy += weights[i] * points[i].x * points[i].y;
            w += weights[i];
        }
    }

    x /= w;
    y /= w;
    x2 /= w;
    y2 /= w;
    xy /= w;

    dx2 = x2 - x * x;
    dy2 = y2 - y * y;
    dxy = xy - x * y;

    t = (float) atan2( 2 * dxy, dx2 - dy2 ) / 2;
    line[0] = (float) cos( t );
    line[1] = (float) sin( t );

    line[2] = (float) x;
    line[3] = (float) y;
wester committed
97 98

    return CV_NO_ERR;
wester committed
99 100
}

wester committed
101 102
static CvStatus
icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line )
wester committed
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
{
    int i;
    float w0 = 0;
    float x0 = 0, y0 = 0, z0 = 0;
    float x2 = 0, y2 = 0, z2 = 0, xy = 0, yz = 0, xz = 0;
    float dx2, dy2, dz2, dxy, dxz, dyz;
    float *v;
    float n;
    float det[9], evc[9], evl[3];

    memset( evl, 0, 3*sizeof(evl[0]));
    memset( evc, 0, 9*sizeof(evl[0]));

    if( weights )
    {
        for( i = 0; i < count; i++ )
        {
            float x = points[i].x;
            float y = points[i].y;
            float z = points[i].z;
            float w = weights[i];


            x2 += x * x * w;
            xy += x * y * w;
            xz += x * z * w;
            y2 += y * y * w;
            yz += y * z * w;
            z2 += z * z * w;
            x0 += x * w;
            y0 += y * w;
            z0 += z * w;
            w0 += w;
        }
    }
    else
    {
        for( i = 0; i < count; i++ )
        {
            float x = points[i].x;
            float y = points[i].y;
            float z = points[i].z;

            x2 += x * x;
            xy += x * y;
            xz += x * z;
            y2 += y * y;
            yz += y * z;
            z2 += z * z;
            x0 += x;
            y0 += y;
            z0 += z;
        }
        w0 = (float) count;
    }

    x2 /= w0;
    xy /= w0;
    xz /= w0;
    y2 /= w0;
    yz /= w0;
    z2 /= w0;

    x0 /= w0;
    y0 /= w0;
    z0 /= w0;

    dx2 = x2 - x0 * x0;
    dxy = xy - x0 * y0;
    dxz = xz - x0 * z0;
    dy2 = y2 - y0 * y0;
    dyz = yz - y0 * z0;
    dz2 = z2 - z0 * z0;

    det[0] = dz2 + dy2;
    det[1] = -dxy;
    det[2] = -dxz;
    det[3] = det[1];
    det[4] = dx2 + dz2;
    det[5] = -dyz;
    det[6] = det[2];
    det[7] = det[5];
    det[8] = dy2 + dx2;

wester committed
187 188 189 190 191 192 193
    /* Searching for a eigenvector of det corresponding to the minimal eigenvalue */
#if 1
    {
    CvMat _det = cvMat( 3, 3, CV_32F, det );
    CvMat _evc = cvMat( 3, 3, CV_32F, evc );
    CvMat _evl = cvMat( 3, 1, CV_32F, evl );
    cvEigenVV( &_det, &_evc, &_evl, 0 );
wester committed
194
    i = evl[0] < evl[1] ? (evl[0] < evl[2] ? 0 : 2) : (evl[1] < evl[2] ? 1 : 2);
wester committed
195 196 197 198 199 200
    }
#else
    {
        CvMat _det = cvMat( 3, 3, CV_32F, det );
        CvMat _evc = cvMat( 3, 3, CV_32F, evc );
        CvMat _evl = cvMat( 1, 3, CV_32F, evl );
wester committed
201

wester committed
202 203 204 205
        cvSVD( &_det, &_evl, &_evc, 0, CV_SVD_MODIFY_A+CV_SVD_U_T );
    }
    i = 2;
#endif
wester committed
206
    v = &evc[i * 3];
wester committed
207
    n = (float) sqrt( (double)v[0] * v[0] + (double)v[1] * v[1] + (double)v[2] * v[2] );
wester committed
208 209 210 211 212 213 214
    n = (float)MAX(n, eps);
    line[0] = v[0] / n;
    line[1] = v[1] / n;
    line[2] = v[2] / n;
    line[3] = x0;
    line[4] = y0;
    line[5] = z0;
wester committed
215 216

    return CV_NO_ERR;
wester committed
217 218
}

wester committed
219 220
static double
icvCalcDist2D( CvPoint2D32f * points, int count, float *_line, float *dist )
wester committed
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
{
    int j;
    float px = _line[2], py = _line[3];
    float nx = _line[1], ny = -_line[0];
    double sum_dist = 0.;

    for( j = 0; j < count; j++ )
    {
        float x, y;

        x = points[j].x - px;
        y = points[j].y - py;

        dist[j] = (float) fabs( nx * x + ny * y );
        sum_dist += dist[j];
    }

    return sum_dist;
}

wester committed
241 242
static double
icvCalcDist3D( CvPoint3D32f * points, int count, float *_line, float *dist )
wester committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
{
    int j;
    float px = _line[3], py = _line[4], pz = _line[5];
    float vx = _line[0], vy = _line[1], vz = _line[2];
    double sum_dist = 0.;

    for( j = 0; j < count; j++ )
    {
        float x, y, z;
        double p1, p2, p3;

        x = points[j].x - px;
        y = points[j].y - py;
        z = points[j].z - pz;

        p1 = vy * z - vz * y;
        p2 = vz * x - vx * z;
        p3 = vx * y - vy * x;

wester committed
262
        dist[j] = (float) sqrt( p1*p1 + p2*p2 + p3*p3 );
wester committed
263 264 265 266 267 268
        sum_dist += dist[j];
    }

    return sum_dist;
}

wester committed
269 270
static void
icvWeightL1( float *d, int count, float *w )
wester committed
271 272 273 274 275 276 277 278 279 280
{
    int i;

    for( i = 0; i < count; i++ )
    {
        double t = fabs( (double) d[i] );
        w[i] = (float)(1. / MAX(t, eps));
    }
}

wester committed
281 282
static void
icvWeightL12( float *d, int count, float *w )
wester committed
283 284 285 286 287
{
    int i;

    for( i = 0; i < count; i++ )
    {
wester committed
288
        w[i] = 1.0f / (float) sqrt( 1 + (double) (d[i] * d[i] * 0.5) );
wester committed
289 290 291 292
    }
}


wester committed
293 294
static void
icvWeightHuber( float *d, int count, float *w, float _c )
wester committed
295 296 297 298 299 300 301 302 303 304 305 306 307 308
{
    int i;
    const float c = _c <= 0 ? 1.345f : _c;

    for( i = 0; i < count; i++ )
    {
        if( d[i] < c )
            w[i] = 1.0f;
        else
            w[i] = c/d[i];
    }
}


wester committed
309 310
static void
icvWeightFair( float *d, int count, float *w, float _c )
wester committed
311 312 313 314 315 316 317 318 319 320
{
    int i;
    const float c = _c == 0 ? 1 / 1.3998f : 1 / _c;

    for( i = 0; i < count; i++ )
    {
        w[i] = 1 / (1 + d[i] * c);
    }
}

wester committed
321 322
static void
icvWeightWelsch( float *d, int count, float *w, float _c )
wester committed
323 324 325 326 327 328
{
    int i;
    const float c = _c == 0 ? 1 / 2.9846f : 1 / _c;

    for( i = 0; i < count; i++ )
    {
wester committed
329
        w[i] = (float) exp( -d[i] * d[i] * c * c );
wester committed
330 331 332 333 334
    }
}


/* Takes an array of 2D points, type of distance (including user-defined
wester committed
335 336 337
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, where (A, B) is the normalized direction vector,
(C, D) is the point that belongs to the line. */
wester committed
338

wester committed
339 340
static CvStatus  icvFitLine2D( CvPoint2D32f * points, int count, int dist,
                               float _param, float reps, float aeps, float *line )
wester committed
341 342 343 344
{
    double EPS = count*FLT_EPSILON;
    void (*calc_weights) (float *, int, float *) = 0;
    void (*calc_weights_param) (float *, int, float *, float) = 0;
wester committed
345 346
    float *w;                   /* weights */
    float *r;                   /* square distances */
wester committed
347 348 349 350 351
    int i, j, k;
    float _line[6], _lineprev[6];
    float rdelta = reps != 0 ? reps : 1.0f;
    float adelta = aeps != 0 ? aeps : 0.01f;
    double min_err = DBL_MAX, err = 0;
wester committed
352
    CvRNG rng = cvRNG(-1);
wester committed
353 354 355 356 357 358

    memset( line, 0, 4*sizeof(line[0]) );

    switch (dist)
    {
    case CV_DIST_L2:
wester committed
359
        return icvFitLine2D_wods( points, count, 0, line );
wester committed
360 361

    case CV_DIST_L1:
wester committed
362
        calc_weights = icvWeightL1;
wester committed
363 364 365
        break;

    case CV_DIST_L12:
wester committed
366
        calc_weights = icvWeightL12;
wester committed
367 368 369
        break;

    case CV_DIST_FAIR:
wester committed
370
        calc_weights_param = icvWeightFair;
wester committed
371 372 373
        break;

    case CV_DIST_WELSCH:
wester committed
374
        calc_weights_param = icvWeightWelsch;
wester committed
375 376 377
        break;

    case CV_DIST_HUBER:
wester committed
378
        calc_weights_param = icvWeightHuber;
wester committed
379 380
        break;

wester committed
381 382 383 384
    /*case CV_DIST_USER:
        calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
        break;*/

wester committed
385
    default:
wester committed
386
        return CV_BADFACTOR_ERR;
wester committed
387 388
    }

wester committed
389 390
    w = (float *) cvAlloc( count * sizeof( float ));
    r = (float *) cvAlloc( count * sizeof( float ));
wester committed
391 392 393 394 395 396 397 398 399

    for( k = 0; k < 20; k++ )
    {
        int first = 1;
        for( i = 0; i < count; i++ )
            w[i] = 0.f;

        for( i = 0; i < MIN(count,10); )
        {
wester committed
400
            j = cvRandInt(&rng) % count;
wester committed
401 402 403 404 405 406 407
            if( w[j] < FLT_EPSILON )
            {
                w[j] = 1.f;
                i++;
            }
        }

wester committed
408
        icvFitLine2D_wods( points, count, w, _line );
wester committed
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
        for( i = 0; i < 30; i++ )
        {
            double sum_w = 0;

            if( first )
            {
                first = 0;
            }
            else
            {
                double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1];
                t = MAX(t,-1.);
                t = MIN(t,1.);
                if( fabs(acos(t)) < adelta )
                {
                    float x, y, d;

                    x = (float) fabs( _line[2] - _lineprev[2] );
                    y = (float) fabs( _line[3] - _lineprev[3] );

                    d = x > y ? x : y;
                    if( d < rdelta )
                        break;
                }
            }
            /* calculate distances */
wester committed
435
            err = icvCalcDist2D( points, count, _line, r );
wester committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
            if( err < EPS )
                break;

            /* calculate weights */
            if( calc_weights )
                calc_weights( r, count, w );
            else
                calc_weights_param( r, count, w, _param );

            for( j = 0; j < count; j++ )
                sum_w += w[j];

            if( fabs(sum_w) > FLT_EPSILON )
            {
                sum_w = 1./sum_w;
                for( j = 0; j < count; j++ )
                    w[j] = (float)(w[j]*sum_w);
            }
            else
            {
                for( j = 0; j < count; j++ )
                    w[j] = 1.f;
            }

            /* save the line parameters */
            memcpy( _lineprev, _line, 4 * sizeof( float ));

            /* Run again... */
wester committed
464
            icvFitLine2D_wods( points, count, w, _line );
wester committed
465 466 467 468 469 470 471 472 473 474
        }

        if( err < min_err )
        {
            min_err = err;
            memcpy( line, _line, 4 * sizeof(line[0]));
            if( err < EPS )
                break;
        }
    }
wester committed
475 476 477 478

    cvFree( &w );
    cvFree( &r );
    return CV_OK;
wester committed
479 480 481 482
}


/* Takes an array of 3D points, type of distance (including user-defined
wester committed
483 484 485 486 487 488 489
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, E, F, where (A, B, C) is the normalized direction vector,
(D, E, F) is the point that belongs to the line. */

static CvStatus
icvFitLine3D( CvPoint3D32f * points, int count, int dist,
              float _param, float reps, float aeps, float *line )
wester committed
490 491 492 493
{
    double EPS = count*FLT_EPSILON;
    void (*calc_weights) (float *, int, float *) = 0;
    void (*calc_weights_param) (float *, int, float *, float) = 0;
wester committed
494 495
    float *w;                   /* weights */
    float *r;                   /* square distances */
wester committed
496 497 498 499 500
    int i, j, k;
    float _line[6]={0,0,0,0,0,0}, _lineprev[6]={0,0,0,0,0,0};
    float rdelta = reps != 0 ? reps : 1.0f;
    float adelta = aeps != 0 ? aeps : 0.01f;
    double min_err = DBL_MAX, err = 0;
wester committed
501
    CvRNG rng = cvRNG(-1);
wester committed
502 503 504 505

    switch (dist)
    {
    case CV_DIST_L2:
wester committed
506
        return icvFitLine3D_wods( points, count, 0, line );
wester committed
507 508

    case CV_DIST_L1:
wester committed
509
        calc_weights = icvWeightL1;
wester committed
510 511 512
        break;

    case CV_DIST_L12:
wester committed
513
        calc_weights = icvWeightL12;
wester committed
514 515 516
        break;

    case CV_DIST_FAIR:
wester committed
517
        calc_weights_param = icvWeightFair;
wester committed
518 519 520
        break;

    case CV_DIST_WELSCH:
wester committed
521
        calc_weights_param = icvWeightWelsch;
wester committed
522 523 524
        break;

    case CV_DIST_HUBER:
wester committed
525
        calc_weights_param = icvWeightHuber;
wester committed
526 527
        break;

wester committed
528 529 530 531 532
    /*case CV_DIST_USER:
        _PFP.p = param;
        calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
        break;*/

wester committed
533
    default:
wester committed
534
        return CV_BADFACTOR_ERR;
wester committed
535 536
    }

wester committed
537 538
    w = (float *) cvAlloc( count * sizeof( float ));
    r = (float *) cvAlloc( count * sizeof( float ));
wester committed
539 540 541 542 543 544 545 546 547

    for( k = 0; k < 20; k++ )
    {
        int first = 1;
        for( i = 0; i < count; i++ )
            w[i] = 0.f;

        for( i = 0; i < MIN(count,10); )
        {
wester committed
548
            j = cvRandInt(&rng) % count;
wester committed
549 550 551 552 553 554 555
            if( w[j] < FLT_EPSILON )
            {
                w[j] = 1.f;
                i++;
            }
        }

wester committed
556
        icvFitLine3D_wods( points, count, w, _line );
wester committed
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
        for( i = 0; i < 30; i++ )
        {
            double sum_w = 0;

            if( first )
            {
                first = 0;
            }
            else
            {
                double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1] + _line[2] * _lineprev[2];
                t = MAX(t,-1.);
                t = MIN(t,1.);
                if( fabs(acos(t)) < adelta )
                {
                    float x, y, z, ax, ay, az, dx, dy, dz, d;

                    x = _line[3] - _lineprev[3];
                    y = _line[4] - _lineprev[4];
                    z = _line[5] - _lineprev[5];
                    ax = _line[0] - _lineprev[0];
                    ay = _line[1] - _lineprev[1];
                    az = _line[2] - _lineprev[2];
                    dx = (float) fabs( y * az - z * ay );
                    dy = (float) fabs( z * ax - x * az );
                    dz = (float) fabs( x * ay - y * ax );

                    d = dx > dy ? (dx > dz ? dx : dz) : (dy > dz ? dy : dz);
                    if( d < rdelta )
                        break;
                }
            }
            /* calculate distances */
wester committed
590 591
            if( icvCalcDist3D( points, count, _line, r ) < FLT_EPSILON*count )
                break;
wester committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617

            /* calculate weights */
            if( calc_weights )
                calc_weights( r, count, w );
            else
                calc_weights_param( r, count, w, _param );

            for( j = 0; j < count; j++ )
                sum_w += w[j];

            if( fabs(sum_w) > FLT_EPSILON )
            {
                sum_w = 1./sum_w;
                for( j = 0; j < count; j++ )
                    w[j] = (float)(w[j]*sum_w);
            }
            else
            {
                for( j = 0; j < count; j++ )
                    w[j] = 1.f;
            }

            /* save the line parameters */
            memcpy( _lineprev, _line, 6 * sizeof( float ));

            /* Run again... */
wester committed
618
            icvFitLine3D_wods( points, count, w, _line );
wester committed
619 620 621 622 623 624 625 626 627 628 629
        }

        if( err < min_err )
        {
            min_err = err;
            memcpy( line, _line, 6 * sizeof(line[0]));
            if( err < EPS )
                break;
        }
    }

wester committed
630 631 632 633
    // Return...
    cvFree( &w );
    cvFree( &r );
    return CV_OK;
wester committed
634 635
}

wester committed
636 637 638 639

CV_IMPL void
cvFitLine( const CvArr* array, int dist, double param,
           double reps, double aeps, float *line )
wester committed
640
{
wester committed
641
    cv::AutoBuffer<schar> buffer;
wester committed
642

wester committed
643 644 645 646 647
    schar* points = 0;
    union { CvContour contour; CvSeq seq; } header;
    CvSeqBlock block;
    CvSeq* ptseq = (CvSeq*)array;
    int type;
wester committed
648

wester committed
649 650
    if( !line )
        CV_Error( CV_StsNullPtr, "NULL pointer to line parameters" );
wester committed
651

wester committed
652
    if( CV_IS_SEQ(ptseq) )
wester committed
653
    {
wester committed
654 655 656 657 658 659 660
        type = CV_SEQ_ELTYPE(ptseq);
        if( ptseq->total == 0 )
            CV_Error( CV_StsBadSize, "The sequence has no points" );
        if( (type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
            CV_ELEM_SIZE(type) != ptseq->elem_size )
            CV_Error( CV_StsUnsupportedFormat,
                "Input sequence must consist of 2d points or 3d points" );
wester committed
661 662
    }
    else
wester committed
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
    {
        CvMat* mat = (CvMat*)array;
        type = CV_MAT_TYPE(mat->type);
        if( !CV_IS_MAT(mat))
            CV_Error( CV_StsBadArg, "Input array is not a sequence nor matrix" );

        if( !CV_IS_MAT_CONT(mat->type) ||
            (type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
            (mat->width != 1 && mat->height != 1))
            CV_Error( CV_StsBadArg,
            "Input array must be 1d continuous array of 2d or 3d points" );

        ptseq = cvMakeSeqHeaderForArray(
            CV_SEQ_KIND_GENERIC|type, sizeof(CvContour), CV_ELEM_SIZE(type), mat->data.ptr,
            mat->width + mat->height - 1, &header.seq, &block );
    }
wester committed
679

wester committed
680 681
    if( reps < 0 || aeps < 0 )
        CV_Error( CV_StsOutOfRange, "Both reps and aeps must be non-negative" );
wester committed
682

wester committed
683 684 685 686 687 688 689 690 691 692
    if( CV_MAT_DEPTH(type) == CV_32F && ptseq->first->next == ptseq->first )
    {
        /* no need to copy data in this case */
        points = ptseq->first->data;
    }
    else
    {
        buffer.allocate(ptseq->total*CV_ELEM_SIZE(type));
        points = buffer;
        cvCvtSeqToArray( ptseq, points, CV_WHOLE_SEQ );
wester committed
693

wester committed
694 695 696 697 698 699 700 701 702
        if( CV_MAT_DEPTH(type) != CV_32F )
        {
            int i, total = ptseq->total*CV_MAT_CN(type);
            assert( CV_MAT_DEPTH(type) == CV_32S );

            for( i = 0; i < total; i++ )
                ((float*)points)[i] = (float)((int*)points)[i];
        }
    }
wester committed
703

wester committed
704 705
    if( dist == CV_DIST_USER )
        CV_Error( CV_StsBadArg, "User-defined distance is not allowed" );
wester committed
706

wester committed
707 708 709 710 711 712 713 714 715 716
    if( CV_MAT_CN(type) == 2 )
    {
        IPPI_CALL( icvFitLine2D( (CvPoint2D32f*)points, ptseq->total,
                                 dist, (float)param, (float)reps, (float)aeps, line ));
    }
    else
    {
        IPPI_CALL( icvFitLine3D( (CvPoint3D32f*)points, ptseq->total,
                                 dist, (float)param, (float)reps, (float)aeps, line ));
    }
wester committed
717 718 719
}

/* End of file. */