# Crop multiple images from single image

This code works alright, but it's very difficult to get the dimensions right and takes a bunch of trial and error. I'm wondering how I could improve it. It's meant to cut up board game pieces from a single sheet to then be used for Vassal modules.

It takes a counter sheet (I'll provide a link with an example) and cuts out / exports the individual pieces to be used by another program, which requires each piece to have its own image.

This is an example of a typical countersheet:

############################################
#
#
#       WARGAME COUNTER-CUTTER
#       Programmed by Ray Weiss
#       lerugray@gmail.com
#
#
############################################

#  imports

import os
from PIL import Image
from sys import argv

save_dir = "results"
filename = argv[1]  # Your counter sheet
img = Image.open(filename)

if not os.path.exists(save_dir):
os.makedirs(save_dir)

coord_input = input("Enter coordinates of first cell x, y: ")
start_pos = start_x, start_y = [int(x) for x in coord_input.split(",")]

counter_input = input("Enter the size of the counters x, y: ")
counter_size = w, h = [int(x) for x in counter_input.split(",")]

major_columns = int(input("Number of Pages: "))
major_columns_w = int(input("Width between cell to cell on the next page: "))
major_rows = int(input("Number of blocks per page: "))
major_rows_h = int(input("height between cell to cell on the next block: "))
columns = int(input("Number of columns inside a block: "))
rows = int(input("Number of rows inside a block: "))

###################################
#
#  End of user supplied arguments
#  Start of program
#
###################################

frame_num = 1

w, h = counter_size

for col_m in range(major_columns):
for row_m in range(major_rows):
for row in range(rows):
for col in range(columns):
x = w * col + start_x + major_columns_w * col_m
y = h * row + start_y + major_rows_h * row_m
crop = img.crop((x, y, x + w, y + h))
save_at_template = os.path.join(save_dir, "counter_{:03}.png")
crop.save(save_at_template.format(frame_num))
frame_num += 1

• Yeah sure, what it does, is takes a countersheet (ill provide a link with an example) and cuts out / exports the individual pieces to be used by another program, which requires each piece to have its own image. this is an example of a typical countersheet cf.geekdo-images.com/images/pic312586_md.jpg – lerugray Dec 19 '17 at 14:18
• If you could edit this in the question, that would be great ^^ – Ludisposed Dec 19 '17 at 14:19
• Right now, it works but it's difficult to get the exact dimensions, so the images are often off center and unaligned, wondering if there is maybe a better way to do so. – lerugray Dec 19 '17 at 14:20
• this is true, what is opencv? how would I use it? – lerugray Dec 19 '17 at 14:37

The images are often off center and unaligned

• That is because those images are probably not 100% accurate compared to the user_input.

You could make use of something like opencv to find the individual pieces. Afterwards you can crop and save those pieces. This will be a big improvement as you could give it a different image, and it would create individual pieces from it... no more measurement from the user!

• if anyone good with opencv could suggest how I would go about using it above, I would very much appreciate it! – lerugray Dec 19 '17 at 16:48
• @lerugrat Sorry, code not yet written falls out of scope of this site. I suggest reading some of the tutorials I linked to, or searching on SO – Ludisposed Dec 19 '17 at 16:50

I at least figured out a way to debug the original quicker, instead of asking for input, it just reads it from an txt file, im sure there is a better way read each line but here is what i ended up grokking.

############################################
#
#
#       WARGAME COUNTER-CUTTER
#       Programmed by Ray Weiss
#       lerugray@gmail.com
#
#
############################################

#  imports

import os
from PIL import Image
from sys import argv

save_dir = "results"
filename = argv[1]  # Your counter sheet
img = Image.open(filename)

if not os.path.exists(save_dir):
os.makedirs(save_dir)

with open("instr.txt") as f:

start_pos = start_x, start_y = [int(x) for x in lines[0].split(",")]
counter_size = w, h = [int(x) for x in lines[1].split(",")]
major_columns = int(lines[2])
major_columns_w = int(lines[3])
major_rows = int(lines[4])
major_rows_h = int(lines[5])
columns = int(lines[6])
rows = int(lines[7])

###################################
#
#  End of user supplied arguments
#  Start of program
#
###################################

frame_num = 1

w, h = counter_size

for col_m in range(major_columns):
for row_m in range(major_rows):
for row in range(rows):
for col in range(columns):
x = w * col + start_x + major_columns_w * col_m
y = h * row + start_y + major_rows_h * row_m
crop = img.crop((x, y, x + w, y + h))
save_at_template = os.path.join(save_dir, "counter_{:03}.png")
crop.save(save_at_template.format(frame_num))
frame_num += 1