I’m trying to create a cross stitch pattern with python as shown in the attached image.
So far I simply have the pixilated image. I could import it in excel and manually add the grid and colors etc. But how can I ‘easily’ automate this in python? Can I use any of the normal figure plotting functions (pyplot), or should I look into tkinter?
I’m fairly ok making scripts in python for engineering purposes, but completely new to GUI-stuff.
Ideally my output would be a vectored pdf
from scipy import misc import matplotlib.pyplot as plt import numpy as np import matplotlib.ticker as plticker arr = misc.imread('Fox_drawing_pixelized.png', mode= 'RGBA') # 640x480x3 array fig = plt.figure() imgplot = plt.imshow(arr) # RGBA ax = plt.gca() ax.grid(True) ax.grid(b=True, which='major', color='b', linestyle='-') plt.minorticks_on() loc = plticker.MultipleLocator(base=1) ax.xaxis.set_minor_locator(loc) ax.yaxis.set_minor_locator(loc) ax.grid(b=True, which='minor', color='k', linestyle='-',linewidth=.3) fig.savefig("foo.pdf", bbox_inches='tight')
How do I set the gridlines at 0.5 rather than on the units (in the middle through each pixel)?
How do I plot text throught each pixel, I already have the image in an array with numbers how to plot this on top?
Advertisement
Answer
To shift the gridlines, you can simply change the ticks position:
ax.set_xticks(np.arange(-0.5, arr.shape[1], 5))
will put one major tick each 5 pixels starting from the border of the first pixel.
ax.set_xticks(np.arange(-0.5, arr.shape[1], 1), minor=True)
does the same thing but every pixel for minor ticks. And then do the same for y but witharr.shape[0]
.To add text, you can simply use
ax.text(x, y, 'text')
. I used a dictionary to match the colors (in hex format because rgb lists cannot be dictionary keys) to the texts. What you need to pay attention to is that (i, j) matrix indexes correspond to (y, x) coordinates.
Here is the full code:
from scipy import misc import matplotlib.pyplot as plt import numpy as np import matplotlib.ticker as plticker from matplotlib.colors import to_hex arr = misc.imread('image.png', mode= 'RGB') # array # adapt figure size to the image size. fig = plt.figure(figsize=(0.2*arr.shape[1], 0.2*arr.shape[0])) imgplot = plt.imshow(arr) # RGB ax = plt.gca() ax.grid(True) ax.grid(b=True, which='major', color='b', linestyle='-') plt.minorticks_on() ax.grid(b=True, which='minor', color='k', linestyle='-',linewidth=.3) # put a major gridline every 5 pixels ax.set_xticks(np.arange(-0.5, arr.shape[1], 5)) ax.set_yticks(np.arange(-0.5, arr.shape[0], 5)) # set ticks label ax.set_xticklabels(np.arange(0, arr.shape[1], 5)) ax.set_yticklabels(np.arange(0, arr.shape[0], 5)) # put a minor gridline every pixel ax.set_xticks(np.arange(-0.5, arr.shape[1], 1), minor=True) ax.set_yticks(np.arange(-0.5, arr.shape[0], 1), minor=True) fig.tight_layout(pad=0) # reduce space around image # display text colors_to_text = {'#000000': 'B', '#ffffff': 'W', '#f58a35': 'O', '#bcbbbb': 'G'} for i in range(arr.shape[0]): for j in range(arr.shape[1]): # get the text corresponding to the pixel color txt = colors_to_text.get(to_hex(arr[i,j]/255), '') # display text (x, y are inverted compared to the i, j indexes of the matrix) ax.text(j, i, txt, color='#888888', horizontalalignment='center', verticalalignment='center', fontsize=7) fig.savefig("foo.pdf", bbox_inches='tight')