Measure PGM Shapes Across Thresholds with pgmminkowski
pgmminkowski turns one grayscale PGM into a table of shape measurements at every intensity threshold the image contains. Give it about fifteen minutes: it only reads the image and writes a report to standard output, so there is nothing to undo and nothing that needs elevated privileges.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes Netpbm 11.05.02-1.1build1, the version installed here. Its manual page is dated 29 October 2002 and the program has no pgmminkowski-specific options, so check your output if your installed package differs substantially.
1. Check the installed command
Confirm which binary your shell will actually run before you trust its output:
$ command -v pgmminkowski
/usr/bin/pgmminkowski
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ pgmminkowski --help
pgmminkowski: Use 'man pgmminkowski' for help.
That help text is deliberately terse: the whole synopsis is pgmminkowski pgmfile, and there are no switches unique to this program. Netpbm's shared options may still be accepted, but nothing here depends on them.
Checkpoint
Only continue once command -v finds the executable and the package is installed. A missing command means installing Netpbm through your normal distribution process, which sits outside this read-only workflow.
2. Confirm the input is really a PGM
- Header fields. A PGM carries a width, a height, a maximum grey value and a raster of pixel data.
- Two flavours. Raw files start with
P5; plain-text files start withP2and store values as decimal text. - Black to white. Pixel values run from zero, black, up to the maximum, white, and lines starting with
#are comments.
$ sed -n '1,5p' input.pgm
P2
# example image
4 3
9
0 9 0 0
A clean-looking header does not guarantee a clean raster: a truncated file can still fail later. If another Netpbm inspection tool is already part of your workflow, use it; pgmminkowski itself will report a read error rather than trying to repair anything.
Checkpoint
Know the input path and be sure it is the image you meant to measure. Keep the original untouched, and if you need to convert or repair a copy, give that copy an explicit, different filename.
3. Run the measurement
Pass the PGM path as the only argument the command needs:
$ pgmminkowski input.pgm
#threshold tiles x-edges y-edges vertices
#--------- ----- ------- ------- --------
0.000000 12 15 16 20 1 1 1
1.000000 2 4 3 6 0.166667 0.428571 1
# check: 0 0 0 0
After the comment header, you get one row per threshold the program considers. Reading left to right: the threshold itself, then the tile, horizontal-edge, vertical-edge and vertex counts, then the normalised measurements used in the Minkowski analysis. Take the column identities from that header and the manual; do not relabel them in a downstream script on a guess.
A threshold splits pixels into black or white, and the white pixels are the foreground. As the threshold shifts, that foreground's area, boundary and Euler characteristic all shift with it, which is exactly why one grayscale image produces several rows instead of a single number.
Redirect the report when you want to keep it for plotting:
$ pgmminkowski input.pgm > measurements.dat
$ sed -n '1,4p' measurements.dat
#threshold tiles x-edges y-edges vertices
#--------- ----- ------- ------- --------
0.000000 12 15 16 20 1 1 1
That redirect is the only state-changing example in this guide: it creates or replaces measurements.dat. Pick a fresh path or back up the destination first if it already holds something useful. There is no way to reconstruct an overwritten file except restoring from a backup or rerunning the command against the original input into a new path.
4. Check success and diagnose failures
A valid image gives you exit status zero. Capture it right after the run:
$ pgmminkowski input.pgm > measurements.dat
$ printf 'exit status: %s\n' "$?"
exit status: 0
A missing file looks completely different from a successful run over a boring image:
$ pgmminkowski /path/to/missing.pgm
pgmminkowski: Unable to open file '/path/to/missing.pgm' for reading. fopen() returns errno 2 (No such file or directory)
$ printf 'exit status: %s\n' "$?"
exit status: 1
Check the path, its spelling and its read permissions first. An ordinary user can read any image that is actually accessible to that user, so do not reach for sudo just because the command failed: elevated access can mask an ownership problem instead of fixing it. If the file is readable but still malformed, inspect its header and raster, and try a known-good sample to separate an input problem from an installation one.
Checkpoint
A usable result means status 0, the expected comment header and real data rows. Keep the input, the command and the package version together with the report if the analysis needs to be reproducible later.
5. Use the data without losing its meaning
This output is built to be a gnuplot datafile. Keep every line starting with #, gnuplot treats them as comments and they document the columns. Any other parser should skip those comment lines and keep the threshold as a numeric field rather than assuming it is a percentage, and never assume the first row is the only useful one: it is one point in the image's progression through intensity levels.
For a quick sanity check, plot a measurement column against the threshold once you have read the header and a few rows. Do not compare two images by row number alone: different maximum grey values place the interesting changes at different thresholds, so compare threshold and value together.
The manual names area, total perimeter and Euler characteristic as the three Minkowski integrals, alongside the horizontal and vertical edge counts also reported here. Remember the foreground is the white pixels after thresholding, not the rectangular canvas of the PGM itself, so a large black border never counts as foreground area.
Done means
- Right binary confirmed.
pgmminkowskiresolves to the Netpbm installation you expect. - Input validated. The file is a readable PGM and you understand its header.
- Run succeeded. The command exits with status
0and produces threshold rows. - Report saved safely. Any output destination was checked or backed up before being replaced.
- Meaning preserved. Any plot or parser keeps the threshold, comments and column identities intact.