+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+static int FindShapes( uint32_t *p_diff, uint32_t *p_smooth,
+ int i_pitch, int i_visible, int i_lines,
+ int *colors,
+ int *color_x_min, int *color_x_max,
+ int *color_y_min, int *color_y_max )
+{
+ int last = 1;
+ int i, j;
+
+ /**
+ * Apply some smoothing to remove noise
+ */
+ GaussianConvolution( p_diff, p_smooth, i_pitch, i_lines, i_visible );
+
+ /**
+ * Label the shapes and build the labels dependencies list
+ */
+ for( j = 0; j < i_pitch; j++ )
+ {
+ p_smooth[j] = 0;
+ p_smooth[(i_lines-1)*i_pitch+j] = 0;
+ }
+ for( i = 1; i < i_lines-1; i++ )
+ {
+ p_smooth[i*i_pitch] = 0;
+ for( j = 1; j < i_pitch-1; j++ )
+ {
+ if( p_smooth[i*i_pitch+j] > 15 )
+ {
+ if( p_smooth[(i-1)*i_pitch+j-1] )
+ {
+ p_smooth[i*i_pitch+j] = p_smooth[(i-1)*i_pitch+j-1];
+ }
+ else if( p_smooth[(i-1)*i_pitch+j] )
+ p_smooth[i*i_pitch+j] = p_smooth[(i-1)*i_pitch+j];
+ else if( p_smooth[i*i_pitch+j-1] )
+ p_smooth[i*i_pitch+j] = p_smooth[i*i_pitch+j-1];
+ else
+ {
+ if( last < NUM_COLORS )
+ {
+ p_smooth[i*i_pitch+j] = last;
+ colors[last] = last;
+ last++;
+ }
+ }
+ #define CHECK( A ) \
+ if( p_smooth[A] && p_smooth[A] != p_smooth[i*i_pitch+j] ) \
+ { \
+ if( p_smooth[A] < p_smooth[i*i_pitch+j] ) \
+ colors[p_smooth[i*i_pitch+j]] = p_smooth[A]; \
+ else \
+ colors[p_smooth[A]] = p_smooth[i*i_pitch+j]; \
+ }
+ CHECK( i*i_pitch+j-1 );
+ CHECK( (i-1)*i_pitch+j-1 );
+ CHECK( (i-1)*i_pitch+j );
+ CHECK( (i-1)*i_pitch+j+1 );
+ #undef CHECK
+ }
+ else
+ {
+ p_smooth[i*i_pitch+j] = 0;
+ }
+ }
+ p_smooth[i*i_pitch+j] = 0;
+ }
+
+ /**
+ * Initialise empty rectangle list
+ */
+ for( i = 1; i < last; i++ )
+ {
+ color_x_min[i] = -1;
+ color_x_max[i] = -1;
+ color_y_min[i] = -1;
+ color_y_max[i] = -1;
+ }
+
+ /**
+ * Compute rectangle coordinates
+ */
+ for( i = 0; i < i_pitch * i_lines; i++ )
+ {
+ if( p_smooth[i] )
+ {
+ while( colors[p_smooth[i]] != (int)p_smooth[i] )
+ p_smooth[i] = colors[p_smooth[i]];
+ if( color_x_min[p_smooth[i]] == -1 )
+ {
+ color_x_min[p_smooth[i]] =
+ color_x_max[p_smooth[i]] = i % i_pitch;
+ color_y_min[p_smooth[i]] =
+ color_y_max[p_smooth[i]] = i / i_pitch;
+ }
+ else
+ {
+ int x = i % i_pitch, y = i / i_pitch;
+ if( x < color_x_min[p_smooth[i]] )
+ color_x_min[p_smooth[i]] = x;
+ if( x > color_x_max[p_smooth[i]] )
+ color_x_max[p_smooth[i]] = x;
+ if( y < color_y_min[p_smooth[i]] )
+ color_y_min[p_smooth[i]] = y;
+ if( y > color_y_max[p_smooth[i]] )
+ color_y_max[p_smooth[i]] = y;
+ }
+ }
+ }
+
+ /**
+ * Merge overlaping rectangles
+ */
+ for( i = 1; i < last; i++ )
+ {
+ if( colors[i] != i ) continue;
+ if( color_x_min[i] == -1 ) continue;
+ for( j = i+1; j < last; j++ )
+ {
+ if( colors[j] != j ) continue;
+ if( color_x_min[j] == -1 ) continue;
+ if( __MAX( color_x_min[i], color_x_min[j] ) < __MIN( color_x_max[i], color_x_max[j] ) &&
+ __MAX( color_y_min[i], color_y_min[j] ) < __MIN( color_y_max[i], color_y_max[j] ) )
+ {
+ color_x_min[i] = __MIN( color_x_min[i], color_x_min[j] );
+ color_x_max[i] = __MAX( color_x_max[i], color_x_max[j] );
+ color_y_min[i] = __MIN( color_y_min[i], color_y_min[j] );
+ color_y_max[i] = __MAX( color_y_max[i], color_y_max[j] );
+ color_x_min[j] = -1;
+ j = 0;
+ }
+ }
+ }
+
+ return last;
+}
+
+static void Draw( filter_t *p_filter, uint8_t *p_pix, int i_pix_pitch, int i_pix_size )
+{
+ filter_sys_t *p_sys = p_filter->p_sys;
+ int i, j;
+
+ for( i = 1, j = 0; i < p_sys->i_colors; i++ )
+ {
+ int x, y;
+
+ if( p_sys->colors[i] != i )
+ continue;
+
+ const int color_x_min = p_sys->color_x_min[i];
+ const int color_x_max = p_sys->color_x_max[i];
+ const int color_y_min = p_sys->color_y_min[i];
+ const int color_y_max = p_sys->color_y_max[i];
+
+ if( color_x_min == -1 )
+ continue;
+ if( ( color_y_max - color_y_min ) * ( color_x_max - color_x_min ) < 16 )
+ continue;
+
+ j++;
+
+ y = color_y_min;
+ for( x = color_x_min; x <= color_x_max; x++ )
+ p_pix[y*i_pix_pitch+x*i_pix_size] = 0xff;
+
+ y = color_y_max;
+ for( x = color_x_min; x <= color_x_max; x++ )
+ p_pix[y*i_pix_pitch+x*i_pix_size] = 0xff;
+
+ x = color_x_min;
+ for( y = color_y_min; y <= color_y_max; y++ )
+ p_pix[y*i_pix_pitch+x*i_pix_size] = 0xff;
+
+ x = color_x_max;
+ for( y = color_y_min; y <= color_y_max; y++ )
+ p_pix[y*i_pix_pitch+x*i_pix_size] = 0xff;
+ }
+ msg_Dbg( p_filter, "Counted %d moving shapes.", j );
+}