-
Notifications
You must be signed in to change notification settings - Fork 367
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b5c6760
commit ee63295
Showing
7 changed files
with
1,227 additions
and
0 deletions.
There are no files selected for viewing
91 changes: 91 additions & 0 deletions
91
Build_Clothing_Prediction_Flask_Web_App/Clothing_Apparel_Prediction_Web_App/app.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#Import necessary libraries | ||
from flask import Flask, render_template, request | ||
import pandas as pd | ||
import numpy as np | ||
import tensorflow as tf | ||
from keras.preprocessing.image import load_img | ||
from keras.preprocessing.image import img_to_array | ||
from keras.models import load_model | ||
import os | ||
|
||
# Create flask instance | ||
app = Flask(__name__) | ||
|
||
#Set Max size of file as 10MB. | ||
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 | ||
|
||
#Allow files with extension png, jpg and jpeg | ||
ALLOWED_EXTENSIONS = ['png', 'jpg', 'jpeg'] | ||
def allowed_file(filename): | ||
return '.' in filename and \ | ||
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS | ||
|
||
def init(): | ||
global graph | ||
graph = tf.get_default_graph() | ||
|
||
# Function to load and prepare the image in right shape | ||
def read_image(filename): | ||
# Load the image | ||
img = load_img(filename, grayscale=True, target_size=(28, 28)) | ||
# Convert the image to array | ||
img = img_to_array(img) | ||
# Reshape the image into a sample of 1 channel | ||
img = img.reshape(1, 28, 28, 1) | ||
# Prepare it as pixel data | ||
img = img.astype('float32') | ||
img = img / 255.0 | ||
return img | ||
|
||
@app.route("/", methods=['GET', 'POST']) | ||
def home(): | ||
|
||
return render_template('home.html') | ||
|
||
@app.route("/predict", methods = ['GET','POST']) | ||
def predict(): | ||
if request.method == 'POST': | ||
file = request.files['file'] | ||
try: | ||
if file and allowed_file(file.filename): | ||
filename = file.filename | ||
file_path = os.path.join('static/images', filename) | ||
file.save(file_path) | ||
img = read_image(file_path) | ||
# Predict the class of an image | ||
|
||
with graph.as_default(): | ||
model1 = load_model('clothing_classification_model.h5') | ||
class_prediction = model1.predict_classes(img) | ||
print(class_prediction) | ||
|
||
#Map apparel category with the numerical class | ||
if class_prediction[0] == 0: | ||
product = "T-shirt/top" | ||
elif class_prediction[0] == 1: | ||
product = "Trouser" | ||
elif class_prediction[0] == 2: | ||
product = "Pullover" | ||
elif class_prediction[0] == 3: | ||
product = "Dress" | ||
elif class_prediction[0] == 4: | ||
product = "Coat" | ||
elif class_prediction[0] == 5: | ||
product = "Sandal" | ||
elif class_prediction[0] == 6: | ||
product = "Shirt" | ||
elif class_prediction[0] == 7: | ||
product = "Sneaker" | ||
elif class_prediction[0] == 8: | ||
product = "Bag" | ||
else: | ||
product = "Ankle boot" | ||
return render_template('predict.html', product = product, user_image = file_path) | ||
except Exception as e: | ||
return "Unable to read the file. Please check if the file extension is correct." | ||
|
||
return render_template('predict.html') | ||
|
||
if __name__ == "__main__": | ||
init() | ||
app.run() |
Binary file added
BIN
+13.8 MB
...iction_Flask_Web_App/Clothing_Apparel_Prediction_Web_App/clothing_classification_model.h5
Binary file not shown.
Binary file added
BIN
+51.7 KB
...tion_Flask_Web_App/Clothing_Apparel_Prediction_Web_App/static/images/sandal.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions
24
...Clothing_Prediction_Flask_Web_App/Clothing_Apparel_Prediction_Web_App/templates/home.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<html> | ||
<head> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
<title>Upload Apparel Image</title> | ||
</head> | ||
<body> | ||
|
||
|
||
|
||
<div class="col-sm"> | ||
<h1><span class="badge badge-danger">Apparel/Clothing Prediction</span></h1> | ||
</div> | ||
|
||
<div class="col-sm"> | ||
<form action = "/predict" method = "post" enctype="multipart/form-data"> | ||
<input type="file" name="file" /> | ||
<input type = "submit" value="Upload"> | ||
</form> | ||
</div> | ||
|
||
|
||
|
||
</body> | ||
</html> |
32 changes: 32 additions & 0 deletions
32
...thing_Prediction_Flask_Web_App/Clothing_Apparel_Prediction_Web_App/templates/predict.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<!-- Required meta tags --> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
<title>Apparel Prediction</title> | ||
</head> | ||
<body> | ||
|
||
<div class="container"> | ||
<div class="row"> | ||
|
||
<div class="col-sm"> | ||
<span class="border border-primary"> | ||
<img src="{{ user_image }}" alt="User Image" class="img-thumbnail"> | ||
</span> | ||
</div> | ||
|
||
<div class="col-sm"> | ||
<h1>Fashion Tag <span class="badge badge-secondary">{{product}}</span></h1> | ||
</div> | ||
|
||
</div> | ||
</div> | ||
|
||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> | ||
</body> | ||
</html> |
860 changes: 860 additions & 0 deletions
860
Build_Clothing_Prediction_Flask_Web_App/Clothing_Classification_CNN.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
220 changes: 220 additions & 0 deletions
220
Build_Clothing_Prediction_Flask_Web_App/Clothing_Classification_CNN.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
# -*- coding: utf-8 -*- | ||
"""Clothing_Classification_CNN.ipynb | ||
Automatically generated by Colaboratory. | ||
Original file is located at | ||
https://colab.research.google.com/drive/18VR6CM3oaugAWZA2smOf0iKdvWrXXfU_ | ||
### Clothing_Apparel_Classification | ||
""" | ||
|
||
#Import necessary Libraries | ||
|
||
import numpy as np | ||
from keras.datasets import fashion_mnist | ||
|
||
# Load fashion MNIST dataset | ||
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data() | ||
|
||
# Explore the dataset | ||
# Check the shape and size of x_train, x_test, y_train, y_test | ||
print ("Number of samples/observations in training data: " + str(len(x_train))) | ||
print ("Number of labels in training data: " + str(len(y_train))) | ||
print ("Dimensions of a single image in x_train:" + str(x_train[0].shape)) | ||
print("-------------------------------------------------------------") | ||
print ("Number of samples/observations in test data: " + str(len(x_test))) | ||
print ("Number of labels in test data: " + str(len(y_test))) | ||
print ("Dimensions of single image in x_test:" + str(x_test[0].shape)) | ||
|
||
"""### View sample images""" | ||
|
||
# Visualization library to visualize images | ||
import matplotlib.pyplot as plt | ||
|
||
# Plotting 5 images, Subplot arugments represent nrows, ncols and index | ||
# Color map is set to grey since our image dataset is grayscale | ||
plt.subplot(231) | ||
random_num = np.random.randint(0,len(x_train)) | ||
plt.imshow(x_train[random_num], cmap=plt.get_cmap('gray')) | ||
|
||
plt.subplot(232) | ||
random_num = np.random.randint(0,len(x_train)) | ||
plt.imshow(x_train[random_num], cmap=plt.get_cmap('gray')) | ||
|
||
plt.subplot(233) | ||
random_num = np.random.randint(0,len(x_train)) | ||
plt.imshow(x_train[random_num], cmap=plt.get_cmap('gray')) | ||
|
||
plt.subplot(234) | ||
random_num = np.random.randint(0,len(x_train)) | ||
plt.imshow(x_train[random_num], cmap=plt.get_cmap('gray')) | ||
|
||
plt.subplot(235) | ||
random_num = np.random.randint(0,len(x_train)) | ||
plt.imshow(x_train[random_num], cmap=plt.get_cmap('gray')) | ||
|
||
|
||
# Visualize the images | ||
plt.show() | ||
|
||
"""### Let's create our model""" | ||
|
||
#Import necessary keras specific libraries | ||
|
||
from keras.utils import np_utils | ||
import keras | ||
from keras.models import Sequential | ||
from keras.layers import Dense, Dropout, Flatten | ||
from keras.layers import Conv2D, MaxPooling2D, BatchNormalization | ||
from keras import backend as K | ||
|
||
# Setting Training Parameters like batch_size, epochs | ||
batch_size = 128 | ||
epochs = 100 | ||
|
||
# Storing the number of rows and columns | ||
img_rows = x_train[0].shape[0] | ||
img_cols = x_train[1].shape[0] | ||
|
||
''' Getting the data in the right 'shape' as required by Keras i.e. adding a 4th | ||
dimension to our data thereby changing the original image shape of (60000,28,28) | ||
to (60000,28,28,1)''' | ||
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) | ||
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) | ||
|
||
# Storing the shape of a single image | ||
input_shape = (img_rows, img_cols, 1) | ||
|
||
# Changing image type to float32 data type | ||
x_train = x_train.astype('float32') | ||
x_test = x_test.astype('float32') | ||
|
||
# Normalizing the data by changing the image pixel range from (0 to 255) to (0 to 1) | ||
x_train /= 255 | ||
x_test /= 255 | ||
|
||
# Performing one hot encoding | ||
y_train = np_utils.to_categorical(y_train) | ||
y_test = np_utils.to_categorical(y_test) | ||
|
||
# Calculate the number of classes and number of pixels | ||
num_classes = y_test.shape[1] | ||
num_pixels = x_train.shape[1] * x_train.shape[2] | ||
|
||
# Create CNN model | ||
model = Sequential() | ||
|
||
model.add(Conv2D(32, kernel_size=(3, 3), | ||
activation='relu', | ||
input_shape=input_shape)) | ||
model.add(BatchNormalization()) | ||
|
||
model.add(Conv2D(64, (3, 3), activation='relu')) | ||
model.add(BatchNormalization()) | ||
|
||
model.add(MaxPooling2D(pool_size=(2, 2))) | ||
model.add(Dropout(0.25)) | ||
|
||
model.add(Flatten()) | ||
model.add(Dense(128, activation='relu')) | ||
model.add(BatchNormalization()) | ||
|
||
model.add(Dropout(0.5)) | ||
model.add(Dense(num_classes, activation='softmax')) | ||
|
||
model.compile(loss = 'categorical_crossentropy', | ||
optimizer = keras.optimizers.Adadelta(), | ||
metrics = ['accuracy']) | ||
|
||
print(model.summary()) | ||
|
||
"""### Let's train our model""" | ||
|
||
model_fitting = model.fit(x_train, y_train, | ||
batch_size=batch_size, | ||
epochs=epochs, | ||
verbose=1, | ||
validation_data=(x_test, y_test)) | ||
|
||
score = model.evaluate(x_test, y_test, verbose=0) | ||
print('Test loss:', score[0]) | ||
print('Test accuracy:', score[1]) | ||
|
||
# Configuration related preprocessing step before mounting the drive | ||
!apt-get install -y -qq software-properties-common python-software-properties module-init-tools | ||
!add-apt-repository -y ppa:alessandro-strada/ppa 2>&1 > /dev/null | ||
!apt-get update -qq 2>&1 > /dev/null | ||
!apt-get -y install -qq google-drive-ocamlfuse fuse | ||
from google.colab import auth | ||
auth.authenticate_user() | ||
from oauth2client.client import GoogleCredentials | ||
creds = GoogleCredentials.get_application_default() | ||
import getpass | ||
!google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} < /dev/null 2>&1 | grep URL | ||
vcode = getpass.getpass() | ||
!echo {vcode} | google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} | ||
|
||
#Mount the google drive | ||
from google.colab import drive | ||
drive.mount('/content/drive') | ||
|
||
# Change the directory to current working directory | ||
import os | ||
os.chdir("/content/drive/My Drive/Youtube_Projects") | ||
|
||
# Save the model with the name clothing_classification_model | ||
model.save('clothing_classification_model.h5') | ||
|
||
# Import few more necessary libraries. | ||
from keras.models import load_model | ||
from keras.preprocessing.image import load_img | ||
from keras.preprocessing.image import img_to_array | ||
|
||
# Function to load and prepare the image in right shape | ||
def load_image(filename): | ||
# Load the image | ||
img = load_img(filename, grayscale=True, target_size=(28, 28)) | ||
# Convert the image to array | ||
img = img_to_array(img) | ||
# Reshape the image into a sample of 1 channel | ||
img = img.reshape(1, 28, 28, 1) | ||
# Prepare it as pixel data | ||
img = img.astype('float32') | ||
img = img / 255.0 | ||
return img | ||
|
||
# Load an image and predict the apparel class | ||
img = load_image('sandal.jpg') | ||
# Load the saved model | ||
model = load_model('clothing_classification_model.h5') | ||
# Predict the apparel class | ||
class_prediction = model.predict_classes(img) | ||
print(class_prediction[0]) | ||
|
||
#Map apparel category with the numerical class | ||
if class_prediction[0] == 0: | ||
product = "T-shirt/top" | ||
elif class_prediction[0] == 1: | ||
product = "Trouser" | ||
elif class_prediction[0] == 2: | ||
product = "Pullover" | ||
elif class_prediction[0] == 3: | ||
product = "Dress" | ||
elif class_prediction[0] == 4: | ||
product = "Coat" | ||
elif class_prediction[0] == 5: | ||
product = "Sandal" | ||
elif class_prediction[0] == 6: | ||
product = "Shirt" | ||
elif class_prediction[0] == 7: | ||
product = "Sneaker" | ||
elif class_prediction[0] == 8: | ||
product = "Bag" | ||
else: | ||
product = "Ankle boot" | ||
|
||
print(product) | ||
|
||
|
||
|