6
\$\begingroup\$

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:

https://cf.geekdo-images.com/images/pic312586_md.jpg

############################################
#
#
#       WARGAME COUNTER-CUTTER
#       Programmed by Ray Weiss
#       [email protected]
#
#
############################################

#  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
\$\endgroup\$
4
  • \$\begingroup\$ 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 \$\endgroup\$
    – lerugray
    Dec 19, 2017 at 14:18
  • 1
    \$\begingroup\$ If you could edit this in the question, that would be great ^^ \$\endgroup\$
    – Ludisposed
    Dec 19, 2017 at 14:19
  • \$\begingroup\$ 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. \$\endgroup\$
    – lerugray
    Dec 19, 2017 at 14:20
  • \$\begingroup\$ this is true, what is opencv? how would I use it? \$\endgroup\$
    – lerugray
    Dec 19, 2017 at 14:37

2 Answers 2

2
\$\begingroup\$

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!

\$\endgroup\$
2
  • \$\begingroup\$ if anyone good with opencv could suggest how I would go about using it above, I would very much appreciate it! \$\endgroup\$
    – lerugray
    Dec 19, 2017 at 16:48
  • 1
    \$\begingroup\$ @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 \$\endgroup\$
    – Ludisposed
    Dec 19, 2017 at 16:50
1
\$\begingroup\$

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
#       [email protected]
#
#
############################################

#  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:
    lines = f.readlines()

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
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.