1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* ---- includes ----------------------------------------------------------- */ 18 19 #include "b_APIEm/BFFaceFinder.h" 20 #include "b_APIEm/Functions.h" 21 #include "b_APIEm/DCR.h" 22 #include "b_BasicEm/Functions.h" 23 #include "b_BasicEm/Math.h" 24 25 /* ------------------------------------------------------------------------- */ 26 27 /* ========================================================================= */ 28 /* */ 29 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ 30 /* */ 31 /* ========================================================================= */ 32 33 /* ------------------------------------------------------------------------- */ 34 35 /* ========================================================================= */ 36 /* */ 37 /* ---- \ghd{ constructor / destructor } ----------------------------------- */ 38 /* */ 39 /* ========================================================================= */ 40 41 /* ------------------------------------------------------------------------- */ 42 43 void bpi_BFFaceFinder_init( struct bbs_Context* cpA, 44 struct bpi_BFFaceFinder* ptrA ) 45 { 46 bpi_FaceFinder_init( cpA, &ptrA->baseE ); 47 ptrA->baseE.typeE = ( uint32 )bpi_FF_BF_FACE_FINDER; 48 ptrA->baseE.vpSetParamsE = bpi_BFFaceFinder_setParams; 49 ptrA->baseE.vpSetRangeE = bpi_BFFaceFinder_setRange; 50 ptrA->baseE.vpProcessE = bpi_BFFaceFinder_processDcr; 51 ptrA->baseE.vpPutDcrE = bpi_BFFaceFinder_putDcr; 52 ptrA->baseE.vpGetDcrE = bpi_BFFaceFinder_getDcr; 53 54 ptrA->detectedFacesE = 0; 55 ptrA->availableFacesE = 0; 56 ptrA->faceDataBufferE = NULL; 57 bbf_ScanDetector_init( cpA, &ptrA->detectorE ); 58 } 59 60 /* ------------------------------------------------------------------------- */ 61 62 void bpi_BFFaceFinder_exit( struct bbs_Context* cpA, 63 struct bpi_BFFaceFinder* ptrA ) 64 { 65 ptrA->detectedFacesE = 0; 66 ptrA->availableFacesE = 0; 67 ptrA->faceDataBufferE = NULL; 68 bbf_ScanDetector_exit( cpA, &ptrA->detectorE ); 69 70 bpi_FaceFinder_exit( cpA, &ptrA->baseE ); 71 } 72 73 /* ------------------------------------------------------------------------- */ 74 75 /* ========================================================================= */ 76 /* */ 77 /* ---- \ghd{ operators } -------------------------------------------------- */ 78 /* */ 79 /* ========================================================================= */ 80 81 /* ------------------------------------------------------------------------- */ 82 83 void bpi_BFFaceFinder_copy( struct bbs_Context* cpA, 84 struct bpi_BFFaceFinder* ptrA, 85 const struct bpi_BFFaceFinder* srcPtrA ) 86 { 87 bpi_FaceFinder_copy( cpA, &ptrA->baseE, &srcPtrA->baseE ); 88 bbf_ScanDetector_copy( cpA, &ptrA->detectorE, &srcPtrA->detectorE ); 89 } 90 91 /* ------------------------------------------------------------------------- */ 92 93 flag bpi_BFFaceFinder_equal( struct bbs_Context* cpA, 94 const struct bpi_BFFaceFinder* ptrA, 95 const struct bpi_BFFaceFinder* srcPtrA ) 96 { 97 if( !bpi_FaceFinder_equal( cpA, &ptrA->baseE, &srcPtrA->baseE ) ) return FALSE; 98 if( !bbf_ScanDetector_equal( cpA, &ptrA->detectorE, &srcPtrA->detectorE ) ) return FALSE; 99 return TRUE; 100 } 101 102 /* ------------------------------------------------------------------------- */ 103 104 /* ========================================================================= */ 105 /* */ 106 /* ---- \ghd{ query functions } -------------------------------------------- */ 107 /* */ 108 /* ========================================================================= */ 109 110 /* ------------------------------------------------------------------------- */ 111 112 uint32 bpi_BFFaceFinder_getMinEyeDistance( const struct bpi_BFFaceFinder* ptrA ) 113 { 114 return ( ( ptrA->detectorE.refDistanceE >> 8 ) * ( ptrA->detectorE.minScaleE >> 12 ) ) >> 16; 115 } 116 117 /* ------------------------------------------------------------------------- */ 118 119 uint32 bpi_BFFaceFinder_getMaxEyeDistance( const struct bpi_BFFaceFinder* ptrA ) 120 { 121 return ( ( ptrA->detectorE.refDistanceE >> 8 ) * ( ptrA->detectorE.maxScaleE >> 12 ) ) >> 16; 122 } 123 124 /* ------------------------------------------------------------------------- */ 125 126 /* ========================================================================= */ 127 /* */ 128 /* ---- \ghd{ modify functions } ------------------------------------------- */ 129 /* */ 130 /* ========================================================================= */ 131 132 /* ------------------------------------------------------------------------- */ 133 134 void bpi_BFFaceFinder_setMinEyeDistance( struct bbs_Context* cpA, 135 struct bpi_BFFaceFinder* ptrA, 136 uint32 distA ) 137 { 138 ptrA->detectorE.minScaleE = ( ( distA << 16 ) / ( ptrA->detectorE.refDistanceE >> 8 ) ) << 12; 139 if( ptrA->detectorE.minScaleE < 0x100000 /* 1.0 */ ) ptrA->detectorE.minScaleE = 0x100000; 140 } 141 142 /* ------------------------------------------------------------------------- */ 143 144 void bpi_BFFaceFinder_setMaxEyeDistance( struct bbs_Context* cpA, 145 struct bpi_BFFaceFinder* ptrA, 146 uint32 distA ) 147 { 148 if( distA > 0x0FFFF ) 149 { 150 ptrA->detectorE.maxScaleE = 0; /* unlimited */ 151 } 152 else 153 { 154 ptrA->detectorE.maxScaleE = ( ( distA << 16 ) / ( ptrA->detectorE.refDistanceE >> 8 ) ) << 12; 155 } 156 } 157 158 /* ------------------------------------------------------------------------- */ 159 160 /* ========================================================================= */ 161 /* */ 162 /* ---- \ghd{ I/O } -------------------------------------------------------- */ 163 /* */ 164 /* ========================================================================= */ 165 166 /* ------------------------------------------------------------------------- */ 167 168 uint32 bpi_BFFaceFinder_memSize( struct bbs_Context* cpA, 169 const struct bpi_BFFaceFinder *ptrA ) 170 { 171 uint32 memSizeL = 0; 172 memSizeL += bbs_SIZEOF16( uint32 ); 173 memSizeL += bbs_SIZEOF16( uint32 ); /* version */ 174 memSizeL += bpi_FaceFinder_memSize( cpA, &ptrA->baseE ); 175 memSizeL += bbf_ScanDetector_memSize( cpA, &ptrA->detectorE ); 176 memSizeL += bbs_SIZEOF16( uint16 ); /* csa */ 177 return memSizeL; 178 } 179 180 /* ------------------------------------------------------------------------- */ 181 182 uint32 bpi_BFFaceFinder_memWrite( struct bbs_Context* cpA, 183 const struct bpi_BFFaceFinder* ptrA, 184 uint16* memPtrA ) 185 { 186 uint32 memSizeL = bpi_BFFaceFinder_memSize( cpA, ptrA ); 187 memPtrA += bbs_memWrite32( &memSizeL, memPtrA ); 188 memPtrA += bbs_memWriteUInt32( bpi_BF_FACE_FINDER_VERSION, memPtrA ); 189 memPtrA += bpi_FaceFinder_memWrite( cpA, &ptrA->baseE, memPtrA ); 190 memPtrA += bbf_ScanDetector_memWrite( cpA, &ptrA->detectorE, memPtrA ); 191 memPtrA += bpi_memWriteCsa16( memPtrA, memSizeL, 0xFFFF ); 192 return memSizeL; 193 } 194 195 /* ------------------------------------------------------------------------- */ 196 197 uint32 bpi_BFFaceFinder_memRead( struct bbs_Context* cpA, 198 struct bpi_BFFaceFinder* ptrA, 199 const uint16* memPtrA, 200 struct bbs_MemTbl* mtpA ) 201 { 202 uint32 memSizeL, versionL; 203 if( bbs_Context_error( cpA ) ) return 0; 204 memPtrA += bbs_memRead32( &memSizeL, memPtrA ); 205 memPtrA += bbs_memReadVersion32( cpA, &versionL, bpi_BF_FACE_FINDER_VERSION, memPtrA ); 206 memPtrA += bpi_FaceFinder_memRead( cpA, &ptrA->baseE, memPtrA ); 207 if( bbs_Context_error( cpA ) ) return 0; 208 209 memPtrA += bbf_ScanDetector_memRead( cpA, &ptrA->detectorE, memPtrA, mtpA ); 210 if( bbs_Context_error( cpA ) ) return 0; 211 memPtrA += bpi_memReadCsa16( memPtrA ); 212 213 /* if( memSizeL != bpi_BFFaceFinder_memSize( cpA, ptrA ) ) 214 { 215 bbs_ERROR0( "uint32 bpi_BFFaceFinder_memRead( .... ):\n" 216 "Module file is corrupt or incorrect. Please check if the face finder module is still supported." ); 217 return 0; 218 } 219 */ 220 return memSizeL; 221 } 222 223 /* ------------------------------------------------------------------------- */ 224 225 /* ========================================================================= */ 226 /* */ 227 /* ---- \ghd{ exec functions } --------------------------------------------- */ 228 /* */ 229 /* ========================================================================= */ 230 231 /* ------------------------------------------------------------------------- */ 232 233 int32 bpi_BFFaceFinder_process( struct bbs_Context* cpA, 234 const struct bpi_BFFaceFinder* ptrA, 235 void* imagePtrA, 236 uint32 imageWidthA, 237 uint32 imageHeightA, 238 const struct bts_Int16Rect* roiPtrA, 239 struct bts_Int16Vec2D* offsPtrA, 240 struct bts_IdCluster2D* idClusterPtrA ) 241 { 242 int32 xL = 0; /* 16.16 */ 243 int32 yL = 0; /* 16.16 */ 244 uint32 scaleL = 0; 245 int32 actL = 0; 246 int32* outArrL; 247 248 struct bts_Flt16Alt2D altL; 249 struct bts_Flt16Vec2D centerL; 250 251 struct bpi_BFFaceFinder* ptrL = ( struct bpi_BFFaceFinder* )ptrA; 252 253 /* reset multi face imformation so they are not accidentally used */ 254 ptrL->detectedFacesE = 0; 255 ptrL->availableFacesE = 0; 256 ptrL->faceDataBufferE = NULL; 257 258 bbf_ScanDetector_process( cpA, ( struct bbf_ScanDetector* )&ptrA->detectorE, imagePtrA, imageWidthA, imageHeightA, roiPtrA, &outArrL ); 259 260 xL = outArrL[ 0 ]; /* 16.16 */ 261 yL = outArrL[ 1 ]; /* 16.16 */ 262 scaleL = outArrL[ 2 ]; /* 12.20 */ 263 actL = outArrL[ 3 ]; /* 4.28 */ 264 265 if( bbs_Context_error( cpA ) ) return 0; 266 267 offsPtrA->xE = xL >> 16; 268 offsPtrA->yE = yL >> 16; 269 xL -= ( ( int32 )offsPtrA->xE << 16 ); 270 yL -= ( ( int32 )offsPtrA->yE << 16 ); 271 272 centerL = bts_Flt16Vec2D_create32( 0, 0, 0 ); 273 altL = bts_Flt16Alt2D_createScale( scaleL, 20, ¢erL ); 274 altL.vecE = bts_Flt16Vec2D_create32( xL, yL, 16 ); 275 276 /* compute cluster */ 277 { 278 uint32 eyeDistL = ( ( ptrA->detectorE.refDistanceE >> 16 ) * scaleL ) >> 20; 279 uint32 logEyeDistL = bbs_intLog2( eyeDistL ); 280 int32 bbpL = 11 - logEyeDistL; 281 bbpL = bbpL < 0 ? 0 : bbpL; 282 bbpL = bbpL > 6 ? 6 : bbpL; 283 bts_IdCluster2D_copyTransform( cpA, idClusterPtrA, &ptrA->detectorE.refClusterE, altL, bbpL ); 284 } 285 286 287 return ( actL + 0x10000000 ) >> 5; /*output range 0...1 in 8.24*/ 288 } 289 290 /* ------------------------------------------------------------------------- */ 291 292 uint32 bpi_BFFaceFinder_multiProcess( struct bbs_Context* cpA, 293 const struct bpi_BFFaceFinder* ptrA, 294 void* imagePtrA, 295 uint32 imageWidthA, 296 uint32 imageHeightA, 297 const struct bts_Int16Rect* roiPtrA ) 298 { 299 struct bpi_BFFaceFinder* ptrL = ( struct bpi_BFFaceFinder* )ptrA; 300 ptrL->detectedFacesE = bbf_ScanDetector_process( cpA, ( struct bbf_ScanDetector* )&ptrA->detectorE, imagePtrA, imageWidthA, imageHeightA, roiPtrA, &ptrL->faceDataBufferE ); 301 ptrL->availableFacesE = ptrA->detectedFacesE > 0 ? ptrA->detectedFacesE : 1; 302 if( bbs_Context_error( cpA ) ) return 0; 303 return ptrL->detectedFacesE; 304 } 305 306 /* ------------------------------------------------------------------------- */ 307 308 uint32 bpi_BFFaceFinder_getFace( struct bbs_Context* cpA, 309 const struct bpi_BFFaceFinder* ptrA, 310 uint32 indexA, 311 struct bts_Int16Vec2D* offsPtrA, 312 struct bts_IdCluster2D* idClusterPtrA ) 313 { 314 bbs_DEF_fNameL( "bpi_BFFaceFinder_getFace" ) 315 int32 xL = 0; /* 16.16 */ 316 int32 yL = 0; /* 16.16 */ 317 uint32 scaleL = 0; 318 int32 actL = 0; 319 struct bts_Flt16Alt2D altL; 320 struct bts_Flt16Vec2D centerL; 321 322 if( bbs_Context_error( cpA ) ) return 0; 323 324 if( ptrA->availableFacesE == 0 || ptrA->faceDataBufferE == NULL ) 325 { 326 bbs_ERROR1( "%s:\nNo faces are availabe. This function was called before the face finder could detect multiple faces in an image", fNameL ); 327 return 0; 328 } 329 330 if( indexA >= ptrA->availableFacesE ) 331 { 332 bbs_ERROR1( "%s:\nface index exceeds number of available faces", fNameL ); 333 return 0; 334 } 335 336 xL = ptrA->faceDataBufferE[ indexA * 4 + 0 ]; /* 16.16 */ 337 yL = ptrA->faceDataBufferE[ indexA * 4 + 1 ]; /* 16.16 */ 338 scaleL = ptrA->faceDataBufferE[ indexA * 4 + 2 ]; /* 12.20 */ 339 actL = ptrA->faceDataBufferE[ indexA * 4 + 3 ]; /* 4.28 */ 340 341 offsPtrA->xE = xL >> 16; 342 offsPtrA->yE = yL >> 16; 343 344 xL -= ( ( int32 )offsPtrA->xE << 16 ); 345 yL -= ( ( int32 )offsPtrA->yE << 16 ); 346 347 centerL = bts_Flt16Vec2D_create32( 0, 0, 0 ); 348 altL = bts_Flt16Alt2D_createScale( scaleL, 20, ¢erL ); 349 altL.vecE = bts_Flt16Vec2D_create32( xL, yL, 16 ); 350 351 /* compute cluster */ 352 { 353 uint32 eyeDistL = ( ( ptrA->detectorE.refDistanceE >> 16 ) * scaleL ) >> 20; 354 uint32 logEyeDistL = bbs_intLog2( eyeDistL ); 355 int32 bbpL = 11 - logEyeDistL; 356 bbpL = bbpL < 0 ? 0 : bbpL; 357 bbpL = bbpL > 6 ? 6 : bbpL; 358 bts_IdCluster2D_copyTransform( cpA, idClusterPtrA, &ptrA->detectorE.refClusterE, altL, bbpL ); 359 } 360 361 return ( actL + 0x10000000 ) >> 5; /*output range 0...1 in 8.24*/ 362 } 363 364 /* ------------------------------------------------------------------------- */ 365 366 void bpi_BFFaceFinder_getFaceDCR( struct bbs_Context* cpA, 367 const struct bpi_BFFaceFinder* ptrA, 368 uint32 indexA, 369 struct bpi_DCR* dcrPtrA ) 370 { 371 int32 confL = bpi_BFFaceFinder_getFace( cpA, ptrA, indexA, &dcrPtrA->offsE, &dcrPtrA->mainClusterE ); 372 bts_IdCluster2D_copy( cpA, &dcrPtrA->sdkClusterE, &dcrPtrA->mainClusterE ); 373 dcrPtrA->confidenceE = confL; 374 dcrPtrA->approvedE = confL > ( ( int32 )1 << 23 ); 375 } 376 377 /* ------------------------------------------------------------------------- */ 378 379 void bpi_BFFaceFinder_setMaxImageSize( struct bbs_Context* cpA, 380 struct bpi_BFFaceFinder* ptrA, 381 uint32 maxImageWidthA, 382 uint32 maxImageHeightA ) 383 { 384 ptrA->detectorE.maxImageWidthE = maxImageWidthA; 385 ptrA->detectorE.maxImageHeightE = maxImageHeightA; 386 } 387 388 /* ------------------------------------------------------------------------- */ 389 390 void bpi_BFFaceFinder_setParams( struct bbs_Context* cpA, 391 struct bpi_FaceFinder* ptrA, 392 uint32 maxImageWidthA, 393 uint32 maxImageHeightA ) 394 { 395 bbs_DEF_fNameL( "bpi_BFFaceFinder_setParams" ); 396 397 if( bbs_Context_error( cpA ) ) return; 398 399 if( ptrA->typeE != bpi_FF_BF_FACE_FINDER ) 400 { 401 bbs_ERROR1( "%s:\nObject type mismatch", fNameL ); 402 return; 403 } 404 bpi_BFFaceFinder_setMaxImageSize( cpA, ( struct bpi_BFFaceFinder* )ptrA, maxImageWidthA, maxImageHeightA ); 405 } 406 407 /* ------------------------------------------------------------------------- */ 408 409 void bpi_BFFaceFinder_setRange( struct bbs_Context* cpA, 410 struct bpi_FaceFinder* ptrA, 411 uint32 minEyeDistanceA, 412 uint32 maxEyeDistanceA ) 413 { 414 bbs_DEF_fNameL( "bpi_BFFaceFinder_setParams" ); 415 416 if( bbs_Context_error( cpA ) ) return; 417 418 if( ptrA->typeE != bpi_FF_BF_FACE_FINDER ) 419 { 420 bbs_ERROR1( "%s:\nObject type mismatch", fNameL ); 421 return; 422 } 423 bpi_BFFaceFinder_setMinEyeDistance( cpA, ( struct bpi_BFFaceFinder* )ptrA, minEyeDistanceA ); 424 bpi_BFFaceFinder_setMaxEyeDistance( cpA, ( struct bpi_BFFaceFinder* )ptrA, maxEyeDistanceA ); 425 } 426 427 /* ------------------------------------------------------------------------- */ 428 429 int32 bpi_BFFaceFinder_processDcr( struct bbs_Context* cpA, 430 const struct bpi_FaceFinder* ptrA, 431 struct bpi_DCR* dcrPtrA ) 432 { 433 bbs_DEF_fNameL( "bpi_BFFaceFinder_processDcr" ); 434 435 if( bbs_Context_error( cpA ) ) return 0; 436 437 if( ptrA->typeE != bpi_FF_BF_FACE_FINDER ) 438 { 439 bbs_ERROR1( "%s:\nObject type mismatch", fNameL ); 440 return 0; 441 } 442 443 return bpi_BFFaceFinder_process( cpA, 444 ( const struct bpi_BFFaceFinder* )ptrA, 445 dcrPtrA->imageDataPtrE, 446 dcrPtrA->imageWidthE, 447 dcrPtrA->imageHeightE, 448 &dcrPtrA->roiRectE, 449 &dcrPtrA->offsE, 450 &dcrPtrA->mainClusterE ); 451 } 452 453 /* ------------------------------------------------------------------------- */ 454 455 int32 bpi_BFFaceFinder_putDcr( struct bbs_Context* cpA, 456 const struct bpi_FaceFinder* ptrA, 457 struct bpi_DCR* dcrPtrA ) 458 { 459 bbs_DEF_fNameL( "bpi_BFFaceFinder_putDcr" ); 460 461 if( bbs_Context_error( cpA ) ) return 0; 462 463 if( ptrA->typeE != bpi_FF_BF_FACE_FINDER ) 464 { 465 bbs_ERROR1( "%s:\nObject type mismatch", fNameL ); 466 return 0; 467 } 468 469 return bpi_BFFaceFinder_multiProcess( cpA, 470 ( const struct bpi_BFFaceFinder* )ptrA, 471 dcrPtrA->imageDataPtrE, 472 dcrPtrA->imageWidthE, 473 dcrPtrA->imageHeightE, 474 &dcrPtrA->roiRectE ); 475 } 476 477 /* ------------------------------------------------------------------------- */ 478 479 void bpi_BFFaceFinder_getDcr( struct bbs_Context* cpA, 480 const struct bpi_FaceFinder* ptrA, 481 uint32 indexA, 482 struct bpi_DCR* dcrPtrA ) 483 { 484 bbs_DEF_fNameL( "bpi_BFFaceFinder_getDcr" ); 485 486 if( bbs_Context_error( cpA ) ) return; 487 488 if( ptrA->typeE != bpi_FF_BF_FACE_FINDER ) 489 { 490 bbs_ERROR1( "%s:\nObject type mismatch", fNameL ); 491 return; 492 } 493 494 bpi_BFFaceFinder_getFaceDCR( cpA, ( const struct bpi_BFFaceFinder* )ptrA, indexA, dcrPtrA ); 495 } 496 497 /* ------------------------------------------------------------------------- */ 498 499 /* ========================================================================= */ 500