added Basic version of Image Generator for generating Char Image Dataset
This commit is contained in:
351
src/ImageGenerator.py
Normal file
351
src/ImageGenerator.py
Normal 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
57
src/MyImageHelper.py
Normal 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
|
||||||
Reference in New Issue
Block a user