Home / Alt manpages / pgmmedian(1)

  • pgmmedian(1)
  • User command
  • linux

Remove Speckle Noise from PGM Images with pgmmedian

You will apply a median filter to a PGM image and write a new, verified PGM file. The filter replaces a pixel with the median of values in a rectangular neighbourhood, which can remove isolated bright or dark speckles while retaining more edge detail than a simple blur. Allow about ten minutes for a first run. You need the Netpbm package, a readable PGM file and enough disk space for another copy of the image.

This guide describes Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1. The command's manual page is dated 20 January 2022. Check your local version if you are scripting across distributions.

1. Check the command and preserve the source

Start with an unprivileged shell. No elevated privileges are needed for an image in your own working directory, and pgmmedian does not need to modify the input.

$ command -v pgmmedian
/usr/bin/pgmmedian
$ pgmmedian --version
pgmmedian: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
...

The version command also prints build details and the instruction to use the manual page. If command -v finds nothing, install Netpbm through your normal package-management process. Do not use sudo just to run the filter.

Checkpoint

Identify the input with a path such as /path/to/input.pgm. Keep that file untouched until the filtered image has been inspected.

2. Run the default 3 by 3 filter

With no mask dimensions specified, pgmmedian uses a width of 3 and a height of 3. Redirect its standard output to a different file:

$ pgmmedian /path/to/input.pgm > /path/to/filtered.pgm
$ printf 'exit status: %s\n' "$?"
exit status: 0

The output is a PGM image on standard output, not a status report. In Netpbm 11.5.2, a successful result is written as a raw, binary PGM with the P5 magic number. It can look empty or contain unreadable characters if you print it in a terminal. Use an image-aware inspection command instead:

$ file /path/to/filtered.pgm
/path/to/filtered.pgm: Netpbm image data, size = 5 x 5, rawbits, greymap
$ head -c 2 /path/to/filtered.pgm
P5

The exact file wording varies. Confirm that the output exists, is non-empty and has the expected dimensions. The source file remains unchanged.

3. Choose the mask size deliberately

A larger mask considers more neighbouring pixels and can remove broader noise, but it also changes more of the image. Set the width and height explicitly when the default is not appropriate:

$ pgmmedian -width 5 -height 5 /path/to/input.pgm > /path/to/filtered-5x5.pgm
$ file /path/to/filtered-5x5.pgm
/path/to/filtered-5x5.pgm: Netpbm image data, size = 5 x 5, rawbits, greymap

The dimensions describe the median mask, not a resize operation. Each value must not exceed the corresponding input image dimension. The manual does not describe an automatic choice based on the file name, so do not assume that a small image has a small optimal mask.

At the image edges, where the complete mask would extend outside the image, the program copies the input pixels. This means the outer part of a result can remain unchanged even when the centre is filtered. Inspect the whole image rather than judging the first or last rows alone.

4. Select the median algorithm when needed

By default, the program chooses between histogram sorting and a select-kth-value method using the image maxval, mask area and a cutoff. The default cutoff is 250. For a reproducible processing pipeline, choose the method directly:

$ pgmmedian -width 3 -height 3 -type histogram_sort \
    /path/to/input.pgm > /path/to/filtered-histogram.pgm
$ pgmmedian -width 3 -height 3 -type select \
    /path/to/input.pgm > /path/to/filtered-select.pgm

The accepted values are exactly histogram_sort and select. The -cutoff option has no effect when -type is supplied. If you leave the method unset, the default selection is normally the useful choice; specify -cutoff only when you have measured a reason to change the trade-off for your images.

5. Avoid losing an existing result

Shell redirection with > truncates its destination before pgmmedian starts. Write to a temporary name, verify it, then replace the old result only if that is what you intend:

$ pgmmedian /path/to/input.pgm > /path/to/filtered.pgm.new
$ test -s /path/to/filtered.pgm.new && file /path/to/filtered.pgm.new
/path/to/filtered.pgm.new: Netpbm image data, size = 5 x 5, rawbits, greymap
$ mv /path/to/filtered.pgm.new /path/to/filtered.pgm

Warning

The final mv replaces an existing destination. Omit it if the old file is still your recovery copy. If filtering fails, inspect the command's diagnostic, keep the source, and remove the incomplete .new file only after checking its path. There is no need to alter the original PGM.

6. Diagnose the common failures

An input error usually means the path, permissions or PGM data is wrong. Check read access without changing anything:

$ ls -l /path/to/input.pgm
$ test -r /path/to/input.pgm && echo readable
readable

If the command writes binary-looking output to your terminal, that is a redirection mistake, not necessarily a filter failure. Interrupt the display if needed and rerun with > pointing to a new file. If the result has unexpected dimensions, check the source with file and review any explicit mask values. If the image looks unchanged around its boundary, remember the documented edge-copy behaviour.

Do not treat exit status 0 as proof that the image looks right. Verify the dimensions and magic number, then inspect the result with an image viewer or a later Netpbm conversion. Keep the original until that visual check is complete.

Done means

  • pgmmedian is installed and its local version is known.
  • The source PGM remains untouched.
  • The filtered output is a non-empty PGM with the expected dimensions.
  • The mask size is suitable for the image, rather than being mistaken for a resize setting.
  • Any algorithm choice is explicit and uses an accepted -type value.
  • An existing output was not overwritten until the replacement had been checked.