Fred's ImageMagick Scripts



    Licensing:

    Copyright © Fred Weinhaus

    My scripts are available free of charge for non-commercial (non-profit) use, ONLY.

    For use of my scripts in commercial (for-profit) environments or non-free applications, please contact me (Fred Weinhaus) for licensing arrangements. My email address is fmw at alink dot net.

    If you: 1) redistribute, 2) incorporate any of these scripts into other free applications or 3) reprogram them in another scripting language, then you must contact me for permission, especially if the result might be used in a commercial or for-profit environment.

    Usage, whether stated or not in the script, is restricted to the above licensing arrangements. It is also subject, in a subordinate manner, to the ImageMagick license, which can be found at: http://www.imagemagick.org/script/license.php

    Please read the Pointers For Use on my home page to properly install and customize my scripts.

MULTICROP


Crops and unrotates multiple images from a scanned image.

Download Script

last modified: February 18, 2021



USAGE: multicrop [-c coords] [-b bcolor] [-f fuzzval] [-g grid] [-d discard] [-p prune] [-u unrotate] [-i innertrim] [-e extend] [-m mask] [-r resize] [-D density] infile outfile
USAGE: multicrop [-h or -help]

-c ........ coords ....... pixel coordinate to extract background color;
.......................... may be expressed as gravity value (NorthWest, etc)
.......................... or as "x,y" value; default is NorthWest=(0,0)
-b ........ bcolor ....... background color to use instead of option -c;
.......................... any valid IM color; default is to use option -c
-f ........ fuzzval ...... fuzz value for separating background color;
.......................... expressed as (integer) percent 0 to 100;
.......................... default=10 (0 is uniform color)
-g ........ grid ......... grid spacing in both x and y as percent of
.......................... image width and height; used to locate images;
.......................... integer>0; default=10;
-d ........ discard ...... discard any region that has a width or height
.......................... smaller than this size; integer>0; default is to
.......................... keep all regions
-p ........ prune ........ prune noisy regions in the mask image using a
.......................... morphology disk shape of the specified size;
.......................... integer>1; default is no pruning
-u ........ unrotate ..... unrotate method; choices are 1 for -deskew,
.......................... 2 for unrotate script, 3 for no unrotate and
.......................... 4 for innercrop;
.......................... default=1
-i ........ innertrim .... trims inside the cropped area to an orthogonal
.......................... rectangle; yes or no; default=no
-e ........ extend ....... extend crop on each side in pixels; integer; default=0
-m ........ mask ......... mask presentation method; choices are view,
.......................... save (to file) or output mask only; default
.......................... is none of the above, just output the images
-r ........ resize ....... resize percent to scale the image down; float>0; .......................... default is no resizing. -D ........ density ...... density to use when reading a single page of a PDF;
.......................... integer>0; default is no assigned density

PURPOSE: To crop and unrotate multiple images from a scanned image.

DESCRIPTION: MULTICROP crops and unrotates multiple images from a scanned image. The images must be well separate so that background color shows between them. The process uses a floofill technique based upon a seed coordinate and a fuzz value to separate the individual images from the background of the scan. The correct choice of fuzz factor is very important. If too small, the images will not be separate. If too larger, parts of the outer area of the image containing similar colors will be lost and the image may be separated into multiple parts. There are two unrotate methods. The first uses the IM deskew function, but is limited to 5 degrees of rotate or less. The second uses my unrotate script. It allows much larger rotations, but will be slower. If using the second method, my unrotate script must be downloaded and installed.

IMPORTANT: The images in the scanned file must be well separated in x and y so that their bounding boxes do not overlap. This is especially important if the images have a significant rotation.

The output images will be named from the specified outfile and -000, -001, -002 etc, will be appended before the .suffix.

ARGUMENTS:

-c coords ... COORDS is any location within the background (non-image) area for the algorithm to find the background color. It may be specified in terms of gravity parameters (NorthWest, North, NorthEast, East, SouthEast, South, SouthWest or West) or as a pixel coordinate "x,y". The default is the upper left corner = NorthWest = "0,0".

-b bcolor ... BCOLOR is the background color to use for flood fill instead of extracting this color from the image. This is useful when an image has no borders with sub-images hard against the edges. Any valid IM color is allowed. The default is to use option -c.

-f fuzzval ... FUZZVAL is the fuzz amount specified as an integer percent value between 0 to 100 (without the % sign). # The correct choice of fuzz factor is very important. If too small, the images will not be separate. If too larger, parts of the outer area of the image containing similar colors will be lost and the image may be separated into multiple parts. Typical values are probably between 5 and 20 percent. The default=10

-g grid ... GRID is the grid spacing for testing points in the input image to see if they are background or image. The grid value is specified as an integer percent greater than 0 and less than 100 of the width and height of the input image. The default=10.

-d discard ... DISCARD any region that has a width or height smaller than the specified discard size. Values are integer>0. The default is to keep all regions.

-p prune ... PRUNE (remove) noisy regions in the mask image using a morphologic disk shape operations of the specified prune size. Values are integer>1 (which will later be divided by 2). The default is no pruning.

-u unrotate ... UNROTATE is the unrotation method. Choices are: 1, 2, 3 or 4. The default is unrotate=1, which is fast and uses the IM -deskew function, but is limited to images that are rotated no more than 5 degrees in the scan. Option unrotate=2 uses my unrotate script. It can handle larger rotations, but is slower. If using the latter method, my unrotate script must be downloaded and also installed so that it is available for this script to use. Option unrotate=3 makes no attempt to unrotate the images. Option unrotate=4 uses my script, autotrim, to do an inner crop to a rectangle.

-i innertrim ... INNERTRIM trims inside the cropped area to an orthogonal rectangle. Requires my script, autotrim. The choices are: yes or no. The default=no.

-e extend ... EXTEND crop on each side for the output images in pixels. The extended region will come from the background of the image. Values are integers. Positive makes the results larger. Negative makes the results smaller. Positive values are only allowed for unrotate=3 (no unrotation) and innertrim=no. The default=0.

-m mask ... MASK provides several options for reviewing the initial mask that is generated by the fuzz value. The choices are: view (display to X11 window), save (to disk) along with the images, or output (without processing the images). The default is to simply process the images without showing or saving the mask. If using the view mode, then processing will stop until the image is closed. But this allows you to then kill the script if the mask is not appropriate. A good approach is to use the output mode repeatedly with various fuzzvals until a reasonable mask is created. Note that the mask must separate the images, but the background can "eat" a little into the images so long as no full edge is lost or the images is split into multiple parts.

-r resize ... RESIZE amount in percent to scale the image down. Values are floats>0. The default is no resizing. This is useful to improve speed and floodfilling when you have a large image, especially if the background is grainy. Note: do not include the % symbol.

-D density ... DENSITY to use when reading a single page of a PDF. Multipage pdf files are not permitted. Values are integers>0. The default is no assigned density.

REQUIREMENTS:
If using unrotate method 2, then my script, unrotate, is required.
If using innertrim, then my script, autotrim is required.

CAVEAT: No guarantee that this script will work on all platforms, nor that trapping of inconsistent parameters is complete and foolproof. Use At Your Own Risk.


EXAMPLES

Example 1: Images Are Rotated 3 Degrees
(unrotate=1; fuzzval=20 is slightly too large, but still
acceptable even though "eats" a little into the images)

Original

Mask

Arguments:
-f 20 -u 1



Example 2: Images Are Rotated 5 to 10 Degrees
(unrotate=2; fuzzval=10 is reasonable to keep from "eating" into images)

Original

Mask

Arguments:
-f 10 -u 2



Example 3: Images Have Zero Rotation
(unrotate=3; fuzzval=5 is not too small)

Original

Mask

Arguments:
-f 5 -u 3



What the script does is as follows:

  • Creates a mask by floodfilling the background with transparency
    and making the images red
  • Loops over a grid of points searching for values that are not transparent
  • If it finds any, it floodfills the local red region with white
    and keeps this temp file
  • It then copies the previous temp file and changes anything
    not white to black
  • Then it clones that black and white file and trim to the
    bounds of white and fills any black with white
  • Then it flattens that trimmed file back onto the untrimmed file
    so that any "eaten-away" areas are refilled with black
  • It then multiply composites the processed black and white mask
    with the original scanned image to separate out that image
  • Then it trims to the bounds of the masked out image, unrotates,
    and then retrims to form the final result for that image
  • It then fills that white area in the first temp file with transparency leaving the original red and transparent mask
    minus the cropped out image as transparent and repeats for the
    next grid point

This is equivalent to the following IM commands for the unrotate=1 case:

  • outnameArr=(`echo "$outfile" | sed -n 's/^\(.*\)[.]\([^.]*\)$/\1 \2/p'`)
  • outname="${outnameArr[0]}"
  • suffix="${outnameArr[1]}"
  • width=`identify -ping -format "%w" $infile`
  • height=`identify -ping -format "%h" $infile`
  • wg=`convert xc: -format "%[fx:round($grid*$width/100)]" info:`
  • hg=`convert xc: -format "%[fx:round($grid*$height/100)]" info:`
  • num=`convert xc: -format "%[fx:round(100/$grid) - 2]" info:`
  • convert $infile -fuzz ${fuzzval}% -fill none \
    -draw "matte $coords floodfill" -fill red +opaque none $tmpA2
  • k=0
  • y=0
  • for ((j=0;j<=$num;j++))
    do
    x=0
    y=$(($y + $hg))
    for ((i=0;i<=$num;i++))
    do
    x=$(($x + $wg))
    testcolor=`convert $tmpA2 -channel rgba -alpha on -format \
    "%[fx:u.p{$x,$y}=="none"?0:1]" info:`
    echo "Processing Image $k"
    convert $tmpA2 -channel rgba -alpha on -fill "white" \
    -draw "color $x,$y floodfill" $tmpA3
    convert \( $tmpA3 -channel rgba -alpha on \
    -fill none +opaque white -alpha off \) \
    \( +clone -trim -fill white -opaque black \) -flatten $tmpA4
    convert $tmpA1 $tmpA4 -compose multiply -composite \
    -fuzz ${fuzzval}% -trim -background "$bgcolor" -deskew 40% \
    -bordercolor "$bgcolor" -border 2 -trim +repage ${outname}-${k}.${suffix}
    convert $tmpA3 -channel rgba -alpha on -fill none -opaque white $tmpA2
    k=$(($k + 1))
    done