added Basic version of Image Generator for generating Char Image Dataset

This commit is contained in:
theAlexGuy
2020-02-10 03:11:56 +01:00
parent 516efb0d37
commit 1ec0cc8a76
2 changed files with 408 additions and 0 deletions

351
src/ImageGenerator.py Normal file
View File

@@ -0,0 +1,351 @@
#from IPython.core.completer import back_latex_name_matches
#from PIL import Image, ImageDraw, ImageFont
# get an image
#base = Image.open('Pillow/Tests/images/hopper.png').convert('RGBA')
# make a blank image for the text, initialized to transparent text color
#img = Image.new('RGB', (30, 30), (255,255,255))
#
# # get a font
# fnt = ImageFont.truetype('resources\HelveticaNeueLight.ttf', 40)
# # get a drawing context
# d = ImageDraw.Draw(img)
#
#
# # draw text
# d.text((0,0), "T", font=fnt, fill=(0,0,0))
# text_width, text_height = d.textsize('T')
# print("width {:d} - height {:d}".format(text_width, text_height))
# ------------------------------ Generate Characters ----------------------------#
# Import python imaging libs
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont, ImageFilter
#from skimage.util import random_noise
#from scipy.misc import toimage
import numpy as np
# Import operating system lib
import os, errno
# Import random generator
from random import randint
import shutil
import csv
import pickle
# ------------------------------------ Cleanup ----------------------------------#
def cleanup():
# Delete ds_store file
if os.path.isfile(font_dir+ '.DS_Store'):
os.unlink(font_dir + '.DS_Store')
if os.path.exists(out_dir):
shutil.rmtree(out_dir, ignore_errors=True)
# Delete all files from output directory
#for file in os.listdir('results'):
# file_path = os.path.join('results', file)
# if os.path.isfile(file_path):
# os.unlink(file_path)
return
def generateCharacters(mode ='image', sample = True):
if(mode == 'image'):
myoffsetsX = offsetsX_sample if sample else offsetsX
myoffsetsY = offsetsY_sample if sample else offsetsY
mydegrees = degrees_sample if sample else degrees
mycharacters = characters_sample if sample else characters
cleanup()
# Counter
k = 1
i= 0
for dirname, dirnames, filenames in os.walk(font_dir):
# For each font do
for filename in filenames:
# Get font full file path
font_resource_file = os.path.join(dirname, filename)
# For each character do
for char in mycharacters:
# For each font size do
for font_size in font_sizes:
if font_size > 0:
# For each background color do
for background_color in background_colors:
for offsetx in myoffsetsX:
for offsety in myoffsetsY:
for degree in mydegrees:
print("image size: {} \t "
"character: {}\t"
"font size: {}\t"
"degree: {}\t \t"
"offsetX: {}\t"
"offsetY: {}".format(image_size, char, font_size, degree,offsetx, offsety))
try:
dir = out_dir+char+'/'
os.makedirs(dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
createImage(dir, background_color, char, font_size, k, font_resource_file, degree, offsetx, offsety,0)
createImage(dir, background_color, char, font_size, k, font_resource_file, degree, offsetx, offsety,1)
createImage(dir, background_color, char, font_size, k, font_resource_file, degree, offsetx, offsety,2)
k = k + 1
return
if(mode == 'csv'):
GenerateCSVData(sample)
def GenerateCSVData(sample = True):
myoffsetsX = offsetsX_sample if sample else offsetsX
myoffsetsY = offsetsY_sample if sample else offsetsY
mydegrees = degrees_sample if sample else degrees
mycharacters = characters_sample if sample else characters
print("image size: {} \t "
"characters: {}\t"
"backgrounds: {}\t"
"font sizes: {}\t"
"degree: {}\t"
"offsetX: {}\t"
"offsetY: {}".format(image_size, mycharacters, background_colors, font_sizes, mydegrees,myoffsetsX, myoffsetsY))
k = 0
i = 0
path, dirs, files = next(os.walk(font_dir))
file_count = len(files)
height = file_count*len(mycharacters)*len(font_sizes)*len(background_colors)*len(myoffsetsX)*len(myoffsetsY)*len(mydegrees)*3
print(height)
width = image_size*image_size+1
output = np.ones((height,width), dtype=object)
mapDic = {}
for dirname, dirnames, filenames in os.walk(font_dir):
# For each font do
for filename in filenames:
# Get font full file path
font_resource_file = os.path.join(dirname, filename)
# For each character do
for char in mycharacters:
mapDic[char] = i
# For each font size do
for font_size in font_sizes:
if font_size > 0:
# For each background color do
for background_color in background_colors:
for offsetx in myoffsetsX:
for offsety in myoffsetsY:
for degree in mydegrees:
#createImage((255, 255, 255), 'A', 16, 1,
# './resources/fonts\\HelveticaNeueLight.ttf', 30)
# print("image size: {} \t "
# "character: {}\t"
# "font size: {}\t"
# "degree: {}\t"
# "offsetX: {}\t"
# "offsetY: {}".format(image_size, char, font_size, degree,offsetx, offsety))
resultImage1 = createImage(dir, background_color, char, font_size, k, font_resource_file, degree, offsetx, offsety,0, False)
resultImage1 = resultImage1.convert('L')
width = resultImage1.size[0]
height = resultImage1.size[1]
imageArray = np.array(resultImage1)
value = np.asarray(resultImage1, dtype=np.int)
value = value.flatten()
value = np.append(i, value)
output[k] = value
resultImage2 = createImage(dir, background_color, char, font_size, k, font_resource_file, degree, offsetx, offsety,1, False)
width = resultImage1.size[0]
height = resultImage1.size[1]
imageArray = np.array(resultImage1)
value = np.asarray(resultImage1, dtype=np.int)
value = value.flatten()
value = np.append(i, value)
output[k+1] = value
resultImage2 = createImage(dir, background_color, char, font_size, k,
font_resource_file, degree, offsetx, offsety, 2,
False)
width = resultImage1.size[0]
height = resultImage1.size[1]
imageArray = np.array(resultImage1)
value = np.asarray(resultImage1, dtype=np.int)
value = value.flatten()
value = np.append(i, value)
output[k + 2] = value
#print(k)
k = k + 3
print(i)
i = i + 1
print("dimensions {}".format(output.shape))
np.savetxt(out_dir+"foo.csv", output,fmt='%5s', delimiter=",")
pickle_out = open(out_dir+"mapDic.pickle", "wb")
pickle.dump(mapDic, pickle_out)
pickle_out.close()
print(output[:,0])
#np.savetxt(out_dir+"mapDic.csv", mapDic,delimiter=",")
return
def getMapDic():
pickle_in = open(out_dir+"mapDic.pickle", "rb")
return pickle.load(pickle_in)
def createImageTemplate(background_color, char, font_size, k, font_filename, degree = 0, offsetX = 0, offsetY = 0, noise = 0):
# Create character image :
# Grayscale, image size, background color
char_image = Image.new('RGBA', (image_size, image_size), \
background_color)
# Draw character image
draw = ImageDraw.Draw(char_image)
# Specify font : Resource file, font size
font = \
ImageFont.truetype(font_filename, font_size)
# Get character width and height
(font_width, font_height) = font.getsize(char)
# Calculate x position
x = (image_size - font_width) / 2 + offsetX*image_size
# Calculate y position
y = (image_size - font_height) / 2 + offsetY*image_size
# Draw text : Position, String,
# Options = Fill color, Font
draw.text((x, y), char,(0,0,0), font=font)
char_image = char_image.rotate(degree)
fontname = os.path.split(font_filename)[1].split('.')[0]
# Final file name
file_name = "{}_f_{}_fs_{}_bc_{}_n_{}_r_{}_ox_{}_oy_{}_{}.png".\
format(char,fontname, font_size,background_color,noise,degree,offsetX,offsetY,k)
#str(font_size) + '_bc_' + \
# str(background_color) + '_r_' + \
# str(background_color) + '_r_' + \
# str(background_color) + '_r_' + \
# str(k) + '.png'
# Save image
#char_image.save('results/' + file_name)
return (char_image, file_name)
def createImage(directory, background_color, char, font_size, k, font_filename, degree = 0, offsetX = 0, offsetY = 0, noise = 0, save = True):
blankImage, file_name = createBlankImage()
blankImage.save('blankIamge.png')
image2, file_name2 = createImageTemplate(background_color, char, font_size, k, font_filename, degree, offsetX, offsetY, noise)
#image2.save('./results/'+str(k)+'.png')
px, py = 0, 0
sx, sy = image2.size
blankImage.paste(image2, (px, py, px + sx, py + sy), image2)
#resultImage = addNoise(blankImage,noise)
resultImage = blankImage
if resultImage.mode != 'RGB':
resultImage = resultImage.convert('RGB')
if(save):
resultImage.save(directory+file_name2)
return resultImage
def addNoise(image, noise = 0):
pix = np.array(image)
if noise == 2:
#print("noise gaussian")
pix = noisy('gauss', pix)
#pix = random_noise(pix, mode='gaussian', clip=True)
elif noise == 1:
pix = noisy('s&p',pix)
#print("noise s and p")
#pix = random_noise(pix, mode='pepper', clip=True, amount = 0.1)
else:
pix = np.array(image)
result =Image.fromarray(pix.astype('uint8'))
#result.show()
return result
def createBlankImage():
# Create character image :
# Grayscale, image size, background color
char_image = Image.new('RGBA', (image_size, image_size), \
(255,255,255))
# w = char_image.rotate(45.5, expand=1)
#char_image.rotate(45).show()
# Final file name
file_name = 'blankoImage {}x{}.png'.format(image_size, image_size)
#print(file_name)
# Save image
#char_image.save('results/' + file_name)
return (char_image, file_name)
#---------------------------------- Input and Output ---------------------------#
# Directory containing fonts
font_dir = './resources/fonts'
# Output
out_dir = './results/'
k = 0
# ------------------------------------ Characters -------------------------------#
# Numbers
numbers = ['0', '1', '2']
# Small letters
small_letters = ['a', 'b', 'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
small_letters_limited = ['k', 'b', 'c','e']
capital_letters = [x.capitalize() for x in small_letters_limited]
#print(big_letters)
# Capital letters
#capital_letters = ["A", 'B', 'C']
# Select characters
characters = small_letters
characters_sample = small_letters_limited
#------------------------------------- Colors ----------------------------------#
# Background color
white_colors = [(255,255,255),(220,220,220)]
white_colors_sample = [(255,255,255)]
black_colors = (0, 10, 20, 30)
gray_colors = [(135, 145, 155)]
#background_colors = white_colors
background_colors = white_colors_sample
# -------------------------------------- Sizes ----------------------------------#
# Character sizes
small_sizes = (10, 14, 16)
medium_sizes = (20, 24, 28)
medium_sizes = (20, 24, 28)
large_sizes = (30,36,40)
large_sizes_sample = (24,30)
font_sizes = large_sizes_sample
# Image size
image_size = 32
offsetsX = [-0.3,-0.1,0,0.1,0.3]
offsetsY = [-0.3,-0.1,0,0.1,0.3]
degrees = [-0.1,-0.5,0,0.5,0.1]
offsetsX_sample = [-0.1,0,0.1]
offsetsY_sample = [-0.3,-0.1,0,0.1,0.3]
degrees_sample = [-0.1,-0.5,0,0.5,0.1]
# -------------------------------------- rotation and offset ----------------------------------#
def main():
generateCharacters('image', True)
#printMapDic()
#GenerateCharacters()
if __name__ == "__main__":
main()
#image1.save('results/blank.png')
#createMovedImage()

57
src/MyImageHelper.py Normal file
View File

@@ -0,0 +1,57 @@
'''
Parameters
----------
image : ndarray
Input image data. Will be converted to float.
mode : str
One of the following strings, selecting the type of noise to add:
'gauss' Gaussian-distributed additive noise.
'poisson' Poisson-distributed noise generated from the data.
's&p' Replaces random pixels with 0 or 1.
'speckle' Multiplicative noise using out = image + n*image,where
'''
import numpy as np
import os
#import cv2
def noisy(noise_typ, image):
if noise_typ == "gauss":
row, col, ch = image.shape
mean = 0
var = 0.1
sigma = var ** 0.5
gauss = np.random.normal(mean, sigma, (row, col, ch))
gauss = gauss.reshape(row, col, ch)
noisy = image + gauss
return noisy
elif noise_typ == "s&p":
row, col, ch = image.shape
s_vs_p = 0.5
amount = 0.01
out = np.copy(image)
#out = np.asarray(image)
blackTreshold = 3
whiteTreshold = 253
# Salt mode
#num_salt = np.ceil(amount * image.size * s_vs_p)
rmatrix = np.random.randint(0,255,(row,col))
for x, y in np.ndenumerate(out):
if(rmatrix[x[0]][x[1]] < blackTreshold):
out[x[0]][x[1]] = (0,0,0,255)
if(rmatrix[x[0]][x[1]] > whiteTreshold):
out[x[0]][x[1]] = (255, 255, 255,255)
return out
elif noise_typ == "poisson":
vals = len(np.unique(image))
vals = 2 ** np.ceil(np.log2(vals))
noisy = np.random.poisson(image * vals) / float(vals)
return noisy
elif noise_typ == "speckle":
row, col, ch = image.shape
gauss = np.random.randn(row, col, ch)
gauss = gauss.reshape(row, col, ch)
noisy = image + image * gauss
return noisy