├── 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'])
--------------------------------------------------------------------------------