Perspec
App and workflow to perspectively correct images. For example whiteboards, document scans, or facades.
| Original | In Progress | Corrected |
|---|---|---|
![]() |
![]() |
![]() |
Installation
Prebuilt
MacOS
Install it via my Homebrew tap:
brew cask install ad-si/tap/perspecYou can also get this (and previous) versions from the releases page.
The app bundle is created from the shell command with Platypus.
From Source
Uses ImageMagick's convert command under the hood.
Check out its
installation instructions
to make it available on your system.
Build it from source with Haskell's stack.
git clone https://github.com/ad-si/Perspec
cd Perspec
stack installThis makes the perspec command available on your path,
which you can then use to open the app with perspec image.jpg
Manual
Interpolation of Missing Parts
Perspect automatically interpolates missing parts by using the closest pixel. (https://www.imagemagick.org/Usage/misc/#edge)
Workflow
- Take images
- Use camera app wich lets you lock rotation (e.g. OpenCamera). Otherwise check out the guide below to fix rotation.
- Use
number-files-{even,odd,reversed}commands to fix order and names - Verify that
- All pages were captured and have the correct filename
- Images are sharp enough
- Images have a high contrast
- Images have correct orientation
- Convert images to lossless format, apply rotations
and convert them to grayscale.
Attention: Exclude the covers!
mogrify -verbose -format png -auto-orient -colorspace gray ./*.jpg - Use Perspec to crop images
- Normalize dynamic range:
mogrify -verbose -normalize ./*.png - Convert to black and white:
#! /usr/bin/env bash find . -iname "*.png" | \ while read -r file do convert \ -verbose \ "$file" \ \( +clone -blur 0x60 -brightness-contrast 40 \) \ -compose minus \ -composite \ -negate \ -auto-threshold otsu \ "$(basename "$file" ".png")"-fixed.png done
In order to rotate all photos to portrait mode you can use either
mogrify -verbose -auto-orient -rotate "90>" ./*.jpgor
mogrify -verbose -auto-orient -rotate "-90>" ./*.jpgUnderlying Imagemagick Commands
Once the corners are marked, the correction is equivalent to:
convert \
images/example.jpg \
-distort Perspective \
'8,35 0,0 27,73 0,66 90,72 63,66 67,10 63,0' \
-crop 63x66+0+0 \
images/example-fixed.jpgDevelopment
TODO
- "Skip" button
- "Reset" button
- "Submit" button
- Label corner markers
- Rescale image on viewport change
- Handle JPEG rotation
- Manual rotation buttons
- Zoom view for corners
- Drag'n'Drop for corner markers
- "Convert to Grayscale" button
- Add support for custom output size (e.g. A4)
- Draw lines between corners to simplify guessing of clipped corners
- Bundle Imagemagick
- Better error if wrong file format is dropped (images/error-message.jpg)
Benchmarking
Use the -bench flag to benchmark Imagemagick operations.
For example:
convert \
doc.jpg \
-bench 50 \
-virtual-pixel black \
-define distort:viewport=1191x598+0+0 \
-distort Perspective \
'277,181 0,0 214,776 0,598 1405,723 1191,598 1256,175 1191,0' \
+repage \
doc-fixed.jpgGenerate Icons
With https://gist.github.com/zlbruce/883605a635df8d5964bab11ed75e46ad:
svg2icns icon.svgGenerate App
Include Imagemagick by following the guide https://blog.schdbr.de/imagemagic-osx-static-relocatable-build.
brew install imagemagick \
--without-modules \
--without-freetype \
--without-libtiff \
--with-zero-configuration
cp /usr/local/bin/convert app-aux-files/convert
chmod 755 app-aux-files/convertSet convertBin = "./convert" in app/Main.hs and build
the core binary with stack install.
Finally run the make build script:
make Perspec.appRelated
Check out ad-si/awesome-scanning for an extensive list of related projects.


