Ricked
Ricked

Reputation: 11

Transforming a picture into a posterized image with matching grid overlay and symbols

First of all, I want to help my mom with her embroidery projects and secondly, I want to get better in Python. So I don't need an exact solution. But it would be great to be pointed in the right direction(s) or libraries.

The result I want to achieve (manually created with Photoshop):

I basically want to automate the following processes, packed in a small tool window like tkinter:

  1. Load image
  2. Reduce its colors to a custom user-defined amount (Quantization)
  3. Pixelize; to a custom 'block size', also user-defined. In pixel units like; 16x16px
  4. Generate grid overlay based on this same 'block size'
  5. Generate unique 'symbols' corresponding to the amount of colors (analyse RGB values), and placing them on the grid/pivot/table.

I managed to build the GUI with ttk and used PIL for the quantization and pixelization. The pixelization option is based on a percentage, which I prefer transforming based on pixels instead. I assume it allows me to create a grid with the exact same size 'blocks'.

I know how to do everything manually in a program like Photoshop. I want help understanding how to do this in python. Especially when the grid size changes.

My research so far, (as a complete beginner in python, with some basic lessons) goes to exploring the options per step. I figured out what type of calculations I need for reducing colors; quantization in PIL, how to pixelate in PIL and how to extract RGB values in order to connect them to the unique generated symbols. But after this I would love to get some directions on how to 'overlay' a grid, with these symbols.

Again, I want to learn so I am not looking for an exact solution.

Here is my set-up

import tkinter as tk
from tkinter import ttk

from PIL import Image

import numpy as np
import os

# root window
root = tk.Tk()
root.geometry('300x200')
root.title('Embroidery Generator')

# Load image button (This is how I would like the tool to operate)
loadLabel= tk.Label(
    root,
    text='Source image',
)

loadLabel.grid(
    row=0,
    column=0,
    sticky='w',
)

loadButton= ttk.Button(
    root,
    text='Load...',
)

loadButton.grid(
    row=0,
    column=1,
    sticky='w',
)

# Max Colors Entry
maxColorsLabel= tk.Label(
    root,
    text='Max. colors'
)

maxColorsLabel.grid(
    row=1,
    column=0,
    sticky='w',
)

e1= tk.Entry(
    root,

)

e1.grid(
    row=1,
    column=1,
    sticky='w',
)

# Grid size Entry
gridLabel= tk.Label(
    root,
    text='Grid size'
)

gridLabel.grid(
    row=2,
    column=0,
    sticky='w',
)

e2= tk.Entry(
    root,
)

e2.grid(
    row=2,
    column=1,
    sticky='w',
)

# Quantization button to reduce max color (will become user input)
def quantize():
    im = Image.open(os.path.expanduser("~/Downloads/surf.png")).convert('RGB')
    im = im.quantize(4, dither=None)
    im.save(os.path.expanduser("~/Downloads/surf_quantized.png"))
    im.show()

quantize_button = ttk.Button(
    root,
    text='1.Quantize',
    command=quantize
)

quantize_button.grid(
    row=4,
    column=0,
    sticky='w',
)

# Pixelate button (will also become user input)
def pixelate():
    im = Image.open(os.path.expanduser("~/Downloads/surf_quantized.png"))
#find its width & height
    w,h = im.size
#find NEW dimensions from user-defined number (in percentages now. Want to transform this in 'blocks' based on pixels)
    new_w = w * 0.05
    new_h = h * 0.05
#round to nearest whole number and convert from float to int
    new_w = np.round(new_w)
    new_w = int(new_w)
    new_h = np.round(new_h)
    new_h = int(new_h)
#downsample image to these new dimensions
    down_sampled = im.resize((new_w, new_h))
#upsample back to original size (using "4" to signify bicubic)
    up_sampled = down_sampled.resize((w, h), resample = 4)
#save the image
    up_sampled.save(os.path.expanduser("~/Downloads/surf_pixalated.png"))
    up_sampled.show()

pixelate_button = ttk.Button(
    root,
    text='2.Pixelate!',
    command=pixelate
)

pixelate_button.grid(
    row=5,
    column=0,
    sticky='w',
)



# exit button
exit= ttk.Button(
    root,
    text="Exit",
    command=lambda: root.quit()
)

exit.grid(
    row=6,
    column=0,
    sticky='w',
)


root.mainloop()

Upvotes: 1

Views: 58

Answers (0)

Related Questions