typename image<T, D>::create_new corner_min_eigenval( const image<T, D>& a, int block_size, int aperture_size) { IplImage* src = a.ipl(); IplImage* dst = cvCreateImage(cvGetSize(src), image_details::ipl_depth<T>(), 1); cvCornerMinEigenVal(src, dst, block_size, aperture_size); typename image<T, D>::create_new r(dst); cvReleaseImage(&src); cvReleaseImage(&dst); return r; }
CV_IMPL void cvGoodFeaturesToTrack( const void* image, void* eigImage, void* tempImage, CvPoint2D32f* corners, int *corner_count, double quality_level, double min_distance, const void* maskImage, int block_size, int use_harris, double harris_k ) { CvMat* _eigImg = 0; CvMat* _tmpImg = 0; CV_FUNCNAME( "cvGoodFeaturesToTrack" ); __BEGIN__; double max_val = 0; int max_count = 0; int count = 0; int x, y, i, k = 0; int min_dist; /* when selecting points, use integer coordinates */ CvPoint *ptr = (CvPoint *) corners; /* process floating-point images using integer arithmetics */ int *eig_data = 0; int *tmp_data = 0; int **ptr_data = 0; uchar *mask_data = 0; int mask_step = 0; CvSize size; int coi1 = 0, coi2 = 0, coi3 = 0; CvMat stub, *img = (CvMat*)image; CvMat eig_stub, *eig = (CvMat*)eigImage; CvMat tmp_stub, *tmp = (CvMat*)tempImage; CvMat mask_stub, *mask = (CvMat*)maskImage; if( corner_count ) { max_count = *corner_count; *corner_count = 0; } CV_CALL( img = cvGetMat( img, &stub, &coi1 )); if( eig ) { CV_CALL( eig = cvGetMat( eig, &eig_stub, &coi2 )); } else { CV_CALL( _eigImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); eig = _eigImg; } if( tmp ) { CV_CALL( tmp = cvGetMat( tmp, &tmp_stub, &coi3 )); } else { CV_CALL( _tmpImg = cvCreateMat( img->rows, img->cols, CV_32FC1 )); tmp = _tmpImg; } if( mask ) { CV_CALL( mask = cvGetMat( mask, &mask_stub )); if( !CV_IS_MASK_ARR( mask )) { CV_ERROR( CV_StsBadMask, "" ); } } if( coi1 != 0 || coi2 != 0 || coi3 != 0 ) CV_ERROR( CV_BadCOI, "" ); if( CV_MAT_CN(img->type) != 1 || CV_MAT_CN(eig->type) != 1 || CV_MAT_CN(tmp->type) != 1 ) CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); if( CV_MAT_DEPTH(tmp->type) != CV_32F || CV_MAT_DEPTH(eig->type) != CV_32F ) CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); if( !corners || !corner_count ) CV_ERROR( CV_StsNullPtr, "" ); if( max_count <= 0 ) CV_ERROR( CV_StsBadArg, "maximal corners number is non positive" ); if( quality_level <= 0 || min_distance < 0 ) CV_ERROR( CV_StsBadArg, "quality level or min distance are non positive" ); if( use_harris ) { CV_CALL( cvCornerHarris( img, eig, block_size, 3, harris_k )); } else { CV_CALL( cvCornerMinEigenVal( img, eig, block_size, 3 )); } CV_CALL( cvMinMaxLoc( eig, 0, &max_val, 0, 0, mask )); CV_CALL( cvThreshold( eig, eig, max_val * quality_level, 0, CV_THRESH_TOZERO )); CV_CALL( cvDilate( eig, tmp )); min_dist = cvRound( min_distance * min_distance ); size = cvGetMatSize( img ); ptr_data = (int**)(tmp->data.ptr); eig_data = (int*)(eig->data.ptr); tmp_data = (int*)(tmp->data.ptr); if( mask ) { mask_data = (uchar*)(mask->data.ptr); mask_step = mask->step; } /* collect list of pointers to features - put them into temporary image */ for( y = 1, k = 0; y < size.height - 1; y++ ) { (char*&)eig_data += eig->step; (char*&)tmp_data += tmp->step; mask_data += mask_step; for( x = 1; x < size.width - 1; x++ ) { int val = eig_data[x]; if( val != 0 && val == tmp_data[x] && (!mask || mask_data[x]) ) ptr_data[k++] = eig_data + x; } } icvSortFeatures( ptr_data, k, 0 ); /* select the strongest features */ for( i = 0; i < k; i++ ) { int j = count, ofs = (int)((uchar*)(ptr_data[i]) - eig->data.ptr); y = ofs / eig->step; x = (ofs - y * eig->step)/sizeof(float); if( min_dist != 0 ) { for( j = 0; j < count; j++ ) { int dx = x - ptr[j].x; int dy = y - ptr[j].y; int dist = dx * dx + dy * dy; if( dist < min_dist ) break; } } if( j == count ) { ptr[count].x = x; ptr[count].y = y; if( ++count >= max_count ) break; } } /* convert points to floating-point format */ for( i = 0; i < count; i++ ) { assert( (unsigned)ptr[i].x < (unsigned)size.width && (unsigned)ptr[i].y < (unsigned)size.height ); corners[i].x = (float)ptr[i].x; corners[i].y = (float)ptr[i].y; } *corner_count = count; __END__; cvReleaseMat( &_eigImg ); cvReleaseMat( &_tmpImg ); }