• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ImageEm/Functions.h"
22 #include "b_BitFeatureEm/LocalScanDetector.h"
23 
24 /* ------------------------------------------------------------------------- */
25 
26 /* ========================================================================= */
27 /*                                                                           */
28 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
29 /*                                                                           */
30 /* ========================================================================= */
31 
32 /* ------------------------------------------------------------------------- */
33 
34 /** applies PCA mapping
35  *  Input and output clusters may be identical
36  */
bbf_LocalScanDetector_pcaMap(struct bbs_Context * cpA,const struct bbf_LocalScanDetector * ptrA,const struct bts_IdCluster2D * inClusterPtrA,struct bts_IdCluster2D * outClusterPtrA)37 void bbf_LocalScanDetector_pcaMap( struct bbs_Context* cpA,
38 								   const struct bbf_LocalScanDetector* ptrA,
39 								   const struct bts_IdCluster2D* inClusterPtrA,
40 								   struct bts_IdCluster2D* outClusterPtrA )
41 {
42 	bbs_DEF_fNameL( "bbf_LocalScanDetector_pcaMap" )
43 
44 	struct bts_Cluster2D* tmpCl1PtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster1E;
45 	struct bts_Cluster2D* tmpCl2PtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster2E;
46 	struct bts_RBFMap2D*  rbfPtrL     = ( struct bts_RBFMap2D* )&ptrA->rbfMapE;
47 	struct bts_Flt16Alt2D altL;
48 	uint32 outBbpL = inClusterPtrA->clusterE.bbpE;
49 	uint32 iL, jL;
50 
51 	/* setup two equivalent clusters holding the essential (alt-free) moves to be handled by PCA */
52 	bts_IdCluster2D_convertToEqivalentClusters( cpA,
53 												inClusterPtrA,
54 												&ptrA->pcaClusterE,
55 												tmpCl1PtrL,
56 												tmpCl2PtrL );
57 
58 	altL = bts_Cluster2D_alt( cpA, tmpCl1PtrL, tmpCl2PtrL, bts_ALT_RIGID );
59 	bts_Cluster2D_transform( cpA, tmpCl1PtrL, altL );
60 	bts_RBFMap2D_compute( cpA, rbfPtrL, tmpCl2PtrL, tmpCl1PtrL );
61 	bts_RBFMap2D_mapCluster( cpA, rbfPtrL, &ptrA->pcaClusterE.clusterE, tmpCl1PtrL, 6/* ! */ );
62 
63 	/* PCA projection: cluster1 -> cluster1 */
64 	{
65 		/* mat elements: 8.8 */
66 		const int16* matPtrL = ptrA->pcaMatE.arrPtrE;
67 
68 		/* same bbp as pca cluster */
69 		const int16* avgPtrL = ptrA->pcaAvgE.arrPtrE;
70 
71 		struct bts_Int16Vec2D* vecArrL = tmpCl1PtrL->vecArrE;
72 
73 		/* projected vector */
74 		int32 prjVecL[ bpi_LOCAL_SCAN_DETECTOR_MAX_PCA_DIM ];
75 
76 		/* width of matrix */
77 		uint16 matWidthL = tmpCl1PtrL->sizeE * 2;
78 
79 		if( ptrA->pcaDimSubSpaceE > bpi_LOCAL_SCAN_DETECTOR_MAX_PCA_DIM )
80 		{
81 			bbs_ERROR1( "%s:\nbpi_RF_LANDMARKER_MAX_PCA_DIM exceeded", fNameL );
82 			return;
83 		}
84 
85 		/* forward trafo */
86 		for( iL = 0; iL < ptrA->pcaDimSubSpaceE; iL++ )
87 		{
88 			int32 sumL = 0;
89 			avgPtrL = ptrA->pcaAvgE.arrPtrE;
90 			for( jL = 0; jL < tmpCl1PtrL->sizeE; jL++ )
91 			{
92 				sumL += matPtrL[ 0 ] * ( vecArrL[ jL ].xE - avgPtrL[ 0 ] );
93 				sumL += matPtrL[ 1 ] * ( vecArrL[ jL ].yE - avgPtrL[ 1 ] );
94 				avgPtrL += 2;
95 				matPtrL += 2;
96 			}
97 			prjVecL[ iL ] = ( sumL + 128 ) >> 8;
98 		}
99 
100 		matPtrL = ptrA->pcaMatE.arrPtrE;
101 		avgPtrL = ptrA->pcaAvgE.arrPtrE;
102 		vecArrL = tmpCl1PtrL->vecArrE;
103 
104 		/* backward trafo */
105 		for( jL = 0; jL < tmpCl1PtrL->sizeE; jL++ )
106 		{
107 			int32 sumL = 0;
108 			for( iL = 0; iL < ptrA->pcaDimSubSpaceE; iL++ )
109 			{
110 				sumL += matPtrL[ iL * matWidthL + 0 ] * prjVecL[ iL ];
111 			}
112 
113 			vecArrL[ jL ].xE = ( ( sumL + 128 ) >> 8 ) + avgPtrL[ 0 ];
114 
115 			sumL = 0;
116 			for( iL = 0; iL < ptrA->pcaDimSubSpaceE; iL++ )
117 			{
118 				sumL += matPtrL[ iL * matWidthL + 1 ] * prjVecL[ iL ];
119 			}
120 
121 			vecArrL[ jL ].yE = ( ( sumL + 128 ) >> 8 ) + avgPtrL[ 1 ];
122 
123 			matPtrL += 2;
124 			avgPtrL += 2;
125 		}
126 	}
127 
128 	/* ALT backtransformation */
129 	bts_IdCluster2D_copy( cpA, outClusterPtrA, &ptrA->pcaClusterE );
130 	bts_Cluster2D_copyTransform( cpA, &outClusterPtrA->clusterE, tmpCl1PtrL, bts_Flt16Alt2D_inverted( &altL ), outBbpL );
131 }
132 
133 /* ------------------------------------------------------------------------- */
134 
135 /* ========================================================================= */
136 /*                                                                           */
137 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
138 /*                                                                           */
139 /* ========================================================================= */
140 
141 /* ------------------------------------------------------------------------- */
142 
bbf_LocalScanDetector_init(struct bbs_Context * cpA,struct bbf_LocalScanDetector * ptrA)143 void bbf_LocalScanDetector_init( struct bbs_Context* cpA,
144 							     struct bbf_LocalScanDetector* ptrA )
145 {
146 	bbs_memset16( ptrA->ftrPtrArrE, 0, bbs_SIZEOF16( ptrA->ftrPtrArrE ) );
147 	bts_RBFMap2D_init( cpA, &ptrA->rbfMapE );
148 	bts_Cluster2D_init( cpA, &ptrA->tmpCluster1E );
149 	bts_Cluster2D_init( cpA, &ptrA->tmpCluster2E );
150 	bts_Cluster2D_init( cpA, &ptrA->tmpCluster3E );
151 	bts_Cluster2D_init( cpA, &ptrA->tmpCluster4E );
152 	bbf_LocalScanner_init( cpA, &ptrA->scannerE );
153 	bbs_Int32Arr_init( cpA, &ptrA->actArrE );
154 	bbs_Int16Arr_init( cpA, &ptrA->idxArrE );
155 	bbs_UInt8Arr_init( cpA, &ptrA->workImageBufE );
156 	ptrA->maxImageWidthE = 0;
157 	ptrA->maxImageHeightE = 0;
158 
159 	ptrA->patchWidthE = 0;
160 	ptrA->patchHeightE = 0;
161 	ptrA->scanWidthE = 0;
162 	ptrA->scanHeightE = 0;
163 	ptrA->scaleExpE = 0;
164 	ptrA->interpolatedWarpingE = TRUE;
165 	ptrA->warpScaleThresholdE = 0;
166 	bts_IdCluster2D_init( cpA, &ptrA->refClusterE );
167 	bts_Cluster2D_init( cpA, &ptrA->scanClusterE );
168 	bbs_UInt16Arr_init( cpA, &ptrA->ftrDataArrE );
169 	bbf_BitParam_init( cpA, &ptrA->bitParamE );
170 	ptrA->outlierDistanceE = 0;
171 	bts_IdCluster2D_init( cpA, &ptrA->pcaClusterE );
172 	bbs_Int16Arr_init( cpA, &ptrA->pcaAvgE );
173 	bbs_Int16Arr_init( cpA, &ptrA->pcaMatE );
174 	ptrA->pcaDimSubSpaceE = 0;
175 	ptrA->maxImageWidthE = 0;
176 	ptrA->maxImageHeightE = 0;
177 }
178 
179 /* ------------------------------------------------------------------------- */
180 
bbf_LocalScanDetector_exit(struct bbs_Context * cpA,struct bbf_LocalScanDetector * ptrA)181 void bbf_LocalScanDetector_exit( struct bbs_Context* cpA,
182 							     struct bbf_LocalScanDetector* ptrA )
183 {
184 	uint16 iL;
185 	for( iL = 0; iL < ptrA->scanClusterE.sizeE; iL++ ) bbf_featureExit( cpA, ptrA->ftrPtrArrE[ iL ] );
186 	bbs_memset16( ptrA->ftrPtrArrE, 0, bbs_SIZEOF16( ptrA->ftrPtrArrE ) );
187 
188 	bts_RBFMap2D_exit( cpA, &ptrA->rbfMapE );
189 	bts_Cluster2D_exit( cpA, &ptrA->tmpCluster1E );
190 	bts_Cluster2D_exit( cpA, &ptrA->tmpCluster2E );
191 	bts_Cluster2D_exit( cpA, &ptrA->tmpCluster3E );
192 	bts_Cluster2D_exit( cpA, &ptrA->tmpCluster4E );
193 	bbf_LocalScanner_exit( cpA, &ptrA->scannerE );
194 	bbs_Int32Arr_exit( cpA, &ptrA->actArrE );
195 	bbs_Int16Arr_exit( cpA, &ptrA->idxArrE );
196 	bbs_UInt8Arr_exit( cpA, &ptrA->workImageBufE );
197 	ptrA->maxImageWidthE = 0;
198 	ptrA->maxImageHeightE = 0;
199 
200 	ptrA->patchWidthE = 0;
201 	ptrA->patchHeightE = 0;
202 	ptrA->scanWidthE = 0;
203 	ptrA->scanHeightE = 0;
204 	ptrA->scaleExpE = 0;
205 	ptrA->interpolatedWarpingE = TRUE;
206 	ptrA->warpScaleThresholdE = 0;
207 	bts_IdCluster2D_exit( cpA, &ptrA->refClusterE );
208 	bts_Cluster2D_exit( cpA, &ptrA->scanClusterE );
209 	bbs_UInt16Arr_exit( cpA, &ptrA->ftrDataArrE );
210 	bbf_BitParam_exit( cpA, &ptrA->bitParamE );
211 	ptrA->outlierDistanceE = 0;
212 	bts_IdCluster2D_exit( cpA, &ptrA->pcaClusterE );
213 	bbs_Int16Arr_exit( cpA, &ptrA->pcaAvgE );
214 	bbs_Int16Arr_exit( cpA, &ptrA->pcaMatE );
215 	ptrA->pcaDimSubSpaceE = 0;
216 	ptrA->maxImageWidthE = 0;
217 	ptrA->maxImageHeightE = 0;
218 }
219 
220 /* ------------------------------------------------------------------------- */
221 
222 /* ========================================================================= */
223 /*                                                                           */
224 /* ---- \ghd{ operators } -------------------------------------------------- */
225 /*                                                                           */
226 /* ========================================================================= */
227 
228 /* ------------------------------------------------------------------------- */
229 
bbf_LocalScanDetector_copy(struct bbs_Context * cpA,struct bbf_LocalScanDetector * ptrA,const struct bbf_LocalScanDetector * srcPtrA)230 void bbf_LocalScanDetector_copy( struct bbs_Context* cpA,
231 						    struct bbf_LocalScanDetector* ptrA,
232 						    const struct bbf_LocalScanDetector* srcPtrA )
233 {
234 	bbs_ERROR0( "bbf_LocalScanDetector_copy:\n Function is not available" );
235 }
236 
237 /* ------------------------------------------------------------------------- */
238 
bbf_LocalScanDetector_equal(struct bbs_Context * cpA,const struct bbf_LocalScanDetector * ptrA,const struct bbf_LocalScanDetector * srcPtrA)239 flag bbf_LocalScanDetector_equal( struct bbs_Context* cpA,
240 						     const struct bbf_LocalScanDetector* ptrA,
241 						     const struct bbf_LocalScanDetector* srcPtrA )
242 {
243 	bbs_ERROR0( "bbf_LocalScanDetector_equal:\n Function is not available" );
244 	return TRUE;
245 }
246 
247 /* ------------------------------------------------------------------------- */
248 
249 /* ========================================================================= */
250 /*                                                                           */
251 /* ---- \ghd{ query functions } -------------------------------------------- */
252 /*                                                                           */
253 /* ========================================================================= */
254 
255 /* ------------------------------------------------------------------------- */
256 
257 /* ========================================================================= */
258 /*                                                                           */
259 /* ---- \ghd{ modify functions } ------------------------------------------- */
260 /*                                                                           */
261 /* ========================================================================= */
262 
263 /* ------------------------------------------------------------------------- */
264 
265 /* ========================================================================= */
266 /*                                                                           */
267 /* ---- \ghd{ I/O } -------------------------------------------------------- */
268 /*                                                                           */
269 /* ========================================================================= */
270 
271 /* ------------------------------------------------------------------------- */
272 
bbf_LocalScanDetector_memSize(struct bbs_Context * cpA,const struct bbf_LocalScanDetector * ptrA)273 uint32 bbf_LocalScanDetector_memSize( struct bbs_Context* cpA,
274 								      const struct bbf_LocalScanDetector* ptrA )
275 {
276 	uint32 iL;
277 	uint32 memSizeL = bbs_SIZEOF16( uint32 ) +
278 					  bbs_SIZEOF16( uint32 ); /* version */
279 
280 	memSizeL += bbs_SIZEOF16( ptrA->patchWidthE );
281 	memSizeL += bbs_SIZEOF16( ptrA->patchHeightE );
282 	memSizeL += bbs_SIZEOF16( ptrA->scanWidthE );
283 	memSizeL += bbs_SIZEOF16( ptrA->scanHeightE );
284 	memSizeL += bbs_SIZEOF16( ptrA->scaleExpE );
285 	memSizeL += bbs_SIZEOF16( ptrA->interpolatedWarpingE );
286 	memSizeL += bbs_SIZEOF16( ptrA->warpScaleThresholdE );
287 	memSizeL += bts_IdCluster2D_memSize( cpA, &ptrA->refClusterE );
288 	memSizeL += bts_Cluster2D_memSize( cpA, &ptrA->scanClusterE );
289 	memSizeL += bbf_BitParam_memSize( cpA, &ptrA->bitParamE );
290 	memSizeL += bbs_SIZEOF16( ptrA->outlierDistanceE );
291 	memSizeL += bts_IdCluster2D_memSize( cpA, &ptrA->pcaClusterE );
292 	memSizeL += bbs_Int16Arr_memSize( cpA, &ptrA->pcaAvgE );
293 	memSizeL += bbs_Int16Arr_memSize( cpA, &ptrA->pcaMatE );
294 	memSizeL += bbs_SIZEOF16( ptrA->pcaDimSubSpaceE );
295 	memSizeL += bbs_SIZEOF16( ptrA->maxImageWidthE );
296 	memSizeL += bbs_SIZEOF16( ptrA->maxImageHeightE );
297 	for( iL = 0; iL < ptrA->scanClusterE.sizeE; iL++ ) memSizeL += bbf_featureMemSize( cpA, ptrA->ftrPtrArrE[ iL ] );
298 
299 	return memSizeL;
300 }
301 
302 /* ------------------------------------------------------------------------- */
303 
bbf_LocalScanDetector_memWrite(struct bbs_Context * cpA,const struct bbf_LocalScanDetector * ptrA,uint16 * memPtrA)304 uint32 bbf_LocalScanDetector_memWrite( struct bbs_Context* cpA,
305 									   const struct bbf_LocalScanDetector* ptrA,
306 									   uint16* memPtrA )
307 {
308 	uint32 iL;
309 	uint32 memSizeL = bbf_LocalScanDetector_memSize( cpA, ptrA );
310 	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
311 	memPtrA += bbs_memWriteUInt32( bbf_LOCAL_SCAN_DETECTOR_VERSION, memPtrA );
312 
313 	memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA );
314 	memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA );
315 	memPtrA += bbs_memWrite32( &ptrA->scanWidthE, memPtrA );
316 	memPtrA += bbs_memWrite32( &ptrA->scanHeightE, memPtrA );
317 	memPtrA += bbs_memWrite32( &ptrA->scaleExpE, memPtrA );
318 	memPtrA += bbs_memWrite32( &ptrA->interpolatedWarpingE, memPtrA );
319 	memPtrA += bbs_memWrite32( &ptrA->warpScaleThresholdE, memPtrA );
320 	memPtrA += bts_IdCluster2D_memWrite( cpA, &ptrA->refClusterE, memPtrA );
321 	memPtrA += bts_Cluster2D_memWrite( cpA, &ptrA->scanClusterE, memPtrA );
322 	memPtrA += bbf_BitParam_memWrite( cpA, &ptrA->bitParamE, memPtrA );
323 	memPtrA += bbs_memWrite32( &ptrA->outlierDistanceE, memPtrA );
324 	memPtrA += bts_IdCluster2D_memWrite( cpA, &ptrA->pcaClusterE, memPtrA );
325 	memPtrA += bbs_Int16Arr_memWrite( cpA, &ptrA->pcaAvgE, memPtrA );
326 	memPtrA += bbs_Int16Arr_memWrite( cpA, &ptrA->pcaMatE, memPtrA );
327 	memPtrA += bbs_memWrite32( &ptrA->pcaDimSubSpaceE, memPtrA );
328 	memPtrA += bbs_memWrite32( &ptrA->maxImageWidthE, memPtrA );
329 	memPtrA += bbs_memWrite32( &ptrA->maxImageHeightE, memPtrA );
330 
331 	for( iL = 0; iL < ptrA->scanClusterE.sizeE; iL++ ) memPtrA += bbf_featureMemWrite( cpA, ptrA->ftrPtrArrE[ iL ], memPtrA );
332 
333 	return memSizeL;
334 }
335 
336 /* ------------------------------------------------------------------------- */
337 
bbf_LocalScanDetector_memRead(struct bbs_Context * cpA,struct bbf_LocalScanDetector * ptrA,const uint16 * memPtrA,struct bbs_MemTbl * mtpA)338 uint32 bbf_LocalScanDetector_memRead( struct bbs_Context* cpA,
339 									  struct bbf_LocalScanDetector* ptrA,
340 									  const uint16* memPtrA,
341 									  struct bbs_MemTbl* mtpA )
342 {
343 	uint32 iL;
344 	uint32 memSizeL, versionL;
345 	struct bbs_MemTbl memTblL = *mtpA;
346 	struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 );
347 	struct bbs_MemSeg* sspL = bbs_MemTbl_sharedSegPtr( cpA, &memTblL, 0 );
348 	if( bbs_Context_error( cpA ) ) return 0;
349 
350 	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
351 	memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_LOCAL_SCAN_DETECTOR_VERSION, memPtrA );
352 
353 
354 	memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA );
355 	memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA );
356 	memPtrA += bbs_memRead32( &ptrA->scanWidthE, memPtrA );
357 	memPtrA += bbs_memRead32( &ptrA->scanHeightE, memPtrA );
358 	memPtrA += bbs_memRead32( &ptrA->scaleExpE, memPtrA );
359 	memPtrA += bbs_memRead32( &ptrA->interpolatedWarpingE, memPtrA );
360 	memPtrA += bbs_memRead32( &ptrA->warpScaleThresholdE, memPtrA );
361 	memPtrA += bts_IdCluster2D_memRead( cpA, &ptrA->refClusterE, memPtrA, espL );
362 	memPtrA += bts_Cluster2D_memRead( cpA, &ptrA->scanClusterE, memPtrA, espL );
363 	memPtrA += bbf_BitParam_memRead( cpA, &ptrA->bitParamE, memPtrA );
364 	memPtrA += bbs_memRead32( &ptrA->outlierDistanceE, memPtrA );
365 	memPtrA += bts_IdCluster2D_memRead( cpA, &ptrA->pcaClusterE, memPtrA, espL );
366 	memPtrA += bbs_Int16Arr_memRead( cpA, &ptrA->pcaAvgE, memPtrA, espL );
367 	memPtrA += bbs_Int16Arr_memRead( cpA, &ptrA->pcaMatE, memPtrA, espL );
368 	memPtrA += bbs_memRead32( &ptrA->pcaDimSubSpaceE, memPtrA );
369 	memPtrA += bbs_memRead32( &ptrA->maxImageWidthE, memPtrA );
370 	memPtrA += bbs_memRead32( &ptrA->maxImageHeightE, memPtrA );
371 
372 	/* check features & allocate data buffer */
373 	{
374 		const uint16* memPtrL = memPtrA;
375 		uint32 dataSizeL = 0;
376 		for( iL = 0; iL < ptrA->scanClusterE.sizeE; iL++ )
377 		{
378 			enum bbf_FeatureType typeL = ( enum bbf_FeatureType )bbs_memPeek32( memPtrL + 4 );
379 			dataSizeL += bbf_featureSizeOf16( cpA, typeL );
380 			memPtrL += bbs_memPeek32( memPtrL );
381 		}
382 		bbs_UInt16Arr_create( cpA, &ptrA->ftrDataArrE, dataSizeL, espL );
383 	}
384 
385 	/* load features & initialize pointers */
386 	{
387 		uint16* dataPtrL = ptrA->ftrDataArrE.arrPtrE;
388 		for( iL = 0; iL < ptrA->scanClusterE.sizeE; iL++ )
389 		{
390 			enum bbf_FeatureType typeL = ( enum bbf_FeatureType )bbs_memPeek32( memPtrA + 4 );
391 			ptrA->ftrPtrArrE[ iL ] = ( struct bbf_Feature* )dataPtrL;
392 			bbf_featureInit( cpA, ptrA->ftrPtrArrE[ iL ], typeL );
393 			memPtrA += bbf_featureMemRead( cpA, ptrA->ftrPtrArrE[ iL ], memPtrA, &memTblL );
394 			dataPtrL += bbf_featureSizeOf16( cpA, typeL );
395 		}
396 	}
397 
398 	if( memSizeL != bbf_LocalScanDetector_memSize( cpA, ptrA ) )
399 	{
400 		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_LocalScanDetector_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n"
401 			        "size mismatch" );
402 		return 0;
403 	}
404 
405 	if( ptrA->maxImageWidthE * ptrA->maxImageHeightE == 0 )
406 	{
407 		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_LocalScanDetector_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n"
408 								        "maximum image width/height not set" );
409 		return 0;
410 	}
411 
412 	/* initialize internal data */
413 
414 	/* ought to be placed on shared memory later */
415 	bts_RBFMap2D_create( cpA, &ptrA->rbfMapE, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
416 	ptrA->rbfMapE.RBFTypeE = bts_RBF_LINEAR;
417 	ptrA->rbfMapE.altTypeE = bts_ALT_RIGID;
418 
419 	bts_Cluster2D_create( cpA, &ptrA->tmpCluster1E, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
420 	bts_Cluster2D_create( cpA, &ptrA->tmpCluster2E, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
421 	bts_Cluster2D_create( cpA, &ptrA->tmpCluster3E, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
422 	bts_Cluster2D_create( cpA, &ptrA->tmpCluster4E, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
423 
424 	bbs_Int32Arr_create( cpA, &ptrA->actArrE, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
425 	bbs_Int16Arr_create( cpA, &ptrA->idxArrE, bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE, sspL );
426 
427 	/* working image memory */
428 	/* ought to be placed on shared memory later */
429 	bbs_UInt8Arr_create( cpA, &ptrA->workImageBufE, ptrA->maxImageWidthE * ptrA->maxImageHeightE, sspL );
430 
431 	/* initialize local scanner (be aware of shared memory usage when moving this create function) */
432 	bbf_LocalScanner_create( cpA, &ptrA->scannerE,
433 							 ptrA->patchWidthE,
434 							 ptrA->patchHeightE,
435 							 ptrA->scaleExpE,
436 							 ptrA->maxImageWidthE,
437 							 ptrA->maxImageHeightE,
438 							 ptrA->scaleExpE,
439 							 ptrA->bitParamE.outerRadiusE,
440 							 &memTblL );
441 
442 	return memSizeL;
443 }
444 
445 /* ------------------------------------------------------------------------- */
446 
447 /* ========================================================================= */
448 /*                                                                           */
449 /* ---- \ghd{ exec functions } --------------------------------------------- */
450 /*                                                                           */
451 /* ========================================================================= */
452 
453 /* ------------------------------------------------------------------------- */
454 
bbf_LocalScanDetector_process(struct bbs_Context * cpA,const struct bbf_LocalScanDetector * ptrA,uint8 * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bts_Int16Vec2D * offsPtrA,const struct bts_IdCluster2D * inClusterPtrA,struct bts_IdCluster2D * outClusterPtrA)455 int32 bbf_LocalScanDetector_process( struct bbs_Context* cpA,
456 									 const struct bbf_LocalScanDetector* ptrA,
457                                      uint8* imagePtrA,
458 									 uint32 imageWidthA,
459 									 uint32 imageHeightA,
460 									 const struct bts_Int16Vec2D*  offsPtrA,
461 									 const struct bts_IdCluster2D* inClusterPtrA,
462 									 struct bts_IdCluster2D* outClusterPtrA )
463 {
464 	bbs_DEF_fNameL( "bbf_LocalScanDetector_process" )
465 
466 	int32 pw0L = ptrA->patchWidthE;
467 	int32 ph0L = ptrA->patchHeightE;
468 	int32 pw1L = pw0L << ptrA->scaleExpE;
469 	int32 ph1L = ph0L << ptrA->scaleExpE;
470 
471 	struct bts_Cluster2D* wrkClPtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster1E;
472 	struct bts_Cluster2D* refClPtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster2E;
473 	struct bts_Cluster2D* dstClPtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster3E;
474 	struct bts_Cluster2D* tmpClPtrL  = ( struct bts_Cluster2D* )&ptrA->tmpCluster4E;
475 	struct bts_RBFMap2D*  rbfPtrL    = ( struct bts_RBFMap2D* )&ptrA->rbfMapE;
476 	struct bbf_LocalScanner* scnPtrL = ( struct bbf_LocalScanner* )&ptrA->scannerE;
477 
478 	int32* actArrL = ( int32* )ptrA->actArrE.arrPtrE;
479 	int16* idxArrL = ( int16* )ptrA->idxArrE.arrPtrE;
480 
481 	uint32 workImageWidthL, workImageHeightL;
482 
483 	struct bts_Flt16Alt2D altL;
484 
485 	int32 confidenceL;
486 	uint32 iL;
487 	uint32 sizeL = ptrA->scanClusterE.sizeE;
488 
489 	if( sizeL > bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE )
490 	{
491 		bbs_ERROR1( "%s:\nScan cluster size exceeds bpi_LOCAL_SCAN_DETECTOR_MAX_CLUSTER_SIZE", fNameL );
492 		return 0;
493 	}
494 
495 	/* compute equivalent clusters (matching ids) from input and reference cluster */
496 	bts_IdCluster2D_convertToEqivalentClusters( cpA, inClusterPtrA, &ptrA->refClusterE, wrkClPtrL, refClPtrL );
497 
498 	/* altL: orig image -> normalized image */
499 	altL = bts_Cluster2D_alt( cpA, wrkClPtrL, refClPtrL, bts_ALT_RIGID );
500 
501 	/* transorm work cluster to normalized image */
502 	bts_Cluster2D_transformBbp( cpA, wrkClPtrL, altL, 6 );
503 
504 	/* map: ref cluster -> work cluster */
505 	bts_RBFMap2D_compute( cpA, rbfPtrL, refClPtrL, wrkClPtrL );
506 
507 	/* copy: scanClusterE -> work cluster */
508 	bts_Cluster2D_copy( cpA, wrkClPtrL, &ptrA->scanClusterE );
509 
510 	/* copy: refClusterE -> ref cluster */
511 	bts_Cluster2D_copy( cpA, refClPtrL, &ptrA->refClusterE.clusterE );
512 
513 	/* apply map to work cluster */
514 	bts_Cluster2D_rbfTransform( cpA, wrkClPtrL, rbfPtrL );
515 
516 	/* apply map to ref cluster */
517 	bts_Cluster2D_rbfTransform( cpA, refClPtrL, rbfPtrL );
518 
519 	{
520 		/* analyze boundaries; get exact dimensions of working image */
521 		int32 workBorderWL = ( ( ptrA->scanWidthE  + pw1L + 1 ) >> 1 ) + 1; /* add a pixel to ensure full search area */
522 		int32 workBorderHL = ( ( ptrA->scanHeightE + ph1L + 1 ) >> 1 ) + 1; /* add a pixel to ensure full search area */
523 		struct bts_Int16Rect workAreaL = bts_Cluster2D_boundingBox( cpA, wrkClPtrL );
524 		workAreaL.x1E = workAreaL.x1E >> wrkClPtrL->bbpE;
525 		workAreaL.y1E = workAreaL.y1E >> wrkClPtrL->bbpE;
526 		workAreaL.x2E = workAreaL.x2E >> wrkClPtrL->bbpE;
527 		workAreaL.y2E = workAreaL.y2E >> wrkClPtrL->bbpE;
528 		workAreaL.x1E -= workBorderWL;
529 		workAreaL.y1E -= workBorderHL;
530 		workAreaL.x2E += workBorderWL;
531 		workAreaL.y2E += workBorderHL;
532 
533 		workImageWidthL  = workAreaL.x2E - workAreaL.x1E;
534 		workImageHeightL = workAreaL.y2E - workAreaL.y1E;
535 
536 		/* truncate if necessary (should not occur in normal operation) */
537 		workImageWidthL = workImageWidthL > ptrA->maxImageWidthE ? ptrA->maxImageWidthE : workImageWidthL;
538 		workImageHeightL = workImageHeightL > ptrA->maxImageHeightE ? ptrA->maxImageHeightE : workImageHeightL;
539 
540 		/* adjust ALT */
541 		altL.vecE.xE -= workAreaL.x1E << altL.vecE.bbpE;
542 		altL.vecE.yE -= workAreaL.y1E << altL.vecE.bbpE;
543 
544 		/* adjust work cluster */
545 		for( iL = 0; iL < wrkClPtrL->sizeE; iL++ )
546 		{
547 			wrkClPtrL->vecArrE[ iL ].xE -= workAreaL.x1E << wrkClPtrL->bbpE;
548 			wrkClPtrL->vecArrE[ iL ].yE -= workAreaL.y1E << wrkClPtrL->bbpE;
549 		}
550 
551 		/* adjust ref cluster */
552 		for( iL = 0; iL < wrkClPtrL->sizeE; iL++ )
553 		{
554 			refClPtrL->vecArrE[ iL ].xE -= workAreaL.x1E << refClPtrL->bbpE;
555 			refClPtrL->vecArrE[ iL ].yE -= workAreaL.y1E << refClPtrL->bbpE;
556 		}
557 
558 		/* transform image */
559 		bim_filterWarp( cpA,
560 					    ptrA->workImageBufE.arrPtrE,
561 						imagePtrA, imageWidthA, imageHeightA,
562 						offsPtrA,
563 						&altL,
564 						workImageWidthL, workImageHeightL,
565 						NULL,
566 						ptrA->warpScaleThresholdE,
567 						ptrA->interpolatedWarpingE );
568 
569 	}
570 
571 	/* scan over all positions of work cluster; target positions are stored in *dstClPtrL*/
572 	{
573 		int32 regionWHL = ( ptrA->scanWidthE  + pw1L + 1 ) >> 1;
574 		int32 regionHHL = ( ptrA->scanHeightE + ph1L + 1 ) >> 1;
575 		struct bts_Int16Vec2D* srcVecArrL = wrkClPtrL->vecArrE;
576 		struct bts_Int16Vec2D* dstVecArrL = dstClPtrL->vecArrE;
577 		int32 vecBbpL = wrkClPtrL->bbpE;
578 		bts_Cluster2D_size( cpA, dstClPtrL, sizeL );
579 		dstClPtrL->bbpE = vecBbpL;
580 
581 		/* initialize scanner */
582 		scnPtrL->patchWidthE = ptrA->patchWidthE;
583 		scnPtrL->patchHeightE = ptrA->patchWidthE;
584 		scnPtrL->scaleExpE = ptrA->scaleExpE;
585 
586 		bbf_LocalScanner_assign( cpA, scnPtrL, ptrA->workImageBufE.arrPtrE, workImageWidthL, workImageHeightL, &ptrA->bitParamE );
587 
588 		bbs_memset32( actArrL, 0x80000000, sizeL );
589 
590 		do
591 		{
592 			for( iL = 0; iL < sizeL; iL++ )
593 			{
594 				int32 bestActL = 0x80000000;
595 				uint32 bestIdxL = 0;
596 				struct bbf_Feature* ftrPtrL = ptrA->ftrPtrArrE[ iL ];
597 
598 				/* set scan region */
599 				{
600 					int32 x0L = ( ( wrkClPtrL->vecArrE[ iL ].xE >> ( wrkClPtrL->bbpE - 1 ) ) + 1 ) >> 1;
601 					int32 y0L = ( ( wrkClPtrL->vecArrE[ iL ].yE >> ( wrkClPtrL->bbpE - 1 ) ) + 1 ) >> 1;
602 					struct bts_Int16Rect scanRegionL = bts_Int16Rect_create( x0L - regionWHL, y0L - regionHHL, x0L + regionWHL, y0L + regionHHL );
603 					bbf_LocalScanner_origScanRegion( cpA, scnPtrL, &scanRegionL );
604 				}
605 
606 				do
607 				{
608 					int32 actL = ftrPtrL->vpActivityE( ftrPtrL, bbf_LocalScanner_getPatch( scnPtrL ) );
609 
610 					if( actL > bestActL )
611 					{
612 						bestActL = actL;
613 						bestIdxL = bbf_LocalScanner_scanIndex( scnPtrL );
614 					}
615 				}
616 				while( bbf_LocalScanner_next( cpA, scnPtrL ) );
617 
618 				{
619 					int32 xL, yL; /* 16.16 */
620 					bbf_LocalScanner_idxPos( scnPtrL, bestIdxL, &xL, &yL );
621 					xL += pw1L << 15;
622 					yL += ph1L << 15;
623 					if( bestActL > actArrL[ iL ] )
624 					{
625 						dstVecArrL[ iL ].xE = ( ( xL >> ( 15 - vecBbpL ) ) + 1 ) >> 1;
626 						dstVecArrL[ iL ].yE = ( ( yL >> ( 15 - vecBbpL ) ) + 1 ) >> 1;
627 						actArrL[ iL ] = bestActL;
628 					}
629 				}
630 			}
631 		}
632 		while( bbf_LocalScanner_nextOffset( cpA, scnPtrL ) );
633 
634 		/* outlier analysis: outliers are disabled by setting their similarity to -1 */
635 		if( ptrA->outlierDistanceE > 0 )
636 		{
637 			/* altL: work cluster -> ref cluster */
638 			struct bts_Flt16Alt2D localAltL = bts_Cluster2D_alt( cpA, wrkClPtrL, dstClPtrL, bts_ALT_RIGID );
639 
640 			/* squared distance 16.16 */
641 			uint32 dist2L = ( ptrA->outlierDistanceE >> 8 ) * ( ptrA->outlierDistanceE >> 8 );
642 
643 			/* analyze deviations */
644 			for( iL = 0; iL < sizeL; iL++ )
645 			{
646 				struct bts_Flt16Vec2D vecL = bts_Flt16Vec2D_create32( srcVecArrL[ iL ].xE, srcVecArrL[ iL ].yE, vecBbpL );
647 				uint32 dev2L; /* squared deviation 16.16 */
648 				vecL = bts_Flt16Alt2D_mapFlt( &localAltL, &vecL );
649 				vecL = bts_Flt16Vec2D_sub( vecL, bts_Flt16Vec2D_create32( dstVecArrL[ iL ].xE, dstVecArrL[ iL ].yE, vecBbpL ) );
650 				dev2L = bbs_convertU32( bts_Flt16Vec2D_norm2( &vecL ), vecL.bbpE << 1, 16 );
651 				if( dev2L > dist2L ) actArrL[ iL ] = 0xF0000000;
652 			}
653 		}
654 
655 		/* remove undetected positions but keep at least 1/2 best positions */
656 		{
657 			flag sortedL;
658 
659 			/* bubble sort (no speed issue in this case) */
660 			for( iL = 0; iL < sizeL; iL++ ) idxArrL[ iL ] = iL;
661 
662 			do
663 			{
664 				sortedL = TRUE;
665 				for( iL = 1; iL < sizeL; iL++ )
666 				{
667 					if( actArrL[ idxArrL[ iL - 1 ] ] < actArrL[ idxArrL[ iL ] ] )
668 					{
669 						int16 tmpL = idxArrL[ iL - 1 ];
670 						idxArrL[ iL - 1 ] = idxArrL[ iL ];
671 						idxArrL[ iL ] = tmpL;
672 						sortedL = FALSE;
673 					}
674 				}
675 			}
676 			while( !sortedL );
677 
678 			for( iL = ( sizeL >> 1 ); iL < sizeL && actArrL[ idxArrL[ iL ] ] >= 0; iL++ );
679 
680 			{
681 				uint32 subSizeL = iL;
682 
683 				/* reorder clusters */
684 				bts_Cluster2D_size( cpA, tmpClPtrL, subSizeL );
685 				{
686 					struct bts_Int16Vec2D* tmpVecArrL = tmpClPtrL->vecArrE;
687 					for( iL = 0; iL < subSizeL; iL++ ) tmpVecArrL[ iL ] = srcVecArrL[ idxArrL[ iL ] ];
688 					for( iL = 0; iL < subSizeL; iL++ ) srcVecArrL[ iL ] = tmpVecArrL[ iL ];
689 					for( iL = 0; iL < subSizeL; iL++ ) tmpVecArrL[ iL ] = dstVecArrL[ idxArrL[ iL ] ];
690 					for( iL = 0; iL < subSizeL; iL++ ) dstVecArrL[ iL ] = tmpVecArrL[ iL ];
691 				}
692 				bts_Cluster2D_size( cpA, wrkClPtrL, subSizeL );
693 				bts_Cluster2D_size( cpA, dstClPtrL, subSizeL );
694 			}
695 		}
696 
697 		/* compute confidence */
698 		{
699 			int16* idxArrL = ptrA->idxArrE.arrPtrE;
700 			int32* actArrL = ptrA->actArrE.arrPtrE;
701 			int32 actSumL = 0; /* .20 */
702 			for( iL = 0; iL < sizeL; iL++ )
703 			{
704 				float actL = ( actArrL[ idxArrL[ iL ] ] + 128 ) >> 8;
705 				if( actL < 0 ) break;
706 				actSumL += actL;
707 			}
708 
709 			/* actSumL = average positive activity */
710 			actSumL = ( iL > 0 ) ? actSumL / iL : 0;
711 
712 			confidenceL = ( ( ( int32 )iL << 20 ) - ( ( ( int32 )1 << 20 ) - actSumL ) ) / sizeL;
713 
714 			/* adjust to 4.28 */
715 			confidenceL <<= 8;
716 		}
717 
718 	}
719 
720 	/* map: wrkCluster -> dstCluster */
721 	bts_RBFMap2D_compute( cpA, rbfPtrL, wrkClPtrL, dstClPtrL );
722 
723 	/* apply map to ref cluster */
724 	bts_Cluster2D_rbfTransform( cpA, refClPtrL, rbfPtrL );
725 
726 	/* copy ref cluster to outCluster */
727 	bts_Cluster2D_copy( cpA, &outClusterPtrA->clusterE, refClPtrL );
728 	bbs_Int16Arr_copy( cpA, &outClusterPtrA->idArrE, &ptrA->refClusterE.idArrE );
729 
730 	/* PCA Mapping */
731 	if( ptrA->pcaDimSubSpaceE > 0 )
732 	{
733 		bbf_LocalScanDetector_pcaMap( cpA, ptrA, outClusterPtrA, outClusterPtrA );
734 	}
735 
736 	/* backtransform out cluster to original image */
737 	bts_Cluster2D_transformBbp( cpA, &outClusterPtrA->clusterE, bts_Flt16Alt2D_inverted( &altL ), inClusterPtrA->clusterE.bbpE );
738 
739 	return confidenceL;
740 }
741 
742 /* ------------------------------------------------------------------------- */
743 
744 /* ========================================================================= */
745 
746