⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alg.c

📁 motion motion
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* Reset mm5 to zero, set the mm6 mask, and store the multiplied noise	 * level as four words in mm7.	 */	movq_m2r(mmtemp, mm7);             /* U */	pcmpeqb_r2r(mm6, mm6);             /* V */		pxor_r2r(mm5, mm5);                /* U */	psrlw_i2r(8, mm6);                 /* V */	/* We must unload mm5 every 255th round, because the diffs accumulate	 * in each packed byte, which can hold at most 255 diffs before it	 * gets saturated.	 */	unload=255;		for (; i>7; i-=8) {		/* Calculate abs(*ref-*new) for 8 pixels in parallel. */		movq_m2r(*ref, mm0);           /* U: mm0 = r7 r6 r5 r4 r3 r2 r1 r0 */		pxor_r2r(mm4, mm4);            /* V: mm4 = 0 */		movq_m2r(*new, mm1);           /* U: mm1 = n7 n6 n5 n4 n3 n2 n1 n0 */		movq_r2r(mm0, mm2);            /* V: mm2 = r7 r6 r5 r4 r3 r2 r1 r0 */		/* These subtractions are saturated, i.e. won't go below 0. */		psubusb_r2r(mm1, mm0);         /* U: mm0 = (r7-n7) ... (r0-n0) */		psubusb_r2r(mm2, mm1);         /* V: mm1 = (n7-r7) ... (n0-r0) */				/* Each byte dX in mm0 is abs(nX-rX). */		por_r2r(mm1, mm0);             /* U: mm0 = d7 d6 d5 d4 d3 d2 d1 d0 */		/* Expand the absolute differences to words in mm0 and mm1. */		movq_r2r(mm0, mm1);            /* U: mm1 = d7 d6 d5 d4 d3 d2 d1 d0 */		punpcklbw_r2r(mm4, mm0);       /* V: mm0 =    d3    d2    d1    d0 */				punpckhbw_r2r(mm4, mm1);       /* U: mm1 =    d7    d6    d5    d4 */		if (mask) {			/* Load and expand 8 mask bytes to words in mm2 and mm3. Then			 * multiply by mm0 and mm1, respectively.			 */			movq_m2r(*mask, mm2);      /* U: mm2 = m7 m6 m5 m4 m3 m2 m1 m0 */			movq_r2r(mm2, mm3);        /* U: mm3 = m7 m6 m5 m4 m3 m2 m1 m0 */			punpcklbw_r2r(mm4, mm2);   /* v: mm2 =    m3    m2    m1    m0 */						punpckhbw_r2r(mm4, mm3);   /* U: mm3 =    m7    m6    m5    m4 */			pmullw_r2r(mm2, mm0);      /* V: mm0 = (d3*m3) ... (d0*m0) */						pmullw_r2r(mm3, mm1);      /* U: mm1 = (d7*m7) ... (d4*m4) */			mask+=8;		}		else {			/* Not using mask - multiply the absolute differences by 255. We			 * do this by left-shifting 8 places and then subtracting dX.			 */			movq_r2r(mm0, mm2);        /* U: mm2 =    d3    d2    d1    d0 */			psllw_i2r(8, mm0);         /* V: mm2 = (256*d3) ... (256*d0) */ 			movq_r2r(mm1, mm3);        /* U: mm3 =    d7    d6    d5    d4 */			psllw_i2r(8, mm1);         /* V: mm3 = (256*d7) ... (256*d4) */			psubusw_r2r(mm2, mm0);     /* U */			psubusw_r2r(mm3, mm1);     /* V */ 		}		/* Next, compare the multiplied absolute differences with the multiplied		 * noise level (repeated as 4 words in mm7), resulting in a "motion flag"		 * for each pixel.		 *		 * Since pcmpgtw performs signed comparisons, we have to subtract noise,		 * test for equality to 0 and then invert the result.		 *		 * Note that it is safe to generate the "motion flags" before the 		 * smartmask code, as all that can happen is that individual flags get		 * reset to 0 because of the smartmask.		 */		psubusw_r2r(mm7, mm0);         /* U: subtract by (multiplied) noise */		psubusw_r2r(mm7, mm1);         /* V */		pcmpeqw_r2r(mm4, mm0);         /* U: test for equality with 0 */		pcmpeqw_r2r(mm4, mm1);         /* V */		pand_r2r(mm6, mm0);            /* U: convert 0xffff -> 0x00ff */		pand_r2r(mm6, mm1);            /* V */		pxor_r2r(mm6, mm0);            /* U: invert the result */		pxor_r2r(mm6, mm1);            /* V */		/* Each fX is the "motion flag" = 0 for no motion, 0xff for motion. */		packuswb_r2r(mm1, mm0);        /* U: mm0 = f7 f6 f5 f4 f3 f2 f1 f0 */		if (smartmask_speed) {			/* Apply the smartmask. Basically, if *smartmask_final is 0, the			 * corresponding "motion flag" in mm0 will be reset.			 */			movq_m2r(*smartmask_final, mm3); /* U: mm3 = s7 s6 s5 s4 s3 s2 s1 s0 */			/* ...but move the "motion flags" to memory before, in order to			 * increment *smartmask_buffer properly below.			 */			movq_r2m(mm0, mmtemp);           /* U */			pcmpeqb_r2r(mm4, mm3);           /* V: mm3 = 0xff where sX==0 */			/* ANDN negates the target before anding. */			pandn_r2r(mm0, mm3);             /* U: mm3 = 0xff where dX>noise && sX>0 */			movq_r2r(mm3, mm0);              /* U */			/* Add to *smartmask_buffer. This is probably the fastest way to do it. */			if (cnt->event_nr != cnt->prev_event) {				if (mmtemp.ub[0]) smartmask_buffer[0]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[1]) smartmask_buffer[1]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[2]) smartmask_buffer[2]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[3]) smartmask_buffer[3]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[4]) smartmask_buffer[4]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[5]) smartmask_buffer[5]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[6]) smartmask_buffer[6]+=SMARTMASK_SENSITIVITY_INCR;				if (mmtemp.ub[7]) smartmask_buffer[7]+=SMARTMASK_SENSITIVITY_INCR;			}			smartmask_buffer+=8;			smartmask_final+=8;		}		movq_m2r(*new, mm2);           /* U: mm1 = n7 n6 n5 n4 n3 n2 n1 n0 */		/* Cancel out pixels in *new according to the "motion flags" in mm0.		 * Each NX is either 0 or nX as from *new.		 */		pand_r2r(mm0, mm2);            /* U: mm1 = N7 N6 N5 N4 N3 N2 N1 N0 */		psubb_r2r(mm0, mm4);           /* V: mm4 = 0x01 where dX>noise */		/* mm5 holds 8 separate counts - each one is increased according to		 * the contents of mm4 (where each byte is either 0x00 or 0x01). 		 */		movq_r2m(mm2, *out);           /* U: this will stall */		paddusb_r2r(mm4, mm5);         /* V: add counts to mm5 */				/* Every 255th turn, we need to unload mm5 into the diffs variable,		 * because otherwise the packed bytes will get saturated.		 */		if (--unload==0) {			/* Unload mm5 to memory and reset it. */			movq_r2m(mm5, mmtemp);     /* U */			pxor_r2r(mm5, mm5);        /* V: mm5 = 0 */			diffs += mmtemp.ub[0] + mmtemp.ub[1] + mmtemp.ub[2] + mmtemp.ub[3] + 				mmtemp.ub[4] + mmtemp.ub[5] + mmtemp.ub[6] + mmtemp.ub[7];			unload=255;		}		out+=8;		ref+=8;		new+=8;	}	/* Check if there are diffs left in mm5 that need to be copied to the	 * diffs variable. 	 */	if (unload<255) {		movq_r2m(mm5, mmtemp);		diffs += mmtemp.ub[0] + mmtemp.ub[1] + mmtemp.ub[2] + mmtemp.ub[3] + 			mmtemp.ub[4] + mmtemp.ub[5] + mmtemp.ub[6] + mmtemp.ub[7];	}	emms();#endif	/* Note that the non-MMX code is present even if the MMX code is present.	 * This is necessary if the resolution is not a multiple of 8, in which	 * case the non-MMX code needs to take care of the remaining pixels.	 */	for (; i>0; i--) {		register unsigned char curdiff=(int)(abs(*ref - *new)); /* using a temp variable is 12% faster */		/* apply fixed mask */		if (mask)			curdiff=((int)(curdiff * *mask++)/255);					if (smartmask_speed) {			if (curdiff > noise) {				/* increase smart_mask sensitivity every frame when motion				   is detected. (with speed=5, mask is increased by 1 every				   second. To be able to increase by 5 every second (with				   speed=10) we add 5 here. NOT related to the 5 at ratio-				   calculation. */				if (cnt->event_nr != cnt->prev_event)					(*smartmask_buffer) += SMARTMASK_SENSITIVITY_INCR;				/* apply smart_mask */				if (!*smartmask_final)					curdiff=0;			}			smartmask_final++;			smartmask_buffer++;		}		/* Pixel still in motion after all the masks? */		if (curdiff > noise) {			*out=*new;			diffs++;		}		out++;		ref++;		new++;	}	return diffs;}/*	Very fast diff function, does not apply mask overlaying.*/static char alg_diff_fast(struct context *cnt, int max_n_changes, unsigned char *new){	struct images *imgs=&cnt->imgs;	int i, diffs=0, step=imgs->motionsize/10000;	int noise=cnt->noise;	unsigned char *ref=imgs->ref;	if (!step%2)		step++;	/* we're checking only 1 of several pixels */	max_n_changes /= step;	i=imgs->motionsize;	for (; i>0; i-=step) {		register unsigned char curdiff=(int)(abs((char)(*ref-*new))); /* using a temp variable is 12% faster */		if (curdiff >  noise) {			diffs++;			if (diffs > max_n_changes)				return 1;		}		ref+=step;		new+=step;	}	return 0;}/* alg_diff uses diff_fast to quickly decide if there is anything worth * sending to diff_standard.*/int alg_diff(struct context *cnt, unsigned char *new){	int diffs=0;		if (alg_diff_fast(cnt, cnt->conf.max_changes/2, new))		diffs=alg_diff_standard(cnt, new);	return diffs;}/* Detect a sudden massive change in the picture.   It is assumed to be the light being switched on or a camera displacement.   In any way the user doesn't think it is worth capturing. */int alg_lightswitch(struct context *cnt, int diffs){	struct images *imgs=&cnt->imgs;		if (cnt->conf.lightswitch < 0)		cnt->conf.lightswitch = 0;	if (cnt->conf.lightswitch > 100)		cnt->conf.lightswitch = 100;		/* is lightswitch percent of the image changed?  */	if (diffs > (imgs->motionsize * cnt->conf.lightswitch / 100))		return 1;		return 0;}int alg_switchfilter(struct context *cnt, int diffs, unsigned char *newimg){	int linediff = diffs / cnt->imgs.height;	unsigned char *out = cnt->imgs.out;	int y, x, line;	int lines=0, vertlines=0;	for (y=0; y < cnt->imgs.height; y++) {		line=0;		for (x=0; x < cnt->imgs.width; x++) {			if (*(out++)) {				line++;			}		}		if (line > cnt->imgs.width/18) {			vertlines++;		}		if (line > linediff*2) {			lines++;		}	}	if (vertlines > cnt->imgs.height/10 && lines < vertlines/3 &&	    (vertlines > cnt->imgs.height/4 || lines - vertlines > lines/2)) {		if (cnt->conf.text_changes) {			char tmp[80];			sprintf(tmp, "%d %d", lines, vertlines);			draw_text(newimg, cnt->imgs.width-10, 20, cnt->imgs.width, tmp, cnt->conf.text_double);		}		return diffs;	}	return 0;}/**  * alg_update_reference_frame * *   Called from 'motion_loop' to calculate the reference frame *   Moving objects are excluded from the reference frame for a certain *   amount of time to improve detection. *  * Parameters: * *   cnt    - current thread's context struct *   action - UPDATE_REF_FRAME or RESET_REF_FRAME * *//* Seconds */#define ACCEPT_STATIC_OBJECT_TIME 10#define EXCLUDE_LEVEL_PERCENT 20void alg_update_reference_frame(struct context *cnt, int action) {	int accept_timer = cnt->lastrate * ACCEPT_STATIC_OBJECT_TIME;	int i, threshold_ref;	int *ref_dyn = cnt->imgs.ref_dyn;	unsigned char *image_virgin = cnt->imgs.image_virgin;	unsigned char *ref = cnt->imgs.ref;	unsigned char *smartmask = cnt->imgs.smartmask_final;	unsigned char *out = cnt->imgs.out;	if (cnt->lastrate > 5)  /* match rate limit */		accept_timer /= (cnt->lastrate / 3);	if (action == UPDATE_REF_FRAME) { /* black&white only for better performance */		threshold_ref = cnt->noise * EXCLUDE_LEVEL_PERCENT / 100;		for (i = cnt->imgs.motionsize; i > 0; i--) {			/* exclude pixels from ref frame well below noise level */			if (((int)(abs(*ref - *image_virgin)) > threshold_ref) && (*smartmask)) {				if (*ref_dyn == 0) { /* Always give new pixels a chance */					*ref_dyn = 1;				}				else if (*ref_dyn > accept_timer) { /* Include static Object after some time */					*ref_dyn = 0;					*ref = *image_virgin;				}				else if (*out)					(*ref_dyn)++; /* Motionpixel? Keep excluding from ref frame */				else {					*ref_dyn = 0; /* Nothing special - release pixel */					*ref = (*ref + *image_virgin) / 2;				}			}			else {  /* No motion: copy to ref frame */				*ref_dyn = 0; /* reset pixel */				*ref = *image_virgin;			}			ref++;			image_virgin++;			smartmask++;			ref_dyn++;			out++;		} /* end for i */	} else {   /* action == RESET_REF_FRAME - also used to initialize the frame at startup */		memcpy(cnt->imgs.ref, cnt->imgs.image_virgin, cnt->imgs.size); /* copy fresh image */		memset(cnt->imgs.ref_dyn, 0, cnt->imgs.motionsize * sizeof(cnt->imgs.ref_dyn));  /* reset static objects */	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -