Related
I am working on a pixel font which I am able to create with Pillow. Pillow can export *.bmp files. I would like to get from *.bmp to *.ttf or *.otf. In my current example I have a letter a (unicode 0061) and letter p (unicode 0070). I will eventually represent the full alphabet, but I use just these two letters for illustration.
How can I make a valid ttf or otf from my individual *.bmp letters?
I currently make *.bmp then convert to *.svg because I have read most font programs like "Glyphs Mini 2" and "Font Forge" can import *.svg. The problem is that I do not know how to combine my individual *.svg into a valid TTF or OTF font file.
Try 1
from PIL import Image, ImageDraw
from potrace import Bitmap
import numpy as np
import os
# p
p = np.array(
[
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[1, 1, 1, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
]
)
# a
a = np.array(
[
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
]
)
dir_bmp = "bmp/"
dir_svg = "svg/"
def array_to_drawing(letter_name: str, array: np.array):
"""Converts a numpy array to a drawing.
Args:
letter_name (str): The name of the letter to save the image as.
array (np.array): The 2D numpy array to convert.
"""
# Create an image with a white background
width = 320
height = 1024
img = Image.new("1", (width, height), color="white")
# Create a draw object to draw on the image
draw = ImageDraw.Draw(img)
# Draw the letter which the 2d numpy array represents
for row in range(array.shape[0]):
for col in range(array.shape[1]):
if array[row, col] == 1:
x0 = col * 64
y0 = row * 64
draw.rectangle([x0, y0, x0 + 64, y0 - 64], fill="black")
img.save(dir_bmp + letter_name + ".bmp")
print(
"potrace "
+ dir_bmp
+ letter_name
+ ".bmp --svg -o "
+ dir_svg
+ letter_name
+ ".svg"
)
os.system(
"potrace "
+ dir_bmp
+ letter_name
+ ".bmp --svg -o "
+ dir_svg
+ letter_name
+ ".svg"
)
array_to_drawing("p", p)
array_to_drawing("a", a)
Letter p
Letter a
I have a tensor with three dimensions and three classes (0: background, 1: first class, 2: second class). I would like to find connected clusters and assign outlier's labels by performing a majority vote. A 2D example:
import numpy as np
data = np.array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 1, 2],
[1, 2, 0, 0, 2, 2, 2],
[0, 1, 0, 0, 0, 2, 0],
[0, 0, 0, 0, 0, 0, 0],])
should be changed to
data = np.array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 2, 2],
[1, 1, 0, 0, 2, 2, 2],
[0, 1, 0, 0, 0, 2, 0],
[0, 0, 0, 0, 0, 0, 0],])
It is enough to see connected regions as one cluster an count the appearence of the labels. I am not looking for any machine learning method.
You can use scipy.ndimage.measurements.label to find the connected components and then use np.bincount for the counting
from scipy.ndimage import measurements
lbl,ncl = measurements.label(data)
lut = np.bincount((data+2*lbl).ravel(),None,2*ncl+3)[1:].reshape(-1,2).argmax(1)+1
lut[0] = 0
lut[lbl]
# array([[0, 0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0, 0],
# [0, 1, 0, 0, 0, 0, 0],
# [1, 1, 1, 0, 0, 2, 2],
# [1, 1, 0, 0, 2, 2, 2],
# [0, 1, 0, 0, 0, 2, 0],
# [0, 0, 0, 0, 0, 0, 0]])
Given a matrix containing a polygon mask (here a small and simplistic case):
array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
The outline is extracted with skimage.segmentation.find_boundaries(), giving:
array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
The outline's [row,column] (i.e. [y,x]) coordinates are then extracted giving:
outline = array([[2,2],[1,2],[1,3],[2,4],[3,5],[4,5],[5,4],[5,3],[5,2],[4,1],[3,1]])
These coordinates are then pruned to a minimal set that define the polygon (i.e. the vertices), giving:
vertices = array([[2,2],[1,2],[1,3],[3,5],[4,5],[5,4],[5,2],[4,1],[3,1]])
(Which corresponds to:)
array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
Is there a fast way using numpy/scipy/skimage/etc to get the outline coordinates (the array outline above) given the vertex coordinates (the array vertices above)?
Further, after getting back the outline coordinates, is there a good numpy/scipy/skimage way to get back the coordinates of all points in the original polygon mask?
Given 2 vertices in a polygon v1, v2 we can get all the points p which are part of the line from v1 to v2 using a line rasterization algorithm. A very fast algorithm for this is Bresenham's line drawing algorithm. After this you can apply this algorithm for each pair of adject vertices in the polygon. Although, I can not guarantee that the outline will be exactly the one in the original polygon since the rasterization algorithm will give the best set of points for the given line, not the one you have in the original algorithm (consider them compression errors).
For the filling algorithm, they are called polygon rasterization algorithm, but I can't help you here since I don't know which are best/fastest.
I have a square matrix filled by -1, 0 or 1. I would like to visualize this matrix with spheres or circles of the same radius. Radius, indeed is not important at all. Those circles though, must have a different colour according to the number of the matrix cell.
For example:
10 x 10 matrix -> 100 circles on a plane, 10 rows x 10 columns
Color of circle in position (2,9) depending on number of matrix in position (2,9).
Thank you!
People I know told me to use matlibplot, but I am new to Python and
I have many issues!
This is what I did up to now:
{`
import numpy as np
#from implementations import *
#from config import *
import matplotlib.pyplot as plt
A = np.array([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
])
rows=len(A) # finding number rows of lattice, so no need to worry about it!
columns=len(A[0]) # finding number columns of lattice, so no need to worry about it!
fig, ax = plt.subplots()
for i in range(rows):
for j in range(columns):
if A[i][j]==-1:
circle1 = plt.Circle((i*4, j*4), 2, color='blue')
fig = plt.gcf()
ax = fig.gca()
ax.add_artist(circle1)
if A[i][j]== 1:
circle2 = plt.Circle((i*4, j*4), 2, color='yellow')
fig = plt.gcf()
ax = fig.gca()
ax.add_artist(circle2)
`}
Here is the matplotlib code that uses scatter matrix:
# Imports
import matplotlib.pyplot as plt
from itertools import chain
# Create plot
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
# Here is our matrix. Note, that it is expected to be rectangular!
matrix = [
[0, 1, 0,1],
[-1,1, 0,0],
[1,-1,-1,1],
]
# Get X-length
X = len(matrix[0])
# Get Y-length
Y = len(matrix)
# Construct grids for scatter
x_grid = list(range(X)) * Y # 1,2,3,4,1,2,3,4...
y_grid = [y for y in range(Y) for _ in range(X)] # 1,1,1,1,2,2,2,2...
# Flatten the matrix because ax.scatter uses flat arrays
matrix_grid = list(chain(*matrix))
plt.scatter(
x_grid, # X-grid array of coordinates
y_grid, # Y-grid array of coordinates
c=matrix_grid, # Our flatten matrix of -1/0/1s
cmap='gist_rainbow' # Color map - defines colors
)
You can directly use a scatter as follows:
import numpy as np
import matplotlib.pyplot as plt
A = np.array([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 1, 2, -1, -1,-1, 2, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
])
X,Y = np.meshgrid(np.arange(A.shape[1]), np.arange(A.shape[0]))
plt.scatter(X.flatten(), Y.flatten(), c=A.flatten())
plt.show()
I've got an np.array 219 by 219 with mostly 0s and 2% of nonzeros and I know want to create new arrays where each of the nonzero values has 90% of chance of becoming a zero.
I now know how to change the n-th non zero value to 0 but how to work with probabilities?
Probably this can be modified:
index=0
for x in range(0, 219):
for y in range(0, 219):
if (index+1) % 10 == 0:
B[x][y] = 0
index+=1
print(B)
You could use np.random.random to create an array of random numbers to compare with 0.9, and then use np.where to select either the original value or 0. Since each draw is independent, it doesn't matter if we replace a 0 with a 0, so we don't need to treat zero and nonzero values differently. For example:
In [184]: A = np.random.randint(0, 2, (8,8))
In [185]: A
Out[185]:
array([[1, 1, 1, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1],
[0, 1, 0, 1, 1, 1, 1, 0],
[1, 1, 0, 1, 1, 0, 0, 0],
[1, 0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 1, 0, 1]])
In [186]: np.where(np.random.random(A.shape) < 0.9, 0, A)
Out[186]:
array([[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0]])
# first method
prob=0.3
print(np.random.choice([2,5], (5,), p=[prob,1-prob]))
# second method (i prefer)
import random
import numpy as np
def randomZerosOnes(a,b, N, prob):
if prob > 1-prob:
n1=int((1-prob)*N)
n0=N-n1
else:
n0=int(prob*N)
n1=N-n0
zo=np.concatenate(([a for _ in range(n0)] ,[b for _ in range(n1)] ), axis=0 )
random.shuffle(zo)
return zo
zo=randomZerosOnes(2,5, N=5, prob=0.3)
print(zo)