# Fast empty page detection

As part of a duplex scanning pipeline I need to detect empty pages such that they can be excluded from the OCR and the resulting PDF document.

Currently, I'm using a 'blurry' trim which works pretty well. Example with ImageMagick:

convert image-0001.png -shave 300x0 -virtual-pixel White -blur 0x15 -fuzz \
15% -trim info:


(if the resulting dimensions are below a threshold then the page is considered empty)

But this is slow.

What are faster alternative approaches for accurately detecting empty pages in scanned images?

Things that complicate the empty page detection:

• the noise - i.e. scanned dust etc.
• margins/punch-holes that may show up as black lines
• almost empty pages (e.g. just 2 words in 12 pt on an otherwise blank pages) must not be detected as empty
• pages without any text but with images must not be detected as empty

What are faster alternative approaches for accurately detecting empty pages in scanned images?

OK, convert is universally known to be rather hungry for RAM and potentially rather slow (due to its internal image model handling). My guess is that if you don't use it but, for example, simply do your whole detection within a scripting language with an image processing library (e.g. Python3 with PIL), you'll be fast enough for this to be a viable approach, as you, as a nice addition, won't be constantly saving and loading images from disk, but keep them in RAM until you're done, which is orders of magnitude faster.

I like the blurring approach; it has the potential of removing noise sufficiently well. But:

Why don't you simply

1. threshold to convert to black&white (might want to do that adaptively based on the average brightness)
2. erode by a few pixels, just enough to kill dust and noise,
3. count the remaining black pixels, and
4. declare clear page based on a threshold?

Since punch holes and margins will be larger in black area than two words, I'd previously try to just exclude them with a simple static mask, if your raw material permits (i.e. if you're scanning shelves of filed documents, then all will have the punch holes in the same place), or by trying to "smartly" detect them (for example, look for circles in potential punch-hole places, diagonal lines in potential staple places and so on).

• I didn't know Pillow (PIL) - thanks for the tip! Its API is quite versatile/good docs. I've tried your approach and it works well. The example ImageMagick convert commands needs ~ 45 s total user time (in the default OpenMP enabled mode where it hogs 4 of 4 available cores) and ~ 24 s user time when restricted to one core. The simple approach implemented with PIL just needs ~ 2.6 s user time (all on a Skylake i7). For the binarization step, I use PIL.ImageStat.Stat().mean and decrement it by 50 to deal with shine-through backsides. I crop the margin a little to ignore any punchholes. Apr 29 '18 at 9:12
• Happy I've been of help :) 2.6s or 24s is still a lot of time! If you really need things to be faster: assuming images are of the same dimension to start with, doing things on GPUs might be a very efficient way. I haven't done much graphics on GPUs in the last decade, but I'd guess that you can do interesting things either directly in OpenCL or with tools like tensorflow Apr 29 '18 at 9:16
• Also, I love the fact that it's faster on a single core. Apr 29 '18 at 9:16