/* makemask v1.0 Use with the program "Motion". Take in multiple image files and output a mask.png mask file to block pixels found to be noisy (edges, wind in trees, etc). Like Motion, only looks at intensity, not color. You might also consider smartmask and despeckle options. Run with: makemask file1.jpg file2.jpg ... where file1, file2, etc are sample images from your camera. Preferably from a windy day and during a few gusts. Compile with: gcc makemask.c -o makemask -lgd -lpng -lz -ljpeg -lfreetype -lm Note: this program outputs a .png file. You need to convert this to a .pgm file to use the mask with motion. GIMP can do this easily. Note: this program can read in .jpg or .png, depending on how it is compiled. Jon Zeeff Public Domain 2008 */ #include "gd.h" /* you need this library */ #include #define THRESH 15 /* try 15. change > than this means noisy pixel */ /* #define PNG /* define this if input files are .png, otherwise jpg */ int min[1000][1000]; /* I know, shouldn't be statically allocated */ int max[1000][1000]; int main (int argc, char *argv[]) { gdImagePtr im; /* Declare the image */ FILE *pngout; /* Declare output files */ /* Declare color indexes */ int black; int white; int height; int width; FILE *in; int row, col; int c; int luma; int masked; /* number of pixels we masked off */ int not_masked; /* number of pixels we didn't mask off */ if (argc < 3) { fprintf (stderr, "need more arguments\n"); return (1); } in = fopen (argv[1], "rb"); if (!in) { fprintf (stderr, "can not open %s\n", argv[1]); return (1); } #ifdef PNG im = gdImageCreateFromPng (in); #else im = gdImageCreateFromJpeg (in); #endif fclose (in); /* find size */ width = gdImageSX (im); height = gdImageSY (im); printf ("image size = %dx%d\n", width, height); /* initialize from first image */ for (row = 0; row < height; ++row) for (col = 0; col < width; ++col) { c = gdImageGetPixel (im, col, row); luma = gdImageRed (im, c) * .3 + gdImageGreen (im, c) * .59 + gdImageBlue (im, c) * .11; min[col][row] = luma; max[col][row] = luma; } printf ("processed first image\n"); /* for each additional image supplied */ for (argv += 2; *argv > 0; ++argv) { printf ("looking at %s\n", *argv); in = fopen (*argv, "rb"); if (!in) { fprintf (stderr, "can not open %s\n", *argv); return (1); } #ifdef PNG im = gdImageCreateFromPng (in); #else im = gdImageCreateFromJpeg (in); #endif fclose (in); /* go through image and update min/max */ for (row = 0; row < height; ++row) { for (col = 0; col < width; ++col) { c = gdImageGetPixel (im, col, row); luma = gdImageRed (im, c) * .3 + gdImageGreen (im, c) * .59 + gdImageBlue (im, c) * .11; if (luma < min[col][row]) min[col][row] = luma; if (luma > max[col][row]) max[col][row] = luma; } } /* for */ } /* for */ /* create the output mask image - noisy pixels are set to black, others are white */ black = gdImageColorAllocate (im, 0, 0, 0); white = gdImageColorAllocate (im, 255, 255, 255); for (masked = not_masked = row = 0; row < height; ++row) for (col = 0; col < width; ++col) { if (max[col][row] - min[col][row] > THRESH) { ++masked; gdImageSetPixel (im, col, row, black); } else { ++not_masked; gdImageSetPixel (im, col, row, white); } } printf ("mask.png created (%dx%d) - %f %% pixels are masked\n", width, height, (masked * 100.0) / (masked + not_masked)); /* Output the image to the disk file in PNG format. */ pngout = fopen ("mask.png", "wb"); gdImagePng (im, pngout); return (0); }