Home | History | Annotate | Download | only in b_APIEm
      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, &centerL );
    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, &centerL );
    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