Skip to content

Instantly share code, notes, and snippets.

@gorayni
Created September 27, 2021 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gorayni/ff5dbbd2e1c5ed409769da72a7c3b0d5 to your computer and use it in GitHub Desktop.
Save gorayni/ff5dbbd2e1c5ed409769da72a7c3b0d5 to your computer and use it in GitHub Desktop.
Isometric projection of images
#!/usr/bin/env python
from argparse import ArgumentParser
from pathlib import Path
import cv2
import numpy as np
from PIL import Image
def project(angle, mirror, img):
height, width = img.shape[:2]
pts_src = np.array([[1, 1],
[width, 1],
[width, height],
[1, height]], dtype=float) - 1
new_width = int(width * np.cos(angle * np.pi / 180.))
added_height = int(width * np.sin(angle * np.pi / 180.))
new_height = height + added_height
pts_dst = np.array([[1, 1],
[new_width, added_height],
[new_width, new_height],
[1, height]], dtype=float) - 1
projected_img = np.zeros((new_height, new_width, 4), dtype=np.uint8)
mask = np.zeros((new_height, new_width), dtype=np.uint8)
cv2.fillConvexPoly(mask, pts_dst.astype(int), 255, 16)
projected_img[:, :, 3] = mask
h = cv2.findHomography(pts_src, pts_dst)[0]
if not mirror:
img = img[:, ::-1]
im_temp = cv2.warpPerspective(img, h, (new_width, new_height))
projected_img[:, :, :3] += im_temp
if not mirror:
projected_img = projected_img[:, ::-1]
return projected_img
if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument('input_img',
help='Path for the input image',
type=lambda p: Path(p))
parser.add_argument('-a', '--angle', required=False,
help='Angle in degrees to project the image',
type=int, default=30)
parser.add_argument('-m', '--mirror', required=False,
help='Horizontally mirror the resulting image',
action='store_true')
parser.add_argument('-o', '--output_img', required=False,
help='Path for the output image',
type=lambda p: Path(p))
args = parser.parse_args()
input_img = cv2.imread(str(args.input_img))
input_img = cv2.cvtColor(input_img, cv2.COLOR_BGR2RGB)
if args.output_img:
output_img = args.output_img
else:
output_img = f'projected_{args.angle}_{args.input_img.stem}.png'
out_img = Image.fromarray(project(args.angle, args.mirror, input_img), 'RGBA')
out_img.save(output_img)
#!/bin/bash
function is_an_image {
while read fpath ; do
if file "$fpath" | grep -qE 'image|bitmap'; then
echo "$fpath"
fi
done
}
export -f is_an_image
function usage() {
echo "Usage: [-a <int>] [-n <int>] [-m] $0" 1>&2;
echo 1>&2;
echo " -a Angle to project in degrees" 1>&2;
echo " -m Horizontally mirror the projected image" 1>&2;
echo " -n Number of cores to use for parallel processing" 1>&2;
echo " -h This help message" 1>&2;
exit 1;
}
function main(){
angle=15
mirror=''
num_cores="$(nproc --ignore=1)"
while getopts ":a:n:mh" opt; do
case "${opt}" in
a) # Angle to project in degrees
angle=${OPTARG}
;;
m) # Mirror
mirror='-m'
;;
n) # Number of cores
num_cores=$OPTARG
;;
h)
usage
;;
*)
usage
;;
esac
done
shift $((OPTIND -1))
export angle
export mirror
project_script="`dirname $0`"/project.py
export project_script
printf '%s\n' "${@}" | \
is_an_image | \
tr '\n' '\0' | \
xargs -0 -P"$num_cores" -I{} python "$project_script" -a "$angle" $mirror "{}"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment