First, backup all data.
Optimal results are achieved by cropping individual images manually. The main challenge is fixed positioning a rectangle to frame the subject in an aesthetically pleasing manner for each image given varied compositions among a set of images. If you want to introduce automation to the process, you can create a crop rectangle relative to the subject’s face. This requires face detection algorithms as is included in a computer vision and machine learning software library like OpenCV. One option is to install OpenCV with Homebrew and modify an existing Python script such as facedetect with Sublime Text for use with ImageMagick in a Bash script.
Create a small sample size folder of n number of jpeg images, selected by variation in size, composition, layout, etc.
If not already installed, install Xcode from the Mac App Store. You can agree to the Xcode license from the command-line in Terminal; enter your password when prompted:
sudo xcodebuild -license
From a Terminal shell, install Homebrew with the following command:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
Install ImageMagick with the following command:
brew install imagemagick
Install OpenCV with the following command:
brew tap homebrew/science && brew install opencv
Homebrew may require you to update PYTHONPATH, If so...copy and paste the following line into your .bash_profile and save:
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages
Reload your .bash_profile with the following command:
source ~/.bash_profile
Download and install Sublime Text.
Download facedetect.
Open the facedetect-master folder you downloaded and move the facedetect executable to your Desktop. Duplicate (Control-click, select Duplicate) the facedetect executable. Move the original facedetect executable into your /usr/local/bin directory (Shift-Command-G from Finder). Option-click the copy you made, select Open With, and select Sublime Text. With the facedetect copy open in Sublime Text, change the path to haarcascade_frontalface_alt2.xml from:
# Profiles
PROFILES = {
'HAAR_FRONTALFACE_ALT2': '/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml'
}

to:
# Profiles
# If in a diferent directory, change the path to the haarcascade xml
PROFILES = {
'HAAR_FRONTALFACE_ALT2':
('/usr/local/Cellar/opencv/2.4.12_2/share/'
'OpenCV/haarcascades/haarcascade_frontalface_alt2.xml')
}

Replace the following lines near the end of the Python script:
else:
for rect in features:
print("{} {} {} {}".format(*rect))

with the following lines:
# Decrease or increase any of the multiplier values for x y w h
else:
for rect in features:
x = int(rect[0] * 0.55) # smaller moves rect left; larger right
y = int(rect[1] * 0.45) # smaller moves rect up; larger down
w = int(rect[2] * 1.80) # rect width
h = int(rect[3] * 1.80) # rect height
print("{} {} {} {}".format(x, y, w, h))

From Sublime Text save, not save as, the script. On your Desktop, rename (click the icon, then click the filename) the facedetect copy to something such as mfacedetect, “m” meaning modified. Move the mfacedetect executable to /usr/local/bin.
In Sublime Text, create a new file and paste the following lines into it:
#!/usr/bin/env bash
for file in /path/to/input_folder/*.jpg; do
name=$(basename "$file")
out=“/path/to/output_folder/$name"
cp "$file" "$out"
/usr/local/bin/facedetect "$file" | while read x y w h; do
mogrify -crop "${w}x${h}+${x}+${y}" \
-define jpeg:extent=55kb \
-strip \
-resize 500x500 +repage "$out"
done
done

If you want to further optimize the file size of the crops, try the following ImageMagick settings in a separate Bash script:
#!/usr/bin/env bash
for file in /path/to/input_folder/*.jpg; do
name=$(basename "$file")
out=“/path/to/output_folder/$name"
cp "$file" "$out"
/usr/local/bin/mfacedetect "$file" | while read x y w h; do
mogrify -crop "${w}x${h}+${x}+${y}" \
-filter Triangle \
-define filter:support=2 \
-thumbnail 500 \
-unsharp 0.25x0.08+8.3+0.045 \
-dither None \
-posterize 136 \
-quality 82 \
-define jpeg:fancy-upsampling=off \
-interlace none \
-colorspace sRGB "$out"
done
done
Make sure to replace the placeholder paths above with the actual input and output folder paths. The path to the input folder is for the sample folder you created of jpegs. Save the Bash script to your Desktop with a name such as facedetect_crop.sh. Duplicate the script, open it in SublimeText, and replace "/usr/local/bin/facedetect” with "/usr/local/bin/mfacedetect” in the script. Save to your Desktop with a name such as mfacedetect_crop.sh. You can save them later to your Scripts folder if you choose. You now have two versions of the Bash script, one including a path to the facedetect executable and one including a path to the mfacedetect executable. Make sure to create separate output folders for each script. Make each script executable by using the following commands in a Terminal shell:
chmod u+x ~/Desktop/facedetect_crop.sh
and:
chmod u+x ~/Desktop/mfacedetect_crop.sh
Try out the facedetect_crop.sh by running it in Terminal:
~/Desktop/facedetect_crop.sh
This will create tight face crops derived from the face detection bounding rectangle in the facedetect Python script. The processed photos will be located in the output folder you specified. The crops will be 500x500 pixels in dimension and no larger than 55 kb in file size. Next, try out the mfacedetect_crop.sh by running it in Terminal:
~/Desktop/mfacedetect_crop.sh
This will create head and shoulders crops (or slightly tighter) derived from the face detection bounding rectangle in the mfacedetect Python script. The photos will be located in the output folder you specified. You can change the x and y values, which specify the co-ordinates for the top left corner of the crop rectangle (rect), and also change the width and height of the crop rectangle. If changing the width and height, input identical multiplier values to maintain a square crop rectangle. Save after each change. Run mfacedetect_crop.sh after each change to see the effect. If you prefer to make the Bash scripts on your Desktop clickable, change the extension from .sh to .command. When you double-click, a shell window will open and run the script, then close upon completion.
The crop rectangle is relative to the face detection bounding rectangle. The position of the face detection bounding rectangle for each image will in part vary depending on the rotation of the head.
Consequently, no single set of x and y multiplier values can accommodate for head rotation in all images. It will be necessary to sort images based on whether the head is rotated, from the viewer’s point of view, to some extent toward the left or right image frame or is in a neutral center orientation. One suggestion is to run the images in the sample folder with one set of x and y values to judge the result based on criteria of how acceptable or pleasing the framing of the subject is. Classify the images that don’t meet the criteria and move them into separate folders based on whether the crop rectangle requires movement left or right, and run each folder through processing with the changed x and y values. Multiplier values you might start with:
Center orientation: 0.55 for x, 0.45 for y, 1.80 for both w and h
Left orientation: 0.30 for x, 0.45 for y, 1.80 for both w and h
Right orientation: 0.70 for x, 0.45 for y, 1.80 for both w and h

Be aware that if selected multiplier values specify a crop rectangle beyond the image frame, the dimensions of the output image will be less than specified (500x500). When you are satisfied with the results on the sample images, you might want to create separate Python and Bash scripts for the left, right, and center processing of images. For instance: mfacedetect_right, mfacedetect_left, and mfacedetect_right for the Python executables, and mfacedetect_crop_right.sh, mfacedetect_crop_left.sh, and mfacedetect_crop_center.sh for the Bash scripts. For convenience, you can download them from this Dropbox link. Make sure to change the placeholder paths in the scripts.
Some things to keep in mind... The haarcascade_frontalface_alt2.xml, as its name implies, is for the detection of frontal faces. If there is too much tilt or rotation of the head in the image, the face likely won’t be detected. Some images with challenging illumination, occlusions (object partially blocking the face), or other confusion elements will make it difficult for the algorithm to detect faces. Consequently, it is unlikely the detection of faces will be 100%. Building on the work of Viola and Jones, ongoing research in face detection algorithms will continue to improve detection rates. By delving into OpenCV, other computer vision algorithms and libraries, including algorithms for thumbnail generation, and other image manipulation tools, you may discover more sophisticated scripts that eliminate the need for sorting images - scripts that employ facial feature detection for instance. Some examples of services that use face detection are Cloudinary, Thumbor, and Google Cloud Vision API; or fun applications such as Faceshift.
The above info should at least provide a starting point and serve as an example for what is possible.