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 #include "_cvaux.h"
42
43 #define _CV_NORM_L2(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]))
44 #define _CV_NORM_L22(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])
45
46 /****************************************************************************************\
47
48 find region where hand is (for gesture recognition)
49 flag = 0 (use left bucket) flag = 1 (use right bucket)
50
51 \****************************************************************************************/
52
53 static CvStatus CV_STDCALL
icvFindHandRegion(CvPoint3D32f * points,int count,CvSeq * indexs,float * line,CvSize2D32f size,int flag,CvPoint3D32f * center,CvMemStorage * storage,CvSeq ** numbers)54 icvFindHandRegion( CvPoint3D32f * points, int count,
55 CvSeq * indexs,
56 float *line, CvSize2D32f size, int flag,
57 CvPoint3D32f * center,
58 CvMemStorage * storage, CvSeq ** numbers )
59 {
60
61 /* IppmVect32f sub, cros; */
62 float *sub, *cros;
63 CvSeqWriter writer;
64 CvSeqReader reader;
65
66 CvStatus status;
67 int nbins = 20, i, l, i_point, left, right;
68 int *bin_counts = 0; // pointer to the point's counter in the bickets
69 int low_count; // low threshold
70
71 CvPoint *tmp_number = 0, *pt;
72 float value, vmin, vmax, vl, bsize, vc;
73 float hand_length, hand_length2, hand_left, hand_right;
74 float threshold, threshold2;
75 float *vv = 0;
76 float a[3];
77
78 status = CV_OK;
79
80 hand_length = size.width;
81 hand_length2 = hand_length / 2;
82
83 threshold = (float) (size.height * 3 / 5.);
84 threshold2 = threshold * threshold;
85
86 /* low_count = count/nbins; */
87 low_count = (int) (count / 60.);
88
89 assert( points != NULL && line != NULL );
90 if( points == NULL || line == NULL )
91 return CV_NULLPTR_ERR;
92
93 assert( count > 5 );
94 if( count < 5 )
95 return CV_BADFLAG_ERR;
96
97 assert( flag == 0 || flag == 1 );
98 if( flag != 0 && flag != 1 )
99 return CV_BADFLAG_ERR;
100
101 /* create vectors */
102 sub = icvCreateVector_32f( 3 );
103 cros = icvCreateVector_32f( 3 );
104 if( sub == NULL || cros == NULL )
105 return CV_OUTOFMEM_ERR;
106
107 /* alloc memory for the point's projections on the line */
108 vv = (float *) cvAlloc( count * sizeof( float ));
109
110 if( vv == NULL )
111 return CV_OUTOFMEM_ERR;
112
113 /* alloc memory for the point's counter in the bickets */
114 bin_counts = (int *) cvAlloc( nbins * sizeof( int ));
115
116 if( bin_counts == NULL )
117 {
118 status = CV_OUTOFMEM_ERR;
119 goto M_END;
120 }
121 memset( bin_counts, 0, nbins * sizeof( int ));
122
123 cvStartReadSeq( indexs, &reader, 0 );
124
125 /* alloc memory for the temporale point's numbers */
126 tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint ));
127 if( tmp_number == NULL )
128 {
129 status = CV_OUTOFMEM_ERR;
130 goto M_END;
131 }
132
133 /* find min and max point's projection on the line */
134 vmin = 1000;
135 vmax = -1000;
136 i_point = 0;
137 for( i = 0; i < count; i++ )
138 {
139 /*
140 icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3);
141
142 icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros);
143 */
144
145 sub[0] = points[i].x - line[3];
146 sub[1] = points[i].y - line[4];
147 sub[2] = points[i].z - line[5];
148 a[0] = sub[0] * line[1] - sub[1] * line[0];
149 a[1] = sub[1] * line[2] - sub[2] * line[1];
150 a[2] = sub[2] * line[0] - sub[0] * line[2];
151
152 /* if(IPPI_NORM_L22 ( cros ) < threshold2) */
153 if( _CV_NORM_L22( a ) < threshold2 )
154 {
155 value = (float)icvDotProduct_32f( sub, &line[0], 3 );
156 if( value > vmax )
157 vmax = value;
158 if( value < vmin )
159 vmin = value;
160
161 vv[i_point] = value;
162
163 pt = (CvPoint*)cvGetSeqElem( indexs, i );
164 tmp_number[i_point] = *pt;
165 i_point++;
166 }
167 }
168
169 /* compute the length of one bucket */
170 vl = vmax - vmin;
171 bsize = vl / nbins;
172
173 /* compute the number of points in each bucket */
174 for( i = 0; i < i_point; i++ )
175 {
176 l = cvRound( (vv[i] - vmin) / bsize );
177 bin_counts[l]++;
178 }
179
180 *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage );
181 assert( numbers != 0 );
182 if( numbers == NULL )
183 {
184 status = CV_OUTOFMEM_ERR;
185 goto M_END;
186 }
187
188 cvStartAppendToSeq( *numbers, &writer );
189
190 if( flag == 0 )
191 {
192 /* find the leftmost bucket */
193 for( l = 0; l < nbins; l++ )
194 {
195 if( bin_counts[l] > low_count )
196 break;
197 }
198 left = l;
199
200 /* compute center point of the left hand */
201 hand_left = vmin + left * bsize;
202 vc = hand_left + hand_length2;
203 hand_right = hand_left + hand_length;
204 }
205 else
206 {
207 /* find the rightmost bucket */
208 for( l = nbins - 1; l >= 0; l-- )
209 {
210 if( bin_counts[l] > low_count )
211 break;
212 }
213 right = l;
214
215 /* compute center point of the right hand */
216 hand_right = vmax - (nbins - right - 1) * bsize;
217 vc = hand_right - hand_length2;
218 hand_left = hand_right - hand_length;
219 }
220
221 icvScaleVector_32f( &line[0], sub, 3, vc );
222 icvAddVector_32f( &line[3], sub, (float *) center, 3 );
223
224 /* select hand's points and calculate mean value */
225
226 //ss.x = ss.y = ss.z = 0;
227 for( l = 0; l < i_point; l++ )
228 {
229 if( vv[l] >= hand_left && vv[l] <= hand_right )
230 {
231 CV_WRITE_SEQ_ELEM( tmp_number[l], writer );
232
233 }
234 }
235
236 cvEndWriteSeq( &writer );
237
238 M_END:
239 if( tmp_number != NULL )
240 cvFree( &tmp_number );
241 if( bin_counts != NULL )
242 cvFree( &bin_counts );
243 if( vv != NULL )
244 cvFree( &vv );
245 if( sub != NULL ) icvDeleteVector (sub);
246 if( cros != NULL ) icvDeleteVector (cros);
247
248 return status;
249
250 }
251
252
253 //////////////////////////////////////////////////////////////////////////////////////////
254 //////////////////////////////////////////////////////////////////////////////////////////
255 //////////////////////////////////////////////////////////////////////////////////////////
256
257
258 #define _CV_NORM_L31(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]))
259 #define _CV_NORM_L32(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])
260
261 /****************************************************************************************\
262
263 find region where hand is (for gesture recognition)
264 flag = 0 (use left bucket) flag = 1 (use right bucket)
265
266 \****************************************************************************************/
267
268 static CvStatus CV_STDCALL
icvFindHandRegionA(CvPoint3D32f * points,int count,CvSeq * indexs,float * line,CvSize2D32f size,int jc,CvPoint3D32f * center,CvMemStorage * storage,CvSeq ** numbers)269 icvFindHandRegionA( CvPoint3D32f * points, int count,
270 CvSeq * indexs,
271 float *line, CvSize2D32f size, int jc,
272 CvPoint3D32f * center,
273 CvMemStorage * storage, CvSeq ** numbers )
274 {
275
276 /* IppmVect32f sub, cros; */
277 float *sub, *cros;
278 float eps = (float) 0.01;
279 CvSeqWriter writer;
280 CvSeqReader reader;
281
282 CvStatus status;
283 float gor[3] = { 1, 0, 0 };
284 float ver[3] = { 0, 1, 0 };
285
286 int nbins = 20, i, l, i_point, left, right, jmin, jmax, jl;
287 int j_left, j_right;
288 int *bin_counts = 0; // pointer to the point's counter in the bickets
289
290 // int *bin_countsj = 0; // pointer to the index's counter in the bickets
291 int low_count; // low threshold
292
293 CvPoint *tmp_number = 0, *pt;
294 float value, vmin, vmax, vl, bsize, bsizej, vc, vcl, vcr;
295 double v_ver, v_gor;
296 float hand_length, hand_length2, hand_left, hand_right;
297 float threshold, threshold2;
298 float *vv = 0;
299 float a[3];
300 char log;
301
302 status = CV_OK;
303
304 hand_length = size.width;
305 hand_length2 = hand_length / 2;
306
307 threshold = (float) (size.height * 3 / 5.);
308 threshold2 = threshold * threshold;
309
310 /* low_count = count/nbins; */
311 low_count = (int) (count / 60.);
312
313 assert( points != NULL && line != NULL );
314 if( points == NULL || line == NULL )
315 return CV_NULLPTR_ERR;
316
317 assert( count > 5 );
318 if( count < 5 )
319 return CV_BADFLAG_ERR;
320
321 /* create vectors */
322 sub = icvCreateVector_32f( 3 );
323 cros = icvCreateVector_32f( 3 );
324 if( sub == NULL || cros == NULL )
325 return CV_OUTOFMEM_ERR;
326
327 /* alloc memory for the point's projections on the line */
328 vv = (float *) cvAlloc( count * sizeof( float ));
329
330 if( vv == NULL )
331 return CV_OUTOFMEM_ERR;
332
333 /* alloc memory for the point's counter in the bickets */
334 bin_counts = (int *) cvAlloc( nbins * sizeof( int ));
335
336 if( bin_counts == NULL )
337 {
338 status = CV_OUTOFMEM_ERR;
339 goto M_END;
340 }
341 memset( bin_counts, 0, nbins * sizeof( int ));
342
343 /* alloc memory for the point's counter in the bickets */
344 // bin_countsj = (int*) icvAlloc(nbins*sizeof(int));
345 // if(bin_countsj == NULL) {status = CV_OUTOFMEM_ERR; goto M_END;}
346 // memset(bin_countsj,0,nbins*sizeof(int));
347
348 cvStartReadSeq( indexs, &reader, 0 );
349
350 /* alloc memory for the temporale point's numbers */
351 tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint ));
352 if( tmp_number == NULL )
353 {
354 status = CV_OUTOFMEM_ERR;
355 goto M_END;
356 }
357
358 /* find min and max point's projection on the line */
359 vmin = 1000;
360 vmax = -1000;
361 jmin = 1000;
362 jmax = -1000;
363 i_point = 0;
364 for( i = 0; i < count; i++ )
365 {
366 /*
367 icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3);
368
369 icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros);
370 */
371
372 sub[0] = points[i].x - line[3];
373 sub[1] = points[i].y - line[4];
374 sub[2] = points[i].z - line[5];
375
376 // if(fabs(sub[0])<eps||fabs(sub[1])<eps||fabs(sub[2])<eps) continue;
377
378 a[0] = sub[0] * line[1] - sub[1] * line[0];
379 a[1] = sub[1] * line[2] - sub[2] * line[1];
380 a[2] = sub[2] * line[0] - sub[0] * line[2];
381
382 v_gor = icvDotProduct_32f( gor, &line[0], 3 );
383 v_ver = icvDotProduct_32f( ver, &line[0], 3 );
384
385 if( v_ver > v_gor )
386 log = true;
387 else
388 log = false;
389
390
391 /* if(IPPI_NORM_L22 ( cros ) < threshold2) */
392 /*
393 if(fabs(a[0])<eps && fabs(a[1])<eps && fabs(a[2])<eps)
394 {
395 icvDotProduct_32f( sub, &line[0], 3, &value);
396 if(value > vmax) vmax = value;
397 if(value < vmin) vmin = value;
398
399 vv[i_point] = value;
400
401 pt = (CvPoint* )icvGetSeqElem ( indexs, i, 0);
402
403 if(pt->x > jmax) jmax = pt->x;
404 if(pt->x < jmin) jmin = pt->x;
405
406 tmp_number[i_point] = *pt;
407 i_point++;
408 }
409 else
410 */
411 {
412 if( _CV_NORM_L32( a ) < threshold2 )
413 {
414 value = (float)icvDotProduct_32f( sub, &line[0], 3 );
415 if( value > vmax )
416 vmax = value;
417 if( value < vmin )
418 vmin = value;
419
420 vv[i_point] = value;
421
422 pt = (CvPoint*)cvGetSeqElem( indexs, i );
423
424 if( !log )
425 {
426 if( pt->x > jmax )
427 jmax = pt->x;
428 if( pt->x < jmin )
429 jmin = pt->x;
430 }
431 else
432 {
433 if( pt->y > jmax )
434 jmax = pt->y;
435 if( pt->y < jmin )
436 jmin = pt->y;
437 }
438
439
440 tmp_number[i_point] = *pt;
441 i_point++;
442 }
443 }
444 }
445
446 /* compute the length of one bucket along the line */
447 vl = vmax - vmin;
448
449 /* examining on the arm's existence */
450 if( vl < eps )
451 {
452 *numbers = NULL;
453 status = CV_OK;
454 goto M_END;
455 }
456
457 bsize = vl / nbins;
458
459 /* compute the number of points in each bucket along the line */
460 for( i = 0; i < i_point; i++ )
461 {
462 l = cvRound( (vv[i] - vmin) / bsize );
463 bin_counts[l]++;
464 }
465
466 /* compute the length of one bucket along the X axe */
467 jl = jmax - jmin;
468 if( jl <= 1 )
469 {
470 *numbers = NULL;
471 status = CV_OK;
472 goto M_END;
473 }
474
475 bsizej = (float) (jl / (nbins + 0.));
476
477 /* compute the number of points in each bucket along the X axe */
478 // for(i=0;i<i_point;i++)
479 // {
480 // l = cvRound((tmp_number[i].x - jmin)/bsizej);
481 // bin_countsj[l]++;
482 // }
483
484
485 left = right = -1;
486
487 /* find the leftmost and the rightmost buckets */
488 for( l = 0; l < nbins; l++ )
489 {
490 if( bin_counts[l] > low_count && left == -1 )
491 left = l;
492 else if( bin_counts[l] > low_count && left >= 0 )
493 right = l;
494
495 }
496
497 /* compute center point of the left hand */
498 if( left == -1 && right == -1 )
499 {
500 *numbers = NULL;
501 status = CV_OK;
502 goto M_END;
503 }
504
505 hand_left = vmin + left * bsize;
506 j_left = (int) (jmin + left * bsizej);
507
508 vcl = hand_left + hand_length2;
509
510 /* compute center point of the right hand */
511 hand_right = vmax - (nbins - right - 1) * bsize;
512 vcr = hand_right - hand_length2;
513
514 j_right = (int) (jmax - (nbins - right - 1) * bsizej);
515
516 j_left = abs( j_left - jc );
517 j_right = abs( j_right - jc );
518
519 if( j_left <= j_right )
520 {
521 hand_right = hand_left + hand_length;
522 vc = vcl;
523 }
524 else
525 {
526 hand_left = hand_right - hand_length;
527 vc = vcr;
528 }
529
530 icvScaleVector_32f( &line[0], sub, 3, vc );
531 icvAddVector_32f( &line[3], sub, (float *) center, 3 );
532
533 /* select hand's points and calculate mean value */
534 *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage );
535 assert( *numbers != 0 );
536 if( *numbers == NULL )
537 {
538 status = CV_OUTOFMEM_ERR;
539 goto M_END;
540 }
541
542 cvStartAppendToSeq( *numbers, &writer );
543
544 for( l = 0; l < i_point; l++ )
545 {
546 if( vv[l] >= hand_left && vv[l] <= hand_right )
547 {
548 CV_WRITE_SEQ_ELEM( tmp_number[l], writer );
549
550 }
551 }
552
553 cvEndWriteSeq( &writer );
554
555 M_END:
556 if( tmp_number != NULL )
557 cvFree( &tmp_number );
558 // if(bin_countsj != NULL) cvFree( &bin_countsj );
559 if( bin_counts != NULL )
560 cvFree( &bin_counts );
561
562 if( vv != NULL )
563 cvFree( &vv );
564
565 if( sub != NULL ) icvDeleteVector (sub);
566 if( cros != NULL ) icvDeleteVector (cros);
567
568 return status;
569 }
570
571
572 /*F///////////////////////////////////////////////////////////////////////////////////////
573 // Name: cvFindHandRegion
574 // Purpose: finds hand region in range image data
575 // Context:
576 // Parameters:
577 // points - pointer to the input point's set.
578 // count - the number of the input points.
579 // indexs - pointer to the input sequence of the point's indexes
580 // line - pointer to the 3D-line
581 // size - size of the hand in meters
582 // flag - hand direction's flag (0 - left, -1 - right,
583 // otherwise j-index of the initial image center)
584 // center - pointer to the output hand center
585 // storage - pointer to the memory storage
586 // numbers - pointer to the output sequence of the point's indexes inside
587 // hand region
588 //
589 // Notes:
590 //F*/
591 CV_IMPL void
cvFindHandRegion(CvPoint3D32f * points,int count,CvSeq * indexs,float * line,CvSize2D32f size,int flag,CvPoint3D32f * center,CvMemStorage * storage,CvSeq ** numbers)592 cvFindHandRegion( CvPoint3D32f * points, int count,
593 CvSeq * indexs,
594 float *line, CvSize2D32f size, int flag,
595 CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers )
596 {
597 CV_FUNCNAME( "cvFindHandRegion" );
598 __BEGIN__;
599
600 if(flag == 0 || flag == -1)
601 {
602 IPPI_CALL( icvFindHandRegion( points, count, indexs, line, size, -flag,
603 center, storage, numbers ));
604 }
605 else
606 IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, flag,
607 center, storage, numbers ));
608
609 __CLEANUP__;
610 __END__;
611 }
612
613 /*F///////////////////////////////////////////////////////////////////////////////////////
614 // Name: cvFindHandRegionA
615 // Purpose: finds hand region in range image data
616 // Context:
617 // Parameters:
618 // points - pointer to the input point's set.
619 // count - the number of the input points.
620 // indexs - pointer to the input sequence of the point's indexes
621 // line - pointer to the 3D-line
622 // size - size of the hand in meters
623 // jc - j-index of the initial image center
624 // center - pointer to the output hand center
625 // storage - pointer to the memory storage
626 // numbers - pointer to the output sequence of the point's indexes inside
627 // hand region
628 //
629 // Notes:
630 //F*/
631 CV_IMPL void
cvFindHandRegionA(CvPoint3D32f * points,int count,CvSeq * indexs,float * line,CvSize2D32f size,int jc,CvPoint3D32f * center,CvMemStorage * storage,CvSeq ** numbers)632 cvFindHandRegionA( CvPoint3D32f * points, int count,
633 CvSeq * indexs,
634 float *line, CvSize2D32f size, int jc,
635 CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers )
636 {
637 CV_FUNCNAME( "cvFindHandRegionA" );
638 __BEGIN__;
639
640 IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, jc,
641 center, storage, numbers ));
642 __CLEANUP__;
643 __END__;
644 }
645
646