Forums
  News| Documentation| Screenshots| Downloads| Support| Forums| Wiki| Shop| Search| DonateHome

Algorithm C code snippet

From ZoneMinder

Jump to: navigation, search

Back

  • The following snippit of code was edited to remove some diagnostics code. The vars are easily related to the config settings, and if you know C, you can easily see the algorithm.

       for ( int y = lo_y; y <= hi_y; y++ )
       {
               pdiff = diff_image->Buffer( lo_x, y );
               for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
               {
                       if ( (*pdiff > min_pixel_threshold) && (!max_pixel_threshold || (*pdiff < max_pixel_threshold)) )
                       {
                               *pdiff = WHITE;
                               alarm_pixels++;
                       }
                       else
                       {
                               *pdiff = BLACK;
                       }
               }
       }
       if ( !alarm_pixels ) return( false );
       if ( min_alarm_pixels && alarm_pixels < min_alarm_pixels ) return( false );
       if ( max_alarm_pixels && alarm_pixels > max_alarm_pixels ) return( false );
       score = (100*alarm_pixels)/(limits.Size().X()*limits.Size().Y());
       if ( check_method >= FILTERED_PIXELS )
       {
               int bx = filter_box.X();
               int by = filter_box.Y();
               int bx1 = bx-1;
               int by1 = by-1;
               if ( bx > 1 || by > 1 )
               {
                       // Now remove any pixels smaller than our filter size
                       unsigned char *pdiff;
                       unsigned char *cpdiff;
                       int ldx, hdx, ldy, hdy;
                       bool block;
                       for ( int y = lo_y; y <= hi_y; y++ )
                       {
                               pdiff = diff_image->Buffer( lo_x, y );
                               for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
                               {
                                       if ( *pdiff == WHITE )
                                       {
                                               // Check participation in an X block
                                               ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
                                               hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
                                               ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
                                               hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
                                               block = false;
                                               for ( int dy = ldy; !block && dy <= hdy; dy++ )
                                               {
                                                       for ( int dx = ldx; !block && dx <= hdx; dx++ )
                                                       {
                                                               block = true;
                                                               for ( int dy2 = 0; block && dy2 < by; dy2++ )
                                                               {
                                                                       for ( int dx2 = 0; block && dx2 < bx; dx2++ )
                                                                       {
                                                                               cpdiff = diff_image->Buffer( x+dx+dx2, y+dy+dy2 );
                                                                               if ( !*cpdiff )
                                                                               {
                                                                                       block = false;
                                                                               }
                                                                       }
                                                               }
                                                       }
                                               }
                                               if ( !block )
                                               {
                                                       *pdiff = BLACK;
                                                       continue;
                                               }
                                               alarm_filter_pixels++;
                                       }
                               }
                       }
               }
               else
               {
                       alarm_filter_pixels = alarm_pixels;
               }
               if ( !alarm_filter_pixels ) return( false );
               if ( min_filter_pixels && alarm_filter_pixels < min_filter_pixels ) return( false );
               if ( max_filter_pixels && alarm_filter_pixels > max_filter_pixels ) return( false );
               score = (100*alarm_filter_pixels)/(limits.Size().X()*limits.Size().Y());
               if ( check_method >= BLOBS )
               {
                       typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
                       BlobStats blob_stats[256];
                       memset( blob_stats, 0, sizeof(BlobStats)*256 );
                       unsigned char *pdiff, *spdiff;
                       int lx, ly;
                       BlobStats *bsx, *bsy;
                       BlobStats *bsm, *bss;
                       for ( int y = lo_y; y <= hi_y; y++ )
                       {
                               pdiff = diff_image->Buffer( lo_x, y );
                               for ( int x = lo_x; x <= hi_x; x++, pdiff++ )
                               {
                                       if ( *pdiff == WHITE )
                                       {
                                               //printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff );
                                               lx = x>lo_x?*(pdiff-1):0;
                                               ly = y>lo_y?*(pdiff-diff_image->Width()):0;
                                               if ( lx )
                                               {
                                                       //printf( "Left neighbour is %d\n", lx );
                                                       bsx = &blob_stats[lx];
                                                       if ( ly )
                                                       {
                                                               //printf( "Top neighbour is %d\n", ly );
                                                               bsy = &blob_stats[ly];
                                                               if ( lx == ly )
                                                               {
                                                                       //printf( "Matching neighbours, setting to %d\n", lx );
                                                                       // Add to the blob from the x side (either side really)
                                                                       *pdiff = lx;
                                                                       bsx->count++;
                                                                       if ( x > bsx->hi_x ) bsx->hi_x = x;
                                                                       if ( y > bsx->hi_y ) bsx->hi_y = y;
                                                               }
                                                               else
                                                               {
                                                                       // Aggregate blobs
                                                                       bsm = bsx->count>=bsy->count?bsx:bsy;
                                                                       bss = bsm==bsx?bsy:bsx;
                                                                       //printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag );
                                                                       // Now change all those pixels to the other setting
                                                                       for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ )
                                                                       {
                                                                               spdiff = diff_image->Buffer( bss->lo_x, sy );
                                                                               for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ )
                                                                               {
                                                                                       //printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff );
                                                                                       if ( *spdiff == bss->tag )
                                                                                       {
                                                                                               //printf( ", setting" );
                                                                                               *spdiff = bsm->tag;
                                                                                       }
                                                                                       //printf( "\n" );
                                                                               }
                                                                       }
                                                                       *pdiff = bsm->tag;
                                                                       // Merge the slave blob into the master
                                                                       bsm->count += bss->count+1;
                                                                       if ( x > bsm->hi_x ) bsm->hi_x = x;
                                                                       if ( y > bsm->hi_y ) bsm->hi_y = y;
                                                                       if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x;
                                                                       if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y;
                                                                       if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x;
                                                                       if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y;
                                                                       alarm_blobs--;
                                                                       Debug( 2, ( "Merging blob %d with %d, %d current blobs", bss->tag, bsm->tag, alarm_blobs ));
                                                                       // Clear out the old blob
                                                                       bss->tag = 0;
                                                                       bss->count = 0;
                                                                       bss->lo_x = 0;
                                                                       bss->lo_y = 0;
                                                                       bss->hi_x = 0;
                                                                       bss->hi_y = 0;
                                                               }
                                                       }
                                                       else
                                                       {
                                                               //printf( "Setting to left neighbour %d\n", lx );
                                                               // Add to the blob from the x side 
                                                               *pdiff = lx;
                                                               bsx->count++;
                                                               if ( x > bsx->hi_x ) bsx->hi_x = x;
                                                               if ( y > bsx->hi_y ) bsx->hi_y = y;
                                                       }
                                               }
                                               else
                                               {
                                                       if ( ly )
                                                       {
                                                               //printf( "Setting to top neighbour %d\n", ly );
                                                               // Add to the blob from the y side
                                                               BlobStats *bsy = &blob_stats[ly];
                                                               *pdiff = ly;
                                                               bsy->count++;
                                                               if ( x > bsy->hi_x ) bsy->hi_x = x;
                                                               if ( y > bsy->hi_y ) bsy->hi_y = y;
                                                       }
                                                       else
                                                       {
                                                               // Create a new blob
                                                               //for ( int i = 1; i < WHITE; i++ )
                                                               for ( int i = (WHITE-1); i > 0; i-- )
                                                               {
                                                                       BlobStats *bs = &blob_stats[i];
                                                                       if ( !bs->count )
                                                                       {
                                                                               //printf( "Creating new blob %d\n", i );
                                                                               *pdiff = i;
                                                                               bs->tag = i;
                                                                               bs->count++;
                                                                               bs->lo_x = bs->hi_x = x;
                                                                               bs->lo_y = bs->hi_y = y;
                                                                               alarm_blobs++;
                                                                               Debug( 2, ( "Created blob %d, %d current blobs", bs->tag, alarm_blobs ));
                                                                               break;
                                                                       }
                                                               }
                                                       }
                                               }
                                       }
                               }
                       }
                       if ( config.record_diag_images )
                       {
                               static char diag_path[PATH_MAX] = "";
                               if ( !diag_path[0] )
                               {
                                       snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
                               }
                               diff_image->WriteJpeg( diag_path );
                       }
                       if ( !alarm_blobs ) return( false );
                       alarm_blob_pixels = alarm_filter_pixels;
                       // Now eliminate blobs under the threshold
                       for ( int i = 1; i < WHITE; i++ )
                       {
                               BlobStats *bs = &blob_stats[i];
                               if ( bs->count && ((min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels)) )
                               {
                                       for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
                                       {
                                               unsigned char *spdiff = diff_image->Buffer( bs->lo_x, sy );
                                               for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ )
                                               {
                                                       if ( *spdiff == bs->tag )
                                                       {
                                                               *spdiff = BLACK;
                                                       }
                                               }
                                       }
                                       alarm_blobs--;
                                       alarm_blob_pixels -= bs->count;
                                       Debug( 2, ( "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ));
                                       bs->tag = 0;
                                       bs->count = 0;
                                       bs->lo_x = 0;
                                       bs->lo_y = 0;
                                       bs->hi_x = 0;
                                       bs->hi_y = 0;
                               }
                               else
                               {
                                       if ( bs->count )
                                       {
                                               if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count;
                                               if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count;
                                       }
                               }
                       }
                       if ( config.record_diag_images )
                       {
                               static char diag_path[PATH_MAX] = "";
                               if ( !diag_path[0] )
                               {
                                       snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
                               }
                               diff_image->WriteJpeg( diag_path );
                       }
                       if ( !alarm_blobs ) return( false );
                       if ( min_blobs && alarm_blobs < min_blobs ) return( false );
                       if ( max_blobs && alarm_blobs > max_blobs ) return( false );
                       alarm_lo_x = hi_x+1;
                       alarm_hi_x = lo_x-1;
                       alarm_lo_y = hi_y+1;
                       alarm_hi_y = lo_y-1;
                       for ( int i = 1; i < WHITE; i++ )
                       {
                               BlobStats *bs = &blob_stats[i];
                               if ( bs->count )
                               {
                                       if ( bs->count == max_blob_size )
                                       {
                                               //if ( monitor->followMotion() )
                                               if ( true )
                                               {
                                                       unsigned long x_total = 0;
                                                       unsigned long y_total = 0;
                                                       for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
                                                       {
                                                               unsigned char *spdiff = diff_image->Buffer( bs->lo_x, sy );
                                                               for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ )
                                                               {
                                                                       if ( *spdiff == bs->tag )
                                                                       {
                                                                               x_total += sx;
                                                                               y_total += sy;
                                                                       }
                                                               }
                                                       }
                                                       alarm_mid_x = int(round(x_total/bs->count));
                                                       alarm_mid_y = int(round(y_total/bs->count));
                                               }
                                       }
                                       if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x;
                                       if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y;
                                       if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x;
                                       if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y;
                               }
                       }
                       score = ((100*alarm_blob_pixels)/int(sqrt((double)alarm_blobs)))/(limits.Size().X()*limits.Size().Y());
               }
       }
       if ( type == INCLUSIVE )
       {
               score /= 2;
       }
       else if ( type == EXCLUSIVE )
       {
               score *= 2;
       }

 ©2006 Triornis Ltd News •  Documentation •  Screenshots •  Downloads •  Support •  Forums •  Wiki •  Shop •  Search •  Donate •  Home