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.

MULTICROP2


Crops and unrotates multiple images from a scanned image.

Download Script

last modified: March 20, 2022



USAGE: multicrop2 [-c coords] [-b bcolor] [-f fuzzval] [-d discard] [-u unrotate] [-i innertrim] [-e extend] [-m mask] [-t threshold] [-D density] [-s showstats] 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)
-d ... discard ..... discard any region that has an area smaller than
.................... this size; integer>0; default is to keep all
-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
-t ... threshold ... threshold on number of objects; aborts if more than
.................... threshold number of objects are detected; integer>0;
.................... default is no abort and keep all objects.
-D ... density ..... density to use when reading a single page of a PDF;
.................... integer>0; default is no assigned density
-S ... sortval ..... sort regions by upper left bounding box x,y coordinates
.................... rounded to the specified positive integer increment;
.................... default is no sorting
-s ... showstats ... show connected components stats; yes or no; default=no
-v ................. keep virtual canvas; default is not to keep virtual canvas;
.................... only valid for -u=3 (no unrotate) and for output format that
.................... supports virtual canvas such as PNG or TIFF.

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

-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.

-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.

-t threshold ... THRESHOLD on the number of objects. The script aborts, if more than the threshold number of objects are detected. Value must be integers greater than 0. The default is no abort and keep all objects. To avoid an abort, use the -d discard option.

-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.

-S sortval ... SORT regions by their upper left bounding box x,y coordinates rounded to the specified positive integer increment. The default is no sorting.

-s showstats ... SHOWSTATS shows the connected components statistics. Choices are: yes (y) or no (n). The default=no.

-v ... keep VIRTUAL CANVAS. The default is not to keep virtual canvas. This option is only valid for -u=3 (no unrotate) and for output format that supports virtual canvas such as PNG or TIFF.

REQUIREMENTS: IM 6.8.9.10 due to the use of -connected-components.
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=10 is a good value)

Original

Mask

Arguments:
-f 10 -u 1 -m save



Example 2: Images Are Rotated 5 to 10 Degrees
(unrotate=2; fuzzval=10 is good value)

Original

Mask

Arguments:
-f 10 -u 2 -m save



Example 3: Images Are Rotated 5 to 10 Degrees
(unrotate=2; fuzzval=20 is too large and leaves small features)

Original

Mask

Arguments:
-f 20 -u 2 -m save -t 3 -s yes

Objects (id: bounding-box centroid area mean-color):
0: 700x636+0+0 366.4,321.2 192038 gray(0)
2: 342x426+346+100 516.3,312.2 123370 gray(255)
3: 289x289+27+330 170.2,474.2 65157 gray(255)
1: 293x295+16+11 161.5,158.4 64614 gray(255)
4: 4x4+292+363 293.3,364.2 10 gray(255)
10: 1x2+298+374 298.0,374.5 2 gray(255)
11: 1x2+296+378 296.0,378.5 2 gray(255)
5: 2x1+296+365 296.5,365.0 2 gray(255)
12: 1x1+232+606 232.0,606.0 1 gray(255)
6: 1x1+290+366 290.0,366.0 1 gray(255)
7: 1x1+296+368 296.0,368.0 1 gray(255)
8: 1x1+298+369 298.0,369.0 1 gray(255)
9: 1x1+288+371 288.0,371.0 1 gray(255)

--- TOO MANY OBJECTS DETECTED ---

Arguments:
-f 20 -u 2 -d 20
(remove any objects smaller than 20 pixels area)



What the script does is as follows:

  • Creates a binary mask by floodfilling the background with transparency
    and making the images white and background black
  • Use -connected-components on the mask to find all isolated regions
    equal to or above the discard area
  • Loop over the list of objects and crop each bounding box in the input image
  • Unrotate if desired

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

  • convert -quiet "$infile" +repage $tmpA1
  • outnameArr=(`echo "$outfile" | sed -n 's/^\(.*\)[.]\([^.]*\)$/\1 \2/p'`)
  • outname="${outnameArr[0]}"
  • suffix="${outnameArr[1]}"
  • convert $tmpA1 -fuzz ${fuzzval}% -fill none \
    -bordercolor $bcolor -border 1x1 \
    -draw "alpha $coords floodfill" \
    -shave 1x1 -fill white +opaque none \
    -background black -alpha background -alpha off -type bilevel \
    $tmpA2
  • data=`convert $tmpA2 \
    -define connected-components:verbose=true \
    -define connected-components:area-threshold=$discard \
    -connected-components 4 null:`
  • bboxArr=(`echo "$data" | tail -n +2 | sed 's/^[ ]*//' | cut -d\ -f2`)
  • colorArr=(`echo "$data" | tail -n +2 | sed 's/^[ ]*//' | cut -d\ -f5`)
  • num=${#bboxArr[*]}
  • for ((i=0; i<num; i++)); do
    color="${colorArr[$i]}"
    if [ "$color" != "gray(0)" ]; then
    echo "Processing Image $k"
    kk=`printf "%03d" "$k"`
    echo "Bounding Box: ${bboxArr[$i]}"
    echo ""
    convert $tmpA1 -crop "${bboxArr[$i]}" +repage -deskew 40% \
    -bordercolor "$bcolor" -border 2 -fuzz ${fuzzval}% -trim +repage \
    "${outname}-${kk}.${suffix}"
    k=$((k+1))
    fi
    done