📄 motiondetect.c
字号:
if( !p_sys->b_old ) { picture_Copy( p_sys->p_old, p_inpic ); p_sys->b_old = true; return p_inpic; } p_outpic = filter_NewPicture( p_filter ); if( !p_outpic ) { picture_Release( p_inpic ); return NULL; } picture_Copy( p_outpic, p_inpic ); /* Substract all planes at once */ for( y = 0; y < p_fmt->i_height; y++ ) { for( x = 0; x < p_fmt->i_width; x+=2 ) { int i; int d; d = abs( p_inpix[y*i_src_pitch+2*x+i_u_offset] - p_oldpix[y*i_old_pitch+2*x+i_u_offset] ) + abs( p_inpix[y*i_src_pitch+2*x+i_v_offset] - p_oldpix[y*i_old_pitch+2*x+i_v_offset] ); for( i = 0; i < 2; i++ ) p_buf2[y*p_fmt->i_width+x+i] = abs( p_inpix[y*i_src_pitch+2*(x+i)+i_y_offset] - p_oldpix[y*i_old_pitch+2*(x+i)+i_y_offset] ) + d; } } /** * Get the areas where movement was detected */ p_sys->i_colors = FindShapes( p_buf2, p_buf, p_fmt->i_width, p_fmt->i_width, p_fmt->i_height, p_sys->colors, p_sys->color_x_min, p_sys->color_x_max, p_sys->color_y_min, p_sys->color_y_max ); /** * Count final number of shapes * Draw rectangles (there can be more than 1 moving shape in 1 rectangle) */ Draw( p_filter, &p_outpic->p[Y_PLANE].p_pixels[i_y_offset], p_outpic->p[Y_PLANE].i_pitch, 2 ); /** * We're done. Lets keep a copy of the picture * TODO we may just picture_Release with a latency of 1 if the filters/vout * handle it correctly */ picture_Copy( p_sys->p_old, p_inpic ); picture_Release( p_inpic ); return p_outpic;}/***************************************************************************** * Gaussian Convolution ***************************************************************************** * Gaussian convolution ( sigma == 1.4 ) * * | 2 4 5 4 2 | | 2 4 4 4 2 | * | 4 9 12 9 4 | | 4 8 12 8 4 | * | 5 12 15 12 5 | ~ | 4 12 16 12 4 | * | 4 9 12 9 4 | | 4 8 12 8 4 | * | 2 4 5 4 2 | | 2 4 4 4 2 | *****************************************************************************/static void GaussianConvolution( uint32_t *p_inpix, uint32_t *p_smooth, int i_src_pitch, int i_num_lines, int i_src_visible ){ int x,y; /* A bit overkill but ... simpler */ memset( p_smooth, 0, sizeof(*p_smooth) * i_src_pitch * i_num_lines ); for( y = 2; y < i_num_lines - 2; y++ ) { for( x = 2; x < i_src_visible - 2; x++ ) { p_smooth[y*i_src_visible+x] = (uint32_t)( /* 2 rows up */ ( p_inpix[(y-2)*i_src_pitch+x-2] ) + ((p_inpix[(y-2)*i_src_pitch+x-1] + p_inpix[(y-2)*i_src_pitch+x] + p_inpix[(y-2)*i_src_pitch+x+1])<<1 ) + ( p_inpix[(y-2)*i_src_pitch+x+2] ) /* 1 row up */ + ((p_inpix[(y-1)*i_src_pitch+x-2] + ( p_inpix[(y-1)*i_src_pitch+x-1]<<1 ) + ( p_inpix[(y-1)*i_src_pitch+x]*3 ) + ( p_inpix[(y-1)*i_src_pitch+x+1]<<1 ) + p_inpix[(y-1)*i_src_pitch+x+2] /* */ + p_inpix[y*i_src_pitch+x-2] + ( p_inpix[y*i_src_pitch+x-1]*3 ) + ( p_inpix[y*i_src_pitch+x]<<2 ) + ( p_inpix[y*i_src_pitch+x+1]*3 ) + p_inpix[y*i_src_pitch+x+2] /* 1 row down */ + p_inpix[(y+1)*i_src_pitch+x-2] + ( p_inpix[(y+1)*i_src_pitch+x-1]<<1 ) + ( p_inpix[(y+1)*i_src_pitch+x]*3 ) + ( p_inpix[(y+1)*i_src_pitch+x+1]<<1 ) + p_inpix[(y+1)*i_src_pitch+x+2] )<<1 ) /* 2 rows down */ + ( p_inpix[(y+2)*i_src_pitch+x-2] ) + ((p_inpix[(y+2)*i_src_pitch+x-1] + p_inpix[(y+2)*i_src_pitch+x] + p_inpix[(y+2)*i_src_pitch+x+1])<<1 ) + ( p_inpix[(y+2)*i_src_pitch+x+2] ) ) >> 6 /* 115 */; } }}/***************************************************************************** * *****************************************************************************/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 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -