1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // Intel License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 22 // * Redistribution's in binary form must reproduce the above copyright notice, 23 // this list of conditions and the following disclaimer in the documentation 24 // and/or other materials provided with the distribution. 25 // 26 // * The name of Intel Corporation may not be used to endorse or promote products 27 // derived from this software without specific prior written permission. 28 // 29 // This software is provided by the copyright holders and contributors "as is" and 30 // any express or implied warranties, including, but not limited to, the implied 31 // warranties of merchantability and fitness for a particular purpose are disclaimed. 32 // In no event shall the Intel Corporation or contributors be liable for any direct, 33 // indirect, incidental, special, exemplary, or consequential damages 34 // (including, but not limited to, procurement of substitute goods or services; 35 // loss of use, data, or profits; or business interruption) however caused 36 // and on any theory of liability, whether in contract, strict liability, 37 // or tort (including negligence or otherwise) arising in any way out of 38 // the use of this software, even if advised of the possibility of such damage. 39 // 40 //M*/ 41 42 #include "_cvaux.h" 43 //#include "cvtypes.h" 44 //#include <float.h> 45 //#include <limits.h> 46 //#include "cv.h" 47 //#include "highgui.h" 48 49 #include <stdio.h> 50 51 /* Valery Mosyagin */ 52 53 /* ===== Function for find corresponding between images ===== */ 54 55 /* Create feature points on image and return number of them. Array points fills by found points */ 56 int icvCreateFeaturePoints(IplImage *image, CvMat *points, CvMat *status) 57 { 58 int foundFeaturePoints = 0; 59 IplImage *grayImage = 0; 60 IplImage *eigImage = 0; 61 IplImage *tmpImage = 0; 62 CvPoint2D32f *cornerPoints = 0; 63 64 CV_FUNCNAME( "icvFeatureCreatePoints" ); 65 __BEGIN__; 66 67 /* Test for errors */ 68 if( image == 0 || points == 0 ) 69 { 70 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 71 } 72 73 /* Test image size */ 74 int w,h; 75 w = image->width; 76 h = image->height; 77 78 if( w <= 0 || h <= 0) 79 { 80 CV_ERROR( CV_StsOutOfRange, "Size of image must be > 0" ); 81 } 82 83 /* Test for matrices */ 84 if( !CV_IS_MAT(points) ) 85 { 86 CV_ERROR( CV_StsUnsupportedFormat, "Input parameter points must be a matrix" ); 87 } 88 89 int needNumPoints; 90 needNumPoints = points->cols; 91 if( needNumPoints <= 0 ) 92 { 93 CV_ERROR( CV_StsOutOfRange, "Number of need points must be > 0" ); 94 } 95 96 if( points->rows != 2 ) 97 { 98 CV_ERROR( CV_StsOutOfRange, "Number of point coordinates must be == 2" ); 99 } 100 101 if( status != 0 ) 102 { 103 /* If status matrix exist test it for correct */ 104 if( !CV_IS_MASK_ARR(status) ) 105 { 106 CV_ERROR( CV_StsUnsupportedFormat, "Statuses must be a mask arrays" ); 107 } 108 109 if( status->cols != needNumPoints ) 110 { 111 CV_ERROR( CV_StsUnmatchedSizes, "Size of points and statuses must be the same" ); 112 } 113 114 if( status->rows !=1 ) 115 { 116 CV_ERROR( CV_StsUnsupportedFormat, "Number of rows of status must be 1" ); 117 } 118 } 119 120 /* Create temporary images */ 121 CV_CALL( grayImage = cvCreateImage(cvSize(w,h), 8,1) ); 122 CV_CALL( eigImage = cvCreateImage(cvSize(w,h),32,1) ); 123 CV_CALL( tmpImage = cvCreateImage(cvSize(w,h),32,1) ); 124 125 /* Create points */ 126 CV_CALL( cornerPoints = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f) * needNumPoints) ); 127 128 int foundNum; 129 double quality; 130 double minDist; 131 132 cvCvtColor(image,grayImage, CV_BGR2GRAY); 133 134 foundNum = needNumPoints; 135 quality = 0.01; 136 minDist = 5; 137 cvGoodFeaturesToTrack(grayImage, eigImage, tmpImage, cornerPoints, &foundNum, quality, minDist); 138 139 /* Copy found points to result */ 140 int i; 141 for( i = 0; i < foundNum; i++ ) 142 { 143 cvmSet(points,0,i,cornerPoints[i].x); 144 cvmSet(points,1,i,cornerPoints[i].y); 145 } 146 147 /* Set status if need */ 148 if( status ) 149 { 150 for( i = 0; i < foundNum; i++ ) 151 { 152 status->data.ptr[i] = 1; 153 } 154 155 for( i = foundNum; i < needNumPoints; i++ ) 156 { 157 status->data.ptr[i] = 0; 158 } 159 } 160 161 foundFeaturePoints = foundNum; 162 163 __END__; 164 165 /* Free allocated memory */ 166 cvReleaseImage(&grayImage); 167 cvReleaseImage(&eigImage); 168 cvReleaseImage(&tmpImage); 169 cvFree(&cornerPoints); 170 171 return foundFeaturePoints; 172 } 173 174 /*-------------------------------------------------------------------------------------*/ 175 176 /* For given points1 (with pntStatus) on image1 finds corresponding points2 on image2 and set pntStatus2 for them */ 177 /* Returns number of corresponding points */ 178 int icvFindCorrForGivenPoints( IplImage *image1,/* Image 1 */ 179 IplImage *image2,/* Image 2 */ 180 CvMat *points1, 181 CvMat *pntStatus1, 182 CvMat *points2, 183 CvMat *pntStatus2, 184 int useFilter,/*Use fundamental matrix to filter points */ 185 double threshold)/* Threshold for good points in filter */ 186 { 187 int resNumCorrPoints = 0; 188 CvPoint2D32f* cornerPoints1 = 0; 189 CvPoint2D32f* cornerPoints2 = 0; 190 char* status = 0; 191 float* errors = 0; 192 CvMat* tmpPoints1 = 0; 193 CvMat* tmpPoints2 = 0; 194 CvMat* pStatus = 0; 195 IplImage *grayImage1 = 0; 196 IplImage *grayImage2 = 0; 197 IplImage *pyrImage1 = 0; 198 IplImage *pyrImage2 = 0; 199 200 CV_FUNCNAME( "icvFindCorrForGivenPoints" ); 201 __BEGIN__; 202 203 /* Test input data for errors */ 204 205 /* Test for null pointers */ 206 if( image1 == 0 || image2 == 0 || 207 points1 == 0 || points2 == 0 || 208 pntStatus1 == 0 || pntStatus2 == 0) 209 { 210 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 211 } 212 213 /* Test image size */ 214 int w,h; 215 w = image1->width; 216 h = image1->height; 217 218 if( w <= 0 || h <= 0) 219 { 220 CV_ERROR( CV_StsOutOfRange, "Size of image1 must be > 0" ); 221 } 222 223 if( image2->width != w || image2->height != h ) 224 { 225 CV_ERROR( CV_StsUnmatchedSizes, "Size of images must be the same" ); 226 } 227 228 /* Test for matrices */ 229 if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || 230 !CV_IS_MAT(pntStatus1) || !CV_IS_MAT(pntStatus2) ) 231 { 232 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters (points and status) must be a matrices" ); 233 } 234 235 /* Test type of status matrices */ 236 if( !CV_IS_MASK_ARR(pntStatus1) || !CV_IS_MASK_ARR(pntStatus2) ) 237 { 238 CV_ERROR( CV_StsUnsupportedFormat, "Statuses must be a mask arrays" ); 239 } 240 241 /* Test number of points */ 242 int numPoints; 243 numPoints = points1->cols; 244 245 if( numPoints <= 0 ) 246 { 247 CV_ERROR( CV_StsOutOfRange, "Number of points1 must be > 0" ); 248 } 249 250 if( points2->cols != numPoints || pntStatus1->cols != numPoints || pntStatus2->cols != numPoints ) 251 { 252 CV_ERROR( CV_StsUnmatchedSizes, "Number of points and statuses must be the same" ); 253 } 254 255 if( points1->rows != 2 || points2->rows != 2 ) 256 { 257 CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be 2" ); 258 } 259 260 if( pntStatus1->rows != 1 || pntStatus2->rows != 1 ) 261 { 262 CV_ERROR( CV_StsOutOfRange, "Status must be a matrix 1xN" ); 263 } 264 /* ----- End test ----- */ 265 266 267 /* Compute number of visible points on image1 */ 268 int numVisPoints; 269 numVisPoints = cvCountNonZero(pntStatus1); 270 271 if( numVisPoints > 0 ) 272 { 273 /* Create temporary images */ 274 /* We must use iplImage againts hughgui images */ 275 276 /* 277 CvvImage grayImage1; 278 CvvImage grayImage2; 279 CvvImage pyrImage1; 280 CvvImage pyrImage2; 281 */ 282 283 /* Create Ipl images */ 284 CV_CALL( grayImage1 = cvCreateImage(cvSize(w,h),8,1) ); 285 CV_CALL( grayImage2 = cvCreateImage(cvSize(w,h),8,1) ); 286 CV_CALL( pyrImage1 = cvCreateImage(cvSize(w,h),8,1) ); 287 CV_CALL( pyrImage2 = cvCreateImage(cvSize(w,h),8,1) ); 288 289 CV_CALL( cornerPoints1 = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f)*numVisPoints) ); 290 CV_CALL( cornerPoints2 = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f)*numVisPoints) ); 291 CV_CALL( status = (char*)cvAlloc( sizeof(char)*numVisPoints) ); 292 CV_CALL( errors = (float*)cvAlloc( 2 * sizeof(float)*numVisPoints) ); 293 294 int i; 295 for( i = 0; i < numVisPoints; i++ ) 296 { 297 status[i] = 1; 298 } 299 300 /* !!! Need test creation errors */ 301 /* 302 if( !grayImage1.Create(w,h,8)) EXIT; 303 if( !grayImage2.Create(w,h,8)) EXIT; 304 if( !pyrImage1. Create(w,h,8)) EXIT; 305 if( !pyrImage2. Create(w,h,8)) EXIT; 306 */ 307 308 cvCvtColor(image1,grayImage1,CV_BGR2GRAY); 309 cvCvtColor(image2,grayImage2,CV_BGR2GRAY); 310 311 /* 312 grayImage1.CopyOf(image1,0); 313 grayImage2.CopyOf(image2,0); 314 */ 315 316 /* Copy points good points from input data */ 317 uchar *stat1 = pntStatus1->data.ptr; 318 uchar *stat2 = pntStatus2->data.ptr; 319 320 int curr = 0; 321 for( i = 0; i < numPoints; i++ ) 322 { 323 if( stat1[i] ) 324 { 325 cornerPoints1[curr].x = (float)cvmGet(points1,0,i); 326 cornerPoints1[curr].y = (float)cvmGet(points1,1,i); 327 curr++; 328 } 329 } 330 331 /* Define number of levels of pyramid */ 332 cvCalcOpticalFlowPyrLK( grayImage1, grayImage2, 333 pyrImage1, pyrImage2, 334 cornerPoints1, cornerPoints2, 335 numVisPoints, cvSize(10,10), 3, 336 status, errors, 337 cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), 338 0/*CV_LKFLOW_PYR_A_READY*/ ); 339 340 341 memset(stat2,0,sizeof(uchar)*numPoints); 342 343 int currVis = 0; 344 int totalCorns = 0; 345 346 /* Copy new points and set status */ 347 /* stat1 may not be the same as stat2 */ 348 for( i = 0; i < numPoints; i++ ) 349 { 350 if( stat1[i] ) 351 { 352 if( status[currVis] && errors[currVis] < 1000 ) 353 { 354 stat2[i] = 1; 355 cvmSet(points2,0,i,cornerPoints2[currVis].x); 356 cvmSet(points2,1,i,cornerPoints2[currVis].y); 357 totalCorns++; 358 } 359 currVis++; 360 } 361 } 362 363 resNumCorrPoints = totalCorns; 364 365 /* Filter points using RANSAC */ 366 if( useFilter ) 367 { 368 resNumCorrPoints = 0; 369 /* Use RANSAC filter for found points */ 370 if( totalCorns > 7 ) 371 { 372 /* Create array with good points only */ 373 CV_CALL( tmpPoints1 = cvCreateMat(2,totalCorns,CV_64F) ); 374 CV_CALL( tmpPoints2 = cvCreateMat(2,totalCorns,CV_64F) ); 375 376 /* Copy just good points */ 377 int currPoint = 0; 378 for( i = 0; i < numPoints; i++ ) 379 { 380 if( stat2[i] ) 381 { 382 cvmSet(tmpPoints1,0,currPoint,cvmGet(points1,0,i)); 383 cvmSet(tmpPoints1,1,currPoint,cvmGet(points1,1,i)); 384 385 cvmSet(tmpPoints2,0,currPoint,cvmGet(points2,0,i)); 386 cvmSet(tmpPoints2,1,currPoint,cvmGet(points2,1,i)); 387 388 currPoint++; 389 } 390 } 391 392 /* Compute fundamental matrix */ 393 CvMat fundMatr; 394 double fundMatr_dat[9]; 395 fundMatr = cvMat(3,3,CV_64F,fundMatr_dat); 396 397 CV_CALL( pStatus = cvCreateMat(1,totalCorns,CV_32F) ); 398 399 int num = cvFindFundamentalMat(tmpPoints1,tmpPoints2,&fundMatr,CV_FM_RANSAC,threshold,0.99,pStatus); 400 if( num > 0 ) 401 { 402 int curr = 0; 403 /* Set final status for points2 */ 404 for( i = 0; i < numPoints; i++ ) 405 { 406 if( stat2[i] ) 407 { 408 if( cvmGet(pStatus,0,curr) == 0 ) 409 { 410 stat2[i] = 0; 411 } 412 curr++; 413 } 414 } 415 resNumCorrPoints = curr; 416 } 417 } 418 } 419 } 420 421 __END__; 422 423 /* Free allocated memory */ 424 cvFree(&cornerPoints1); 425 cvFree(&cornerPoints2); 426 cvFree(&status); 427 cvFree(&errors); 428 cvFree(&tmpPoints1); 429 cvFree(&tmpPoints2); 430 cvReleaseMat( &pStatus ); 431 cvReleaseImage( &grayImage1 ); 432 cvReleaseImage( &grayImage2 ); 433 cvReleaseImage( &pyrImage1 ); 434 cvReleaseImage( &pyrImage2 ); 435 436 return resNumCorrPoints; 437 } 438 /*-------------------------------------------------------------------------------------*/ 439 int icvGrowPointsAndStatus(CvMat **oldPoints,CvMat **oldStatus,CvMat *addPoints,CvMat *addStatus,int addCreateNum) 440 { 441 /* Add to existing points and status arrays new points or just grow */ 442 CvMat *newOldPoint = 0; 443 CvMat *newOldStatus = 0; 444 int newTotalNumber = 0; 445 446 CV_FUNCNAME( "icvGrowPointsAndStatus" ); 447 __BEGIN__; 448 449 /* Test for errors */ 450 if( oldPoints == 0 || oldStatus == 0 ) 451 { 452 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 453 } 454 455 if( *oldPoints == 0 || *oldStatus == 0 ) 456 { 457 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 458 } 459 460 if( !CV_IS_MAT(*oldPoints)) 461 { 462 CV_ERROR( CV_StsUnsupportedFormat, "oldPoints must be a pointer to a matrix" ); 463 } 464 465 if( !CV_IS_MASK_ARR(*oldStatus)) 466 { 467 CV_ERROR( CV_StsUnsupportedFormat, "oldStatus must be a pointer to a mask array" ); 468 } 469 470 int oldNum; 471 oldNum = (*oldPoints)->cols; 472 if( oldNum < 1 ) 473 { 474 CV_ERROR( CV_StsOutOfRange, "Number of old points must be > 0" ); 475 } 476 477 /* Define if need number of add points */ 478 int addNum; 479 addNum = 0; 480 if( addPoints != 0 && addStatus != 0 ) 481 {/* We have aditional points */ 482 if( CV_IS_MAT(addPoints) && CV_IS_MASK_ARR(addStatus) ) 483 { 484 addNum = addPoints->cols; 485 if( addStatus->cols != addNum ) 486 { 487 CV_ERROR( CV_StsOutOfRange, "Number of add points and statuses must be the same" ); 488 } 489 } 490 } 491 492 /* */ 493 494 int numCoord; 495 numCoord = (*oldPoints)->rows; 496 newTotalNumber = oldNum + addNum + addCreateNum; 497 498 if( newTotalNumber ) 499 { 500 /* Free allocated memory */ 501 newOldPoint = cvCreateMat(numCoord,newTotalNumber,CV_64F); 502 newOldStatus = cvCreateMat(1,newTotalNumber,CV_8S); 503 504 /* Copy old values to */ 505 int i; 506 507 /* Clear all values */ 508 cvZero(newOldPoint); 509 cvZero(newOldStatus); 510 511 for( i = 0; i < oldNum; i++ ) 512 { 513 int currCoord; 514 for( currCoord = 0; currCoord < numCoord; currCoord++ ) 515 { 516 cvmSet(newOldPoint,currCoord,i,cvmGet(*oldPoints,currCoord,i)); 517 } 518 newOldStatus->data.ptr[i] = (*oldStatus)->data.ptr[i]; 519 } 520 521 /* Copy additional points and statuses */ 522 if( addNum ) 523 { 524 for( i = 0; i < addNum; i++ ) 525 { 526 int currCoord; 527 for( currCoord = 0; currCoord < numCoord; currCoord++ ) 528 { 529 cvmSet(newOldPoint,currCoord,i+oldNum,cvmGet(addPoints,currCoord,i)); 530 } 531 newOldStatus->data.ptr[i+oldNum] = addStatus->data.ptr[i]; 532 //cvmSet(newOldStatus,0,i,cvmGet(addStatus,0,i)); 533 } 534 } 535 536 /* Delete previous data */ 537 cvReleaseMat(oldPoints); 538 cvReleaseMat(oldStatus); 539 540 /* copy pointers */ 541 *oldPoints = newOldPoint; 542 *oldStatus = newOldStatus; 543 544 } 545 __END__; 546 547 return newTotalNumber; 548 } 549 /*-------------------------------------------------------------------------------------*/ 550 int icvRemoveDoublePoins( CvMat *oldPoints,/* Points on prev image */ 551 CvMat *newPoints,/* New points */ 552 CvMat *oldStatus,/* Status for old points */ 553 CvMat *newStatus, 554 CvMat *origStatus, 555 float threshold)/* Status for new points */ 556 { 557 558 CvMemStorage* storage = 0; 559 CvSubdiv2D* subdiv = 0; 560 CvSeq* seq = 0; 561 562 int originalPoints = 0; 563 564 CV_FUNCNAME( "icvRemoveDoublePoins" ); 565 __BEGIN__; 566 567 /* Test input data */ 568 if( oldPoints == 0 || newPoints == 0 || 569 oldStatus == 0 || newStatus == 0 || origStatus == 0 ) 570 { 571 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 572 } 573 574 if( !CV_IS_MAT(oldPoints) || !CV_IS_MAT(newPoints) ) 575 { 576 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters points must be a matrices" ); 577 } 578 579 if( !CV_IS_MASK_ARR(oldStatus) || !CV_IS_MASK_ARR(newStatus) || !CV_IS_MASK_ARR(origStatus) ) 580 { 581 CV_ERROR( CV_StsUnsupportedFormat, "Input parameters statuses must be a mask array" ); 582 } 583 584 int oldNumPoints; 585 oldNumPoints = oldPoints->cols; 586 if( oldNumPoints < 0 ) 587 { 588 CV_ERROR( CV_StsOutOfRange, "Number of oldPoints must be >= 0" ); 589 } 590 591 if( oldStatus->cols != oldNumPoints ) 592 { 593 CV_ERROR( CV_StsUnmatchedSizes, "Number of old Points and old Statuses must be the same" ); 594 } 595 596 int newNumPoints; 597 newNumPoints = newPoints->cols; 598 if( newNumPoints < 0 ) 599 { 600 CV_ERROR( CV_StsOutOfRange, "Number of newPoints must be >= 0" ); 601 } 602 603 if( newStatus->cols != newNumPoints ) 604 { 605 CV_ERROR( CV_StsUnmatchedSizes, "Number of new Points and new Statuses must be the same" ); 606 } 607 608 if( origStatus->cols != newNumPoints ) 609 { 610 CV_ERROR( CV_StsUnmatchedSizes, "Number of new Points and new original Status must be the same" ); 611 } 612 613 if( oldPoints->rows != 2) 614 { 615 CV_ERROR( CV_StsOutOfRange, "OldPoints must have 2 coordinates >= 0" ); 616 } 617 618 if( newPoints->rows != 2) 619 { 620 CV_ERROR( CV_StsOutOfRange, "NewPoints must have 2 coordinates >= 0" ); 621 } 622 623 if( oldStatus->rows != 1 || newStatus->rows != 1 || origStatus->rows != 1 ) 624 { 625 CV_ERROR( CV_StsOutOfRange, "Statuses must have 1 row" ); 626 } 627 628 /* we have points on image and wants add new points */ 629 /* use subdivision for find nearest points */ 630 631 /* Define maximum and minimum X and Y */ 632 float minX,minY; 633 float maxX,maxY; 634 635 minX = minY = FLT_MAX; 636 maxX = maxY = FLT_MIN; 637 638 int i; 639 640 for( i = 0; i < oldNumPoints; i++ ) 641 { 642 if( oldStatus->data.ptr[i] ) 643 { 644 float x = (float)cvmGet(oldPoints,0,i); 645 float y = (float)cvmGet(oldPoints,1,i); 646 647 if( x < minX ) 648 minX = x; 649 650 if( x > maxX ) 651 maxX = x; 652 653 if( y < minY ) 654 minY = y; 655 656 if( y > maxY ) 657 maxY = y; 658 } 659 } 660 661 for( i = 0; i < newNumPoints; i++ ) 662 { 663 if( newStatus->data.ptr[i] ) 664 { 665 float x = (float)cvmGet(newPoints,0,i); 666 float y = (float)cvmGet(newPoints,1,i); 667 668 if( x < minX ) 669 minX = x; 670 671 if( x > maxX ) 672 maxX = x; 673 674 if( y < minY ) 675 minY = y; 676 677 if( y > maxY ) 678 maxY = y; 679 } 680 } 681 682 683 /* Creare subdivision for old image */ 684 storage = cvCreateMemStorage(0); 685 // subdiv = cvCreateSubdivDelaunay2D( cvRect( 0, 0, size.width, size.height ), storage ); 686 subdiv = cvCreateSubdivDelaunay2D( cvRect( cvRound(minX)-5, cvRound(minY)-5, cvRound(maxX-minX)+10, cvRound(maxY-minY)+10 ), storage ); 687 seq = cvCreateSeq( 0, sizeof(*seq), sizeof(CvPoint2D32f), storage ); 688 689 /* Insert each point from first image */ 690 for( i = 0; i < oldNumPoints; i++ ) 691 { 692 /* Add just exist points */ 693 if( oldStatus->data.ptr[i] ) 694 { 695 CvPoint2D32f pt; 696 pt.x = (float)cvmGet(oldPoints,0,i); 697 pt.y = (float)cvmGet(oldPoints,1,i); 698 699 CvSubdiv2DPoint* point; 700 point = cvSubdivDelaunay2DInsert( subdiv, pt ); 701 } 702 } 703 704 705 /* Find nearest points */ 706 /* for each new point */ 707 int flag; 708 for( i = 0; i < newNumPoints; i++ ) 709 { 710 flag = 0; 711 /* Test just exist points */ 712 if( newStatus->data.ptr[i] ) 713 { 714 flag = 1; 715 /* Let this is a good point */ 716 //originalPoints++; 717 718 CvPoint2D32f pt; 719 720 pt.x = (float)cvmGet(newPoints,0,i); 721 pt.y = (float)cvmGet(newPoints,1,i); 722 723 CvSubdiv2DPoint* point = cvFindNearestPoint2D( subdiv, pt ); 724 725 if( point ) 726 { 727 /* Test distance of found nearest point */ 728 double minDistance = icvSqDist2D32f( pt, point->pt ); 729 730 if( minDistance < threshold*threshold ) 731 { 732 /* Point is double. Turn it off */ 733 /* Set status */ 734 //newStatus->data.ptr[i] = 0; 735 736 /* No this is a double point */ 737 //originalPoints--; 738 flag = 0; 739 } 740 } 741 } 742 originalPoints += flag; 743 origStatus->data .ptr[i] = (uchar)flag; 744 } 745 746 __END__; 747 748 cvReleaseMemStorage( &storage ); 749 750 751 return originalPoints; 752 753 754 } 755 756 void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr); 757 758 /*-------------------------------------------------------------------------------------*/ 759 void icvComputeProjectMatrixStatus(CvMat *objPoints4D,CvMat *points2,CvMat *status, CvMat *projMatr) 760 { 761 /* Compute number of good points */ 762 int num = cvCountNonZero(status); 763 764 /* Create arrays */ 765 CvMat *objPoints = 0; 766 objPoints = cvCreateMat(4,num,CV_64F); 767 768 CvMat *points2D = 0; 769 points2D = cvCreateMat(2,num,CV_64F); 770 771 int currVis = 0; 772 int i; 773 #if 1 774 FILE *file; 775 file = fopen("d:\\test\\projStatus.txt","w"); 776 #endif 777 int totalNum = objPoints4D->cols; 778 for( i = 0; i < totalNum; i++ ) 779 { 780 fprintf(file,"%d (%d) ",i,status->data.ptr[i]); 781 if( status->data.ptr[i] ) 782 { 783 784 #if 1 785 double X,Y,Z,W; 786 double x,y; 787 X = cvmGet(objPoints4D,0,i); 788 Y = cvmGet(objPoints4D,1,i); 789 Z = cvmGet(objPoints4D,2,i); 790 W = cvmGet(objPoints4D,3,i); 791 792 x = cvmGet(points2,0,i); 793 y = cvmGet(points2,1,i); 794 fprintf(file,"%d (%lf %lf %lf %lf) - (%lf %lf)",i,X,Y,Z,W,x,y ); 795 #endif 796 cvmSet(objPoints,0,currVis,cvmGet(objPoints4D,0,i)); 797 cvmSet(objPoints,1,currVis,cvmGet(objPoints4D,1,i)); 798 cvmSet(objPoints,2,currVis,cvmGet(objPoints4D,2,i)); 799 cvmSet(objPoints,3,currVis,cvmGet(objPoints4D,3,i)); 800 801 cvmSet(points2D,0,currVis,cvmGet(points2,0,i)); 802 cvmSet(points2D,1,currVis,cvmGet(points2,1,i)); 803 804 currVis++; 805 } 806 807 fprintf(file,"\n"); 808 } 809 810 #if 1 811 fclose(file); 812 #endif 813 814 icvComputeProjectMatrix(objPoints,points2D,projMatr); 815 816 /* Free allocated memory */ 817 cvReleaseMat(&objPoints); 818 cvReleaseMat(&points2D); 819 } 820 821 822 823 /*-------------------------------------------------------------------------------------*/ 824 /* For given N images 825 we have corresponding points on N images 826 computed projection matrices 827 reconstructed 4D points 828 829 we must to compute 830 831 832 */ 833 834 void icvAddNewImageToPrevious____( 835 IplImage *newImage,//Image to add 836 IplImage *oldImage,//Previous image 837 CvMat *oldPoints,// previous 2D points on prev image (some points may be not visible) 838 CvMat *oldPntStatus,//Status for each point on prev image 839 CvMat *objPoints4D,//prev 4D points 840 CvMat *newPoints, //Points on new image corr for prev 841 CvMat *newPntStatus,// New point status for new image 842 CvMat *newFPoints2D1,//new feature points on prev image 843 CvMat *newFPoints2D2,//new feature points on new image 844 CvMat *newFPointsStatus, 845 CvMat *newProjMatr, 846 int useFilter, 847 double threshold)//New projection matrix 848 { 849 CvMat *points2 = 0; 850 CvMat *status = 0; 851 CvMat *newFPointsStatusTmp = 0; 852 853 //CV_FUNCNAME( "icvAddNewImageToPrevious____" ); 854 __BEGIN__; 855 856 /* First found correspondence points for images */ 857 858 /* Test input params */ 859 860 int numPoints; 861 numPoints = oldPoints->cols; 862 863 /* Allocate memory */ 864 865 points2 = cvCreateMat(2,numPoints,CV_64F); 866 status = cvCreateMat(1,numPoints,CV_8S); 867 newFPointsStatusTmp = cvCreateMat(1, newFPoints2D1->cols,CV_8S); 868 869 int corrNum; 870 corrNum = icvFindCorrForGivenPoints( oldImage,/* Image 1 */ 871 newImage,/* Image 2 */ 872 oldPoints, 873 oldPntStatus, 874 points2, 875 status, 876 useFilter,/*Use fundamental matrix to filter points */ 877 threshold);/* Threshold for good points in filter */ 878 879 cvCopy(status,newPntStatus); 880 cvCopy(points2,newPoints); 881 882 CvMat projMatr; 883 double projMatr_dat[12]; 884 projMatr = cvMat(3,4,CV_64F,projMatr_dat); 885 886 if( corrNum >= 6 ) 887 {/* We can compute projection matrix */ 888 // icvComputeProjectMatrix(objPoints4D,points2,&projMatr); 889 icvComputeProjectMatrixStatus(objPoints4D,points2,status,&projMatr); 890 cvCopy(&projMatr,newProjMatr); 891 892 /* Create new points and find correspondence */ 893 icvCreateFeaturePoints(newImage, newFPoints2D2,newFPointsStatus); 894 895 /* Good if we test new points before find corr points */ 896 897 /* Find correspondence for new found points */ 898 icvFindCorrForGivenPoints( newImage,/* Image 1 */ 899 oldImage,/* Image 2 */ 900 newFPoints2D2, 901 newFPointsStatus,//prev status 902 newFPoints2D1, 903 newFPointsStatusTmp,//new status 904 useFilter,/*Use fundamental matrix to filter points */ 905 threshold);/* Threshold for good points in filter */ 906 907 /* We generated new points on image test for exist points */ 908 909 /* Remove all new double points */ 910 911 int origNum; 912 /* Find point of old image */ 913 origNum = icvRemoveDoublePoins( oldPoints,/* Points on prev image */ 914 newFPoints2D1,/* New points */ 915 oldPntStatus,/* Status for old points */ 916 newFPointsStatusTmp, 917 newFPointsStatusTmp,//orig status 918 20);/* Status for new points */ 919 920 /* Find double points on new image */ 921 origNum = icvRemoveDoublePoins( newPoints,/* Points on prev image */ 922 newFPoints2D2,/* New points */ 923 newPntStatus,/* Status for old points */ 924 newFPointsStatusTmp, 925 newFPointsStatusTmp,//orig status 926 20);/* Status for new points */ 927 928 929 930 /* Add all new good points to result */ 931 932 933 /* Copy new status to old */ 934 cvCopy(newFPointsStatusTmp,newFPointsStatus); 935 936 937 } 938 939 940 941 __END__; 942 943 /* Free allocated memory */ 944 945 return; 946 } 947 /*-------------------------------------------------------------------------------------*/ 948 //int icvDelete// 949 //CreateGood 950 951 /*-------------------------------------------------------------------------------------*/ 952 int icvDeleteSparsInPoints( int numImages, 953 CvMat **points, 954 CvMat **status, 955 CvMat *wasStatus)/* status of previous configuration */ 956 { 957 /* Delete points which no exist on any of images */ 958 /* numImages - number of images */ 959 /* points - arrays of points for each image. Changing */ 960 /* status - arrays of status for each image. Changing */ 961 /* Function returns number of common points */ 962 963 int comNumber = 0; 964 CV_FUNCNAME( "icvDeleteSparsInPoints" ); 965 __BEGIN__; 966 967 /* Test for errors */ 968 if( numImages < 1 ) 969 { 970 CV_ERROR( CV_StsOutOfRange, "Number of images must be more than 0" ); 971 } 972 973 if( points == 0 || status == 0 ) 974 { 975 CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); 976 } 977 int numPoints; 978 979 numPoints = points[0]->cols; 980 ////////// TESTS ////////// 981 982 int numCoord; 983 numCoord = points[0]->rows;// !!! may be number of coordinates is not correct !!! 984 985 int i; 986 int currExistPoint; 987 currExistPoint = 0; 988 989 if( wasStatus ) 990 { 991 cvZero(wasStatus); 992 } 993 994 int currImage; 995 for( i = 0; i < numPoints; i++ ) 996 { 997 int flag = 0; 998 for( currImage = 0; currImage < numImages; currImage++ ) 999 { 1000 flag |= status[currImage]->data.ptr[i]; 1001 } 1002 1003 if( flag ) 1004 { 1005 /* Current point exists */ 1006 /* Copy points and status */ 1007 if( currExistPoint != i )/* Copy just if different */ 1008 { 1009 for( currImage = 0; currImage < numImages; currImage++ ) 1010 { 1011 /* Copy points */ 1012 for( int currCoord = 0; currCoord < numCoord; currCoord++ ) 1013 { 1014 cvmSet(points[currImage],currCoord,currExistPoint, cvmGet(points[currImage],currCoord,i) ); 1015 } 1016 1017 /* Copy status */ 1018 status[currImage]->data.ptr[currExistPoint] = status[currImage]->data.ptr[i]; 1019 } 1020 } 1021 if( wasStatus ) 1022 { 1023 wasStatus->data.ptr[i] = 1; 1024 } 1025 1026 currExistPoint++; 1027 1028 } 1029 } 1030 1031 /* Rest of final status of points must be set to 0 */ 1032 for( i = currExistPoint; i < numPoints; i++ ) 1033 { 1034 for( currImage = 0; currImage < numImages; currImage++ ) 1035 { 1036 status[currImage]->data.ptr[i] = 0; 1037 } 1038 } 1039 1040 comNumber = currExistPoint; 1041 1042 __END__; 1043 return comNumber; 1044 } 1045 1046 #if 0 1047 /*-------------------------------------------------------------------------------------*/ 1048 void icvGrowPointsArray(CvMat **points) 1049 { 1050 1051 1052 } 1053 1054 /*-------------------------------------------------------------------------------------*/ 1055 void icvAddNewArrayPoints() 1056 { 1057 1058 } 1059 1060 /*-------------------------------------------------------------------------------------*/ 1061 #endif 1062 1063 ////////////////////////////////////////////////////////////////////////////////////////// 1064 ////////////////////////////////////////////////////////////////////////////////////////// 1065 ////////////////////////////////////////////////////////////////////////////////////////// 1066 ////////////////////////////////////////////////////////////////////////////////////////// 1067 1068 /* Add image to existing images and corr points */ 1069 #if 0 1070 /* Returns: 1 if new image was added good */ 1071 /* 0 image was not added. Not enought corr points */ 1072 int AddImageToStruct( IplImage *newImage,//Image to add 1073 IplImage *oldImage,//Previous image 1074 CvMat *oldPoints,// previous 2D points on prev image (some points may be not visible) 1075 CvMat *oldPntStatus,//Status for each point on prev image 1076 CvMat *objPoints4D,//prev 4D points 1077 CvMat *newPntStatus,// New point status for new image 1078 CvMat *newPoints,//New corresponding points on new image 1079 CvMat *newPoints2D1,//new points on prev image 1080 CvMat *newPoints2D2,//new points on new image 1081 CvMat *newProjMatr);//New projection matrix 1082 { 1083 1084 /* Add new image. Create new corr points */ 1085 /* Track exist points from oldImage to newImage */ 1086 /* Create new vector status */ 1087 CvMat *status; 1088 int numPoints = oldPoints->cols; 1089 status = cvCreateMat(1,numPoints,CV_64F); 1090 /* Copy status */ 1091 cvConvert(pntStatus,status); 1092 1093 int corrNum = FindCorrForGivenPoints(oldImage,newImage,oldPoints,newPoints,status); 1094 1095 /* Status has new status of points */ 1096 1097 CvMat projMatr; 1098 double projMatr_dat[12]; 1099 projMatr = cvMat(3,4,CV_64F,projMatr_dat); 1100 1101 /* If number of corr points is 6 or more can compute projection matrix */ 1102 if( corrNum >= 6) 1103 { 1104 /* Compute projection matrix for new image using corresponding points */ 1105 icvComputeProjectMatrix(objPoints4D,newPoints,&projMatr); 1106 1107 CvMat *tmpPoints; 1108 /* Create new points and find correspondence */ 1109 int num = FindFeaturePoints(newImage, &tmpPoints); 1110 if( num > 0 ) 1111 { 1112 CvMat *newPoints; 1113 newPoints = cvCreateMat(2,num,CV_64F); 1114 CvMat *status; 1115 status = cvCreateMat(1,num,CV_64F); 1116 /* Set status for all points */ 1117 int i; 1118 for( i = 0; i < num; i++ ) 1119 { 1120 cvmSet(status,0,i,1.0); 1121 } 1122 1123 int corrNum2 = FindCorrForGivenPoints(oldImage,newImage,tmpPoints,newPoints,status); 1124 1125 /* !!! Filter points using projection matrices or not ??? */ 1126 1127 /* !!! Need to filter nearest points */ 1128 1129 /* Add new found points to exist points and optimize again */ 1130 CvMat *new2DPoints; 1131 CvMat *newStatus; 1132 1133 /* add new status to old status */ 1134 1135 1136 1137 1138 1139 } 1140 else 1141 { 1142 /* No new points were found */ 1143 } 1144 } 1145 else 1146 { 1147 /* We can't compute projection matrix for new image */ 1148 return 0; 1149 } 1150 1151 } 1152 #endif 1153