| /*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" |
| |
| #define _CV_NORM_L2(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])) |
| #define _CV_NORM_L22(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) |
| |
| /****************************************************************************************\ |
| |
| find region where hand is (for gesture recognition) |
| flag = 0 (use left bucket) flag = 1 (use right bucket) |
| |
| \****************************************************************************************/ |
| |
| static CvStatus CV_STDCALL |
| icvFindHandRegion( CvPoint3D32f * points, int count, |
| CvSeq * indexs, |
| float *line, CvSize2D32f size, int flag, |
| CvPoint3D32f * center, |
| CvMemStorage * storage, CvSeq ** numbers ) |
| { |
| |
| /* IppmVect32f sub, cros; */ |
| float *sub, *cros; |
| CvSeqWriter writer; |
| CvSeqReader reader; |
| |
| CvStatus status; |
| int nbins = 20, i, l, i_point, left, right; |
| int *bin_counts = 0; // pointer to the point's counter in the bickets |
| int low_count; // low threshold |
| |
| CvPoint *tmp_number = 0, *pt; |
| float value, vmin, vmax, vl, bsize, vc; |
| float hand_length, hand_length2, hand_left, hand_right; |
| float threshold, threshold2; |
| float *vv = 0; |
| float a[3]; |
| |
| status = CV_OK; |
| |
| hand_length = size.width; |
| hand_length2 = hand_length / 2; |
| |
| threshold = (float) (size.height * 3 / 5.); |
| threshold2 = threshold * threshold; |
| |
| /* low_count = count/nbins; */ |
| low_count = (int) (count / 60.); |
| |
| assert( points != NULL && line != NULL ); |
| if( points == NULL || line == NULL ) |
| return CV_NULLPTR_ERR; |
| |
| assert( count > 5 ); |
| if( count < 5 ) |
| return CV_BADFLAG_ERR; |
| |
| assert( flag == 0 || flag == 1 ); |
| if( flag != 0 && flag != 1 ) |
| return CV_BADFLAG_ERR; |
| |
| /* create vectors */ |
| sub = icvCreateVector_32f( 3 ); |
| cros = icvCreateVector_32f( 3 ); |
| if( sub == NULL || cros == NULL ) |
| return CV_OUTOFMEM_ERR; |
| |
| /* alloc memory for the point's projections on the line */ |
| vv = (float *) cvAlloc( count * sizeof( float )); |
| |
| if( vv == NULL ) |
| return CV_OUTOFMEM_ERR; |
| |
| /* alloc memory for the point's counter in the bickets */ |
| bin_counts = (int *) cvAlloc( nbins * sizeof( int )); |
| |
| if( bin_counts == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| memset( bin_counts, 0, nbins * sizeof( int )); |
| |
| cvStartReadSeq( indexs, &reader, 0 ); |
| |
| /* alloc memory for the temporale point's numbers */ |
| tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint )); |
| if( tmp_number == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| |
| /* find min and max point's projection on the line */ |
| vmin = 1000; |
| vmax = -1000; |
| i_point = 0; |
| for( i = 0; i < count; i++ ) |
| { |
| /* |
| icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3); |
| |
| icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros); |
| */ |
| |
| sub[0] = points[i].x - line[3]; |
| sub[1] = points[i].y - line[4]; |
| sub[2] = points[i].z - line[5]; |
| a[0] = sub[0] * line[1] - sub[1] * line[0]; |
| a[1] = sub[1] * line[2] - sub[2] * line[1]; |
| a[2] = sub[2] * line[0] - sub[0] * line[2]; |
| |
| /* if(IPPI_NORM_L22 ( cros ) < threshold2) */ |
| if( _CV_NORM_L22( a ) < threshold2 ) |
| { |
| value = (float)icvDotProduct_32f( sub, &line[0], 3 ); |
| if( value > vmax ) |
| vmax = value; |
| if( value < vmin ) |
| vmin = value; |
| |
| vv[i_point] = value; |
| |
| pt = (CvPoint*)cvGetSeqElem( indexs, i ); |
| tmp_number[i_point] = *pt; |
| i_point++; |
| } |
| } |
| |
| /* compute the length of one bucket */ |
| vl = vmax - vmin; |
| bsize = vl / nbins; |
| |
| /* compute the number of points in each bucket */ |
| for( i = 0; i < i_point; i++ ) |
| { |
| l = cvRound( (vv[i] - vmin) / bsize ); |
| bin_counts[l]++; |
| } |
| |
| *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage ); |
| assert( numbers != 0 ); |
| if( numbers == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| |
| cvStartAppendToSeq( *numbers, &writer ); |
| |
| if( flag == 0 ) |
| { |
| /* find the leftmost bucket */ |
| for( l = 0; l < nbins; l++ ) |
| { |
| if( bin_counts[l] > low_count ) |
| break; |
| } |
| left = l; |
| |
| /* compute center point of the left hand */ |
| hand_left = vmin + left * bsize; |
| vc = hand_left + hand_length2; |
| hand_right = hand_left + hand_length; |
| } |
| else |
| { |
| /* find the rightmost bucket */ |
| for( l = nbins - 1; l >= 0; l-- ) |
| { |
| if( bin_counts[l] > low_count ) |
| break; |
| } |
| right = l; |
| |
| /* compute center point of the right hand */ |
| hand_right = vmax - (nbins - right - 1) * bsize; |
| vc = hand_right - hand_length2; |
| hand_left = hand_right - hand_length; |
| } |
| |
| icvScaleVector_32f( &line[0], sub, 3, vc ); |
| icvAddVector_32f( &line[3], sub, (float *) center, 3 ); |
| |
| /* select hand's points and calculate mean value */ |
| |
| //ss.x = ss.y = ss.z = 0; |
| for( l = 0; l < i_point; l++ ) |
| { |
| if( vv[l] >= hand_left && vv[l] <= hand_right ) |
| { |
| CV_WRITE_SEQ_ELEM( tmp_number[l], writer ); |
| |
| } |
| } |
| |
| cvEndWriteSeq( &writer ); |
| |
| M_END: |
| if( tmp_number != NULL ) |
| cvFree( &tmp_number ); |
| if( bin_counts != NULL ) |
| cvFree( &bin_counts ); |
| if( vv != NULL ) |
| cvFree( &vv ); |
| if( sub != NULL ) icvDeleteVector (sub); |
| if( cros != NULL ) icvDeleteVector (cros); |
| |
| return status; |
| |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| |
| |
| #define _CV_NORM_L31(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])) |
| #define _CV_NORM_L32(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) |
| |
| /****************************************************************************************\ |
| |
| find region where hand is (for gesture recognition) |
| flag = 0 (use left bucket) flag = 1 (use right bucket) |
| |
| \****************************************************************************************/ |
| |
| static CvStatus CV_STDCALL |
| icvFindHandRegionA( CvPoint3D32f * points, int count, |
| CvSeq * indexs, |
| float *line, CvSize2D32f size, int jc, |
| CvPoint3D32f * center, |
| CvMemStorage * storage, CvSeq ** numbers ) |
| { |
| |
| /* IppmVect32f sub, cros; */ |
| float *sub, *cros; |
| float eps = (float) 0.01; |
| CvSeqWriter writer; |
| CvSeqReader reader; |
| |
| CvStatus status; |
| float gor[3] = { 1, 0, 0 }; |
| float ver[3] = { 0, 1, 0 }; |
| |
| int nbins = 20, i, l, i_point, left, right, jmin, jmax, jl; |
| int j_left, j_right; |
| int *bin_counts = 0; // pointer to the point's counter in the bickets |
| |
| // int *bin_countsj = 0; // pointer to the index's counter in the bickets |
| int low_count; // low threshold |
| |
| CvPoint *tmp_number = 0, *pt; |
| float value, vmin, vmax, vl, bsize, bsizej, vc, vcl, vcr; |
| double v_ver, v_gor; |
| float hand_length, hand_length2, hand_left, hand_right; |
| float threshold, threshold2; |
| float *vv = 0; |
| float a[3]; |
| char log; |
| |
| status = CV_OK; |
| |
| hand_length = size.width; |
| hand_length2 = hand_length / 2; |
| |
| threshold = (float) (size.height * 3 / 5.); |
| threshold2 = threshold * threshold; |
| |
| /* low_count = count/nbins; */ |
| low_count = (int) (count / 60.); |
| |
| assert( points != NULL && line != NULL ); |
| if( points == NULL || line == NULL ) |
| return CV_NULLPTR_ERR; |
| |
| assert( count > 5 ); |
| if( count < 5 ) |
| return CV_BADFLAG_ERR; |
| |
| /* create vectors */ |
| sub = icvCreateVector_32f( 3 ); |
| cros = icvCreateVector_32f( 3 ); |
| if( sub == NULL || cros == NULL ) |
| return CV_OUTOFMEM_ERR; |
| |
| /* alloc memory for the point's projections on the line */ |
| vv = (float *) cvAlloc( count * sizeof( float )); |
| |
| if( vv == NULL ) |
| return CV_OUTOFMEM_ERR; |
| |
| /* alloc memory for the point's counter in the bickets */ |
| bin_counts = (int *) cvAlloc( nbins * sizeof( int )); |
| |
| if( bin_counts == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| memset( bin_counts, 0, nbins * sizeof( int )); |
| |
| /* alloc memory for the point's counter in the bickets */ |
| // bin_countsj = (int*) icvAlloc(nbins*sizeof(int)); |
| // if(bin_countsj == NULL) {status = CV_OUTOFMEM_ERR; goto M_END;} |
| // memset(bin_countsj,0,nbins*sizeof(int)); |
| |
| cvStartReadSeq( indexs, &reader, 0 ); |
| |
| /* alloc memory for the temporale point's numbers */ |
| tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint )); |
| if( tmp_number == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| |
| /* find min and max point's projection on the line */ |
| vmin = 1000; |
| vmax = -1000; |
| jmin = 1000; |
| jmax = -1000; |
| i_point = 0; |
| for( i = 0; i < count; i++ ) |
| { |
| /* |
| icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3); |
| |
| icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros); |
| */ |
| |
| sub[0] = points[i].x - line[3]; |
| sub[1] = points[i].y - line[4]; |
| sub[2] = points[i].z - line[5]; |
| |
| // if(fabs(sub[0])<eps||fabs(sub[1])<eps||fabs(sub[2])<eps) continue; |
| |
| a[0] = sub[0] * line[1] - sub[1] * line[0]; |
| a[1] = sub[1] * line[2] - sub[2] * line[1]; |
| a[2] = sub[2] * line[0] - sub[0] * line[2]; |
| |
| v_gor = icvDotProduct_32f( gor, &line[0], 3 ); |
| v_ver = icvDotProduct_32f( ver, &line[0], 3 ); |
| |
| if( v_ver > v_gor ) |
| log = true; |
| else |
| log = false; |
| |
| |
| /* if(IPPI_NORM_L22 ( cros ) < threshold2) */ |
| /* |
| if(fabs(a[0])<eps && fabs(a[1])<eps && fabs(a[2])<eps) |
| { |
| icvDotProduct_32f( sub, &line[0], 3, &value); |
| if(value > vmax) vmax = value; |
| if(value < vmin) vmin = value; |
| |
| vv[i_point] = value; |
| |
| pt = (CvPoint* )icvGetSeqElem ( indexs, i, 0); |
| |
| if(pt->x > jmax) jmax = pt->x; |
| if(pt->x < jmin) jmin = pt->x; |
| |
| tmp_number[i_point] = *pt; |
| i_point++; |
| } |
| else |
| */ |
| { |
| if( _CV_NORM_L32( a ) < threshold2 ) |
| { |
| value = (float)icvDotProduct_32f( sub, &line[0], 3 ); |
| if( value > vmax ) |
| vmax = value; |
| if( value < vmin ) |
| vmin = value; |
| |
| vv[i_point] = value; |
| |
| pt = (CvPoint*)cvGetSeqElem( indexs, i ); |
| |
| if( !log ) |
| { |
| if( pt->x > jmax ) |
| jmax = pt->x; |
| if( pt->x < jmin ) |
| jmin = pt->x; |
| } |
| else |
| { |
| if( pt->y > jmax ) |
| jmax = pt->y; |
| if( pt->y < jmin ) |
| jmin = pt->y; |
| } |
| |
| |
| tmp_number[i_point] = *pt; |
| i_point++; |
| } |
| } |
| } |
| |
| /* compute the length of one bucket along the line */ |
| vl = vmax - vmin; |
| |
| /* examining on the arm's existence */ |
| if( vl < eps ) |
| { |
| *numbers = NULL; |
| status = CV_OK; |
| goto M_END; |
| } |
| |
| bsize = vl / nbins; |
| |
| /* compute the number of points in each bucket along the line */ |
| for( i = 0; i < i_point; i++ ) |
| { |
| l = cvRound( (vv[i] - vmin) / bsize ); |
| bin_counts[l]++; |
| } |
| |
| /* compute the length of one bucket along the X axe */ |
| jl = jmax - jmin; |
| if( jl <= 1 ) |
| { |
| *numbers = NULL; |
| status = CV_OK; |
| goto M_END; |
| } |
| |
| bsizej = (float) (jl / (nbins + 0.)); |
| |
| /* compute the number of points in each bucket along the X axe */ |
| // for(i=0;i<i_point;i++) |
| // { |
| // l = cvRound((tmp_number[i].x - jmin)/bsizej); |
| // bin_countsj[l]++; |
| // } |
| |
| |
| left = right = -1; |
| |
| /* find the leftmost and the rightmost buckets */ |
| for( l = 0; l < nbins; l++ ) |
| { |
| if( bin_counts[l] > low_count && left == -1 ) |
| left = l; |
| else if( bin_counts[l] > low_count && left >= 0 ) |
| right = l; |
| |
| } |
| |
| /* compute center point of the left hand */ |
| if( left == -1 && right == -1 ) |
| { |
| *numbers = NULL; |
| status = CV_OK; |
| goto M_END; |
| } |
| |
| hand_left = vmin + left * bsize; |
| j_left = (int) (jmin + left * bsizej); |
| |
| vcl = hand_left + hand_length2; |
| |
| /* compute center point of the right hand */ |
| hand_right = vmax - (nbins - right - 1) * bsize; |
| vcr = hand_right - hand_length2; |
| |
| j_right = (int) (jmax - (nbins - right - 1) * bsizej); |
| |
| j_left = abs( j_left - jc ); |
| j_right = abs( j_right - jc ); |
| |
| if( j_left <= j_right ) |
| { |
| hand_right = hand_left + hand_length; |
| vc = vcl; |
| } |
| else |
| { |
| hand_left = hand_right - hand_length; |
| vc = vcr; |
| } |
| |
| icvScaleVector_32f( &line[0], sub, 3, vc ); |
| icvAddVector_32f( &line[3], sub, (float *) center, 3 ); |
| |
| /* select hand's points and calculate mean value */ |
| *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage ); |
| assert( *numbers != 0 ); |
| if( *numbers == NULL ) |
| { |
| status = CV_OUTOFMEM_ERR; |
| goto M_END; |
| } |
| |
| cvStartAppendToSeq( *numbers, &writer ); |
| |
| for( l = 0; l < i_point; l++ ) |
| { |
| if( vv[l] >= hand_left && vv[l] <= hand_right ) |
| { |
| CV_WRITE_SEQ_ELEM( tmp_number[l], writer ); |
| |
| } |
| } |
| |
| cvEndWriteSeq( &writer ); |
| |
| M_END: |
| if( tmp_number != NULL ) |
| cvFree( &tmp_number ); |
| // if(bin_countsj != NULL) cvFree( &bin_countsj ); |
| if( bin_counts != NULL ) |
| cvFree( &bin_counts ); |
| |
| if( vv != NULL ) |
| cvFree( &vv ); |
| |
| if( sub != NULL ) icvDeleteVector (sub); |
| if( cros != NULL ) icvDeleteVector (cros); |
| |
| return status; |
| } |
| |
| |
| /*F/////////////////////////////////////////////////////////////////////////////////////// |
| // Name: cvFindHandRegion |
| // Purpose: finds hand region in range image data |
| // Context: |
| // Parameters: |
| // points - pointer to the input point's set. |
| // count - the number of the input points. |
| // indexs - pointer to the input sequence of the point's indexes |
| // line - pointer to the 3D-line |
| // size - size of the hand in meters |
| // flag - hand direction's flag (0 - left, -1 - right, |
| // otherwise j-index of the initial image center) |
| // center - pointer to the output hand center |
| // storage - pointer to the memory storage |
| // numbers - pointer to the output sequence of the point's indexes inside |
| // hand region |
| // |
| // Notes: |
| //F*/ |
| CV_IMPL void |
| cvFindHandRegion( CvPoint3D32f * points, int count, |
| CvSeq * indexs, |
| float *line, CvSize2D32f size, int flag, |
| CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers ) |
| { |
| CV_FUNCNAME( "cvFindHandRegion" ); |
| __BEGIN__; |
| |
| if(flag == 0 || flag == -1) |
| { |
| IPPI_CALL( icvFindHandRegion( points, count, indexs, line, size, -flag, |
| center, storage, numbers )); |
| } |
| else |
| IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, flag, |
| center, storage, numbers )); |
| |
| __CLEANUP__; |
| __END__; |
| } |
| |
| /*F/////////////////////////////////////////////////////////////////////////////////////// |
| // Name: cvFindHandRegionA |
| // Purpose: finds hand region in range image data |
| // Context: |
| // Parameters: |
| // points - pointer to the input point's set. |
| // count - the number of the input points. |
| // indexs - pointer to the input sequence of the point's indexes |
| // line - pointer to the 3D-line |
| // size - size of the hand in meters |
| // jc - j-index of the initial image center |
| // center - pointer to the output hand center |
| // storage - pointer to the memory storage |
| // numbers - pointer to the output sequence of the point's indexes inside |
| // hand region |
| // |
| // Notes: |
| //F*/ |
| CV_IMPL void |
| cvFindHandRegionA( CvPoint3D32f * points, int count, |
| CvSeq * indexs, |
| float *line, CvSize2D32f size, int jc, |
| CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers ) |
| { |
| CV_FUNCNAME( "cvFindHandRegionA" ); |
| __BEGIN__; |
| |
| IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, jc, |
| center, storage, numbers )); |
| __CLEANUP__; |
| __END__; |
| } |
| |