-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimage_classification.py
143 lines (109 loc) · 5.15 KB
/
image_classification.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from PIL import Image
from collections import OrderedDict
from sklearn.decomposition import PCA #, RandomizedPCA
from sklearn.neighbors import KNeighborsClassifier
from csv import reader, writer
from datetime import datetime
from multiprocessing import Pool
from functools import partial
import time
import numpy as np
def main():
# Execution time
start_time = time.time()
# Initialize a pool of worker for multiprocessing tasks
pool = Pool(3)
# Fetch the data
folder = 'data/roof_images/'
# Get nb_img/all the training examples
print "|| Learning phase ||"
nb_img = 3000 # None to consider all the images (i.e 8000 images)
colors = False # True to consider RGB values, False for black & white
labels = get_img_labels('training', nb_img)
Y_train = np.array(labels.values())
print "Number of images considered for training: %d" % len(Y_train)
# Get the relative paths of the chosen images
images_path = [folder + img_ID + '.jpg' for img_ID in labels.keys()]
# Determine the average size of the images to resize them
images_size = np.array([Image.open(filename).size for filename in images_path])
STANDARD_SIZE = np.mean(images_size, axis=0, dtype=int)
print "Average size of the pictures of the training data: %d x %d pixels" % (STANDARD_SIZE[0], STANDARD_SIZE[1])
#print dispersion_size = np.std(images_size, axis=0) # Standard variation: [46 48] -> Pretty dispersed
print "Convert the images into a matrix of RGB pixels values & resize them to the average size ..."
images = img_to_matrix(images_path, STANDARD_SIZE, colors=colors)
# PCA to reduce the number of features
print "Perform Principal Components Analysis (PCA) ..."
pca = PCA(n_components=0.99) # Choose n_components such as the percentage of variance remaining is superior to this
X_train = pca.fit_transform(images)
print "... Number of components of PCA transformation: %d" % pca.n_components_
# Train a K-Neighbors classifier
print "Train a K-Neighbors classifier ..."
knn = KNeighborsClassifier()
knn.fit(X_train, Y_train)
# Get the test examples
labels_test = get_img_labels('test')
images_path = [folder + img_ID + '.jpg' for img_ID in labels_test.keys()]
# Multiprocess the predictions on the test set (13 999 images)
print "|| Predicting phase ||"
predictions_pool = partial(predictions, STANDARD_SIZE, pca, knn, colors)
Y_test = pool.map(predictions_pool,images_path)
# Write the results into a new csv file
write_results(labels_test.keys(), Y_test)
# Print execution time
print("--- %s seconds ---" % (time.time() - start_time))
def predictions(STANDARD_SIZE, pca, knn, colors, image_path):
# Convert them to a matrix after resizing
X_test = img_to_matrix(image_path, STANDARD_SIZE, colors=colors)
# Apply the PCA on them
X_test = pca.transform(X_test)
# Predict the classes thanks to the model
return knn.predict(X_test)[0]
def img_to_matrix(filenames, STANDARD_SIZE=None, verbose=False, colors=True):
"""
takes one or several filenames and turns them into a numpy array of RGB pixels
"""
if type(filenames) is not list:
filenames = [filenames]
# Initialize an empty array of dimension (Number of images * (3 * number of pixels after resizing))
if colors:
images = np.zeros((len(filenames), 3*STANDARD_SIZE[0]*STANDARD_SIZE[1]), dtype=np.uint8) # Unsigned 8 bits
else:
images = np.zeros((len(filenames), STANDARD_SIZE[0]*STANDARD_SIZE[1]), dtype=np.bool_) # Black or white
for ind, filename in enumerate(filenames):
img = Image.open(filename) # Open image
img = resize_img(img, STANDARD_SIZE)
if not colors:
img = img.convert('1') # convert image to black and white
img = np.array(img.getdata()).reshape(1, -1) # Flatten the RGB arrays into a 1D array along axis = 1
images[(ind,)] = img
return images
def resize_img(img, STANDARD_SIZE, verbose=False):
"""
See also SIFT method
"""
if verbose:
print "changing size from %s to %s" % (str(img.size), str(STANDARD_SIZE))
img = img.resize(STANDARD_SIZE)
return img
def get_img_labels(task, nb_img=None):
"""
returns the ID/class of the images
"""
# Read the csv file matching the ids of the images with the classes
labels = OrderedDict()
with open('data/' + ('id_train' if task == 'training' else 'sample_submission4') + '.csv', 'rb') as csvfile:
rows = reader(csvfile, delimiter=',')
rows.next() # Skip the header
for row in rows:
if nb_img is not None and len(labels) >= nb_img:
break
labels[row[0]] = int(row[1]) # Integer conversion of the labels
return labels
def write_results(IDs, predictions):
with open('output/sample_submission%s.csv' % datetime.today().strftime('_%Y-%m-%d_%H.%M'), 'wb') as csvfile:
labelswriter = writer(csvfile, delimiter=',')
labelswriter.writerow(['Id', 'label']) # Header
for ind, prediction in enumerate(predictions):
labelswriter.writerow([IDs[ind], prediction])
if __name__ == "__main__":
main()