| /*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 "_cvaux.h" |
| //#include "cvtypes.h" |
| //#include <float.h> |
| //#include <limits.h> |
| //#include "cv.h" |
| //#include "highgui.h" |
| |
| #include <stdio.h> |
| |
| /* Valery Mosyagin */ |
| |
| /* ===== Function for find corresponding between images ===== */ |
| |
| /* Create feature points on image and return number of them. Array points fills by found points */ |
| int icvCreateFeaturePoints(IplImage *image, CvMat *points, CvMat *status) |
| { |
| int foundFeaturePoints = 0; |
| IplImage *grayImage = 0; |
| IplImage *eigImage = 0; |
| IplImage *tmpImage = 0; |
| CvPoint2D32f *cornerPoints = 0; |
| |
| CV_FUNCNAME( "icvFeatureCreatePoints" ); |
| __BEGIN__; |
| |
| /* Test for errors */ |
| if( image == 0 || points == 0 ) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| |
| /* Test image size */ |
| int w,h; |
| w = image->width; |
| h = image->height; |
| |
| if( w <= 0 || h <= 0) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Size of image must be > 0" ); |
| } |
| |
| /* Test for matrices */ |
| if( !CV_IS_MAT(points) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Input parameter points must be a matrix" ); |
| } |
| |
| int needNumPoints; |
| needNumPoints = points->cols; |
| if( needNumPoints <= 0 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of need points must be > 0" ); |
| } |
| |
| if( points->rows != 2 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of point coordinates must be == 2" ); |
| } |
| |
| if( status != 0 ) |
| { |
| /* If status matrix exist test it for correct */ |
| if( !CV_IS_MASK_ARR(status) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Statuses must be a mask arrays" ); |
| } |
| |
| if( status->cols != needNumPoints ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Size of points and statuses must be the same" ); |
| } |
| |
| if( status->rows !=1 ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Number of rows of status must be 1" ); |
| } |
| } |
| |
| /* Create temporary images */ |
| CV_CALL( grayImage = cvCreateImage(cvSize(w,h), 8,1) ); |
| CV_CALL( eigImage = cvCreateImage(cvSize(w,h),32,1) ); |
| CV_CALL( tmpImage = cvCreateImage(cvSize(w,h),32,1) ); |
| |
| /* Create points */ |
| CV_CALL( cornerPoints = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f) * needNumPoints) ); |
| |
| int foundNum; |
| double quality; |
| double minDist; |
| |
| cvCvtColor(image,grayImage, CV_BGR2GRAY); |
| |
| foundNum = needNumPoints; |
| quality = 0.01; |
| minDist = 5; |
| cvGoodFeaturesToTrack(grayImage, eigImage, tmpImage, cornerPoints, &foundNum, quality, minDist); |
| |
| /* Copy found points to result */ |
| int i; |
| for( i = 0; i < foundNum; i++ ) |
| { |
| cvmSet(points,0,i,cornerPoints[i].x); |
| cvmSet(points,1,i,cornerPoints[i].y); |
| } |
| |
| /* Set status if need */ |
| if( status ) |
| { |
| for( i = 0; i < foundNum; i++ ) |
| { |
| status->data.ptr[i] = 1; |
| } |
| |
| for( i = foundNum; i < needNumPoints; i++ ) |
| { |
| status->data.ptr[i] = 0; |
| } |
| } |
| |
| foundFeaturePoints = foundNum; |
| |
| __END__; |
| |
| /* Free allocated memory */ |
| cvReleaseImage(&grayImage); |
| cvReleaseImage(&eigImage); |
| cvReleaseImage(&tmpImage); |
| cvFree(&cornerPoints); |
| |
| return foundFeaturePoints; |
| } |
| |
| /*-------------------------------------------------------------------------------------*/ |
| |
| /* For given points1 (with pntStatus) on image1 finds corresponding points2 on image2 and set pntStatus2 for them */ |
| /* Returns number of corresponding points */ |
| int icvFindCorrForGivenPoints( IplImage *image1,/* Image 1 */ |
| IplImage *image2,/* Image 2 */ |
| CvMat *points1, |
| CvMat *pntStatus1, |
| CvMat *points2, |
| CvMat *pntStatus2, |
| int useFilter,/*Use fundamental matrix to filter points */ |
| double threshold)/* Threshold for good points in filter */ |
| { |
| int resNumCorrPoints = 0; |
| CvPoint2D32f* cornerPoints1 = 0; |
| CvPoint2D32f* cornerPoints2 = 0; |
| char* status = 0; |
| float* errors = 0; |
| CvMat* tmpPoints1 = 0; |
| CvMat* tmpPoints2 = 0; |
| CvMat* pStatus = 0; |
| IplImage *grayImage1 = 0; |
| IplImage *grayImage2 = 0; |
| IplImage *pyrImage1 = 0; |
| IplImage *pyrImage2 = 0; |
| |
| CV_FUNCNAME( "icvFindCorrForGivenPoints" ); |
| __BEGIN__; |
| |
| /* Test input data for errors */ |
| |
| /* Test for null pointers */ |
| if( image1 == 0 || image2 == 0 || |
| points1 == 0 || points2 == 0 || |
| pntStatus1 == 0 || pntStatus2 == 0) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| |
| /* Test image size */ |
| int w,h; |
| w = image1->width; |
| h = image1->height; |
| |
| if( w <= 0 || h <= 0) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Size of image1 must be > 0" ); |
| } |
| |
| if( image2->width != w || image2->height != h ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Size of images must be the same" ); |
| } |
| |
| /* Test for matrices */ |
| if( !CV_IS_MAT(points1) || !CV_IS_MAT(points2) || |
| !CV_IS_MAT(pntStatus1) || !CV_IS_MAT(pntStatus2) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Input parameters (points and status) must be a matrices" ); |
| } |
| |
| /* Test type of status matrices */ |
| if( !CV_IS_MASK_ARR(pntStatus1) || !CV_IS_MASK_ARR(pntStatus2) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Statuses must be a mask arrays" ); |
| } |
| |
| /* Test number of points */ |
| int numPoints; |
| numPoints = points1->cols; |
| |
| if( numPoints <= 0 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of points1 must be > 0" ); |
| } |
| |
| if( points2->cols != numPoints || pntStatus1->cols != numPoints || pntStatus2->cols != numPoints ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Number of points and statuses must be the same" ); |
| } |
| |
| if( points1->rows != 2 || points2->rows != 2 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be 2" ); |
| } |
| |
| if( pntStatus1->rows != 1 || pntStatus2->rows != 1 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Status must be a matrix 1xN" ); |
| } |
| /* ----- End test ----- */ |
| |
| |
| /* Compute number of visible points on image1 */ |
| int numVisPoints; |
| numVisPoints = cvCountNonZero(pntStatus1); |
| |
| if( numVisPoints > 0 ) |
| { |
| /* Create temporary images */ |
| /* We must use iplImage againts hughgui images */ |
| |
| /* |
| CvvImage grayImage1; |
| CvvImage grayImage2; |
| CvvImage pyrImage1; |
| CvvImage pyrImage2; |
| */ |
| |
| /* Create Ipl images */ |
| CV_CALL( grayImage1 = cvCreateImage(cvSize(w,h),8,1) ); |
| CV_CALL( grayImage2 = cvCreateImage(cvSize(w,h),8,1) ); |
| CV_CALL( pyrImage1 = cvCreateImage(cvSize(w,h),8,1) ); |
| CV_CALL( pyrImage2 = cvCreateImage(cvSize(w,h),8,1) ); |
| |
| CV_CALL( cornerPoints1 = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f)*numVisPoints) ); |
| CV_CALL( cornerPoints2 = (CvPoint2D32f*)cvAlloc( sizeof(CvPoint2D32f)*numVisPoints) ); |
| CV_CALL( status = (char*)cvAlloc( sizeof(char)*numVisPoints) ); |
| CV_CALL( errors = (float*)cvAlloc( 2 * sizeof(float)*numVisPoints) ); |
| |
| int i; |
| for( i = 0; i < numVisPoints; i++ ) |
| { |
| status[i] = 1; |
| } |
| |
| /* !!! Need test creation errors */ |
| /* |
| if( !grayImage1.Create(w,h,8)) EXIT; |
| if( !grayImage2.Create(w,h,8)) EXIT; |
| if( !pyrImage1. Create(w,h,8)) EXIT; |
| if( !pyrImage2. Create(w,h,8)) EXIT; |
| */ |
| |
| cvCvtColor(image1,grayImage1,CV_BGR2GRAY); |
| cvCvtColor(image2,grayImage2,CV_BGR2GRAY); |
| |
| /* |
| grayImage1.CopyOf(image1,0); |
| grayImage2.CopyOf(image2,0); |
| */ |
| |
| /* Copy points good points from input data */ |
| uchar *stat1 = pntStatus1->data.ptr; |
| uchar *stat2 = pntStatus2->data.ptr; |
| |
| int curr = 0; |
| for( i = 0; i < numPoints; i++ ) |
| { |
| if( stat1[i] ) |
| { |
| cornerPoints1[curr].x = (float)cvmGet(points1,0,i); |
| cornerPoints1[curr].y = (float)cvmGet(points1,1,i); |
| curr++; |
| } |
| } |
| |
| /* Define number of levels of pyramid */ |
| cvCalcOpticalFlowPyrLK( grayImage1, grayImage2, |
| pyrImage1, pyrImage2, |
| cornerPoints1, cornerPoints2, |
| numVisPoints, cvSize(10,10), 3, |
| status, errors, |
| cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), |
| 0/*CV_LKFLOW_PYR_A_READY*/ ); |
| |
| |
| memset(stat2,0,sizeof(uchar)*numPoints); |
| |
| int currVis = 0; |
| int totalCorns = 0; |
| |
| /* Copy new points and set status */ |
| /* stat1 may not be the same as stat2 */ |
| for( i = 0; i < numPoints; i++ ) |
| { |
| if( stat1[i] ) |
| { |
| if( status[currVis] && errors[currVis] < 1000 ) |
| { |
| stat2[i] = 1; |
| cvmSet(points2,0,i,cornerPoints2[currVis].x); |
| cvmSet(points2,1,i,cornerPoints2[currVis].y); |
| totalCorns++; |
| } |
| currVis++; |
| } |
| } |
| |
| resNumCorrPoints = totalCorns; |
| |
| /* Filter points using RANSAC */ |
| if( useFilter ) |
| { |
| resNumCorrPoints = 0; |
| /* Use RANSAC filter for found points */ |
| if( totalCorns > 7 ) |
| { |
| /* Create array with good points only */ |
| CV_CALL( tmpPoints1 = cvCreateMat(2,totalCorns,CV_64F) ); |
| CV_CALL( tmpPoints2 = cvCreateMat(2,totalCorns,CV_64F) ); |
| |
| /* Copy just good points */ |
| int currPoint = 0; |
| for( i = 0; i < numPoints; i++ ) |
| { |
| if( stat2[i] ) |
| { |
| cvmSet(tmpPoints1,0,currPoint,cvmGet(points1,0,i)); |
| cvmSet(tmpPoints1,1,currPoint,cvmGet(points1,1,i)); |
| |
| cvmSet(tmpPoints2,0,currPoint,cvmGet(points2,0,i)); |
| cvmSet(tmpPoints2,1,currPoint,cvmGet(points2,1,i)); |
| |
| currPoint++; |
| } |
| } |
| |
| /* Compute fundamental matrix */ |
| CvMat fundMatr; |
| double fundMatr_dat[9]; |
| fundMatr = cvMat(3,3,CV_64F,fundMatr_dat); |
| |
| CV_CALL( pStatus = cvCreateMat(1,totalCorns,CV_32F) ); |
| |
| int num = cvFindFundamentalMat(tmpPoints1,tmpPoints2,&fundMatr,CV_FM_RANSAC,threshold,0.99,pStatus); |
| if( num > 0 ) |
| { |
| int curr = 0; |
| /* Set final status for points2 */ |
| for( i = 0; i < numPoints; i++ ) |
| { |
| if( stat2[i] ) |
| { |
| if( cvmGet(pStatus,0,curr) == 0 ) |
| { |
| stat2[i] = 0; |
| } |
| curr++; |
| } |
| } |
| resNumCorrPoints = curr; |
| } |
| } |
| } |
| } |
| |
| __END__; |
| |
| /* Free allocated memory */ |
| cvFree(&cornerPoints1); |
| cvFree(&cornerPoints2); |
| cvFree(&status); |
| cvFree(&errors); |
| cvFree(&tmpPoints1); |
| cvFree(&tmpPoints2); |
| cvReleaseMat( &pStatus ); |
| cvReleaseImage( &grayImage1 ); |
| cvReleaseImage( &grayImage2 ); |
| cvReleaseImage( &pyrImage1 ); |
| cvReleaseImage( &pyrImage2 ); |
| |
| return resNumCorrPoints; |
| } |
| /*-------------------------------------------------------------------------------------*/ |
| int icvGrowPointsAndStatus(CvMat **oldPoints,CvMat **oldStatus,CvMat *addPoints,CvMat *addStatus,int addCreateNum) |
| { |
| /* Add to existing points and status arrays new points or just grow */ |
| CvMat *newOldPoint = 0; |
| CvMat *newOldStatus = 0; |
| int newTotalNumber = 0; |
| |
| CV_FUNCNAME( "icvGrowPointsAndStatus" ); |
| __BEGIN__; |
| |
| /* Test for errors */ |
| if( oldPoints == 0 || oldStatus == 0 ) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| |
| if( *oldPoints == 0 || *oldStatus == 0 ) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| |
| if( !CV_IS_MAT(*oldPoints)) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "oldPoints must be a pointer to a matrix" ); |
| } |
| |
| if( !CV_IS_MASK_ARR(*oldStatus)) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "oldStatus must be a pointer to a mask array" ); |
| } |
| |
| int oldNum; |
| oldNum = (*oldPoints)->cols; |
| if( oldNum < 1 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of old points must be > 0" ); |
| } |
| |
| /* Define if need number of add points */ |
| int addNum; |
| addNum = 0; |
| if( addPoints != 0 && addStatus != 0 ) |
| {/* We have aditional points */ |
| if( CV_IS_MAT(addPoints) && CV_IS_MASK_ARR(addStatus) ) |
| { |
| addNum = addPoints->cols; |
| if( addStatus->cols != addNum ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of add points and statuses must be the same" ); |
| } |
| } |
| } |
| |
| /* */ |
| |
| int numCoord; |
| numCoord = (*oldPoints)->rows; |
| newTotalNumber = oldNum + addNum + addCreateNum; |
| |
| if( newTotalNumber ) |
| { |
| /* Free allocated memory */ |
| newOldPoint = cvCreateMat(numCoord,newTotalNumber,CV_64F); |
| newOldStatus = cvCreateMat(1,newTotalNumber,CV_8S); |
| |
| /* Copy old values to */ |
| int i; |
| |
| /* Clear all values */ |
| cvZero(newOldPoint); |
| cvZero(newOldStatus); |
| |
| for( i = 0; i < oldNum; i++ ) |
| { |
| int currCoord; |
| for( currCoord = 0; currCoord < numCoord; currCoord++ ) |
| { |
| cvmSet(newOldPoint,currCoord,i,cvmGet(*oldPoints,currCoord,i)); |
| } |
| newOldStatus->data.ptr[i] = (*oldStatus)->data.ptr[i]; |
| } |
| |
| /* Copy additional points and statuses */ |
| if( addNum ) |
| { |
| for( i = 0; i < addNum; i++ ) |
| { |
| int currCoord; |
| for( currCoord = 0; currCoord < numCoord; currCoord++ ) |
| { |
| cvmSet(newOldPoint,currCoord,i+oldNum,cvmGet(addPoints,currCoord,i)); |
| } |
| newOldStatus->data.ptr[i+oldNum] = addStatus->data.ptr[i]; |
| //cvmSet(newOldStatus,0,i,cvmGet(addStatus,0,i)); |
| } |
| } |
| |
| /* Delete previous data */ |
| cvReleaseMat(oldPoints); |
| cvReleaseMat(oldStatus); |
| |
| /* copy pointers */ |
| *oldPoints = newOldPoint; |
| *oldStatus = newOldStatus; |
| |
| } |
| __END__; |
| |
| return newTotalNumber; |
| } |
| /*-------------------------------------------------------------------------------------*/ |
| int icvRemoveDoublePoins( CvMat *oldPoints,/* Points on prev image */ |
| CvMat *newPoints,/* New points */ |
| CvMat *oldStatus,/* Status for old points */ |
| CvMat *newStatus, |
| CvMat *origStatus, |
| float threshold)/* Status for new points */ |
| { |
| |
| CvMemStorage* storage = 0; |
| CvSubdiv2D* subdiv = 0; |
| CvSeq* seq = 0; |
| |
| int originalPoints = 0; |
| |
| CV_FUNCNAME( "icvRemoveDoublePoins" ); |
| __BEGIN__; |
| |
| /* Test input data */ |
| if( oldPoints == 0 || newPoints == 0 || |
| oldStatus == 0 || newStatus == 0 || origStatus == 0 ) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| |
| if( !CV_IS_MAT(oldPoints) || !CV_IS_MAT(newPoints) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Input parameters points must be a matrices" ); |
| } |
| |
| if( !CV_IS_MASK_ARR(oldStatus) || !CV_IS_MASK_ARR(newStatus) || !CV_IS_MASK_ARR(origStatus) ) |
| { |
| CV_ERROR( CV_StsUnsupportedFormat, "Input parameters statuses must be a mask array" ); |
| } |
| |
| int oldNumPoints; |
| oldNumPoints = oldPoints->cols; |
| if( oldNumPoints < 0 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of oldPoints must be >= 0" ); |
| } |
| |
| if( oldStatus->cols != oldNumPoints ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Number of old Points and old Statuses must be the same" ); |
| } |
| |
| int newNumPoints; |
| newNumPoints = newPoints->cols; |
| if( newNumPoints < 0 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of newPoints must be >= 0" ); |
| } |
| |
| if( newStatus->cols != newNumPoints ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Number of new Points and new Statuses must be the same" ); |
| } |
| |
| if( origStatus->cols != newNumPoints ) |
| { |
| CV_ERROR( CV_StsUnmatchedSizes, "Number of new Points and new original Status must be the same" ); |
| } |
| |
| if( oldPoints->rows != 2) |
| { |
| CV_ERROR( CV_StsOutOfRange, "OldPoints must have 2 coordinates >= 0" ); |
| } |
| |
| if( newPoints->rows != 2) |
| { |
| CV_ERROR( CV_StsOutOfRange, "NewPoints must have 2 coordinates >= 0" ); |
| } |
| |
| if( oldStatus->rows != 1 || newStatus->rows != 1 || origStatus->rows != 1 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Statuses must have 1 row" ); |
| } |
| |
| /* we have points on image and wants add new points */ |
| /* use subdivision for find nearest points */ |
| |
| /* Define maximum and minimum X and Y */ |
| float minX,minY; |
| float maxX,maxY; |
| |
| minX = minY = FLT_MAX; |
| maxX = maxY = FLT_MIN; |
| |
| int i; |
| |
| for( i = 0; i < oldNumPoints; i++ ) |
| { |
| if( oldStatus->data.ptr[i] ) |
| { |
| float x = (float)cvmGet(oldPoints,0,i); |
| float y = (float)cvmGet(oldPoints,1,i); |
| |
| if( x < minX ) |
| minX = x; |
| |
| if( x > maxX ) |
| maxX = x; |
| |
| if( y < minY ) |
| minY = y; |
| |
| if( y > maxY ) |
| maxY = y; |
| } |
| } |
| |
| for( i = 0; i < newNumPoints; i++ ) |
| { |
| if( newStatus->data.ptr[i] ) |
| { |
| float x = (float)cvmGet(newPoints,0,i); |
| float y = (float)cvmGet(newPoints,1,i); |
| |
| if( x < minX ) |
| minX = x; |
| |
| if( x > maxX ) |
| maxX = x; |
| |
| if( y < minY ) |
| minY = y; |
| |
| if( y > maxY ) |
| maxY = y; |
| } |
| } |
| |
| |
| /* Creare subdivision for old image */ |
| storage = cvCreateMemStorage(0); |
| // subdiv = cvCreateSubdivDelaunay2D( cvRect( 0, 0, size.width, size.height ), storage ); |
| subdiv = cvCreateSubdivDelaunay2D( cvRect( cvRound(minX)-5, cvRound(minY)-5, cvRound(maxX-minX)+10, cvRound(maxY-minY)+10 ), storage ); |
| seq = cvCreateSeq( 0, sizeof(*seq), sizeof(CvPoint2D32f), storage ); |
| |
| /* Insert each point from first image */ |
| for( i = 0; i < oldNumPoints; i++ ) |
| { |
| /* Add just exist points */ |
| if( oldStatus->data.ptr[i] ) |
| { |
| CvPoint2D32f pt; |
| pt.x = (float)cvmGet(oldPoints,0,i); |
| pt.y = (float)cvmGet(oldPoints,1,i); |
| |
| CvSubdiv2DPoint* point; |
| point = cvSubdivDelaunay2DInsert( subdiv, pt ); |
| } |
| } |
| |
| |
| /* Find nearest points */ |
| /* for each new point */ |
| int flag; |
| for( i = 0; i < newNumPoints; i++ ) |
| { |
| flag = 0; |
| /* Test just exist points */ |
| if( newStatus->data.ptr[i] ) |
| { |
| flag = 1; |
| /* Let this is a good point */ |
| //originalPoints++; |
| |
| CvPoint2D32f pt; |
| |
| pt.x = (float)cvmGet(newPoints,0,i); |
| pt.y = (float)cvmGet(newPoints,1,i); |
| |
| CvSubdiv2DPoint* point = cvFindNearestPoint2D( subdiv, pt ); |
| |
| if( point ) |
| { |
| /* Test distance of found nearest point */ |
| double minDistance = icvSqDist2D32f( pt, point->pt ); |
| |
| if( minDistance < threshold*threshold ) |
| { |
| /* Point is double. Turn it off */ |
| /* Set status */ |
| //newStatus->data.ptr[i] = 0; |
| |
| /* No this is a double point */ |
| //originalPoints--; |
| flag = 0; |
| } |
| } |
| } |
| originalPoints += flag; |
| origStatus->data .ptr[i] = (uchar)flag; |
| } |
| |
| __END__; |
| |
| cvReleaseMemStorage( &storage ); |
| |
| |
| return originalPoints; |
| |
| |
| } |
| |
| void icvComputeProjectMatrix(CvMat* objPoints,CvMat* projPoints,CvMat* projMatr); |
| |
| /*-------------------------------------------------------------------------------------*/ |
| void icvComputeProjectMatrixStatus(CvMat *objPoints4D,CvMat *points2,CvMat *status, CvMat *projMatr) |
| { |
| /* Compute number of good points */ |
| int num = cvCountNonZero(status); |
| |
| /* Create arrays */ |
| CvMat *objPoints = 0; |
| objPoints = cvCreateMat(4,num,CV_64F); |
| |
| CvMat *points2D = 0; |
| points2D = cvCreateMat(2,num,CV_64F); |
| |
| int currVis = 0; |
| int i; |
| #if 1 |
| FILE *file; |
| file = fopen("d:\\test\\projStatus.txt","w"); |
| #endif |
| int totalNum = objPoints4D->cols; |
| for( i = 0; i < totalNum; i++ ) |
| { |
| fprintf(file,"%d (%d) ",i,status->data.ptr[i]); |
| if( status->data.ptr[i] ) |
| { |
| |
| #if 1 |
| double X,Y,Z,W; |
| double x,y; |
| X = cvmGet(objPoints4D,0,i); |
| Y = cvmGet(objPoints4D,1,i); |
| Z = cvmGet(objPoints4D,2,i); |
| W = cvmGet(objPoints4D,3,i); |
| |
| x = cvmGet(points2,0,i); |
| y = cvmGet(points2,1,i); |
| fprintf(file,"%d (%lf %lf %lf %lf) - (%lf %lf)",i,X,Y,Z,W,x,y ); |
| #endif |
| cvmSet(objPoints,0,currVis,cvmGet(objPoints4D,0,i)); |
| cvmSet(objPoints,1,currVis,cvmGet(objPoints4D,1,i)); |
| cvmSet(objPoints,2,currVis,cvmGet(objPoints4D,2,i)); |
| cvmSet(objPoints,3,currVis,cvmGet(objPoints4D,3,i)); |
| |
| cvmSet(points2D,0,currVis,cvmGet(points2,0,i)); |
| cvmSet(points2D,1,currVis,cvmGet(points2,1,i)); |
| |
| currVis++; |
| } |
| |
| fprintf(file,"\n"); |
| } |
| |
| #if 1 |
| fclose(file); |
| #endif |
| |
| icvComputeProjectMatrix(objPoints,points2D,projMatr); |
| |
| /* Free allocated memory */ |
| cvReleaseMat(&objPoints); |
| cvReleaseMat(&points2D); |
| } |
| |
| |
| |
| /*-------------------------------------------------------------------------------------*/ |
| /* For given N images |
| we have corresponding points on N images |
| computed projection matrices |
| reconstructed 4D points |
| |
| we must to compute |
| |
| |
| */ |
| |
| void icvAddNewImageToPrevious____( |
| IplImage *newImage,//Image to add |
| IplImage *oldImage,//Previous image |
| CvMat *oldPoints,// previous 2D points on prev image (some points may be not visible) |
| CvMat *oldPntStatus,//Status for each point on prev image |
| CvMat *objPoints4D,//prev 4D points |
| CvMat *newPoints, //Points on new image corr for prev |
| CvMat *newPntStatus,// New point status for new image |
| CvMat *newFPoints2D1,//new feature points on prev image |
| CvMat *newFPoints2D2,//new feature points on new image |
| CvMat *newFPointsStatus, |
| CvMat *newProjMatr, |
| int useFilter, |
| double threshold)//New projection matrix |
| { |
| CvMat *points2 = 0; |
| CvMat *status = 0; |
| CvMat *newFPointsStatusTmp = 0; |
| |
| //CV_FUNCNAME( "icvAddNewImageToPrevious____" ); |
| __BEGIN__; |
| |
| /* First found correspondence points for images */ |
| |
| /* Test input params */ |
| |
| int numPoints; |
| numPoints = oldPoints->cols; |
| |
| /* Allocate memory */ |
| |
| points2 = cvCreateMat(2,numPoints,CV_64F); |
| status = cvCreateMat(1,numPoints,CV_8S); |
| newFPointsStatusTmp = cvCreateMat(1, newFPoints2D1->cols,CV_8S); |
| |
| int corrNum; |
| corrNum = icvFindCorrForGivenPoints( oldImage,/* Image 1 */ |
| newImage,/* Image 2 */ |
| oldPoints, |
| oldPntStatus, |
| points2, |
| status, |
| useFilter,/*Use fundamental matrix to filter points */ |
| threshold);/* Threshold for good points in filter */ |
| |
| cvCopy(status,newPntStatus); |
| cvCopy(points2,newPoints); |
| |
| CvMat projMatr; |
| double projMatr_dat[12]; |
| projMatr = cvMat(3,4,CV_64F,projMatr_dat); |
| |
| if( corrNum >= 6 ) |
| {/* We can compute projection matrix */ |
| // icvComputeProjectMatrix(objPoints4D,points2,&projMatr); |
| icvComputeProjectMatrixStatus(objPoints4D,points2,status,&projMatr); |
| cvCopy(&projMatr,newProjMatr); |
| |
| /* Create new points and find correspondence */ |
| icvCreateFeaturePoints(newImage, newFPoints2D2,newFPointsStatus); |
| |
| /* Good if we test new points before find corr points */ |
| |
| /* Find correspondence for new found points */ |
| icvFindCorrForGivenPoints( newImage,/* Image 1 */ |
| oldImage,/* Image 2 */ |
| newFPoints2D2, |
| newFPointsStatus,//prev status |
| newFPoints2D1, |
| newFPointsStatusTmp,//new status |
| useFilter,/*Use fundamental matrix to filter points */ |
| threshold);/* Threshold for good points in filter */ |
| |
| /* We generated new points on image test for exist points */ |
| |
| /* Remove all new double points */ |
| |
| int origNum; |
| /* Find point of old image */ |
| origNum = icvRemoveDoublePoins( oldPoints,/* Points on prev image */ |
| newFPoints2D1,/* New points */ |
| oldPntStatus,/* Status for old points */ |
| newFPointsStatusTmp, |
| newFPointsStatusTmp,//orig status |
| 20);/* Status for new points */ |
| |
| /* Find double points on new image */ |
| origNum = icvRemoveDoublePoins( newPoints,/* Points on prev image */ |
| newFPoints2D2,/* New points */ |
| newPntStatus,/* Status for old points */ |
| newFPointsStatusTmp, |
| newFPointsStatusTmp,//orig status |
| 20);/* Status for new points */ |
| |
| |
| |
| /* Add all new good points to result */ |
| |
| |
| /* Copy new status to old */ |
| cvCopy(newFPointsStatusTmp,newFPointsStatus); |
| |
| |
| } |
| |
| |
| |
| __END__; |
| |
| /* Free allocated memory */ |
| |
| return; |
| } |
| /*-------------------------------------------------------------------------------------*/ |
| //int icvDelete// |
| //CreateGood |
| |
| /*-------------------------------------------------------------------------------------*/ |
| int icvDeleteSparsInPoints( int numImages, |
| CvMat **points, |
| CvMat **status, |
| CvMat *wasStatus)/* status of previous configuration */ |
| { |
| /* Delete points which no exist on any of images */ |
| /* numImages - number of images */ |
| /* points - arrays of points for each image. Changing */ |
| /* status - arrays of status for each image. Changing */ |
| /* Function returns number of common points */ |
| |
| int comNumber = 0; |
| CV_FUNCNAME( "icvDeleteSparsInPoints" ); |
| __BEGIN__; |
| |
| /* Test for errors */ |
| if( numImages < 1 ) |
| { |
| CV_ERROR( CV_StsOutOfRange, "Number of images must be more than 0" ); |
| } |
| |
| if( points == 0 || status == 0 ) |
| { |
| CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" ); |
| } |
| int numPoints; |
| |
| numPoints = points[0]->cols; |
| ////////// TESTS ////////// |
| |
| int numCoord; |
| numCoord = points[0]->rows;// !!! may be number of coordinates is not correct !!! |
| |
| int i; |
| int currExistPoint; |
| currExistPoint = 0; |
| |
| if( wasStatus ) |
| { |
| cvZero(wasStatus); |
| } |
| |
| int currImage; |
| for( i = 0; i < numPoints; i++ ) |
| { |
| int flag = 0; |
| for( currImage = 0; currImage < numImages; currImage++ ) |
| { |
| flag |= status[currImage]->data.ptr[i]; |
| } |
| |
| if( flag ) |
| { |
| /* Current point exists */ |
| /* Copy points and status */ |
| if( currExistPoint != i )/* Copy just if different */ |
| { |
| for( currImage = 0; currImage < numImages; currImage++ ) |
| { |
| /* Copy points */ |
| for( int currCoord = 0; currCoord < numCoord; currCoord++ ) |
| { |
| cvmSet(points[currImage],currCoord,currExistPoint, cvmGet(points[currImage],currCoord,i) ); |
| } |
| |
| /* Copy status */ |
| status[currImage]->data.ptr[currExistPoint] = status[currImage]->data.ptr[i]; |
| } |
| } |
| if( wasStatus ) |
| { |
| wasStatus->data.ptr[i] = 1; |
| } |
| |
| currExistPoint++; |
| |
| } |
| } |
| |
| /* Rest of final status of points must be set to 0 */ |
| for( i = currExistPoint; i < numPoints; i++ ) |
| { |
| for( currImage = 0; currImage < numImages; currImage++ ) |
| { |
| status[currImage]->data.ptr[i] = 0; |
| } |
| } |
| |
| comNumber = currExistPoint; |
| |
| __END__; |
| return comNumber; |
| } |
| |
| #if 0 |
| /*-------------------------------------------------------------------------------------*/ |
| void icvGrowPointsArray(CvMat **points) |
| { |
| |
| |
| } |
| |
| /*-------------------------------------------------------------------------------------*/ |
| void icvAddNewArrayPoints() |
| { |
| |
| } |
| |
| /*-------------------------------------------------------------------------------------*/ |
| #endif |
| |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| |
| /* Add image to existing images and corr points */ |
| #if 0 |
| /* Returns: 1 if new image was added good */ |
| /* 0 image was not added. Not enought corr points */ |
| int AddImageToStruct( IplImage *newImage,//Image to add |
| IplImage *oldImage,//Previous image |
| CvMat *oldPoints,// previous 2D points on prev image (some points may be not visible) |
| CvMat *oldPntStatus,//Status for each point on prev image |
| CvMat *objPoints4D,//prev 4D points |
| CvMat *newPntStatus,// New point status for new image |
| CvMat *newPoints,//New corresponding points on new image |
| CvMat *newPoints2D1,//new points on prev image |
| CvMat *newPoints2D2,//new points on new image |
| CvMat *newProjMatr);//New projection matrix |
| { |
| |
| /* Add new image. Create new corr points */ |
| /* Track exist points from oldImage to newImage */ |
| /* Create new vector status */ |
| CvMat *status; |
| int numPoints = oldPoints->cols; |
| status = cvCreateMat(1,numPoints,CV_64F); |
| /* Copy status */ |
| cvConvert(pntStatus,status); |
| |
| int corrNum = FindCorrForGivenPoints(oldImage,newImage,oldPoints,newPoints,status); |
| |
| /* Status has new status of points */ |
| |
| CvMat projMatr; |
| double projMatr_dat[12]; |
| projMatr = cvMat(3,4,CV_64F,projMatr_dat); |
| |
| /* If number of corr points is 6 or more can compute projection matrix */ |
| if( corrNum >= 6) |
| { |
| /* Compute projection matrix for new image using corresponding points */ |
| icvComputeProjectMatrix(objPoints4D,newPoints,&projMatr); |
| |
| CvMat *tmpPoints; |
| /* Create new points and find correspondence */ |
| int num = FindFeaturePoints(newImage, &tmpPoints); |
| if( num > 0 ) |
| { |
| CvMat *newPoints; |
| newPoints = cvCreateMat(2,num,CV_64F); |
| CvMat *status; |
| status = cvCreateMat(1,num,CV_64F); |
| /* Set status for all points */ |
| int i; |
| for( i = 0; i < num; i++ ) |
| { |
| cvmSet(status,0,i,1.0); |
| } |
| |
| int corrNum2 = FindCorrForGivenPoints(oldImage,newImage,tmpPoints,newPoints,status); |
| |
| /* !!! Filter points using projection matrices or not ??? */ |
| |
| /* !!! Need to filter nearest points */ |
| |
| /* Add new found points to exist points and optimize again */ |
| CvMat *new2DPoints; |
| CvMat *newStatus; |
| |
| /* add new status to old status */ |
| |
| |
| |
| |
| |
| } |
| else |
| { |
| /* No new points were found */ |
| } |
| } |
| else |
| { |
| /* We can't compute projection matrix for new image */ |
| return 0; |
| } |
| |
| } |
| #endif |