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 43void 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 62void 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 83void 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 93flag 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 112uint32 bpi_BFFaceFinder_getMinEyeDistance( const struct bpi_BFFaceFinder* ptrA ) 113{ 114 return ( ( ptrA->detectorE.refDistanceE >> 8 ) * ( ptrA->detectorE.minScaleE >> 12 ) ) >> 16; 115} 116 117/* ------------------------------------------------------------------------- */ 118 119uint32 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 134void 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 144void 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 168uint32 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 182uint32 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 197uint32 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 233int32 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 292uint32 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 308uint32 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 366void 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 379void 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 390void 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 409void 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 429int32 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 455int32 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 479void 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