├── LICENSE ├── README.md ├── delete_images.py ├── examples ├── a.jpg └── txt.jpg ├── images ├── not_notes │ └── IMG-20170407-WA0005.jpg └── notes │ └── IMG_20160728_160850659_HDR.jpg ├── lenet.py ├── mymodel.h5 ├── plot.png ├── test1.JPG ├── test2.JPG ├── test_network.py └── train_network.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chandu Parmar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exam_Notes_Detection 2 | 3 | At the time of exams most of the time student share their notes via social media and after the exam gets over it become really difficut to delete all those images manually. So face this problem I have created this system which detects exam notes(pictures which are clicked from mobile camera) and deletes it. 4 | 5 | 6 | ## Getting Started 7 | 8 | System contains 4 python files, 1 trained model file and 2 folders. 9 | I have used LeNet Convolutional Neural Networks and Keras. 10 | 11 | ### Prerequisites 12 | ``` 13 | Keras 14 | Scikit 15 | cv2 16 | matplotlib 17 | imutils 18 | ``` 19 | 20 | ### Installing 21 | I have already trained the model so you can direcly use it. 22 | ``` 23 | mymodel.h5 24 | ``` 25 | You can also train you own network by running "train_network.py" 26 | to train you own network you have to add images to images/notes and images/not_notes (There were many of my personal images so I did not upload it) 27 | ``` 28 | run: train_network.py 29 | ``` 30 | Testing the network. Add testing images to "examples/" and to run test.py give command line argument like below: 31 | ``` 32 | python test_network.py --image examples/image_name.jpg 33 | ``` 34 | To Delete the image from the desired folder change the path from delete_images.py and directly run the file 35 | ``` 36 | python delete_images.py 37 | ``` 38 | 39 | ## Built With 40 | 41 | * [Keras](https://keras.io/) - Deep Leanring framework 42 | * [LeNet](http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf/) - Research Paper 43 | 44 | ## Examples 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /delete_images.py: -------------------------------------------------------------------------------- 1 | from keras.preprocessing.image import img_to_array 2 | from keras.models import load_model 3 | import numpy as np 4 | import argparse 5 | import imutils 6 | import cv2 7 | import os 8 | 9 | ap = argparse.ArgumentParser() 10 | 11 | # ap.add_argument("-i", "--image", required=True, 12 | # help="path to input image") 13 | #args = vars(ap.parse_args()) 14 | 15 | #image = cv2.imread(args['image']) 16 | examples = 'examples\\' 17 | image = [] 18 | 19 | for img in os.listdir(examples): 20 | img = os.path.join(examples,img) 21 | image = cv2.imread(img) 22 | # orig = image.copy() 23 | image = cv2.resize(image,(28,28)) 24 | image = image.astype('float')/255.0 25 | image = img_to_array(image) 26 | image = np.expand_dims(image, axis=0) 27 | model = load_model('mymodel.h5') 28 | (not_notes, notes) = model.predict(image)[0] 29 | label = 'notes' if notes > not_notes else "not_notes" 30 | proba = notes if notes > not_notes else not_notes 31 | label = "{}: {:.2f}%".format(label,proba*100) 32 | if(notes > not_notes): 33 | os.remove(img) 34 | 35 | 36 | # output = imutils.resize(orig,width=400) 37 | # cv2.putText(output,label,(10,25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,0), 2) 38 | 39 | # cv2.imshow("Output", output) 40 | # cv2.waitKey(0) -------------------------------------------------------------------------------- /examples/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/examples/a.jpg -------------------------------------------------------------------------------- /examples/txt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/examples/txt.jpg -------------------------------------------------------------------------------- /images/not_notes/IMG-20170407-WA0005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/images/not_notes/IMG-20170407-WA0005.jpg -------------------------------------------------------------------------------- /images/notes/IMG_20160728_160850659_HDR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/images/notes/IMG_20160728_160850659_HDR.jpg -------------------------------------------------------------------------------- /lenet.py: -------------------------------------------------------------------------------- 1 | from keras.models import Sequential 2 | from keras.layers.convolutional import Conv2D 3 | from keras.layers.convolutional import MaxPooling2D 4 | from keras.layers.core import Activation 5 | from keras.layers.core import Flatten 6 | from keras.layers.core import Dense 7 | from keras import backend as K 8 | 9 | 10 | class LeNet: 11 | @staticmethod 12 | def build(widht,height,depth,classes): 13 | model = Sequential() 14 | inputShape = (height,widht,depth) 15 | 16 | if K.image_data_format() == 'channels_first': 17 | inputShape = (depth,height,widht) 18 | 19 | model.add(Conv2D(20,(5,5), padding='SAME' ,input_shape=inputShape)) 20 | model.add(Activation('relu')) 21 | model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2))) 22 | 23 | model.add(Conv2D(50,(5,5), padding='SAME')) 24 | model.add(Activation('relu')) 25 | model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2))) 26 | 27 | model.add(Flatten()) 28 | model.add(Dense(500)) 29 | model.add(Activation('relu')) 30 | 31 | model.add(Dense(classes)) 32 | model.add(Activation('softmax')) 33 | 34 | return model 35 | -------------------------------------------------------------------------------- /mymodel.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/mymodel.h5 -------------------------------------------------------------------------------- /plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/plot.png -------------------------------------------------------------------------------- /test1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/test1.JPG -------------------------------------------------------------------------------- /test2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshilparmar/Exam_Notes_Detection/f2c30ef671bc8baa0e7d4c43801c1b95c7ae71a5/test2.JPG -------------------------------------------------------------------------------- /test_network.py: -------------------------------------------------------------------------------- 1 | from keras.preprocessing.image import img_to_array 2 | from keras.models import load_model 3 | import numpy as np 4 | import argparse 5 | import imutils 6 | import cv2 7 | 8 | ap = argparse.ArgumentParser() 9 | 10 | ap.add_argument("-i", "--image", required=True, 11 | help="path to input image") 12 | args = vars(ap.parse_args()) 13 | 14 | image = cv2.imread(args['image']) 15 | orig = image.copy() 16 | 17 | image = cv2.resize(image,(28,28)) 18 | image = image.astype('float')/255.0 19 | image = img_to_array(image) 20 | image = np.expand_dims(image, axis=0) 21 | 22 | 23 | model = load_model('mymodel.h5') 24 | 25 | (not_notes, notes) = model.predict(image)[0] 26 | 27 | label = 'notes' if notes > not_notes else "not_notes" 28 | proba = notes if notes > not_notes else not_notes 29 | label = "{}: {:.2f}%".format(label,proba*100) 30 | 31 | output = imutils.resize(orig,width=400) 32 | cv2.putText(output,label,(10,25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,0), 2) 33 | 34 | cv2.imshow("Output", output) 35 | cv2.waitKey(0) -------------------------------------------------------------------------------- /train_network.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('Agg') 3 | 4 | from keras.preprocessing.image import ImageDataGenerator 5 | from keras.optimizers import Adam 6 | from sklearn.model_selection import train_test_split 7 | from keras.preprocessing.image import img_to_array 8 | from keras.utils import to_categorical 9 | from lenet import LeNet 10 | from imutils import paths 11 | import matplotlib.pyplot as plt 12 | import numpy as np 13 | import argparse 14 | import random 15 | import cv2 16 | import os 17 | 18 | ap = argparse.ArgumentParser() 19 | # ap.add_argument('-d', "--dataset", required=True, help='path to input dataset') 20 | # ap.add_argument('-m', '--model', required=True, help='path to output model') 21 | ap.add_argument('-p', '--plot', type=str, default='plot.png', help='path to utput accuracy/loss plot') 22 | args = vars(ap.parse_args()) 23 | 24 | EPOCHS = 25 25 | INIT_LR = 1e-3 26 | BS = 32 27 | 28 | #initialize the data and labels 29 | print("[INFO] Loading images....") 30 | data = [] 31 | labels = [] 32 | imagePaths = [] 33 | 34 | #image paths and shuffle them 35 | # imagePaths = sorted(list(paths.list_images(args['dataset']))) 36 | 37 | notes = 'images\\notes' 38 | not_notes = 'images\\not_notes' 39 | for filename in os.listdir(notes): 40 | img = os.path.join(notes,filename) 41 | imagePaths.append(img) 42 | 43 | for filename in os.listdir(not_notes): 44 | img = os.path.join(not_notes,filename) 45 | imagePaths.append(img) 46 | 47 | random.seed(42) 48 | random.shuffle(imagePaths) 49 | 50 | for imagePath in imagePaths: 51 | 52 | image = cv2.imread(imagePath) 53 | image = cv2.resize(image,(28,28)) 54 | image = img_to_array(image) 55 | data.append(image) 56 | 57 | 58 | label = imagePath.split(os.path.sep)[-2] 59 | label = 1 if label == 'notes' else 0 60 | labels.append(label) 61 | 62 | #scale image in range [0,1] 63 | data = np.array(data,dtype='float')/255.0 64 | labels = np.array(labels) 65 | (trainX,testX,trainY,testY) = train_test_split(data,labels,test_size=0.25,random_state=42) 66 | 67 | #convert labels from int to vector 68 | trainY = to_categorical(trainY,num_classes=2) 69 | testY = to_categorical(testY,num_classes=2) 70 | 71 | #data augmentation 72 | 73 | # construct the image generator for data augmentation 74 | aug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1, 75 | height_shift_range=0.1, shear_range=0.2, zoom_range=0.2, 76 | horizontal_flip=True, fill_mode="nearest") 77 | 78 | 79 | #initialize the model 80 | print("[INFO] compiling model...") 81 | model = LeNet.build(widht=28,height=28,depth=3,classes=2) 82 | opt = Adam(lr=INIT_LR, decay = INIT_LR/EPOCHS) 83 | model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy']) 84 | 85 | 86 | #train the network 87 | print('[INFO] training network...') 88 | H = model.fit_generator(aug.flow(trainX,trainY,batch_size=BS), 89 | validation_data=(testX,testY), steps_per_epoch=len(trainX)//BS, 90 | epochs=EPOCHS, verbose=1) 91 | 92 | print('[INFO] serializing network...') 93 | model.save('mymodel.h5') 94 | 95 | 96 | plt.style.use("ggplot") 97 | plt.figure() 98 | N = EPOCHS 99 | plt.plot(np.arange(0,N), H.history['loss'], label = 'train_loss') 100 | plt.plot(np.arange(0,N), H.history['val_loss'], label = 'val_loss') 101 | plt.plot(np.arange(0,N), H.history['acc'], label = 'train_acc') 102 | plt.plot(np.arange(0,N), H.history['val_acc'], label = 'val_acc') 103 | plt.title("Training loss and accuracy on Notes/Not Notes") 104 | plt.xlabel("Epoch#") 105 | plt.ylabel("Loss/Accuracy") 106 | plt.legend(loc='lower left') 107 | plt.savefig(args['plot']) --------------------------------------------------------------------------------