Archived
137 lines
3.7 KiB
Python
137 lines
3.7 KiB
Python
import json
|
|
import cv2
|
|
import random
|
|
import numpy as np
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
from sys import argv
|
|
|
|
IMGPATH = "blank_sheet.png"
|
|
|
|
|
|
with open("cells.json") as f:
|
|
cells = json.load(f)
|
|
|
|
|
|
def put_text_in_box(image, text, top_left, bottom_right, font_path, font_size=20, color=(0, 0, 0)):
|
|
"""
|
|
Puts text inside a bounding box on the cv2 image with automatic text wrapping, using PIL for text rendering.
|
|
|
|
:param image: Source cv2 image (numpy array).
|
|
:param text: Text string to be put.
|
|
:param top_left: Tuple (x, y) defining the top-left corner of the bounding box.
|
|
:param bottom_right: Tuple (x, y) defining the bottom-right corner of the bounding box.
|
|
:param font_path: Path to a .ttf font file.
|
|
:param font_size: Initial font size.
|
|
:param color: Text color in RGB.
|
|
:return: Image with text (numpy array).
|
|
"""
|
|
|
|
# Convert the cv2 image to a PIL image
|
|
image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
|
draw = ImageDraw.Draw(image_pil)
|
|
font = ImageFont.truetype(font_path, font_size)
|
|
|
|
# Calculate text size and wrapping
|
|
x1, y1 = top_left
|
|
x2, y2 = bottom_right
|
|
w, h = x2 - x1, y2 - y1
|
|
lines = []
|
|
line = []
|
|
|
|
for word in text.split():
|
|
# Check if adding the word to the line would exceed the width
|
|
line_width, _ = draw.textsize(' '.join(line + [word]), font=font)
|
|
if line_width <= w:
|
|
line.append(word)
|
|
else:
|
|
lines.append(' '.join(line))
|
|
line = [word]
|
|
|
|
# Add the last line
|
|
lines.append(' '.join(line))
|
|
|
|
# Draw text
|
|
y = y1
|
|
for line in lines:
|
|
draw.text((x1, y), line, fill=color, font=font)
|
|
y += font.getsize(line)[1]
|
|
|
|
# Convert back to cv2 image format and update the original image
|
|
cv2_image = cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)
|
|
np.copyto(image, cv2_image)
|
|
|
|
|
|
def sample_cells(players: list[str]) -> dict[str, list[str]]:
|
|
assert 0 < len(players) <= 6
|
|
|
|
default_space = cells["all"]
|
|
|
|
if len(players) < 5:
|
|
default_space += cells["randoms"]
|
|
|
|
player_cells = {
|
|
|
|
}
|
|
|
|
for player in players:
|
|
other_players = players.copy()
|
|
other_players.remove(player)
|
|
player_space = default_space + [i for op in other_players for i in cells.get(op, [])]
|
|
other_players.append("du")
|
|
player_space += [s.format(random.choice(other_players)) for s in cells["parameterized"]]
|
|
|
|
sampled_cells = np.random.choice(player_space, replace=False, size=25)
|
|
player_cells[player] = list(sampled_cells)
|
|
|
|
print(player_cells)
|
|
return player_cells
|
|
|
|
|
|
def generate_sheets(players):
|
|
sample_space = sample_cells(players)
|
|
assert len(sample_space) == len(players)
|
|
image = cv2.imread(IMGPATH)
|
|
|
|
player_sheets = {
|
|
|
|
}
|
|
|
|
for player in players:
|
|
player_sheets[player] = generate_sheet(sample_space[player], image)
|
|
|
|
for p, sheet in player_sheets.items():
|
|
cv2.imwrite(p + ".png", sheet)
|
|
|
|
|
|
def generate_sheet(sample_space: list, image: np.ndarray):
|
|
image = image.copy()
|
|
|
|
start = 8, 294
|
|
end = 625, 910
|
|
|
|
sliced = image[295:910, 10:625]
|
|
patches = []
|
|
|
|
for i in range(0, 5):
|
|
for j in range(0, 5):
|
|
print(sample_space)
|
|
|
|
width = 123
|
|
put_text_in_box(
|
|
sliced, sample_space.pop(), (i*width+1, j*width+1), ((i+1)*width, (j+1)*width), font_path="/mnt/c/Windows/Fonts/comic.ttf"
|
|
)
|
|
|
|
return image
|
|
|
|
|
|
def main():
|
|
if len(argv) < 2:
|
|
raise ValueError("You have to supply players separated by a comma. example: python generate_sheets.py player1,player2,player3")
|
|
|
|
players = argv[1]
|
|
players = players.split(",")
|
|
generate_sheets(players)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |