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_BasicEm/Functions.h"
20#include "b_BasicEm/Math.h"
21#include "b_BitFeatureEm/ScanDetector.h"
22
23/* ------------------------------------------------------------------------- */
24
25/* ========================================================================= */
26/*                                                                           */
27/* ---- \ghd{ auxiliary functions } ---------------------------------------- */
28/*                                                                           */
29/* ========================================================================= */
30
31/* ------------------------------------------------------------------------- */
32
33/* ========================================================================= */
34/*                                                                           */
35/* ---- \ghd{ constructor / destructor } ----------------------------------- */
36/*                                                                           */
37/* ========================================================================= */
38
39/* ------------------------------------------------------------------------- */
40
41void bbf_ScanDetector_init( struct bbs_Context* cpA,
42						    struct bbf_ScanDetector* ptrA )
43{
44	uint32 iL;
45
46	ptrA->minScaleE = 0;
47	ptrA->maxScaleE = 0;
48	ptrA->maxImageWidthE = 0;
49	ptrA->maxImageHeightE = 0;
50	bbf_Scanner_init( cpA, &ptrA->scannerE );
51
52	ptrA->patchWidthE = 0;
53	ptrA->patchHeightE = 0;
54	ptrA->minDefScaleE = 0;
55	ptrA->maxDefScaleE = 0;
56	ptrA->scaleStepE = 0;
57	ptrA->overlapThrE = 0;
58	ptrA->borderWidthE = 0;
59	ptrA->borderHeightE = 0;
60	ptrA->featuresE = 0;
61	for( iL = 0; iL < bbf_SCAN_DETECTOR_MAX_FEATURES; iL++ ) bbf_BitParam_init( cpA, &ptrA->bitParamArrE[ iL ] );
62	for( iL = 0; iL < bbf_SCAN_DETECTOR_MAX_FEATURES; iL++ ) bbf_Sequence_init( cpA, &ptrA->featureArrE[ iL ] );
63	bts_IdCluster2D_init( cpA, &ptrA->refClusterE );
64	ptrA->refDistanceE = 10;
65}
66
67/* ------------------------------------------------------------------------- */
68
69void bbf_ScanDetector_exit( struct bbs_Context* cpA,
70						    struct bbf_ScanDetector* ptrA )
71{
72	uint32 iL;
73
74	ptrA->minScaleE = 0;
75	ptrA->maxScaleE = 0;
76	ptrA->maxImageWidthE = 0;
77	ptrA->maxImageHeightE = 0;
78	bbf_Scanner_exit( cpA, &ptrA->scannerE );
79
80	ptrA->patchWidthE = 0;
81	ptrA->patchHeightE = 0;
82	ptrA->minDefScaleE = 0;
83	ptrA->maxDefScaleE = 0;
84	ptrA->scaleStepE = 0;
85	ptrA->overlapThrE = 0;
86	ptrA->borderWidthE = 0;
87	ptrA->borderHeightE = 0;
88	ptrA->featuresE = 0;
89	for( iL = 0; iL < bbf_SCAN_DETECTOR_MAX_FEATURES; iL++ ) bbf_BitParam_exit( cpA, &ptrA->bitParamArrE[ iL ] );
90	for( iL = 0; iL < bbf_SCAN_DETECTOR_MAX_FEATURES; iL++ ) bbf_Sequence_exit( cpA, &ptrA->featureArrE[ iL ] );
91	bts_IdCluster2D_exit( cpA, &ptrA->refClusterE );
92	ptrA->refDistanceE = 0;
93}
94
95/* ------------------------------------------------------------------------- */
96
97/* ========================================================================= */
98/*                                                                           */
99/* ---- \ghd{ operators } -------------------------------------------------- */
100/*                                                                           */
101/* ========================================================================= */
102
103/* ------------------------------------------------------------------------- */
104
105void bbf_ScanDetector_copy( struct bbs_Context* cpA,
106						    struct bbf_ScanDetector* ptrA,
107						    const struct bbf_ScanDetector* srcPtrA )
108{
109	bbs_ERROR0( "bbf_ScanDetector_copy:\n Function is not available" );
110}
111
112/* ------------------------------------------------------------------------- */
113
114flag bbf_ScanDetector_equal( struct bbs_Context* cpA,
115						     const struct bbf_ScanDetector* ptrA,
116						     const struct bbf_ScanDetector* srcPtrA )
117{
118	bbs_ERROR0( "bbf_ScanDetector_equal:\n Function is not available" );
119	return TRUE;
120}
121
122/* ------------------------------------------------------------------------- */
123
124/* ========================================================================= */
125/*                                                                           */
126/* ---- \ghd{ query functions } -------------------------------------------- */
127/*                                                                           */
128/* ========================================================================= */
129
130/* ------------------------------------------------------------------------- */
131
132/* ========================================================================= */
133/*                                                                           */
134/* ---- \ghd{ modify functions } ------------------------------------------- */
135/*                                                                           */
136/* ========================================================================= */
137
138/* ------------------------------------------------------------------------- */
139
140/* ========================================================================= */
141/*                                                                           */
142/* ---- \ghd{ I/O } -------------------------------------------------------- */
143/*                                                                           */
144/* ========================================================================= */
145
146/* ------------------------------------------------------------------------- */
147
148uint32 bbf_ScanDetector_memSize( struct bbs_Context* cpA,
149							     const struct bbf_ScanDetector* ptrA )
150{
151	uint32 iL;
152	uint32 memSizeL = bbs_SIZEOF16( uint32 ) +
153					  bbs_SIZEOF16( uint32 ); /* version */
154
155	memSizeL += bbs_SIZEOF16( ptrA->patchWidthE );
156	memSizeL += bbs_SIZEOF16( ptrA->patchHeightE );
157	memSizeL += bbs_SIZEOF16( ptrA->minDefScaleE );
158	memSizeL += bbs_SIZEOF16( ptrA->maxDefScaleE );
159	memSizeL += bbs_SIZEOF16( ptrA->scaleStepE );
160	memSizeL += bbs_SIZEOF16( ptrA->overlapThrE );
161	memSizeL += bbs_SIZEOF16( ptrA->borderWidthE );
162	memSizeL += bbs_SIZEOF16( ptrA->borderHeightE );
163	memSizeL += bbs_SIZEOF16( ptrA->featuresE );
164	for( iL = 0; iL < ptrA->featuresE; iL++ ) memSizeL += bbf_BitParam_memSize( cpA, &ptrA->bitParamArrE[ iL ] );
165	for( iL = 0; iL < ptrA->featuresE; iL++ ) memSizeL += bbf_Sequence_memSize( cpA, &ptrA->featureArrE[ iL ] );
166	memSizeL += bts_IdCluster2D_memSize( cpA, &ptrA->refClusterE );
167	memSizeL += bbs_SIZEOF16( ptrA->refDistanceE );
168
169	return memSizeL;
170}
171
172/* ------------------------------------------------------------------------- */
173
174uint32 bbf_ScanDetector_memWrite( struct bbs_Context* cpA,
175							      const struct bbf_ScanDetector* ptrA,
176								  uint16* memPtrA )
177{
178	uint32 iL;
179	uint32 memSizeL = bbf_ScanDetector_memSize( cpA, ptrA );
180	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
181	memPtrA += bbs_memWriteUInt32( bbf_SCAN_DETECTOR_VERSION, memPtrA );
182
183	memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA );
184	memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA );
185	memPtrA += bbs_memWrite32( &ptrA->minDefScaleE, memPtrA );
186	memPtrA += bbs_memWrite32( &ptrA->maxDefScaleE, memPtrA );
187	memPtrA += bbs_memWrite32( &ptrA->scaleStepE, memPtrA );
188	memPtrA += bbs_memWrite32( &ptrA->overlapThrE, memPtrA );
189	memPtrA += bbs_memWrite32( &ptrA->borderWidthE, memPtrA );
190	memPtrA += bbs_memWrite32( &ptrA->borderHeightE, memPtrA );
191	memPtrA += bbs_memWrite32( &ptrA->featuresE, memPtrA );
192	for( iL = 0; iL < ptrA->featuresE; iL++ ) memPtrA += bbf_BitParam_memWrite( cpA, &ptrA->bitParamArrE[ iL ], memPtrA );
193	for( iL = 0; iL < ptrA->featuresE; iL++ ) memPtrA += bbf_Sequence_memWrite( cpA, &ptrA->featureArrE[ iL ], memPtrA );
194	memPtrA += bts_IdCluster2D_memWrite( cpA, &ptrA->refClusterE, memPtrA );
195	memPtrA += bbs_memWrite32( &ptrA->refDistanceE, memPtrA );
196
197	return memSizeL;
198}
199
200/* ------------------------------------------------------------------------- */
201
202uint32 bbf_ScanDetector_memRead( struct bbs_Context* cpA,
203							     struct bbf_ScanDetector* ptrA,
204							     const uint16* memPtrA,
205							     struct bbs_MemTbl* mtpA )
206{
207	bbs_DEF_fNameL( "bbf_ScanDetector_memRead" )
208
209	/* debugging hint: set this flag to FALSE when you suspect a shared memory conflict */
210	const flag maximizeSharedMemoryL = TRUE;
211
212	uint32 iL;
213	uint32 memSizeL, versionL;
214	struct bbs_MemTbl memTblL = *mtpA;
215	struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 );
216	if( bbs_Context_error( cpA ) ) return 0;
217
218	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
219	memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_SCAN_DETECTOR_VERSION, memPtrA );
220
221	memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA );
222	memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA );
223	memPtrA += bbs_memRead32( &ptrA->minDefScaleE, memPtrA );
224	memPtrA += bbs_memRead32( &ptrA->maxDefScaleE, memPtrA );
225	memPtrA += bbs_memRead32( &ptrA->scaleStepE, memPtrA );
226	memPtrA += bbs_memRead32( &ptrA->overlapThrE, memPtrA );
227	memPtrA += bbs_memRead32( &ptrA->borderWidthE, memPtrA );
228	memPtrA += bbs_memRead32( &ptrA->borderHeightE, memPtrA );
229	memPtrA += bbs_memRead32( &ptrA->featuresE, memPtrA );
230	for( iL = 0; iL < ptrA->featuresE; iL++ ) memPtrA += bbf_BitParam_memRead( cpA, &ptrA->bitParamArrE[ iL ], memPtrA );
231	for( iL = 0; iL < ptrA->featuresE; iL++ ) memPtrA += bbf_Sequence_memRead( cpA, &ptrA->featureArrE[ iL ], memPtrA, &memTblL );
232	memPtrA += bts_IdCluster2D_memRead( cpA, &ptrA->refClusterE, memPtrA, espL );
233	memPtrA += bbs_memRead32( &ptrA->refDistanceE, memPtrA );
234/*
235	if( memSizeL != bbf_ScanDetector_memSize( cpA, ptrA ) )
236	{
237		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_ScanDetector_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n"
238			        "size mismatch" );
239		return 0;
240	}
241*/
242
243	ptrA->minScaleE = ptrA->minDefScaleE;
244	ptrA->maxScaleE = ptrA->maxDefScaleE;
245
246	/* initialize scanner; be aware of shared memory settings(!) */
247	{
248		uint32 maxImageSizeL = ptrA->maxImageWidthE * ptrA->maxImageHeightE;
249
250		/* estimate of maximal possible faces in image */
251		uint32 maxFacesL = maxImageSizeL / ( 768 << 1 );
252
253		uint32 maxRadiusL = 0;
254
255		if( maxImageSizeL == 0 )
256		{
257			bbs_ERROR1( "%s:\nMaximum image size was not defined (size variables must be set before calling _memRead)", fNameL );
258			return memSizeL;
259		}
260
261		for( iL = 0; iL < ptrA->featuresE; iL++ )
262		{
263			maxRadiusL = maxRadiusL > ptrA->bitParamArrE[ iL ].outerRadiusE ? maxRadiusL : ptrA->bitParamArrE[ iL ].outerRadiusE;
264		}
265
266		if( maxFacesL < 1 ) maxFacesL = 1;
267
268		bbf_Scanner_create( cpA, &ptrA->scannerE,
269							maximizeSharedMemoryL,
270							ptrA->maxImageWidthE,
271							ptrA->maxImageHeightE,
272							maxRadiusL,
273							ptrA->patchWidthE,
274							ptrA->patchHeightE,
275							ptrA->minScaleE,
276							ptrA->maxScaleE,
277							ptrA->scaleStepE,
278							ptrA->borderWidthE,
279							ptrA->borderHeightE,
280							maxFacesL * 20,  /* bufferSizeA */
281							&memTblL );
282	}
283
284	return memSizeL;
285}
286
287/* ------------------------------------------------------------------------- */
288
289/* ========================================================================= */
290/*                                                                           */
291/* ---- \ghd{ exec functions } --------------------------------------------- */
292/*                                                                           */
293/* ========================================================================= */
294
295/* ------------------------------------------------------------------------- */
296
297uint32 bbf_ScanDetector_process( struct bbs_Context* cpA,
298							     struct bbf_ScanDetector* ptrA,
299							     const void* imagePtrA,
300								 uint32 imageWidthA,
301								 uint32 imageHeightA,
302								 const struct bts_Int16Rect* roiPtrA,
303								 int32** outArrPtrPtrA )
304{
305	/* best global values (used when no positives could be found) */
306	int32 bestGlobalActL = ( int32 )0x80000000;
307	int32 bestGlobalXL = 0;
308	int32 bestGlobalYL = 0;
309	uint32 bestGlobalScaleL = 0;
310
311	struct bbf_Scanner* scannerPtrL = &ptrA->scannerE;
312
313	scannerPtrL->minScaleE = ptrA->minScaleE;
314	scannerPtrL->maxScaleE = ptrA->maxScaleE;
315
316	*outArrPtrPtrA = NULL;
317
318	if( bbs_Context_error( cpA ) ) return 0;
319	if( ptrA->featuresE == 0 )
320	{
321		bbs_ERROR0( "bbf_ScanDetector_process: detector has no features" );
322		return 0;
323	}
324
325	if( imageWidthA > ptrA->maxImageWidthE || imageHeightA > ptrA->maxImageHeightE )
326	{
327		bbs_ERROR0( "bbf_ScanDetector_process: images size exceeds preallocated size" );
328		return 0;
329	}
330
331	/* resets output positions */
332	bbf_Scanner_resetOutPos( cpA, scannerPtrL );
333
334	/* assign image to scanner - reset scanner */
335	bbf_Scanner_assign( cpA, scannerPtrL, imagePtrA, imageWidthA, imageHeightA, roiPtrA, &ptrA->bitParamArrE[ 0 ] );
336
337	while( bbf_Scanner_positions( scannerPtrL ) > 0 )
338	{
339		int32 bestActL = ( int32 )0x80000000;
340		uint32 bestIdxL = 0;
341		uint32 bestLvlL = 0;
342		uint32 iL;
343
344		const struct bbf_Feature* featurePtrL = ( const struct bbf_Feature* )&ptrA->featureArrE[ 0 ];
345		const struct bbf_BitParam* paramPtrL = &ptrA->bitParamArrE[ 0 ];
346		bbf_Scanner_bitParam( cpA, scannerPtrL, paramPtrL );
347
348		/* resets internal positions */
349		bbf_Scanner_resetIntPos( cpA, scannerPtrL );
350
351		do
352		{
353			int32 actL = featurePtrL->vpActivityE( featurePtrL, bbf_Scanner_getPatch( scannerPtrL ) );
354			if( actL > 0 )
355			{
356				bbf_Scanner_addIntPos( cpA, scannerPtrL, bbf_Scanner_scanIndex( scannerPtrL ), actL );
357			}
358
359			if( actL > bestActL )
360			{
361				bestActL = actL;
362				bestIdxL = bbf_Scanner_scanIndex( scannerPtrL );
363			}
364		}
365		while( bbf_Scanner_next( cpA, scannerPtrL ) );
366
367		for( iL = 1; iL < ptrA->featuresE; iL++ )
368		{
369			const struct bbf_Feature* featurePtrL = ( const struct bbf_Feature* )&ptrA->featureArrE[ iL ];
370			const struct bbf_BitParam* paramPtrL = &ptrA->bitParamArrE[ iL ];
371			uint32* idxArrL = scannerPtrL->idxArrE.arrPtrE;
372			int32* actArrL = scannerPtrL->actArrE.arrPtrE;
373
374			uint32 kL = 0;
375			uint32 jL;
376
377			if( scannerPtrL->intCountE == 0 ) break;
378			bestActL = ( int32 )0x80000000;
379			bbf_Scanner_bitParam( cpA, scannerPtrL, paramPtrL );
380
381			for( jL = 0; jL < scannerPtrL->intCountE; jL++ )
382			{
383				int32 actL;
384				bbf_Scanner_goToIndex( cpA, scannerPtrL, idxArrL[ jL ] );
385				actL = featurePtrL->vpActivityE( featurePtrL, bbf_Scanner_getPatch( scannerPtrL ) );
386				if( actL > 0 )
387				{
388					idxArrL[ kL ] = idxArrL[ jL ];
389					actArrL[ kL ] = ( actArrL[ jL ] + actL ) >> 1;
390					kL++;
391				}
392
393				if( actL > bestActL )
394				{
395					bestActL = actL;
396					bestIdxL = idxArrL[ jL ];
397					bestLvlL = iL;
398				}
399			}
400
401			scannerPtrL->intCountE = kL;
402		}
403
404		if( scannerPtrL->intCountE == 0 )
405		{
406			int32 xL, yL;
407			uint32 scaleL;
408
409			/* 8.24 */
410			int32 actL = ( bestActL >> 4 ) + ( ( ( int32 )( bestLvlL + 1 - ptrA->featuresE ) << 24 ) / ( int32 )ptrA->featuresE );
411
412			/* 4.28 */
413			actL <<= 4;
414
415			bbf_Scanner_idxPos( scannerPtrL, bestIdxL, &xL, &yL, &scaleL );
416
417			if( actL > bestGlobalActL )
418			{
419            	bestGlobalActL = actL;
420				bestGlobalXL = xL;
421				bestGlobalYL = yL;
422				bestGlobalScaleL = scaleL;
423			}
424		}
425		else
426		{
427			/* remove overlaps for current scale */
428			bbf_Scanner_removeIntOverlaps( cpA, scannerPtrL, ptrA->overlapThrE );
429
430			for( iL = 0; iL < scannerPtrL->intCountE; iL++ )
431			{
432				int32 xL, yL;
433				uint32 scaleL;
434				uint32* idxArrL = scannerPtrL->idxArrE.arrPtrE;
435				int32* actArrL = scannerPtrL->actArrE.arrPtrE;
436
437				int32 actL = actArrL[ iL ];
438				bbf_Scanner_idxPos( scannerPtrL, idxArrL[ iL ], &xL, &yL, &scaleL );
439
440				/* add external position */
441				bbf_Scanner_addOutPos( cpA, scannerPtrL, xL, yL, scaleL, actL );
442			}
443
444			/* remove overlapping positions */
445			bbf_Scanner_removeOutOverlaps( cpA, scannerPtrL, ptrA->overlapThrE );
446
447		}
448
449		if( !bbf_Scanner_nextScale( cpA, scannerPtrL ) ) break;
450	}
451/*
452	{
453		uint32 iL;
454		printf( "\n-----------------------------------------------" );
455		for( iL = 0; iL < scannerPtrL->outCountE; iL++ )
456		{
457			printf( "\n%02i: %6.1f %6.1f %6.2f %6.3f",
458					iL,
459					( float )scannerPtrL->outArrE.arrPtrE[ iL * 4 + 0 ] / ( 1L << 16 ),
460					( float )scannerPtrL->outArrE.arrPtrE[ iL * 4 + 1 ] / ( 1L << 16 ),
461					( float )scannerPtrL->outArrE.arrPtrE[ iL * 4 + 2 ] / ( 1L << 20 ),
462					( float )scannerPtrL->outArrE.arrPtrE[ iL * 4 + 3 ] / ( 1L << 28 ) );
463
464		}
465	}
466*/
467
468	*outArrPtrPtrA = scannerPtrL->outArrE.arrPtrE;
469	if( scannerPtrL->outCountE == 0 )
470	{
471		/* no positive activities found: store best negative activity */
472		bbf_Scanner_addOutPos( cpA, scannerPtrL, bestGlobalXL, bestGlobalYL, bestGlobalScaleL, bestGlobalActL );
473		return 0;
474	}
475	else
476	{
477		return scannerPtrL->outCountE;
478	}
479}
480
481/* ------------------------------------------------------------------------- */
482
483/* ========================================================================= */
484
485