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

📄 motion.c

📁 motion motion
💻 C
📖 第 1 页 / 共 5 页
字号:
					 * watchdog will start us again 					 * Set lost_connection flag on */					cnt->lost_connection = 1;					break;				}				/* First missed frame - store timestamp 				 * Don't reset time when thread restarts*/				if (cnt->connectionlosttime == 0)					cnt->connectionlosttime = cnt->currenttime;				/* Increase missing_frame_counter				 * The first MISSING_FRAMES_TIMEOUT seconds we copy previous virgin image				 * After 30 seconds we put a grey error image in the buffer				 * If we still have not yet received the initial image from a camera				 * we go straight for the grey error image.				 */				++cnt->missing_frame_counter;				if (cnt->video_dev >= 0 &&				    cnt->missing_frame_counter < (MISSING_FRAMES_TIMEOUT * cnt->conf.frame_limit)) {					memcpy(cnt->current_image->image, cnt->imgs.image_virgin, cnt->imgs.size);				} else {					const char *tmpin;					char tmpout[80];					struct tm tmptime;					cnt->lost_connection = 1;							if (cnt->video_dev >= 0)						tmpin = "CONNECTION TO CAMERA LOST\\nSINCE %Y-%m-%d %T";					else						tmpin = "UNABLE TO OPEN VIDEO DEVICE\\nSINCE %Y-%m-%d %T";					localtime_r(&cnt->connectionlosttime, &tmptime);					memset(cnt->current_image->image, 0x80, cnt->imgs.size);					mystrftime(cnt, tmpout, sizeof(tmpout), tmpin, &tmptime, NULL, 0);					draw_text(cnt->current_image->image, 10, 20 * text_size_factor, cnt->imgs.width,					          tmpout, cnt->conf.text_double);					/* Write error message only once */					if (cnt->missing_frame_counter == MISSING_FRAMES_TIMEOUT * cnt->conf.frame_limit) {						motion_log(LOG_ERR, 0, "Video signal lost - Adding grey image");						// Event for lost video signal can be called from here						event(cnt, EVENT_CAMERA_LOST, NULL, NULL,						      NULL, cnt->currenttime_tm);					}					/* If we don't get a valid frame for a long time, try to close/reopen device 					 * Only try this when a device is open */					if ( (cnt->video_dev > 0) && 					     (cnt->missing_frame_counter == (MISSING_FRAMES_TIMEOUT * 4) * cnt->conf.frame_limit) ) {						motion_log(LOG_ERR, 0, "Video signal still lost - Trying to close video device");						vid_close(cnt);					}				}			}		/***** MOTION LOOP - MOTION DETECTION SECTION *****/			/* The actual motion detection takes place in the following			 * diffs is the number of pixels detected as changed			 * Make a differences picture in image_out			 *			 * alg_diff_standard is the slower full feature motion detection algorithm			 * alg_diff first calls a fast detection algorithm which only looks at a			 *   fraction of the pixels. If this detects possible motion alg_diff_standard			 *   is called.			 */			if (cnt->threshold && !cnt->pause) {				/* if we've already detected motion and we want to see if there's				 * still motion, don't bother trying the fast one first. IF there's				 * motion, the alg_diff will trigger alg_diff_standard				 * anyway				 */				if (cnt->detecting_motion || cnt->conf.setup_mode)					cnt->current_image->diffs = alg_diff_standard(cnt, cnt->imgs.image_virgin);				else					cnt->current_image->diffs = alg_diff(cnt, cnt->imgs.image_virgin);				/* Lightswitch feature - has light intensity changed?				 * This can happen due to change of light conditions or due to a sudden change of the camera				 * sensitivity. If alg_lightswitch detects lightswitch we suspend motion detection the next				 * 5 frames to allow the camera to settle.				 * Don't check if we have lost connection, we detect "Lost signal" frame as lightswitch				 */				if (cnt->conf.lightswitch && !cnt->lost_connection) {					if (alg_lightswitch(cnt, cnt->current_image->diffs)) {						if (cnt->conf.setup_mode)							motion_log(-1, 0, "Lightswitch detected");						if (cnt->moved < 5)							cnt->moved = 5;						cnt->current_image->diffs = 0;						alg_update_reference_frame(cnt, RESET_REF_FRAME);					}				}				/* Switchfilter feature tries to detect a change in the video signal				 * from one camera to the next. This is normally used in the Round				 * Robin feature. The algorithm is not very safe.				 * The algorithm takes a little time so we only call it when needed				 * ie. when feature is enabled and diffs>threshold.				 * We do not suspend motion detection like we did for lightswitch				 * because with Round Robin this is controlled by roundrobin_skip.				 */				if (cnt->conf.switchfilter && cnt->current_image->diffs > cnt->threshold) {					cnt->current_image->diffs = alg_switchfilter(cnt, cnt->current_image->diffs, cnt->current_image->image);					if (cnt->current_image->diffs <= cnt->threshold) {						cnt->current_image->diffs = 0;						if (cnt->conf.setup_mode)							motion_log(-1, 0, "Switchfilter detected");					}				}				/* Despeckle feature				 * First we run (as given by the despeckle option iterations				 * of erode and dilate algorithms.				 * Finally we run the labelling feature.				 * All this is done in the alg_despeckle code.				 */				cnt->current_image->total_labels = 0;				cnt->imgs.largest_label = 0;				olddiffs = 0;				if (cnt->conf.despeckle && cnt->current_image->diffs > 0) {					olddiffs = cnt->current_image->diffs;					cnt->current_image->diffs = alg_despeckle(cnt, olddiffs);				}else if (cnt->imgs.labelsize_max)					cnt->imgs.labelsize_max = 0; /* Disable labeling if enabled */			} else if (!cnt->conf.setup_mode)				cnt->current_image->diffs = 0;			/* Manipulate smart_mask sensitivity (only every smartmask_ratio seconds) */			if (cnt->smartmask_speed && (cnt->event_nr != cnt->prev_event)) {				if (!--smartmask_count){					alg_tune_smartmask(cnt);					smartmask_count = smartmask_ratio;				}			}			/* cnt->moved is set by the tracking code when camera has been asked to move.			 * When camera is moving we do not want motion to detect motion or we will			 * get our camera chasing itself like crazy and we will get motion detected			 * which is not really motion. So we pretend there is no motion by setting			 * cnt->diffs = 0.			 * We also pretend to have a moving camera when we start Motion and when light			 * switch has been detected to allow camera to settle.			 */			if (cnt->moved) {				cnt->moved--;				cnt->current_image->diffs = 0;			}		/***** MOTION LOOP - TUNING SECTION *****/			/* if noise tuning was selected, do it now. but only when			 * no frames have been recorded and only once per second			 */			if (cnt->conf.noise_tune && cnt->shots == 0) {				if (!cnt->detecting_motion && (cnt->current_image->diffs <= cnt->threshold))					alg_noise_tune(cnt, cnt->imgs.image_virgin);			}			/* if we are not noise tuning lets make sure that remote controlled			 * changes of noise_level are used.			 */			if (!cnt->conf.noise_tune)				cnt->noise = cnt->conf.noise;			/* threshold tuning if enabled			 * if we are not threshold tuning lets make sure that remote controlled			 * changes of threshold are used.			 */			if (cnt->conf.threshold_tune)				alg_threshold_tune(cnt, cnt->current_image->diffs, cnt->detecting_motion);			else				cnt->threshold = cnt->conf.max_changes;			/* If motion is detected (cnt->current_image->diffs > cnt->threshold) and before we add text to the pictures			   we find the center and size coordinates of the motion to be used for text overlays and later			   for adding the locate rectangle */			if (cnt->current_image->diffs > cnt->threshold)				 alg_locate_center_size(&cnt->imgs, cnt->imgs.width, cnt->imgs.height, &cnt->current_image->location);			/* Update reference frame. */			/* micro-lighswitch: e.g. neighbors cat switched on the motion sensitive *			 * frontdoor illumination. Updates are rate-limited to 3 per second at   *			 * framerates above 5fps to save CPU resources and to keep sensitivity   *			 * at a constant level.                                                  *			 */			ref_frame_limit++;			if (ref_frame_limit >= (cnt->lastrate / 3)) {				ref_frame_limit = 0;				if ((cnt->current_image->diffs > cnt->threshold) && 				    (cnt->lightswitch_framecounter < (cnt->lastrate * 2)) && /* two seconds window */				    ((abs(previous_diffs - cnt->current_image->diffs)) < (previous_diffs / 15)) &&				    ((abs(cnt->current_image->location.x - previous_location_x)) <= (cnt->imgs.width / 150)) &&				    ((abs(cnt->current_image->location.y - previous_location_y)) <= (cnt->imgs.height / 150))) {					alg_update_reference_frame(cnt, RESET_REF_FRAME);					cnt->current_image->diffs = 0;					cnt->lightswitch_framecounter = 0;					if (cnt->conf.setup_mode)						motion_log(-1, 0, "micro-lightswitch!");				} else {	    					alg_update_reference_frame(cnt, UPDATE_REF_FRAME);				}				previous_diffs = cnt->current_image->diffs;				previous_location_x = cnt->current_image->location.x;				previous_location_y = cnt->current_image->location.y;			}		/***** MOTION LOOP - TEXT AND GRAPHICS OVERLAY SECTION *****/			/* Some overlays on top of the motion image			 * Note that these now modifies the cnt->imgs.out so this buffer			 * can no longer be used for motion detection features until next			 * picture frame is captured.			 */			/* Smartmask overlay */			if (cnt->smartmask_speed && (cnt->conf.motion_img || cnt->conf.ffmpeg_cap_motion || cnt->conf.setup_mode) )				overlay_smartmask(cnt, cnt->imgs.out);			/* Largest labels overlay */			if (cnt->imgs.largest_label && (cnt->conf.motion_img || cnt->conf.ffmpeg_cap_motion || cnt->conf.setup_mode) )				overlay_largest_label(cnt, cnt->imgs.out);			/* Fixed mask overlay */			if (cnt->imgs.mask && (cnt->conf.motion_img || cnt->conf.ffmpeg_cap_motion || cnt->conf.setup_mode) )				overlay_fixed_mask(cnt, cnt->imgs.out);			/* Initialize the double sized characters if needed. */			if(cnt->conf.text_double && text_size_factor == 1)				text_size_factor = 2;			/* If text_double is set to off, then reset the scaling text_size_factor. */			else if(!cnt->conf.text_double && text_size_factor == 2) {				text_size_factor = 1;			}			/* Add changed pixels in upper right corner of the pictures */			if (cnt->conf.text_changes) {				char tmp[15];				if (!cnt->pause)					sprintf(tmp, "%d", cnt->current_image->diffs);				else					sprintf(tmp, "-");				draw_text(cnt->current_image->image, cnt->imgs.width - 10, 10, cnt->imgs.width, tmp, cnt->conf.text_double);			}			/* Add changed pixels to motion-images (for webcam) in setup_mode			   and always overlay smartmask (not only when motion is detected) */			if (cnt->conf.setup_mode) {				char tmp[PATH_MAX];				sprintf(tmp, "D:%5d L:%3d N:%3d", cnt->current_image->diffs, cnt->current_image->total_labels, cnt->noise);				draw_text(cnt->imgs.out, cnt->imgs.width - 10, cnt->imgs.height - 30 * text_size_factor,				          cnt->imgs.width, tmp, cnt->conf.text_double);				sprintf(tmp, "THREAD %d SETUP", cnt->threadnr);				draw_text(cnt->imgs.out, cnt->imgs.width - 10, cnt->imgs.height - 10 * text_size_factor,				          cnt->imgs.width, tmp, cnt->conf.text_double);			}			/* Add text in lower left corner of the pictures */			if (cnt->conf.text_left) {				char tmp[PATH_MAX];				mystrftime(cnt, tmp, sizeof(tmp), cnt->conf.text_left, &cnt->current_image->timestamp_tm, NULL, 0);				draw_text(cnt->current_image->image, 10, cnt->imgs.height - 10 * text_size_factor, cnt->imgs.width,				          tmp, cnt->conf.text_double);			}			/* Add text in lower right corner of the pictures */			if (cnt->conf.text_right) {				char tmp[PATH_MAX];				mystrftime(cnt, tmp, sizeof(tmp), cnt->conf.text_right, &cnt->current_image->timestamp_tm, NULL, 0);				draw_text(cnt->current_image->image, cnt->imgs.width - 10, cnt->imgs.height - 10 * text_size_factor,				          cnt->imgs.width, tmp, cnt->conf.text_double);			}		/***** MOTION LOOP - ACTIONS AND EVENT CONTROL SECTION *****/			if (cnt->current_image->diffs > cnt->threshold) {				/* flag this image, it have motion */				cnt->current_image->flags |= IMAGE_MOTION;				cnt->lightswitch_framecounter++; /* micro lightswitch */			} else cnt->lightswitch_framecounter = 0;			/* If motion has been detected we take action and start saving			 * pictures and movies etc by calling motion_detected().			 * Is output_all enabled we always call motion_detected()			 * If post_capture is enabled we also take care of this in the this			 * code section.			 */			if ( cnt->conf.output_all && (cnt->startup_frames == 0) ) {				cnt->detecting_motion = 1;				/* Setup the postcap counter */				cnt->postcap = cnt->conf.post_capture;				cnt->current_image->flags |= (IMAGE_TRIGGER | IMAGE_SAVE);				motion_detected(cnt, cnt->video_dev, cnt->current_image);			} else if ( (cnt->current_image->flags & IMAGE_MOTION) && (cnt->startup_frames == 0) ) {				/* Did we detect motion (like the cat just walked in :) )?				 * If so, ensure the motion is sustained if minimum_motion_frames				 */				/* Count how many frames with motion there is in the last minimum_motion_frames in precap buffer */				int frame_count = 0;				int pos = cnt->imgs.image_ring_in;				for(i = 0; i < cnt->conf.minimum_motion_frames; i++)				{					if(cnt->imgs.image_ring[pos].flags & IMAGE_MOTION)						frame_count++;					if (pos == 0) {						pos = cnt->imgs.image_ring_size-1;					} else {						pos--;					}				}				if (frame_count >= cnt->conf.minimum_motion_frames) {					cnt->current_image->flags |= (IMAGE_TRIGGER | IMAGE_SAVE);					cnt->detecting_motion = 1;					/* Setup the postcap counter */					cnt->postcap = cnt->conf.post_capture;					/* Mark all images in image_ring to be saved */					for(i = 0; i < cnt->imgs.image_ring_size; i++) {						cnt->imgs.image_ring[i].flags |= IMAGE_SAVE;					}				}				else if (cnt->postcap) { /* we have motion in this frame, but not enought frames for trigger. Check postcap */					cnt->current_image->flags |= (IMAGE_POSTCAP | IMAGE_SAVE);					cnt->postcap--;				} else {					cnt->current_image->flags |= IMAGE_PRECAP;				}				/* Always call motion_detected when we have a motion image */				motion_detected(cnt, cnt->video_dev, cnt->current_image);			} else if (cnt->postcap) {				/* No motion, doing postcap */				cnt->current_image->flags |= (IMAGE_POSTCAP | IMAGE_SAVE);				cnt->postcap--;			} else {				/* Done with postcap, so just have the image in the precap buffer */				cnt->current_image->flags |= IMAGE_PRECAP;				cnt->detecting_motion = 0;			}			/* Update last frame saved time, so we can end event after gap time */			if (cnt->current_image->flags & IMAGE_SAVE) {				cnt->lasttime = cnt->current_image->timestamp;			}			/* Simple hack to recognize motion in a specific area */			/* Do we need a new coversion specifier as well?? */			if ((cnt->conf.area_detect) && (cnt->event_nr != area_once) && (cnt->current_image->flags & IMAGE_TRIGGER)) {				j = strlen(cnt->conf.area_detect);				for (i = 0; i < j; i++) {					z = cnt->conf.area_detect[i] - 49; /* 1 becomes 0 */					if ((z >= 0) && (z < 9)) {						if (cnt->current_image->location.x > area_minx[z] &&						    cnt->current_image->location.x < area_maxx[z] &&						    cnt->current_image->location.y > area_miny[z] &&						    cnt->current_image->location.y < area_maxy[z]) {							event(cnt, EVENT_AREA_DETECTED, NULL, NULL,							      NULL, cnt->currenttime_tm);							area_once = cnt->event_nr; /* Fire script only once per event */							if (cnt->conf.setup_mode)								motion_log(-1, 0, "Motion in area %d detected.\n", z+1);							break;						}					}				}			}						/* Is the mpeg movie to long? Then make movies			 * First test for max mpegtime			 */			if (cnt->conf.maxmpegtime && cnt->event_nr == cnt->prev_event)				if (cnt->currenttime - cnt->eventtime >= cnt->conf.maxmpegtime)

⌨️ 快捷键说明

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