@@ -244,7 +244,7 @@ static void _ccv_atan2(float* x, float* y, float* angle, float* mag, int len)
244244
245245void ccv_gradient (ccv_dense_matrix_t * a , ccv_dense_matrix_t * * theta , int ttype , ccv_dense_matrix_t * * m , int mtype , int dx , int dy )
246246{
247- assert (a -> type & CCV_C1 );
247+ assert (CCV_GET_CHANNEL ( a -> type ) == CCV_C1 );
248248 ccv_declare_matrix_signature (tsig , a -> sig != 0 , ccv_sign_with_literal ("ccv_gradient_theta" ), a -> sig , 0 );
249249 ccv_declare_matrix_signature (msig , a -> sig != 0 , ccv_sign_with_literal ("ccv_gradient_m" ), a -> sig , 0 );
250250 ccv_dense_matrix_t * dtheta = * theta = ccv_dense_matrix_renew (* theta , a -> rows , a -> cols , CCV_32F | CCV_C1 , CCV_32F | CCV_C1 , tsig );
@@ -260,53 +260,164 @@ void ccv_gradient(ccv_dense_matrix_t* a, ccv_dense_matrix_t** theta, int ttype,
260260 ccv_matrix_free (ty );
261261}
262262
263- void ccv_hog (ccv_dense_matrix_t * a , ccv_dense_matrix_t * * b , int type , int size )
263+ void ccv_hog (ccv_dense_matrix_t * a , ccv_dense_matrix_t * * b , int b_type , int sbin , int size )
264264{
265- assert (a -> type & CCV_C1 );
266- int border_size = size / 2 ;
267- ccv_declare_matrix_signature ( sig , a -> sig != 0 , ccv_sign_with_literal ( "ccv_hog" ), a -> sig , 0 ) ;
268- type = ( type == 0 ) ? CCV_32S | CCV_C1 : CCV_GET_DATA_TYPE ( type ) | CCV_C1 ;
269- ccv_dense_matrix_t * db = * b = ccv_dense_matrix_renew (* b , a -> rows - border_size * 2 , ( a -> cols - border_size * 2 ) * 8 , CCV_C1 | CCV_ALL_DATA_TYPE , type , sig );
265+ assert (CCV_GET_CHANNEL ( a -> type ) == CCV_C1 );
266+ int rows = a -> rows / size ;
267+ int cols = a -> cols / size ;
268+ ccv_declare_matrix_signature ( sig , a -> sig != 0 , ccv_sign_with_format ( 64 , "ccv_hog(%d,%d)" , sbin , size ), a -> sig , 0 ) ;
269+ ccv_dense_matrix_t * db = * b = ccv_dense_matrix_renew (* b , rows , cols , CCV_64F | ( 4 + sbin * 3 ), CCV_64F | ( 4 + sbin * 3 ) , sig );
270270 ccv_matrix_return_if_cached (, db );
271271 ccv_dense_matrix_t * ag = 0 ;
272272 ccv_dense_matrix_t * mg = 0 ;
273- ccv_gradient (a , & ag , 0 , & mg , 0 , 3 , 3 );
274- int i , j , x , y ;
275- ag -> type = (ag -> type & ~CCV_32F ) | CCV_32S ;
276- for (i = 0 ; i < a -> rows * a -> cols ; i ++ )
277- ag -> data .i [i ] = ((int )(ag -> data .fl [i ] / 45 + 0.5 )) & 0x7 ;
278- int * agi = ag -> data .i ;
279- float * mgfl = mg -> data .fl ;
280- int * bi = db -> data .i ;
281- for (y = 0 ; y <= a -> rows - size ; y ++ )
273+ ccv_gradient (a , & ag , 0 , & mg , 0 , 1 , 1 );
274+ float * agp = ag -> data .fl ;
275+ float * mgp = mg -> data .fl ;
276+ int i , j , k ;
277+ ccv_dense_matrix_t * cn = ccv_dense_matrix_new (rows , cols , CCV_64F | (sbin * 2 ), 0 , 0 );
278+ ccv_dense_matrix_t * ca = ccv_dense_matrix_new (rows , cols , CCV_64F | CCV_C1 , 0 , 0 );
279+ ccv_zero (cn );
280+ double * cnp = cn -> data .db ;
281+ int sizec = 0 ;
282+ for (i = 0 ; i < rows * size ; i ++ )
282283 {
283- float hog [] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
284- for (i = 0 ; i < size ; i ++ )
285- for (j = 0 ; j < size ; j ++ )
286- hog [agi [i * a -> cols + j ]] += mgfl [i * a -> cols + j ];
287- for (i = 0 ; i < 8 ; i ++ )
288- bi [i ] = (int )hog [i ];
289- bi += 8 ;
290- mgfl ++ ;
291- agi ++ ;
292- for (x = 1 ; x <= a -> cols - size ; x ++ )
284+ for (j = 0 ; j < cols ; j ++ )
293285 {
294- for (i = 0 ; i < size ; i ++ )
286+ for (k = j * size ; k < j * size + size ; k ++ )
295287 {
296- hog [agi [i * a -> cols - 1 ]] -= mgfl [i * a -> cols - 1 ];
297- hog [agi [i * a -> cols - 1 + size ]] += mgfl [i * a -> cols - 1 + size ];
288+ int ag0 , ag1 ;
289+ double agr ;
290+ agr = (agp [k ] / 360.0 ) * (sbin * 2 );
291+ ag0 = (int )agr ;
292+ ag1 = (ag0 + 1 < sbin * 2 ) ? ag0 + 1 : 0 ;
293+ agr = agr - ag0 ;
294+ cnp [ag0 ] += (1.0 - agr ) * mgp [k ] / 255.0 ;
295+ cnp [ag1 ] += agr * mgp [k ] / 255.0 ;
298296 }
299- for (i = 0 ; i < 8 ; i ++ )
300- bi [i ] = (int )hog [i ];
301- bi += 8 ;
302- mgfl ++ ;
303- agi ++ ;
297+ cnp += 2 * sbin ;
304298 }
305- agi += border_size * 2 ;
306- mgfl += border_size * 2 ;
299+ agp += a -> cols ;
300+ mgp += a -> cols ;
301+ if (++ sizec < size )
302+ cnp -= cn -> cols ;
303+ else
304+ sizec = 0 ;
307305 }
308306 ccv_matrix_free (ag );
309307 ccv_matrix_free (mg );
308+ cnp = cn -> data .db ;
309+ double * cap = ca -> data .db ;
310+ for (i = 0 ; i < rows ; i ++ )
311+ {
312+ for (j = 0 ; j < cols ; j ++ )
313+ {
314+ * cap = 0 ;
315+ for (k = 0 ; k < sbin * 2 ; k ++ )
316+ {
317+ * cap += (* cnp ) * (* cnp );
318+ cnp ++ ;
319+ }
320+ cap ++ ;
321+ }
322+ }
323+ cnp = cn -> data .db ;
324+ cap = ca -> data .db ;
325+ ccv_zero (db );
326+ double * dbp = db -> data .db ;
327+ // normalize sbin direction-sensitive and sbin * 2 insensitive over 4 normalization factor
328+ // accumulating them over sbin * 2 + sbin + 4 channels
329+ // TNA - truncation - normalization - accumulation
330+ #define TNA (idx , a , b , c , d ) \
331+ { \
332+ double norm = 1.0 / sqrt(cap[a] + cap[b] + cap[c] + cap[d] + 1e-4); \
333+ for (k = 0; k < sbin * 2; k++) \
334+ { \
335+ double v = 0.5 * ccv_min(cnp[k] * norm, 0.2); \
336+ dbp[5 + sbin + k] += v; \
337+ dbp[1 + idx] += v; \
338+ } \
339+ dbp[sbin * 3 + idx] *= 0.2357; \
340+ for (k = 0; k < sbin; k++) \
341+ { \
342+ double v = 0.5 * ccv_min((cnp[k] + cnp[k + sbin]) * norm, 0.2); \
343+ dbp[5 + k] += v; \
344+ } \
345+ }
346+ TNA (0 , 0 , 0 , 0 , 0 );
347+ TNA (1 , 1 , 1 , 0 , 0 );
348+ TNA (2 , 0 , ca -> cols , ca -> cols , 0 );
349+ TNA (3 , 1 , ca -> cols + 1 , ca -> cols , 0 );
350+ cnp += 2 * sbin ;
351+ dbp += 3 * sbin + 4 ;
352+ cap ++ ;
353+ for (j = 1 ; j < cols - 1 ; j ++ )
354+ {
355+ TNA (0 , -1 , -1 , 0 , 0 );
356+ TNA (1 , 1 , 1 , 0 , 0 );
357+ TNA (2 , -1 , ca -> cols - 1 , ca -> cols , 0 );
358+ TNA (3 , 1 , ca -> cols + 1 , ca -> cols , 0 );
359+ cnp += 2 * sbin ;
360+ dbp += 3 * sbin + 4 ;
361+ cap ++ ;
362+ }
363+ TNA (0 , -1 , -1 , 0 , 0 );
364+ TNA (1 , 0 , 0 , 0 , 0 );
365+ TNA (2 , -1 , ca -> cols - 1 , ca -> cols , 0 );
366+ TNA (3 , 0 , ca -> cols , ca -> cols , 0 );
367+ cnp += 2 * sbin ;
368+ dbp += 3 * sbin + 4 ;
369+ cap ++ ;
370+ for (i = 1 ; i < rows - 1 ; i ++ )
371+ {
372+ TNA (0 , 0 , - ca -> cols , - ca -> cols , 0 );
373+ TNA (1 , 1 , - ca -> cols + 1 , - ca -> cols , 0 );
374+ TNA (2 , 0 , ca -> cols , ca -> cols , 0 );
375+ TNA (3 , 1 , ca -> cols + 1 , ca -> cols , 0 );
376+ cnp += 2 * sbin ;
377+ dbp += 3 * sbin + 4 ;
378+ cap ++ ;
379+ for (j = 1 ; j < cols - 1 ; j ++ )
380+ {
381+ TNA (0 , -1 , - ca -> cols - 1 , - ca -> cols , 0 );
382+ TNA (1 , 1 , - ca -> cols + 1 , - ca -> cols , 0 );
383+ TNA (2 , -1 , ca -> cols - 1 , ca -> cols , 0 );
384+ TNA (3 , 1 , ca -> cols + 1 , ca -> cols , 0 );
385+ cnp += 2 * sbin ;
386+ dbp += 3 * sbin + 4 ;
387+ cap ++ ;
388+ }
389+ TNA (0 , -1 , - ca -> cols - 1 , - ca -> cols , 0 );
390+ TNA (1 , 0 , - ca -> cols , - ca -> cols , 0 );
391+ TNA (2 , -1 , ca -> cols - 1 , ca -> cols , 0 );
392+ TNA (3 , 0 , ca -> cols , ca -> cols , 0 );
393+ cnp += 2 * sbin ;
394+ dbp += 3 * sbin + 4 ;
395+ cap ++ ;
396+ }
397+ TNA (0 , 0 , - ca -> cols , - ca -> cols , 0 );
398+ TNA (1 , 1 , - ca -> cols + 1 , - ca -> cols , 0 );
399+ TNA (2 , 0 , 0 , 0 , 0 );
400+ TNA (3 , 1 , 1 , 0 , 0 );
401+ cnp += 2 * sbin ;
402+ dbp += 3 * sbin + 4 ;
403+ cap ++ ;
404+ for (j = 1 ; j < cols - 1 ; j ++ )
405+ {
406+ TNA (0 , -1 , - ca -> cols - 1 , - ca -> cols , 0 );
407+ TNA (1 , 1 , - ca -> cols + 1 , - ca -> cols , 0 );
408+ TNA (2 , -1 , -1 , 0 , 0 );
409+ TNA (3 , 1 , 1 , 0 , 0 );
410+ cnp += 2 * sbin ;
411+ dbp += 3 * sbin + 4 ;
412+ cap ++ ;
413+ }
414+ TNA (0 , -1 , - ca -> cols - 1 , - ca -> cols , 0 );
415+ TNA (1 , 0 , - ca -> cols , - ca -> cols , 0 );
416+ TNA (2 , -1 , -1 , 0 , 0 );
417+ TNA (3 , 0 , 0 , 0 , 0 );
418+ #undef TNA
419+ ccv_matrix_free (cn );
420+ ccv_matrix_free (ca );
310421}
311422
312423/* it is a supposely cleaner and faster implementation than original OpenCV (ccv_canny_deprecated,
@@ -678,7 +789,7 @@ void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int
678789 break ;
679790 case CCV_INTER_CUBIC :
680791 break ;
681- case CCV_INTER_LACZOS :
792+ case CCV_INTER_LANCZOS :
682793 break ;
683794 }
684795}
@@ -707,7 +818,7 @@ void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, in
707818 * it is not desirable to have that offset when we try to wrap it into our 5-row buffer (
708819 * because in later rearrangement, we have no src_y to backup the arrangement). In
709820 * such micro scope, we managed to stripe 5 addition into one shift and addition. */
710- #define for_block (x_block , _for_get_a , _for_get , _for_set , _for_set_b ) \
821+ #define for_block (_for_get_a , _for_get , _for_set , _for_set_b ) \
711822 for (dy = 0; dy < db->rows; dy++) \
712823 { \
713824 for(; sy <= dy * 2 + 2 + src_y; sy++) \
@@ -730,20 +841,19 @@ void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, in
730841 b_ptr += db->step; \
731842 }
732843 int no_8u_type = (a -> type & CCV_8U ) ? CCV_32S : a -> type ;
733- /* here is the new technique to expand for loop with condition in manual way */
734844 if (src_x > 0 )
735845 {
736846#define x_block (_for_get_a , _for_get , _for_set , _for_set_b ) \
737847 for (dx = cols0 * ch; dx < db->cols * ch; dx += ch) \
738848 for (k = 0; k < ch; k++) \
739849 _for_set(row, dx + k, _for_get_a(a_ptr, tab[dx * 2 + sx + k], 0) * 6 + (_for_get_a(a_ptr, tab[dx * 2 + sx + k - ch], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch], 0)) * 4 + _for_get_a(a_ptr, tab[dx * 2 + sx + k - ch * 2], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch * 2], 0), 0);
740- ccv_unswitch_block ( x_block , ccv_matrix_getter_a , a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
850+ ccv_matrix_getter_a ( a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
741851#undef x_block
742852 } else {
743853#define x_block (_for_get_a , _for_get , _for_set , _for_set_b ) \
744854 for (k = 0; k < ch; k++) \
745855 _for_set(row, (db->cols - 1) * ch + k, _for_get_a(a_ptr, a->cols * ch + sx - ch + k, 0) * 10 + _for_get_a(a_ptr, (a->cols - 2) * ch + sx + k, 0) * 5 + _for_get_a(a_ptr, (a->cols - 3) * ch + sx + k, 0), 0);
746- ccv_unswitch_block ( x_block , ccv_matrix_getter_a , a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
856+ ccv_matrix_getter_a ( a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
747857#undef x_block
748858 }
749859#undef for_block
@@ -767,7 +877,7 @@ void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int
767877 int bufstep = db -> cols * ch * ccv_max (CCV_GET_DATA_TYPE_SIZE (db -> type ), sizeof (int ));
768878 unsigned char * b_ptr = db -> data .ptr ;
769879 /* why src_y * 2: the same argument as in ccv_sample_down */
770- #define for_block (x_block , _for_get_a , _for_get , _for_set , _for_set_b ) \
880+ #define for_block (_for_get_a , _for_get , _for_set , _for_set_b ) \
771881 for (y = 0; y < a->rows; y++) \
772882 { \
773883 for (; sy <= y + 1 + src_y; sy++) \
@@ -820,7 +930,7 @@ void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int
820930 _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) + _for_get_a(a_ptr, tab[x + sx + k], 0) * 6 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0), 0); \
821931 _for_set(row, x * 2 + ch + k, (_for_get_a(a_ptr, tab[x + sx + k], 0) + _for_get_a(a_ptr, tab[x + sx + ch + k], 0)) * 4, 0); \
822932 }
823- ccv_unswitch_block ( x_block , ccv_matrix_getter_a , a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
933+ ccv_matrix_getter_a ( a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
824934#undef x_block
825935 } else {
826936#define x_block (_for_get_a , _for_get , _for_set , _for_set_b ) \
@@ -829,7 +939,7 @@ void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int
829939 _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * 7, 0); \
830940 _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * 4, 0); \
831941 }
832- ccv_unswitch_block ( x_block , ccv_matrix_getter_a , a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
942+ ccv_matrix_getter_a ( a -> type , ccv_matrix_getter , no_8u_type , ccv_matrix_setter , no_8u_type , ccv_matrix_setter_b , db -> type , for_block );
833943#undef x_block
834944 }
835945#undef for_block
0 commit comments