📄 alg.c
字号:
labelsize=iflood(ix, iy, width, height, out, labels, current_label+32768, current_label); imgs->labelgroup_max+=labelsize; imgs->labels_above++; } if( imgs->labelsize_max < labelsize ){ imgs->labelsize_max=labelsize; imgs->largest_label=current_label; } cnt->current_image->total_labels++; current_label++; } } pixelpos++; /* compensate for ix<width-1 */ } //printf( "%i Labels found. Largest connected Area: %i Pixel(s). Largest Label: %i\n", imgs->total_labels, imgs->labelsize_max, cnt->current_image->largest_label); /* return group of significant labels */ return imgs->labelgroup_max;}/* Dilates a 3x3 box */static int dilate9(unsigned char *img, int width, int height, void *buffer){ /* - row1, row2 and row3 represent lines in the temporary buffer * - window is a sliding window containing max values of the columns * in the 3x3 matrix * - widx is an index into the sliding window (this is faster than * doing modulo 3 on i) * - blob keeps the current max value */ int y, i, sum = 0, widx; unsigned char *row1, *row2, *row3, *rowTemp,*yp; unsigned char window[3], blob, latest; /* Set up row pointers in the temporary buffer. */ row1 = buffer; row2 = row1 + width; row3 = row2 + width; /* Init rows 2 and 3. */ memset(row2, 0, width); memcpy(row3, img, width); /* Pointer to the current row in img. */ yp = img; for (y = 0; y < height; y++) { /* Move down one step; row 1 becomes the previous row 2 and so on. */ rowTemp = row1; row1 = row2; row2 = row3; row3 = rowTemp; /* If we're at the last row, fill with zeros, otherwise copy from img. */ if(y == height - 1) memset(row3, 0, width); else memcpy(row3, yp+width, width); /* Init slots 0 and 1 in the moving window. */ window[0] = MAX3(row1[0], row2[0], row3[0]); window[1] = MAX3(row1[1], row2[1], row3[1]); /* Init blob to the current max, and set window index. */ blob = MAX2(window[0], window[1]); widx = 2; /* Iterate over the current row; index i is off by one to eliminate * a lot of +1es in the loop. */ for (i = 2; i <= width - 1; i++) { /* Get the max value of the next column in the 3x3 matrix. */ latest = window[widx] = MAX3(row1[i], row2[i], row3[i]); /* If the value is larger than the current max, use it. Otherwise, * calculate a new max (because the new value may not be the max. */ if(latest >= blob) blob = latest; else blob = MAX3(window[0], window[1], window[2]); /* Write the max value (blob) to the image. */ if (blob != 0) { *(yp + i - 1) = blob; sum++; } /* Wrap around the window index if necessary. */ if(++widx == 3) widx = 0; } /* Store zeros in the vertical sides. */ *yp = *(yp + width - 1) = 0; yp += width; } return sum;}/* Dilates a + shape */static int dilate5(unsigned char *img, int width, int height, void *buffer){ /* - row1, row2 and row3 represent lines in the temporary buffer * - mem holds the max value of the overlapping part of two + shapes */ int y, i, sum = 0; unsigned char *row1, *row2, *row3, *rowTemp, *yp; unsigned char blob, mem, latest; /* Set up row pointers in the temporary buffer. */ row1 = buffer; row2 = row1 + width; row3 = row2 + width; /* Init rows 2 and 3. */ memset(row2, 0, width); memcpy(row3, img, width); /* Pointer to the current row in img. */ yp = img; for (y = 0; y < height; y++) { /* Move down one step; row 1 becomes the previous row 2 and so on. */ rowTemp = row1; row1 = row2; row2 = row3; row3 = rowTemp; /* If we're at the last row, fill with zeros, otherwise copy from img. */ if (y == height - 1) memset(row3, 0, width); else memcpy(row3, yp+width, width); /* Init mem and set blob to force an evaluation of the entire + shape. */ mem = MAX2(row2[0], row2[1]); blob = 1; /* dummy value, must be > 0 */ for (i = 1; i < width - 1; i++) { /* Get the max value of the "right edge" of the + shape. */ latest = MAX3(row1[i], row2[i + 1], row3[i]); if (blob == 0) { /* In case the last blob is zero, only latest matters. */ blob = latest; mem = row2[i + 1]; } else { /* Otherwise, we have to check both latest and mem. */ blob = MAX2(mem, latest); mem = MAX2(row2[i], row2[i+1]); } /* Write the max value (blob) to the image. */ if (blob != 0) { *(yp + i) = blob; sum++; } } /* Store zeros in the vertical sides. */ *yp = *(yp + width - 1) = 0; yp += width; } return sum;}/* Erodes a 3x3 box */static int erode9(unsigned char *img, int width, int height, void *buffer, unsigned char flag){ int y, i, sum = 0; char *Row1,*Row2,*Row3; Row1 = buffer; Row2 = Row1 + width; Row3 = Row1 + 2*width; memset(Row2, flag, width); memcpy(Row3, img, width); for (y = 0; y < height; y++) { memcpy(Row1, Row2, width); memcpy(Row2, Row3, width); if (y == height-1) memset(Row3, flag, width); else memcpy(Row3, img+(y+1)*width, width); for (i = width-2; i >= 1; i--) { if (Row1[i-1] == 0 || Row1[i] == 0 || Row1[i+1] == 0 || Row2[i-1] == 0 || Row2[i] == 0 || Row2[i+1] == 0 || Row3[i-1] == 0 || Row3[i] == 0 || Row3[i+1] == 0) img[y*width+i] = 0; else sum++; } img[y*width] = img[y*width+width-1] = flag; } return sum;}/* Erodes in a + shape */static int erode5(unsigned char *img, int width, int height, void *buffer, unsigned char flag){ int y, i, sum = 0; char *Row1,*Row2,*Row3; Row1 = buffer; Row2 = Row1 + width; Row3 = Row1 + 2*width; memset(Row2, flag, width); memcpy(Row3, img, width); for (y = 0; y < height; y++) { memcpy(Row1, Row2, width); memcpy(Row2, Row3, width); if (y == height-1) memset(Row3, flag, width); else memcpy(Row3, img+(y+1)*width, width); for (i = width-2; i >= 1; i--) { if (Row1[i] == 0 || Row2[i-1] == 0 || Row2[i] == 0 || Row2[i+1] == 0 || Row3[i] == 0) img[y*width+i] = 0; else sum++; } img[y*width] = img[y*width+width-1] = flag; } return sum;}/* * Despeckling routine to remove noisy detections. */int alg_despeckle(struct context *cnt, int olddiffs){ int diffs = 0; unsigned char *out = cnt->imgs.out; int width = cnt->imgs.width; int height= cnt->imgs.height; int done = 0, i, len = strlen(cnt->conf.despeckle); unsigned char *common_buffer = cnt->imgs.common_buffer; for (i = 0; i < len; i++) { switch (cnt->conf.despeckle[i]) { case 'E': if ((diffs = erode9(out, width, height, common_buffer, 0)) == 0) i=len; done=1; break; case 'e': if ((diffs = erode5(out, width, height, common_buffer, 0)) == 0) i=len; done=1; break; case 'D': diffs = dilate9(out, width, height, common_buffer); done=1; break; case 'd': diffs = dilate5(out, width, height, common_buffer); done=1; break; /* no further despeckle after labeling! */ case 'l': diffs = alg_labeling(cnt); i=len; done=2; break; } } /* If conf.despeckle contains any valid action EeDdl */ if (done){ if (done != 2) cnt->imgs.labelsize_max = 0; // Disable Labeling return diffs; } else cnt->imgs.labelsize_max = 0; // Disable Labeling return olddiffs;}/* Generate actual smartmask. Calculate sensitivity based on motion */void alg_tune_smartmask(struct context *cnt){ int i, diff; int motionsize = cnt->imgs.motionsize; unsigned char *smartmask = cnt->imgs.smartmask; unsigned char *smartmask_final = cnt->imgs.smartmask_final; int *smartmask_buffer = cnt->imgs.smartmask_buffer; int sensitivity=cnt->lastrate*(11-cnt->smartmask_speed); for (i=0; i<motionsize; i++) { /* Decrease smart_mask sensitivity every 5*speed seconds only */ if (smartmask[i] > 0) smartmask[i]--; /* Increase smart_mask sensitivity based on the buffered values */ diff = smartmask_buffer[i]/sensitivity; if (diff){ if (smartmask[i] <= diff+80) smartmask[i]+=diff; else smartmask[i]=80; smartmask_buffer[i]%=sensitivity; } /* Transfer raw mask to the final stage when above trigger value */ if (smartmask[i]>20) smartmask_final[i]=0; else smartmask_final[i]=255; } /* Further expansion (here:erode due to inverted logic!) of the mask */ diff = erode9(smartmask_final, cnt->imgs.width, cnt->imgs.height, cnt->imgs.common_buffer, 255); diff = erode5(smartmask_final, cnt->imgs.width, cnt->imgs.height, cnt->imgs.common_buffer, 255);}/* Increment for *smartmask_buffer in alg_diff_standard. */#define SMARTMASK_SENSITIVITY_INCR 5int alg_diff_standard (struct context *cnt, unsigned char *new){ struct images *imgs=&cnt->imgs; int i, diffs=0; int noise=cnt->noise; int smartmask_speed=cnt->smartmask_speed; unsigned char *ref=imgs->ref; unsigned char *out=imgs->out; unsigned char *mask=imgs->mask; unsigned char *smartmask_final=imgs->smartmask_final; int *smartmask_buffer=imgs->smartmask_buffer;#ifdef HAVE_MMX mmx_t mmtemp; /* used for transferring to/from memory */ int unload; /* counter for unloading diff counts */#endif i=imgs->motionsize; memset(out+i, 128, i/2); /* motion pictures are now b/w i.o. green */ /* Keeping this memset in the MMX case when zeroes are necessarily * written anyway seems to be beneficial in terms of speed. Perhaps a * cache thing? */ memset(out, 0, i);#ifdef HAVE_MMX /* NOTE: The Pentium has two instruction pipes: U and V. I have grouped MMX * instructions in pairs according to how I think they will be scheduled in * the U and V pipes. Due to pairing constraints, the V pipe will sometimes * be empty (for example, memory access always goes into the U pipe). * * The following MMX registers are kept throughout the loop: * mm5 - 8 separate diff counters (unloaded periodically) * mm6 - mask: 00ff 00ff 00ff 00ff * mm7 - noise level as 8 packed bytes * * -- Per Jonsson */ /* To avoid a div, we work with differences multiplied by 255 in the * default case and *mask otherwise. Thus, the limit to compare with is * 255*(noise+1)-1). */ mmtemp.uw[0] = mmtemp.uw[1] = mmtemp.uw[2] = mmtemp.uw[3] = (unsigned short)(noise * 255 + 254);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -