0

I am trying to get the image data (i.e. the grayscale values per pixel) for multiple images, and output them in a CSV file that contains one row for each image, and one column for each pixel. Eventually I want to run a convolutional neural network on them so that I can classify the shapes even if they are in different locations on the image.

Here is how I generated the shapes, if you want to do that yourself:

import numpy as np
import os
import tensorflow as tf
import tensorflow_datasets as tfds
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D
from PIL import ImageDraw
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage
from sklearn.preprocessing import LabelEncoder
import random
import imageio
import csv
import glob
print(tf.__version__)

# https://stackoverflow.com/questions/20747345/python-pil-draw-circle
#  https://diycomputerscienceandelectronics.wordpress.com/2017/04/28/pygame-and-python-continued-draw-shapes-randomly-at-random-positions-on-the-screen20170428orderasc/

training = np.array([])
n=1
for i in range(1000):

  img_size = 28
  rand_num1 = random.uniform(0,img_size-0.25*img_size)
  rand_num2 = random.uniform(0,img_size-0.3*img_size)
  rand_num3 = random.uniform(0,img_size-0.3*img_size)
  rand_num4 = random.uniform(0,img_size-0.3*img_size)
  rand_num5 = random.uniform(0,img_size-0.15*img_size)
  rand_num6 = random.uniform(0,img_size-0.15*img_size)
  
  image = Image.new('RGBA', (img_size,img_size))
  draw = ImageDraw.Draw(image)

  if n % 3 == 1:
    draw.ellipse((rand_num5, rand_num6, rand_num5+0.15*img_size, rand_num6+0.15*img_size), fill = 'black')
    training = np.append(training, [['circle']])
    image.save('circle%d.png' % i)
  if n % 3 == 2:
    draw.polygon([(rand_num3,rand_num2), (rand_num3+0.08*img_size, rand_num2+0.2*img_size), (rand_num3+0.25*img_size,rand_num2+0.05*img_size)], fill = "black")
    training = np.append(training, [['triangle']])
    image.save('triangle%d.png' % i)
  if n % 3 == 0:
    draw.rectangle(((rand_num1, rand_num4), (rand_num1+0.15*img_size, rand_num4+0.25*img_size)), fill="black")
    training = np.append(training, [['rectangle']])
    image.save('rectangle%d.png' % i)
  n = n + 1

testing = np.array([])

for i in range(1000):

  img_size = 28
  rand_num1 = random.uniform(0,img_size-0.25*img_size)
  rand_num2 = random.uniform(0,img_size-0.3*img_size)
  rand_num3 = random.uniform(0,img_size-0.3*img_size)
  rand_num4 = random.uniform(0,img_size-0.3*img_size)
  rand_num5 = random.uniform(0,img_size-0.15*img_size)
  rand_num6 = random.uniform(0,img_size-0.15*img_size)
  
  image = Image.new('RGBA', (img_size,img_size))
  draw = ImageDraw.Draw(image)

  if n % 3 == 1:
    draw.ellipse((rand_num5, rand_num6, rand_num5+0.15*img_size, rand_num6+0.15*img_size), fill = 'blue', outline ='blue')
    testing = np.append(testing, [['circle']])
    
  if n % 3 == 2:
    draw.polygon([(rand_num3,rand_num2), (rand_num3+0.08*img_size, rand_num2+0.2*img_size), (rand_num3+0.25*img_size,rand_num2+0.05*img_size)], fill = (255,0,0))
    testing = np.append(testing, [['triangle']])
    
  if n % 3 == 0:
    draw.rectangle(((rand_num1, rand_num4), (rand_num1+0.15*img_size, rand_num4+0.25*img_size)), fill="black")
    testing = np.append(testing, [['rectangle']])
    
  n = n + 1

I am aware of these links which get close to what I want, but don't quite: How can I convert a png to a dataframe for python? Converting images to csv file in python

When I attempt to use these solutions, I don't get any pixel data - just zeros - and I am only able to make the program work for only one image, not the 1000 that I have in my database.

Here is what I have tried:

import numpy as np
import cv2 
import csv 

for filen in glob.glob('*.png'):
#img_file = Image.open(filen)
  img = cv2.imread(filen, 0) # load grayscale image. Shape (28,28)

  flattened = img.flatten() # flatten the image, new shape (784,)

  flattened = np.insert(flattened, 0, 0) # insert the label at the beginning of the array, in this case we add a 0 at the index 0. Shape (785,0)


  #create column names 
  column_names = []
  column_names.append("label")
  [column_names.append("pixel"+str(x)) for x in range(0, 784)] # shape (785,0)

  # write to csv 
  with open('custom_test.csv', 'w') as file:
      writer = csv.writer(file, delimiter=';')
      writer.writerows([column_names]) # dump names into csv
      writer.writerows([flattened]) # add image row 
      # optional: add addtional image rows

and


def createFileList(myDir, format='.pgn'):
  fileList = []
  print(myDir)
  for root, dirs, files in os.walk(myDir, topdown=False):
      for name in files:
          if name.endswith(format):
              fullName = os.path.join(root, name)
              fileList.append(fullName)
  return fileList

for filen in glob.glob('*.png'):
    print(filen) 
    img_file = Image.open(filen)
    # img_file.show()

    # get original image parameters...
    width, height = img_file.size
    format = img_file.format
    mode = img_file.mode

    # Make image Greyscale
    #img_grey = img_file.convert('L')
    #img_grey.save('result.png')
    #img_grey.show()

    
    # Save Greyscale values
    value = np.asarray(img_file.getdata(), dtype=np.int).reshape((28, 28))
    value = value.flatten()
    train_example.append(value)
    print(value)
    with open("training_data.csv", 'w') as f:
        writer = csv.writer(f)
        writer.writerow(value) 
print(train_example)

1 Answers1

0

UPDATE: I think for some reason my pixel information was being saved into the alpha channel. I just get it from there for your grey scale image so I wrote

img_grey = img_file.getchannel("A")

Then got my np array from img_grey.

Also, to make sure that each new input image wasn't being overwritten in the CSV file (leaving me with one row in the CSV file with only the last image from the input), I changed the 'w' in with open("training_data.csv", 'w') as f: to an 'a'.