diff -Nu motion-3.1.12/alg.c ./alg.c
--- motion-3.1.12/alg.c	2004-04-12 03:49:22.000000000 +0100
+++ ./alg.c	2004-04-14 09:04:17.000000000 +0100
@@ -11,6 +11,7 @@
 #include "conf.h"
 #include "alg.h"
 #include "event.h"
+#define MAX(x, y) (abs(x) > abs(y) ? (x) : (y))
 
 /* locate the center of the movement. */
 struct coord alg_locate_center (struct images *imgs, int width, int height)
@@ -254,6 +255,186 @@
 	printf("New threshold: %d\n", cnt->threshold);
 }
 
+/* Dilates a 3x3 box */
+static int dilate9(char *img, int width, int height, void *buffer)
+{
+	int y, i, sum = 0;
+	char *Row1,*Row2,*Row3;
+	Row1 = buffer;
+	Row2 = Row1 + width;
+	Row3 = Row1 + 2*width;
+	memset(Row2, 0, 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, 0, width);
+		else
+			memcpy(Row3, img+(y+1)*width, width);
+
+		for (i = width-2; i >= 1; i--) {
+		  int blob;
+		  blob = MAX(Row1[i-1], Row1[i]);
+		  blob = MAX(blob, Row1[i+1]);
+		  blob = MAX(blob, Row2[i-1]);
+		  blob = MAX(blob, Row2[i]);
+		  blob = MAX(blob, Row2[i+1]);
+		  blob = MAX(blob, Row3[i-1]);
+		  blob = MAX(blob, Row3[i]);
+		  blob = MAX(blob, Row3[i+1]);
+		  if (blob != 0) {
+		    img[y*width+i] = blob;
+		    sum++;
+		  }
+		}
+		img[y*width] = img[y*width+width-1] = 0;
+	}
+	return sum;
+}
+
+
+/* Dilates a + shape */
+static int dilate5(char *img, int width, int height, void *buffer)
+{
+	int y, i, sum = 0;
+	char *Row1,*Row2,*Row3;
+	Row1 = buffer;
+	Row2 = Row1 + width;
+	Row3 = Row1 + 2*width;
+	memset(Row2, 0, 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, 0, width);
+		else
+			memcpy(Row3, img+(y+1)*width, width);
+
+		for (i = width-2; i >= 1; i--) {
+		  int blob;
+		  blob = MAX(Row1[i], Row2[i-1]);
+		  blob = MAX(blob, Row2[i]);
+		  blob = MAX(blob, Row2[i+1]);
+		  blob = MAX(blob, Row3[i]);
+		  if (blob != 0) {
+		    img[y*width+i] = blob;
+		    sum++;
+		  }
+		}
+		img[y*width] = img[y*width+width-1] = 0;
+	}
+	return sum;
+}
+
+
+/* Erodes a 3x3 box */
+static int erode9(char *img, int width, int height, void *buffer)
+{
+	int y, i, sum = 0;
+	char *Row1,*Row2,*Row3;
+	Row1 = buffer;
+	Row2 = Row1 + width;
+	Row3 = Row1 + 2*width;
+	memset(Row2, 0, 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, 0, 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] = 0;
+	}
+	return sum;
+}
+
+/* Erodes in a + shape */
+static int erode5(char *img, int width, int height, void *buffer)
+{
+	int y, i, sum = 0;
+	char *Row1,*Row2,*Row3;
+	Row1 = buffer;
+	Row2 = Row1 + width;
+	Row3 = Row1 + 2*width;
+	memset(Row2, 0, 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, 0, 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] = 0;
+	}
+	return sum;
+}
+
+
+/* 
+ * Despeckling routine to remove noisy detections.
+ */
+int alg_despeckle(struct context *cnt)
+{
+	int diffs = 0;
+	char *out = cnt->imgs.out;
+	int width = cnt->imgs.width;
+	int height= cnt->imgs.height;
+	int i, len = strlen(cnt->conf.despeckle);
+	void *buffer = malloc(3*width);
+
+        if (!buffer) return 0;
+
+	for (i = 0; i < len; i++) {
+		switch (cnt->conf.despeckle[i]) {
+		case 'E':
+			diffs = erode9(out, width, height, buffer);
+			break;
+		case 'e':
+			diffs = erode5(out, width, height, buffer);
+			break;
+		case 'D':
+			diffs = dilate9(out, width, height, buffer);
+			break;
+		case 'd':
+			diffs = dilate5(out, width, height, buffer);
+			break;
+		}
+	}
+        free(buffer);
+	return diffs;
+}
+
+
 /*	The heart of the motion detector
  *	Basicly: ref-new and count the pixels that are over a noise threshold
  */
diff -Nu motion-3.1.12/alg.h ./alg.h
--- motion-3.1.12/alg.h	2004-04-09 15:54:52.000000000 +0100
+++ ./alg.h	2004-04-13 20:26:37.000000000 +0100
@@ -56,5 +56,6 @@
 void alg_predict_result (struct context *, char *);
 void alg_noise_tune (struct context *, char *new);
 void alg_threshold_tune (struct context *, int, int);
+int alg_despeckle (struct context *);
 
 #endif /* _INCLUDE_ALG_H */
diff -Nu motion-3.1.12/conf.c ./conf.c
--- motion-3.1.12/conf.c	2004-04-11 15:21:16.000000000 +0100
+++ ./conf.c	2004-04-15 12:53:39.000000000 +0100
@@ -109,6 +109,7 @@
 	drawtext_changes: 0,
 	drawtext_shots: 0,
 	drawtext_user:  NULL,
+	despeckle:		NULL,
 	debug_parameter: 0
 };
 
@@ -256,6 +257,13 @@
 	print_bool
 	},
 	{
+	"despeckle",
+	"Despeckle motion image using (e)rode or (d)ilate",
+	CONF_OFFSET(despeckle),
+	copy_string,
+	print_string
+	},
+	{
 	"gap",
 	"Minimum gap between two events (seconds)",
 	CONF_OFFSET(gap),
diff -Nu motion-3.1.12/conf.h ./conf.h
--- motion-3.1.12/conf.h	2004-04-09 15:02:40.000000000 +0100
+++ ./conf.h	2004-04-13 20:26:37.000000000 +0100
@@ -95,6 +95,7 @@
 	int drawtext_changes;
 	int drawtext_shots;
 	char *drawtext_user;
+	char *despeckle;
 	int debug_parameter;
 	int argc;
 	char **argv;
Common subdirectories: motion-3.1.12/motion-3.1.12 and ./motion-3.1.12
diff -Nu motion-3.1.12/motion.c ./motion.c
--- motion-3.1.12/motion.c	2004-04-11 15:22:08.000000000 +0100
+++ ./motion.c	2004-04-13 20:35:19.000000000 +0100
@@ -571,6 +571,15 @@
 				diffs=alg_diff_standard(cnt, newimg);
 			else
 				diffs=alg_diff(cnt, newimg);
+ 
+			if (cnt->conf.despeckle) {
+				int olddiffs = diffs;
+				diffs=alg_despeckle(cnt);
+				if (cnt->conf.always_diff)
+					printf("Despeckle %d (%s) from %d to %d\n",
+						cnt->threadnr, cnt->conf.despeckle,
+						olddiffs, diffs);
+			}
 		} else
 			diffs=0;
 		if (cnt->conf.autobright)
diff -Nu motion-3.1.12/motion.conf ./motion.conf
--- motion-3.1.12/motion.conf	2004-04-12 04:55:28.000000000 +0100
+++ ./motion.conf	2004-04-13 20:26:37.000000000 +0100
@@ -45,6 +45,9 @@
 #Automaticly tune the noise threshold
 noise_tune off
 
+#Despeckle motion image using (e)rode or (d)ilate
+# despeckle EedD
+
 #Minimum gap between two events (seconds)
 gap 60
 
