├── Icons
├── 698827-icon-101-folder-search-512.png
├── 698831-icon-105-folder-add-512.png
├── Rocket-icon-blue.png
├── cancel-symbol-transparent-9.png
├── create.png
├── icons8-cbs-512.ico
├── icons8-cbs-512.png
├── icons8-faq-100 (1).png
├── repeat-pngrepo-com.png
└── start.png
├── README.md
└── Source Code
├── ELA_Training_Module_Final.py
├── Main_window_Final.py
├── Result_Retraind_Window_Final.py
├── Result_Window_Final.py
├── Test_window_Final.py
├── Test_with_Retraind_Modules.py
├── Training_window_Final.py
├── VGG16_Training_Module_Final.py
├── VGG19_Training_Module_Final.py
└── help_Window.py
/Icons/698827-icon-101-folder-search-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/698827-icon-101-folder-search-512.png
--------------------------------------------------------------------------------
/Icons/698831-icon-105-folder-add-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/698831-icon-105-folder-add-512.png
--------------------------------------------------------------------------------
/Icons/Rocket-icon-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/Rocket-icon-blue.png
--------------------------------------------------------------------------------
/Icons/cancel-symbol-transparent-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/cancel-symbol-transparent-9.png
--------------------------------------------------------------------------------
/Icons/create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/create.png
--------------------------------------------------------------------------------
/Icons/icons8-cbs-512.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/icons8-cbs-512.ico
--------------------------------------------------------------------------------
/Icons/icons8-cbs-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/icons8-cbs-512.png
--------------------------------------------------------------------------------
/Icons/icons8-faq-100 (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/icons8-faq-100 (1).png
--------------------------------------------------------------------------------
/Icons/repeat-pngrepo-com.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/repeat-pngrepo-com.png
--------------------------------------------------------------------------------
/Icons/start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HXM14/Image-Forgery-Detection-using-Deep-learning/fe13bf51484bb64528ef440d00f9f9c17237e4a9/Icons/start.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [important Note] this was my graduation project if you want to reuse it use only training py Files for training Models the whole application will not work as this was for local testing only and i didn't upload h5 files which is trained models because it was about ~3GB size which is too much you can use Kaggle API with collab to train models easily, thanks :)
7 |
8 |
9 |
10 |
11 | # Image-Forgery-Detection-using-Deep-learning
12 | Image processing with convolutional neural network to detect tampering in image
13 | ## Project Description
14 | This project combines different deep learning techniques and image processing techniques to detect image tampering "Copy Move and Splicing" forgery in different image formats (either lossy or lossless formats). We implement two different techniques to detect tampering. I built my own model with ELA preprocessing and used fine tuning with two different pre-trained Models (VGG19 , VGG15) which are trained using [Google Colab](https://colab.research.google.com/notebooks/welcome.ipynb#recent=true),Image Forgery detection application gives user the ability to test images with the application trained models **OR** train the application model with new dataset and test images with this new trained model.
15 |
16 | You Can watch Application Demo From [Youtube](https://www.youtube.com/watch?v=8les9jfMM-U&t=111s)
17 | ### Models
18 | 1. Error Level Analysis"ELA" **[1][2]** top Accuracy **(94.54% , epoc12)** You can read More about ELA from [Here!](https://fotoforensics.com/tutorial-ela.php).
19 | 2. VGG16 Pretraind Model.
20 | 3. VGG19 Pretraind Model.
21 | ### Datasets
22 | Those Models are trained on Many Datasets to Achieve the highest Accuracy
23 | 1. MICCF2000 copyMove Dataset :contains 2000 images (1300 authentic-700 tampered ) color images 2048x1536 pixels.
24 | 2. CASIAV2 splicing Dataset :contains 12,614 image (7491 authentic -5123 tampered) color images 384x265 pixels.
25 | ### Application Description[libraries , Python version , IDE]
26 | Application coded using GUI library PyQt5, tensorflow Keras API , Numpy ,......etc .IDE used - Pycharm community edition and Anaconda Enviroment with python 3.5.4.
27 | ### References
28 | **[1]** Agus Gunawan[1], Holy Lovenia[2], Adrian Hartarto Pramudita[3] "Detection og Image tampering With ELA and Deep learning" Informatics Engineering School of Electrical and Informatics Engineering, Bandung Institute of Technology.
29 |
30 | **[2]** Nor Bakiah A. W.[1], Mohd. Yamani I. I. [2], Ainuddin Wahid A. W. [3], Rosli Salleh [4] "An Evaluation of Error Level Analysis in Image Forensics" in IEEE 5th International Conference on System Engineering and Technology, Aug 2015. 10 - 11, UiTM, Shah Alam, Malaysia.
31 |
32 |
--------------------------------------------------------------------------------
/Source Code/ELA_Training_Module_Final.py:
--------------------------------------------------------------------------------
1 | from sklearn.model_selection import train_test_split
2 | from sklearn.metrics import confusion_matrix
3 | from keras.utils.np_utils import to_categorical
4 | from keras.models import Sequential
5 | from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D
6 | from keras.optimizers import RMSprop
7 | from pylab import *
8 | from PIL import Image, ImageChops, ImageEnhance
9 | import pandas as pd
10 | import numpy as np
11 | import itertools
12 | import matplotlib.pyplot as plt
13 | import os
14 | import random
15 |
16 | def train_Ela_Model(csv_file , lr , ep):
17 | def convert_to_ela_image(path, quality):
18 | filename = path
19 | resaved_filename = filename.split('.')[0] + '.resaved.jpg'
20 | im = Image.open(filename).convert('RGB')
21 | im.save(resaved_filename, 'JPEG', quality=quality)
22 | resaved_im = Image.open(resaved_filename)
23 | ela_im = ImageChops.difference(im, resaved_im)
24 | extrema = ela_im.getextrema()
25 | max_diff = max([ex[1] for ex in extrema])
26 | if max_diff == 0:
27 | max_diff = 1
28 | scale = 255.0 / max_diff
29 |
30 | ela_im = ImageEnhance.Brightness(ela_im).enhance(scale)
31 | return ela_im
32 |
33 |
34 | dataset = pd.read_csv(csv_file)
35 | X = []
36 | Y = []
37 | for index, row in dataset.iterrows():
38 | X.append(array(convert_to_ela_image(row[0], 90).resize((128, 128))).flatten() / 255.0)
39 | Y.append(row[1])
40 |
41 | X = np.array(X)
42 | Y = to_categorical(Y, 2)
43 | X = X.reshape(-1, 128, 128, 3)
44 | X_train, X_val, Y_train, Y_val = train_test_split(X, Y, test_size=0.1, random_state=5, shuffle=True)
45 |
46 | model = Sequential()
47 |
48 | model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='valid', activation='relu', input_shape=(128, 128, 3)))
49 | model.add(Conv2D(filters=32, kernel_size=(5, 5), strides=(2, 2), padding='valid', activation='relu'))
50 | model.add(MaxPool2D(pool_size=2, strides=None, padding='valid', data_format='channels_last'))
51 | model.add(Dropout(0.25))
52 |
53 | model.add(Flatten())
54 |
55 | model.add(Dense(256, activation="relu"))
56 | model.add(Dropout(0.50))
57 | model.add(Dense(2, activation="softmax"))
58 | model.summary()
59 |
60 | optimizer = RMSprop(lr=lr, rho=0.9, epsilon=1e-08, decay=0.0)
61 | model.compile(optimizer=optimizer, loss="categorical_crossentropy", metrics=["accuracy"])
62 |
63 | #early_stopping = EarlyStopping(monitor='val_acc', min_delta=0, patience=2, verbose=0, mode='auto')
64 |
65 | epochs = ep
66 | batch_size = 5
67 |
68 | history = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, validation_data=(X_val, Y_val), verbose=2)
69 |
70 | fig, ax = plt.subplots(3, 1)
71 | ax[0].plot(history.history['loss'], color='b', label="Training loss")
72 | ax[0].plot(history.history['val_loss'], color='r', label="validation loss", axes=ax[0])
73 | legend = ax[0].legend(loc='best', shadow=True)
74 |
75 | ax[1].plot(history.history['acc'], color='b', label="Training accuracy")
76 | ax[1].plot(history.history['val_acc'], color='r', label="Validation accuracy")
77 | legend_ = ax[1].legend(loc='best', shadow=True)
78 |
79 |
80 | def plot_confusion_matrix(cm_, classes, normalize=False, title_='Confusion matrix', cmap=cm.get_cmap("Spectral")):
81 | """
82 | This function prints and plots the confusion matrix.
83 | Normalization can be applied by setting `normalize=True`.
84 | """
85 | plt.imshow(cm_, interpolation='nearest', cmap=cmap)
86 | plt.title(title_)
87 | plt.colorbar()
88 | tick_marks = np.arange(len(classes))
89 | plt.xticks(tick_marks, classes)
90 | plt.yticks(tick_marks, classes)
91 |
92 | if normalize:
93 | cm_ = cm_.astype('float') / cm_.sum(axis=1)[:, np.newaxis]
94 |
95 | thresh = cm_.max() / 2.
96 | for i, j in itertools.product(range(cm_.shape[0]), range(cm_.shape[1])):
97 | plt.text(j, i, cm_[i, j],
98 | horizontalalignment="center",
99 | color="white" if cm_[i, j] > thresh else "black")
100 |
101 | plt.tight_layout()
102 | plt.ylabel('True label')
103 | plt.xlabel('Predicted label')
104 |
105 |
106 | Y_pred = model.predict(X_val)
107 | Y_pred_classes = np.argmax(Y_pred, axis=1)
108 | Y_true = np.argmax(Y_val, axis=1)
109 |
110 | confusion_mtx = confusion_matrix(Y_true, Y_pred_classes)
111 | plot_confusion_matrix(confusion_mtx, classes=range(2))
112 |
113 | #plt.show()
114 | image_path = os.getcwd()+"\\Figures"
115 | Models_path = os.getcwd()+"\\Re_Traind_Models"
116 | file_number =random.randint(1, 1000000)
117 | plot_Name = image_path+"\\ELA_"+str(file_number)+".png"
118 | Model_Name = Models_path+"\\ELA_"+str(file_number)+".h5"
119 | plt.savefig(plot_Name , transparent =True , bbox_incehs="tight" , pad_inches = 2 , dpi = 50)
120 | model.save(Model_Name)
121 | return plot_Name , Model_Name
122 |
123 |
--------------------------------------------------------------------------------
/Source Code/Main_window_Final.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication , QComboBox, QLabel, QWidget, QPushButton
2 | from PyQt5.QtGui import QPixmap
3 | from PyQt5.QtCore import *
4 | from PyQt5 import QtCore
5 | from PyQt5 import QtGui
6 |
7 | from Test_window_Final import Test_window
8 | from Training_window_Final import Training_window
9 |
10 | import sys
11 |
12 | class MainWindow(QWidget):
13 | def __init__(self, parent = None):
14 | """constructor to create a new window with charactersitis after create object from class window"""
15 | super().__init__()
16 | self.title = "IFD Application"
17 | self.top = 200
18 | self.left = 500
19 | self.width = 550
20 | self.height = 260
21 | self.file_path = ""
22 | self.init_window()
23 |
24 | def init_window(self):
25 | """initialize Main IFD window"""
26 |
27 | self.setWindowTitle(self.title)
28 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico")) #icon Pic File name
29 | self.setGeometry(self.left , self.top , self.width , self.height)
30 | self.setFixedSize(self.width , self.height)
31 |
32 | label = QLabel(self)
33 | label.move(175,40)
34 | label.setText('Image')
35 | label.setFont(QtGui.QFont("Sanserif" , 24))
36 |
37 |
38 |
39 | label = QLabel(self)
40 | label.move(175, 70)
41 | label.setText('Forgery')
42 | label.setFont(QtGui.QFont("Sanserif", 24))
43 |
44 | label = QLabel(self)
45 | label.move(175, 100)
46 | label.setText('Detection')
47 | label.setFont(QtGui.QFont("Sanserif", 24))
48 |
49 | label = QLabel(self)
50 | label.move(20, 200)
51 | label.setText('Click training or testing to start the process:')
52 | label.setFont(QtGui.QFont("Sanserif", 8))
53 |
54 | pixmap = QPixmap("*\\icons8-cbs-512.png")
55 | self.label = QLabel(self)
56 | self.label.setPixmap(pixmap)
57 | self.label.resize(190, 190)
58 | self.label.move(0, 10)
59 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
60 | self.label.show()
61 |
62 |
63 | self.combo = QComboBox(self)
64 | self.combo.addItem("Training")
65 | self.combo.addItem("Testing")
66 | self.combo.setGeometry(QRect(234, 198,300 , 20))
67 |
68 |
69 | self.button = QPushButton("Start", self)
70 | self.button.setGeometry(QRect(445, 230, 90, 20))
71 | self.button.setIcon(QtGui.QIcon("start.png")) #icon Pic File name
72 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
73 | self.button.setToolTip("Lunch Your choice either Training or Testing")
74 | self.button.clicked.connect(self.on_click)
75 |
76 |
77 | self.show()
78 |
79 | def on_click(self):
80 | if str(self.combo.currentText()) == "Training":
81 | self.training_window = Training_window()
82 | self.training_window.show()
83 | self.close()
84 |
85 | elif str(self.combo.currentText()) == "Testing":
86 | self.test_window= Test_window()
87 | self.test_window.show()
88 | self.close()
89 |
90 |
91 | if __name__ == "__main__":
92 | App = QApplication(sys.argv)
93 | App.setStyle('Fusion')
94 | window = MainWindow()
95 | sys.exit(App.exec())
96 |
--------------------------------------------------------------------------------
/Source Code/Result_Retraind_Window_Final.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication, QVBoxLayout, QMessageBox, QPushButton , QDialog , QHBoxLayout
2 | from PyQt5 import QtGui
3 | from PyQt5 import QtCore
4 |
5 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
6 | from matplotlib.figure import Figure
7 |
8 | import numpy as np
9 | import sys
10 |
11 |
12 |
13 | class ResultWindow(QDialog):
14 | def __init__(self , label ="Not Forged" , prob = 0.50 , model_path = ".\\sys_models\\ELA_Model.h5" ,model_name = "ELA"):
15 | super().__init__()
16 | self.title = "Result"
17 | self.top = 200
18 | self.left = 500
19 | self.width = 400
20 | self.height = 400
21 | self.model_path = model_path
22 | self.model_name = model_name
23 | self.button_Test_again = QPushButton("Test Again", self)
24 | self.button_quit = QPushButton("Quit", self)
25 | label = label
26 | prob = prob
27 | self.init_window(label , prob)
28 | def init_window(self,label , prob):
29 | self.setWindowTitle(self.title)
30 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
31 | self.setGeometry(self.left, self.top, self.width, self.height)
32 | self.setFixedSize(self.width, self.height)
33 | hbox = QHBoxLayout()
34 | hbox.addStretch(1)
35 | m = PlotCanvas(self, width=5, height=4, dpi=80,label=label ,prob=prob)
36 | m.move(0,0)
37 |
38 | self.button_Test_again.setToolTip("to test Another image just Click Test button")
39 | self.button_Test_again.setIcon(QtGui.QIcon("698827-icon-101-folder-search-512.png"))
40 | self.button_Test_again.setIconSize(QtCore.QSize(15, 15))
41 | self.button_Test_again.clicked.connect(self.test_again)
42 | hbox.addWidget(self.button_Test_again)
43 |
44 | self.button_quit.setToolTip("Close the program")
45 | self.button_quit.setIcon(QtGui.QIcon("cancel-symbol-transparent-9.png"))
46 | self.button_quit.setIconSize(QtCore.QSize(15, 15))
47 | self.button_quit.clicked.connect(self.close_main_window)
48 | hbox.addWidget(self.button_quit)
49 |
50 | vbox = QVBoxLayout()
51 | vbox.addStretch(1)
52 | vbox.addLayout(hbox)
53 |
54 | self.setLayout(vbox)
55 |
56 | self.show()
57 |
58 | def test_again(self):
59 | from Test_with_Retraind_Modules import Test_window
60 | self.Main_window = Test_window(model_path=self.model_path , model_name= self.model_name)
61 | self.Main_window.show()
62 | self.close()
63 |
64 | def close_main_window(self):
65 | """
66 | Generate 'question' dialog on clicking 'X' button in title bar.
67 | Reimplement the closeEvent() event handler to include a 'Question'
68 | dialog with options on how to proceed - Save, Close, Cancel buttons
69 | """
70 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
71 | QMessageBox.Cancel | QMessageBox.Close)
72 |
73 | if reply == QMessageBox.Close:
74 | self.close()
75 |
76 | class PlotCanvas(FigureCanvas):
77 | def __init__(self, parent=None, width=5, height=4, dpi=80 , label = "Forged" , prob = 0.1):
78 | """
79 | Ploting Different
80 | Validation process Discription
81 | Tuuning parameters
82 | Choosed parameters
83 | be sure what u see
84 | :param parent:
85 | :param width:
86 | :param height:
87 | :param dpi:
88 | :param label:
89 | :param prob:
90 | """
91 | fig = Figure(figsize=(width, height), dpi=dpi)
92 | self.axes = fig.add_subplot(111)
93 | FigureCanvas.__init__(self, fig)
94 | self.setParent(parent)
95 | self.label = label
96 | self.prob = prob
97 | self.plotpie(self.label , self.prob )
98 |
99 | def plotpie(self , label , prob):
100 | ax = self.figure.add_subplot(111)
101 | if label == "Forged":
102 | labels = [label, "Not Forged"]
103 | probs = [np.abs(prob*100), np.abs(prob-1)*100]
104 | print(np.abs(prob*100), np.abs(prob-1)*100)
105 | colors = ['Red', 'Blue']
106 | ax.text(0.25, 0.95, 'Decision '+"Forged", transform=ax.transAxes)
107 | ax.axis("equal")
108 | ax.pie(probs, autopct='%1.1f%%', shadow=True, colors=colors , radius=1.5,counterclock=True)
109 | ax.legend(labels, loc=3)
110 | self.draw()
111 | elif label == "Not_Forged":
112 | labels = [label, "Forged"]
113 | probs = [np.abs(prob*100), np.abs((prob-1)*100)]
114 | print(np.abs(prob*100), np.abs(prob-1)*100)
115 | colors = ['Blue', 'Red']
116 | ax.text(0.25, 0.95, 'Decision '+" Not Forged", transform=ax.transAxes)
117 | ax.axis("equal")
118 | ax.pie(probs, autopct='%1.1f%%', shadow=True, colors=colors, radius=1.5 ,counterclock=True)
119 | ax.legend(labels, loc=3)
120 | self.draw()
121 |
122 |
123 |
124 |
125 |
126 | if __name__ == "__main__":
127 | App = QApplication(sys.argv)
128 | App.setStyle('Fusion')
129 | window = ResultWindow()
130 | sys.exit(App.exec())
--------------------------------------------------------------------------------
/Source Code/Result_Window_Final.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication, QVBoxLayout, QMessageBox, QPushButton , QDialog , QHBoxLayout
2 | from PyQt5 import QtGui
3 | from PyQt5 import QtCore
4 |
5 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
6 | from matplotlib.figure import Figure
7 |
8 | import numpy as np
9 | import sys
10 |
11 |
12 |
13 | class ResultWindow(QDialog):
14 | def __init__(self , label , prob ):
15 | super().__init__()
16 | self.title = "Result"
17 | self.top = 200
18 | self.left = 500
19 | self.width = 400
20 | self.height = 400
21 | self.button_Test_again = QPushButton("Test Again", self)
22 | self.button_quit = QPushButton("Quit", self)
23 | label = label
24 | prob = prob
25 | self.init_window(label , prob)
26 | def init_window(self,label , prob):
27 | self.setWindowTitle(self.title)
28 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
29 | self.setGeometry(self.left, self.top, self.width, self.height)
30 | self.setFixedSize(self.width, self.height)
31 | hbox = QHBoxLayout()
32 | hbox.addStretch(1)
33 | m = PlotCanvas(self, width=5, height=4, dpi=80,label=label ,prob=prob)
34 | m.move(0,0)
35 |
36 | self.button_Test_again.setToolTip("to test Another image just Click Test button")
37 | self.button_Test_again.setIcon(QtGui.QIcon("698827-icon-101-folder-search-512.png"))
38 | self.button_Test_again.setIconSize(QtCore.QSize(15, 15))
39 | self.button_Test_again.clicked.connect(self.test_again)
40 | hbox.addWidget(self.button_Test_again)
41 |
42 | self.button_quit.setToolTip("Close the program")
43 | self.button_quit.setIcon(QtGui.QIcon("cancel-symbol-transparent-9.png"))
44 | self.button_quit.setIconSize(QtCore.QSize(15, 15))
45 | self.button_quit.clicked.connect(self.close_main_window)
46 | hbox.addWidget(self.button_quit)
47 |
48 | vbox = QVBoxLayout()
49 | vbox.addStretch(1)
50 | vbox.addLayout(hbox)
51 |
52 | self.setLayout(vbox)
53 |
54 | self.show()
55 |
56 | def test_again(self):
57 | from Test_window_Final import Test_window
58 | self.Main_window = Test_window()
59 | self.Main_window.show()
60 | self.close()
61 |
62 | def close_main_window(self):
63 | """
64 | Generate 'question' dialog on clicking 'X' button in title bar.
65 | Reimplement the closeEvent() event handler to include a 'Question'
66 | dialog with options on how to proceed - Save, Close, Cancel buttons
67 | """
68 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
69 | QMessageBox.Cancel | QMessageBox.Close)
70 |
71 | if reply == QMessageBox.Close:
72 | self.close()
73 |
74 | class PlotCanvas(FigureCanvas):
75 | def __init__(self, parent=None, width=5, height=4, dpi=80 , label = "Forged" , prob = 0.1):
76 | fig = Figure(figsize=(width, height), dpi=dpi)
77 | self.axes = fig.add_subplot(111)
78 | FigureCanvas.__init__(self, fig)
79 | self.setParent(parent)
80 | self.label = label
81 | self.prob = prob
82 | self.plotpie(self.label , self.prob )
83 |
84 | def plotpie(self , label , prob):
85 | ax = self.figure.add_subplot(111)
86 | if label == "Forged":
87 | labels = [label, "Not Forged"]
88 | probs = [np.abs(prob*100), np.abs(prob-1)*100]
89 | print(np.abs(prob*100), np.abs(prob-1)*100)
90 | colors = ['Red', 'Blue']
91 | ax.text(0.25, 0.95, 'Decision '+"Forged", transform=ax.transAxes)
92 | ax.axis("equal")
93 | ax.pie(probs, autopct='%1.1f%%', shadow=True, colors=colors , radius=1.5,counterclock=True)
94 | ax.legend(labels, loc=3)
95 | self.draw()
96 | elif label == "Not_Forged":
97 | labels = [label, "Forged"]
98 | probs = [np.abs(prob*100), np.abs((prob-1)*100)]
99 | print(np.abs(prob*100), np.abs(prob-1)*100)
100 | colors = ['Blue', 'Red']
101 | ax.text(0.25, 0.95, 'Decision '+" Not Forged", transform=ax.transAxes)
102 | ax.axis("equal")
103 | ax.pie(probs, autopct='%1.1f%%', shadow=True, colors=colors, radius=1.5 ,counterclock=True)
104 | ax.legend(labels, loc=3)
105 | self.draw()
106 |
107 |
108 |
109 |
110 |
111 | if __name__ == "__main__":
112 | App = QApplication(sys.argv)
113 | App.setStyle('Fusion')
114 | window = ResultWindow(label = "Test" , prob = 50)
115 | sys.exit(App.exec())
--------------------------------------------------------------------------------
/Source Code/Test_window_Final.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication , QFileDialog , QFrame,QComboBox, QLineEdit , QLabel, QMessageBox, QWidget, QPushButton
2 | from PyQt5.QtCore import *
3 | from PyQt5 import QtGui
4 | from PyQt5 import QtCore
5 | from PyQt5.QtGui import QPixmap
6 | from Result_Window_Final import ResultWindow
7 | from PIL import Image, ImageChops, ImageEnhance
8 | from keras.models import load_model
9 | from pylab import *
10 | import os
11 |
12 | class Thread(QThread):
13 | def __init__(self):
14 | QThread.__init__(self)
15 |
16 | def __del__(self):
17 | self.wait()
18 |
19 | def test_image_with_ela(self, image_path, model_path):
20 | """
21 | Error Level Analysis
22 | :param image_path
23 | :return label[Forged , Not Forged] , prob[class probability]
24 | """
25 | # loading Model
26 | model = load_model(model_path)
27 | # Read image
28 | image_saved_path = image_path.split('.')[0] + '.saved.jpg'
29 |
30 | # calculate ELA
31 | image = Image.open(image_path).convert('RGB')
32 | image.save(image_saved_path, 'JPEG', quality=90)
33 | saved_image = Image.open(image_saved_path)
34 | ela = ImageChops.difference(image, saved_image)
35 | extrema = ela.getextrema()
36 | max_diff = max([ex[1] for ex in extrema])
37 | if max_diff == 0:
38 | max_diff = 1
39 | scale = 255.0 / max_diff
40 | ela_im = ImageEnhance.Brightness(ela).enhance(scale)
41 |
42 | # prepare image for testing
43 | image = array(ela_im.resize((128, 128))).flatten() / 255.0
44 | image = image.reshape(-1, 128, 128, 3)
45 | # prediction
46 | prob = model.predict(image)[0]
47 | idx = np.argmax(prob)
48 | pred = model.predict(image)
49 | pred = pred.argmax(axis=1)[0]
50 |
51 | label = "Forged" if pred == 1 else "Not_Forged"
52 | return label, prob[idx]
53 |
54 |
55 | def test_image_with_vgg16(self , image_path,model_path):
56 | """
57 | VGG16 GoogleNet Competition Pre-trained Model
58 | :param image_path
59 | :return label[Forged , Not Forged] , prob[class probability]
60 | """
61 | model = load_model(model_path)
62 | # Read image
63 | image = Image.open(image_path).convert('RGB')
64 |
65 | # prepare image for testing
66 | image = array(image.resize((300, 300))).flatten() / 255.0
67 | image = image.reshape(-1, 300, 300, 3)
68 |
69 | # Make predictions on the input image
70 | prob = model.predict(image)[0]
71 | idx = np.argmax(prob)
72 |
73 | # predictions
74 | prob = model.predict(image)[0]
75 | idx = np.argmax(prob)
76 | pred = model.predict(image)
77 | pred = pred.argmax(axis=1)[0]
78 |
79 | label = "Forged" if pred == 1 else "Not_Forged"
80 | return label, prob[idx]
81 |
82 | def test_image_with_vgg19(self , image_path,model_path):
83 | """
84 | VGG19 GoogleNet Competition Pre-trained Model
85 | :param image_path
86 | :return label[Forged , Not Forged] , prob[class probability]
87 | """
88 | model = load_model(model_path)
89 | # Read image
90 | image = Image.open(image_path).convert('RGB')
91 |
92 | # prepare image for testing
93 | image = array(image.resize((100, 100))).flatten() / 255.0
94 | image = image.reshape(-1, 100, 100, 3)
95 |
96 | prob = model.predict(image)[0]
97 | idx = np.argmax(prob)
98 |
99 | prob = model.predict(image)[0]
100 | idx = np.argmax(prob)
101 | pred = model.predict(image)
102 | pred = pred.argmax(axis=1)[0]
103 |
104 | label = "Forged" if pred == 1 else "Not_Forged"
105 |
106 | return label, prob[idx]
107 |
108 |
109 |
110 | class Test_window(QWidget):
111 | def __init__(self, parent = None , model_path = "C:\\Users\\Mohamed-PC\\PycharmProjects\\graduation_project\\ELA_Model.h5" ):
112 | super().__init__()
113 | self.title = "IFD Application"
114 | self.top = 200
115 | self.left = 500
116 | self.width = 550
117 | self.height = 345
118 | self.file_path = ""
119 | self.model_path = model_path
120 | self.init_window()
121 |
122 | def init_window(self):
123 | """initialize window"""
124 | self.setWindowTitle(self.title)
125 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico")) #icon Pic File name
126 | self.setGeometry(self.left , self.top , self.width , self.height)
127 | self.setFixedSize(self.width , self.height)
128 | self.label = QLabel(self)
129 | self.label2 = QLabel(self)
130 | self.label3 = QLabel(self)
131 | self.label4 = QLabel(self)
132 | self.label_1 = QLabel(self)
133 | self.label_2 = QLabel(self)
134 |
135 | #quit = QAction("Quit", self)
136 | #quit.triggered.connect(self.closex)
137 |
138 |
139 | #Label
140 | label = QLabel(self)
141 | label.move(10,44)
142 | label.setText('Image Name ')
143 | label.setFont(QtGui.QFont("Sanserif" , 8))
144 |
145 | #text Box
146 | self.line_edit = QLineEdit(self)
147 | self.line_edit.setReadOnly(True)
148 | self.line_edit.setFont(QtGui.QFont("Sanserif", 8))
149 | self.line_edit.setGeometry(QRect(80, 40, 365, 20))
150 | self.line_edit.setPlaceholderText("image Name here!")
151 |
152 | #Button
153 | self.button = QPushButton("Browse", self)
154 | self.button.setGeometry(QRect(450, 40, 90, 20))
155 | self.button.setToolTip("Browse image from your computer to start test!") # Notice using h2 tags From Html
156 | self.button.setIcon(QtGui.QIcon("698831-icon-105-folder-add-512.png")) #icon Pic File name
157 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
158 | self.button.clicked.connect(self.getfiles)
159 |
160 | #Button
161 | self.button = QPushButton("Test", self)
162 | self.button.setGeometry(QRect(270, 310, 90, 20))
163 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
164 | self.button.setIcon(QtGui.QIcon("698827-icon-101-folder-search-512.png")) #icon Pic File name
165 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
166 | self.button.clicked.connect(self.on_click)
167 |
168 | #Button
169 | self.button = QPushButton("Back", self)
170 | self.button.setGeometry(QRect(180, 310, 90, 20))
171 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
172 | self.button.setIcon(QtGui.QIcon("repeat-pngrepo-com.png")) #icon Pic File name
173 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
174 | self.button.clicked.connect(self.back_to_Main)
175 |
176 |
177 | #Button
178 | self.button = QPushButton(" Quit", self)
179 | self.button.setGeometry(QRect(360, 310, 90, 20))
180 | self.button.setToolTip("Close the program!") # Notice using h2 tags From Html
181 | self.button.setIcon(QtGui.QIcon("cancel-symbol-transparent-9.png")) #icon Pic File name
182 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
183 | self.button.clicked.connect(self.close_main_window)
184 |
185 | #Button
186 | #self.button = QPushButton("Help", self)
187 | #self.button.setGeometry(QRect(450, 310, 90, 20))
188 | #self.button.setToolTip("Help!") # Notice using h2 tags From Html
189 | #self.button.setIcon(QtGui.QIcon("icons8-faq-100 (1).png")) #icon Pic File name
190 | #self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
191 | #self.button.clicked.connect(self.on_click_help)
192 |
193 |
194 | label = QLabel(self)
195 | label.setText('Model ')
196 | label.setFont(QtGui.QFont("Sanserif", 8))
197 | label.move(10, 20)
198 |
199 |
200 | self.combo = QComboBox(self)
201 | self.combo.addItem("Error Level Analysis")
202 | self.combo.addItem("VGG16")
203 | self.combo.addItem("VGG19")
204 |
205 | self.combo.setGeometry(QRect(80, 15,460 , 20))
206 |
207 |
208 |
209 | label = QLabel(self)
210 | label.setText('Image Informations')
211 | label.setFont(QtGui.QFont("Sanserif", 8))
212 | label.move(50, 75)
213 |
214 | topleft = QFrame(self)
215 | topleft.setFrameShape(QFrame.StyledPanel)
216 | topleft.setGeometry(QRect(10, 90,175 , 200))
217 |
218 | label = QLabel(self)
219 | label.setText('Image')
220 | label.setFont(QtGui.QFont("Sanserif", 8))
221 | label.move(290, 75)
222 |
223 | topleft = QFrame(self)
224 | topleft.setFrameShape(QFrame.StyledPanel)
225 | topleft.setGeometry(QRect(200, 90,200 , 200))
226 |
227 | self.show()
228 |
229 |
230 | @pyqtSlot()
231 | def back_to_Main(self):
232 | from Main_window_Final import MainWindow
233 | self.Main_window = MainWindow()
234 | self.Main_window.show()
235 | self.close()
236 |
237 | @pyqtSlot()
238 | def getfiles(self):
239 | fileName, extention = QFileDialog.getOpenFileName(self, 'Single File', 'C:\'',"*.png *.xpm *.jpg *.tiff *.jpg *.bmp")
240 | self.file_path = fileName
241 | if self.file_path != "":
242 | head, tail = os.path.split(fileName)
243 | self.line_edit.setText(tail)
244 | self.label.hide()
245 | self.label2.hide()
246 | self.label3.hide()
247 | self.label4.hide()
248 | self.label_1.hide()
249 | self.label_2.hide()
250 |
251 | self.label_1.move(410, 125)
252 | self.label_1.setText('and please wait..')
253 | self.label_1.setFont(QtGui.QFont("Sanserif", 12))
254 |
255 | self.label_2.move(410, 100)
256 | self.label_2.setText('click test')
257 | self.label_2.setFont(QtGui.QFont("Sanserif", 12))
258 |
259 |
260 | pixmap = QPixmap(self.file_path)
261 | self.label.setPixmap(pixmap)
262 | self.label.resize(190, 190)
263 | self.label.move(205, 95)
264 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
265 |
266 | #image information
267 | image = Image.open(self.file_path)
268 | width, height = image.size
269 | resolution = "Resolution "+str(width)+"X"+str(height)
270 | self.label2.setText(resolution)
271 | self.label2.setFont(QtGui.QFont("Sanserif", 8))
272 | self.label2.move(15,100)
273 |
274 | head, tail = os.path.split(self.file_path)
275 | tail2 = tail.split('.')[1]
276 | file_type = "Item Type "+str(tail2)
277 | self.label3.setText(file_type)
278 | self.label3.setFont(QtGui.QFont("Sanserif", 8))
279 | self.label3.move(15,112)
280 |
281 |
282 | size = os.path.getsize(self.file_path)
283 | size = np.int(size/1000)
284 | text = str(size) + "KB"
285 | self.label4.setText(text)
286 | self.label4.setFont(QtGui.QFont("Sanserif", 8))
287 | self.label4.move(15,124)
288 |
289 | self.label_1.show()
290 | self.label_2.show()
291 | self.label2.show()
292 | self.label3.show()
293 | self.label4.show()
294 | self.label.show()
295 | else:
296 | pass
297 |
298 |
299 | @pyqtSlot()
300 | def on_click(self):
301 | if self.file_path == "":
302 | msg = QMessageBox()
303 | msg.setIcon(QMessageBox.Critical)
304 | msg.setText("Choose image from your computer !")
305 | msg.setWindowTitle("Error")
306 | msg.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
307 | msg.exec_()
308 | else:
309 | if str(self.combo.currentText()) == "Error Level Analysis":
310 | model = ".\\sys_models\\ELA_Model.h5"
311 | self.myThread = Thread()
312 | label, prob = self.myThread.test_image_with_ela(self.file_path, model_path=model)
313 | self.myThread.start()
314 | self.close()
315 | self.result_window = ResultWindow(label, prob)
316 | self.result_window.show()
317 |
318 | elif str(self.combo.currentText()) == "VGG16":
319 | model = ".\\sys_models\\VGG16_Model.h5"
320 | self.myThread = Thread()
321 | label, prob = self.myThread.test_image_with_vgg16(self.file_path, model_path=model)
322 | self.myThread.start()
323 | self.close()
324 | self.result_window = ResultWindow(label, prob)
325 | self.result_window.show()
326 | elif str(self.combo.currentText()) == "VGG19":
327 | model = ".\\sys_models\\VGG19_Model.h5"
328 | self.myThread = Thread()
329 | label, prob = self.myThread.test_image_with_vgg19(self.file_path, model_path=model)
330 | self.myThread.start()
331 | self.close()
332 | self.result_window = ResultWindow(label, prob)
333 | self.result_window.show()
334 |
335 |
336 | @pyqtSlot()
337 | def closex(self):
338 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
339 | QMessageBox.Cancel | QMessageBox.Close)
340 | if reply== QMessageBox.Yes:
341 | self.close()
342 |
343 |
344 | @pyqtSlot()
345 | def keyPressEvent(self, event):
346 | """Close application from escape key.
347 |
348 | results in QMessageBox dialog from closeEvent, good but how/why?
349 | """
350 | if event.key() == Qt.Key_Escape:
351 | reply = QMessageBox.question(
352 | self, "Message",
353 | "Are you sure you want to quit?",
354 | QMessageBox.Close | QMessageBox.Cancel)
355 |
356 | if reply == QMessageBox.Close:
357 | self.close()
358 |
359 | @pyqtSlot()
360 | def close_main_window(self):
361 | """
362 | Generate 'question' dialog on clicking 'X' button in title bar.
363 | Reimplement the closeEvent() event handler to include a 'Question'
364 | dialog with options on how to proceed - Save, Close, Cancel buttons
365 | """
366 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
367 | QMessageBox.Cancel | QMessageBox.Close)
368 |
369 | if reply == QMessageBox.Close:
370 | self.close()
371 |
372 |
373 |
374 |
375 | if __name__ == "__main__":
376 | App = QApplication(sys.argv)
377 | App.setStyle('Fusion')
378 | window = Test_window()
379 | sys.exit(App.exec())
380 |
--------------------------------------------------------------------------------
/Source Code/Test_with_Retraind_Modules.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication , QFileDialog , QFrame,QComboBox, QLineEdit , QLabel, QMessageBox, QWidget, QPushButton
2 | from PyQt5.QtCore import *
3 | from PyQt5 import QtGui
4 | from PyQt5 import QtCore
5 | from PyQt5.QtGui import QPixmap
6 | from Result_Retraind_Window_Final import ResultWindow
7 | from PIL import Image, ImageChops, ImageEnhance
8 | from keras.models import load_model
9 | from pylab import *
10 | import os
11 |
12 |
13 | class Thread(QThread):
14 | def __init__(self):
15 | QThread.__init__(self)
16 |
17 | def __del__(self):
18 | self.wait()
19 |
20 | def test_image_with_ela(self, image_path, model_path):
21 | """
22 | Error Level Analysis
23 | :param image_path
24 | :return label[Forged , Not Forged] , prob[class probability]
25 | """
26 | # loading Model
27 | model = load_model(model_path)
28 | # Read image
29 | image_saved_path = image_path.split('.')[0] + '.saved.jpg'
30 |
31 | # calculate ELA
32 | image = Image.open(image_path).convert('RGB')
33 | image.save(image_saved_path, 'JPEG', quality=90)
34 | saved_image = Image.open(image_saved_path)
35 | ela = ImageChops.difference(image, saved_image)
36 | extrema = ela.getextrema()
37 | max_diff = max([ex[1] for ex in extrema])
38 | if max_diff == 0:
39 | max_diff = 1
40 | scale = 255.0 / max_diff
41 | ela_im = ImageEnhance.Brightness(ela).enhance(scale)
42 |
43 | # prepare image for testing
44 | image = array(ela_im.resize((128, 128))).flatten() / 255.0
45 | image = image.reshape(-1, 128, 128, 3)
46 | # prediction
47 | prob = model.predict(image)[0]
48 | idx = np.argmax(prob)
49 | pred = model.predict(image)
50 | pred = pred.argmax(axis=1)[0]
51 |
52 | label = "Forged" if pred == 1 else "Not_Forged"
53 | return label, prob[idx]
54 |
55 |
56 | def test_image_with_vgg16(self , image_path,model_path):
57 | """
58 | VGG16 GoogleNet Competition Pre-trained Model
59 | :param image_path
60 | :return label[Forged , Not Forged] , prob[class probability]
61 | """
62 | model = load_model(model_path)
63 | # Read image
64 | image = Image.open(image_path).convert('RGB')
65 |
66 | # prepare image for testing
67 | image = array(image.resize((300, 300))).flatten() / 255.0
68 | image = image.reshape(-1, 300, 300, 3)
69 |
70 | # Make predictions on the input image
71 | prob = model.predict(image)[0]
72 | idx = np.argmax(prob)
73 |
74 | # predictions
75 | prob = model.predict(image)[0]
76 | idx = np.argmax(prob)
77 | pred = model.predict(image)
78 | pred = pred.argmax(axis=1)[0]
79 |
80 | label = "Forged" if pred == 1 else "Not_Forged"
81 | return label, prob[idx]
82 |
83 | def test_image_with_vgg19(self , image_path,model_path):
84 | """
85 | VGG19 GoogleNet Competition Pre-trained Model
86 | :param image_path
87 | :return label[Forged , Not Forged] , prob[class probability]
88 | """
89 | model = load_model(model_path)
90 | # Read image
91 | image = Image.open(image_path).convert('RGB')
92 |
93 | # prepare image for testing
94 | image = array(image.resize((100, 100))).flatten() / 255.0
95 | image = image.reshape(-1, 100, 100, 3)
96 |
97 | prob = model.predict(image)[0]
98 | idx = np.argmax(prob)
99 |
100 | prob = model.predict(image)[0]
101 | idx = np.argmax(prob)
102 | pred = model.predict(image)
103 | pred = pred.argmax(axis=1)[0]
104 |
105 | label = "Forged" if pred == 1 else "Not_Forged"
106 |
107 | return label, prob[idx]
108 |
109 |
110 |
111 | class Test_window(QWidget):
112 | def __init__(self, parent = None , model_name = "ELA" , model_path = ".\\sys_models\\ELA_Model.h5" , flag = "here"):
113 | super().__init__()
114 | self.title = "IFD Application"
115 | self.top = 200
116 | self.left = 500
117 | self.width = 550
118 | self.height = 345
119 | self.file_path = ""
120 | self.model_path = model_path
121 | self.model_name = model_name
122 | self.model = ""
123 | self.flag = flag
124 | self.init_window()
125 |
126 | def init_window(self):
127 | """initialize window"""
128 | self.setWindowTitle(self.title)
129 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico")) #icon Pic File name
130 | self.setGeometry(self.left , self.top , self.width , self.height)
131 | self.setFixedSize(self.width , self.height)
132 | self.label = QLabel(self)
133 | self.label2 = QLabel(self)
134 | self.label3 = QLabel(self)
135 | self.label4 = QLabel(self)
136 | self.label_1 = QLabel(self)
137 | self.label_2 = QLabel(self)
138 |
139 | #quit = QAction("Quit", self)
140 | #quit.triggered.connect(self.closex)
141 |
142 |
143 | #Label
144 | label = QLabel(self)
145 | label.move(10,44)
146 | label.setText('Image Name ')
147 | label.setFont(QtGui.QFont("Sanserif" , 8))
148 |
149 | #text Box
150 | self.line_edit = QLineEdit(self)
151 | self.line_edit.setReadOnly(True)
152 | self.line_edit.setFont(QtGui.QFont("Sanserif", 8))
153 | self.line_edit.setGeometry(QRect(80, 40, 365, 20))
154 | self.line_edit.setPlaceholderText("image Name here!")
155 |
156 | #Button
157 | self.button = QPushButton("Browse", self)
158 | self.button.setGeometry(QRect(450, 40, 90, 20))
159 | self.button.setToolTip("Browse image from your computer to start test!") # Notice using h2 tags From Html
160 | self.button.setIcon(QtGui.QIcon("698831-icon-105-folder-add-512.png")) #icon Pic File name
161 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
162 | self.button.clicked.connect(self.getfiles)
163 |
164 | #Button
165 | self.button = QPushButton("Test", self)
166 | self.button.setGeometry(QRect(270, 310, 90, 20))
167 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
168 | self.button.setIcon(QtGui.QIcon("698827-icon-101-folder-search-512.png")) #icon Pic File name
169 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
170 | self.button.clicked.connect(self.on_click)
171 |
172 | #Button
173 | self.button = QPushButton("Back", self)
174 | self.button.setGeometry(QRect(180, 310, 90, 20))
175 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
176 | self.button.setIcon(QtGui.QIcon("repeat-pngrepo-com.png")) #icon Pic File name
177 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
178 | self.button.clicked.connect(self.back_to_Main)
179 |
180 |
181 | #Button
182 | self.button = QPushButton(" Quit", self)
183 | self.button.setGeometry(QRect(360, 310, 90, 20))
184 | self.button.setToolTip("Close the program!") # Notice using h2 tags From Html
185 | self.button.setIcon(QtGui.QIcon("cancel-symbol-transparent-9.png")) #icon Pic File name
186 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
187 | self.button.clicked.connect(self.close_main_window)
188 |
189 | #Button
190 | #self.button = QPushButton("Help", self)
191 | #self.button.setGeometry(QRect(450, 310, 90, 20))
192 | #self.button.setToolTip("Help!") # Notice using h2 tags From Html
193 | #self.button.setIcon(QtGui.QIcon("icons8-faq-100 (1).png")) #icon Pic File name
194 | #self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
195 | #self.button.clicked.connect(self.on_click_help)
196 |
197 |
198 | label = QLabel(self)
199 | label.setText('Model ')
200 | label.setFont(QtGui.QFont("Sanserif", 8))
201 | label.move(10, 20)
202 |
203 | head, tail = os.path.split(self.model_name)
204 | self.combo = QComboBox(self)
205 | self.combo.addItem(tail)
206 |
207 | self.combo.setGeometry(QRect(80, 15,460 , 20))
208 |
209 | label = QLabel(self)
210 | label.setText('Image Informations')
211 | label.setFont(QtGui.QFont("Sanserif", 8))
212 | label.move(50, 75)
213 |
214 | topleft = QFrame(self)
215 | topleft.setFrameShape(QFrame.StyledPanel)
216 | topleft.setGeometry(QRect(10, 90,175 , 200))
217 |
218 | label = QLabel(self)
219 | label.setText('Image')
220 | label.setFont(QtGui.QFont("Sanserif", 8))
221 | label.move(290, 75)
222 |
223 | topleft = QFrame(self)
224 | topleft.setFrameShape(QFrame.StyledPanel)
225 | topleft.setGeometry(QRect(200, 90,200 , 200))
226 |
227 | self.show()
228 |
229 |
230 | @pyqtSlot()
231 | def back_to_Main(self):
232 | from Main_window_Final import MainWindow
233 | self.Main_window = MainWindow()
234 | self.Main_window.show()
235 | self.close()
236 |
237 | @pyqtSlot()
238 | def getfiles(self):
239 | fileName, extention = QFileDialog.getOpenFileName(self, 'Single File', 'C:\'',"*.png *.xpm *.jpg *.tiff *.jpg *.bmp")
240 | self.file_path = fileName
241 | if self.file_path != "":
242 | head, tail = os.path.split(fileName)
243 | self.line_edit.setText(tail)
244 |
245 | self.label.hide()
246 | self.label2.hide()
247 | self.label3.hide()
248 | self.label4.hide()
249 | self.label_1.hide()
250 | self.label_2.hide()
251 |
252 | self.label_1.move(410, 125)
253 | self.label_1.setText('and please wait..')
254 | self.label_1.setFont(QtGui.QFont("Sanserif", 12))
255 |
256 | self.label_2.move(410, 100)
257 | self.label_2.setText('click test')
258 | self.label_2.setFont(QtGui.QFont("Sanserif", 12))
259 |
260 | pixmap = QPixmap(self.file_path)
261 | self.label.setPixmap(pixmap)
262 | self.label.resize(190, 190)
263 | self.label.move(205, 95)
264 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
265 |
266 | # image information
267 | image = Image.open(self.file_path)
268 | width, height = image.size
269 | resolution = "Resolution " + str(width) + "X" + str(height)
270 | self.label2.setText(resolution)
271 | self.label2.setFont(QtGui.QFont("Sanserif", 8))
272 | self.label2.move(15, 100)
273 |
274 | head, tail = os.path.split(self.file_path)
275 | tail2 = tail.split('.')[1]
276 | file_type = "Item Type " + str(tail2)
277 | self.label3.setText(file_type)
278 | self.label3.setFont(QtGui.QFont("Sanserif", 8))
279 | self.label3.move(15, 112)
280 |
281 | size = os.path.getsize(self.file_path)
282 | size = np.int(size / 1000)
283 | text = str(size) + "KB"
284 | self.label4.setText(text)
285 | self.label4.setFont(QtGui.QFont("Sanserif", 8))
286 | self.label4.move(15, 124)
287 |
288 | self.label2.show()
289 | self.label3.show()
290 | self.label4.show()
291 | self.label.show()
292 | self.label_1.show()
293 | self.label_2.show()
294 |
295 | else:
296 | self.file_path = fileName
297 | head, tail = os.path.split(fileName)
298 | self.line_edit.setText(tail)
299 |
300 | self.label.hide()
301 | self.label2.hide()
302 | self.label3.hide()
303 | self.label4.hide()
304 |
305 | self.label_1.move(410, 125)
306 | self.label_1.setText('and please wait..')
307 | self.label_1.setFont(QtGui.QFont("Sanserif", 12))
308 |
309 | self.label_2.move(410, 100)
310 | self.label_2.setText('click test')
311 | self.label_2.setFont(QtGui.QFont("Sanserif", 12))
312 |
313 | pixmap = QPixmap(self.file_path)
314 | self.label.setPixmap(pixmap)
315 | self.label.resize(190, 190)
316 | self.label.move(205, 95)
317 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
318 |
319 | # image information
320 | image = Image.open(self.file_path)
321 | width, height = image.size
322 | resolution = "Resolution " + str(width) + "X" + str(height)
323 | self.label2.setText(resolution)
324 | self.label2.setFont(QtGui.QFont("Sanserif", 8))
325 | self.label2.move(15, 100)
326 |
327 | head, tail = os.path.split(self.file_path)
328 | tail2 = tail.split('.')[1]
329 | file_type = "Item Type " + str(tail2)
330 | self.label3.setText(file_type)
331 | self.label3.setFont(QtGui.QFont("Sanserif", 8))
332 | self.label3.move(15, 112)
333 |
334 | size = os.path.getsize(self.file_path)
335 | size = np.int(size / 1000)
336 | text = str(size) + "KB"
337 | self.label4.setText(text)
338 | self.label4.setFont(QtGui.QFont("Sanserif", 8))
339 | self.label4.move(15, 124)
340 |
341 | self.label_1.show()
342 | self.label_2.show()
343 | self.label2.show()
344 | self.label3.show()
345 | self.label4.show()
346 |
347 | @pyqtSlot()
348 | def on_click(self):
349 | if self.file_path == "":
350 | msg = QMessageBox()
351 | msg.setIcon(QMessageBox.Critical)
352 | msg.setText("Choose image from your computer !")
353 | msg.setWindowTitle("Error")
354 | msg.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
355 | msg.exec_()
356 | else:
357 | file_name = self.model_name
358 | name_1 = file_name.split('.')[0]
359 | print("*"*50)
360 | print("Test_with_Retraind_window")
361 | print(name_1)
362 | name_2 = name_1.split('_')[0]
363 | print(name_2)
364 | print("*"*50)
365 | if str(name_2) == "ELA":
366 | model = self.model_path
367 | self.myThread = Thread()
368 | label, prob = self.myThread.test_image_with_ela(self.file_path, model_path=model)
369 | self.myThread.start()
370 | self.close()
371 | self.result_window = ResultWindow(label, prob , model_path=self.model_path ,model_name = name_2)
372 | self.result_window.show()
373 | if str(name_2) == "VGG16":
374 | model = self.model_path
375 | self.myThread = Thread()
376 | label, prob = self.myThread.test_image_with_vgg16(self.file_path, model_path=model)
377 | self.myThread.start()
378 | self.close()
379 | self.result_window = ResultWindow(label, prob , model_path=self.model_path ,model_name = name_2)
380 | self.result_window.show()
381 | if str(self.combo.currentText()) == "VGG19":
382 | model = self.model_path
383 | self.myThread = Thread()
384 | label, prob = self.myThread.test_image_with_vgg19(self.file_path, model_path=model)
385 | self.myThread.start()
386 | self.close()
387 | self.result_window = ResultWindow(label, prob , model_path=self.model_path ,model_name = name_2)
388 | self.result_window.show()
389 |
390 | @pyqtSlot()
391 | def closex(self):
392 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
393 | QMessageBox.Cancel | QMessageBox.Close)
394 | if reply== QMessageBox.Yes:
395 | self.close()
396 |
397 |
398 | @pyqtSlot()
399 | def keyPressEvent(self, event):
400 | """Close application from escape key.
401 |
402 | results in QMessageBox dialog from closeEvent, good but how/why?
403 | """
404 | if event.key() == Qt.Key_Escape:
405 | reply = QMessageBox.question(
406 | self, "Message",
407 | "Are you sure you want to quit?",
408 | QMessageBox.Close | QMessageBox.Cancel)
409 |
410 | if reply == QMessageBox.Close:
411 | self.close()
412 |
413 | @pyqtSlot()
414 | def close_main_window(self):
415 | """
416 | Generate 'question' dialog on clicking 'X' button in title bar.
417 | Reimplement the closeEvent() event handler to include a 'Question'
418 | dialog with options on how to proceed - Save, Close, Cancel buttons
419 | """
420 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
421 | QMessageBox.Cancel | QMessageBox.Close)
422 |
423 | if reply == QMessageBox.Close:
424 | self.close()
425 |
426 |
427 |
428 |
429 | if __name__ == "__main__":
430 | App = QApplication(sys.argv)
431 | App.setStyle('Fusion')
432 | window = Test_window()
433 | sys.exit(App.exec())
434 |
--------------------------------------------------------------------------------
/Source Code/Training_window_Final.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication , QFileDialog , QFrame,QComboBox, QLineEdit , QLabel, QAction, QMessageBox, QWidget, QPushButton
2 | from PyQt5.QtCore import *
3 | from PyQt5 import QtGui
4 | from PyQt5 import QtCore
5 | from PyQt5.QtGui import QPixmap
6 |
7 | from pylab import *
8 |
9 | import sys
10 | import shutil
11 | import random
12 | import os
13 | import csv
14 |
15 | import ELA_Training_Module_Final
16 | import VGG16_Training_Module_Final
17 | import VGG19_Training_Module_Final
18 |
19 | #import Test_with_Retraind_Modules
20 |
21 | from help_Window import HelpWindow
22 |
23 |
24 | class thread(QThread):
25 | def __init__(self):
26 | QThread.__init__(self)
27 | def __del__(self):
28 | self.wait()
29 |
30 | def train_model(self , CSV_file , lr , ep, flag = ""):
31 | if flag == "ELA":
32 | plot , model = ELA_Training_Module_Final.train_Ela_Model(CSV_file , lr , ep)
33 | return plot , model
34 | elif flag == "VGG16":
35 | plot, model = VGG16_Training_Module_Final.train_VGG16_Model(CSV_file , lr , ep)
36 | return plot, model
37 | elif flag == "VGG19":
38 | plot, model = VGG19_Training_Module_Final.train_VGG19_Model(CSV_file , lr , ep)
39 | return plot, model
40 |
41 |
42 | class Training_window(QWidget):
43 | def __init__(self, parent = None):
44 | """constructor to create a new window with charactersitis after create object from class window"""
45 | super().__init__()
46 | self.title = "IFD Application"
47 | self.top = 200
48 | self.left = 500
49 | self.width = 550
50 | self.height = 390
51 | self.file_path_Authentic = ""
52 | self.file_path_Tampered = ""
53 | self.csv_file = ""
54 | self.plot = ""
55 | self.model = ""
56 | self.current = os.getcwd()
57 | self.Dataset = "\CSV_files"
58 | self.figures = "\Figures"
59 | self.Models = "\Re_Traind_Models"
60 | try:
61 | # Create target Directory
62 | os.mkdir(self.current + self.Dataset)
63 | except FileExistsError:
64 | pass
65 | try:
66 | # Create target Directory
67 | os.mkdir(self.current + self.figures)
68 | except FileExistsError:
69 | pass
70 | try:
71 | # Create target Directory
72 | os.mkdir(self.current + self.Models)
73 | except FileExistsError:
74 | pass
75 |
76 | self.init_window()
77 |
78 | def init_window(self):
79 | """initialize window"""
80 | self.setWindowTitle(self.title)
81 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico")) #icon Pic File name
82 | self.setGeometry(self.left , self.top , self.width , self.height)
83 | self.setFixedSize(self.width , self.height)
84 | self.label = QLabel(self)
85 | self.label2 = QLabel(self)
86 | self.label3 = QLabel(self)
87 | self.label4 = QLabel(self)
88 | self.label_1 = QLabel(self)
89 | self.label_2 = QLabel(self)
90 |
91 | quit = QAction("Quit", self)
92 | quit.triggered.connect(self.closex)
93 |
94 | #Label
95 | label = QLabel(self)
96 | label.move(10,44)
97 | label.setText('Tampered')
98 | label.setFont(QtGui.QFont("Sanserif" ,8))
99 |
100 | #Label
101 | label = QLabel(self)
102 | label.move(10,68)
103 | label.setText('Authentic')
104 | label.setFont(QtGui.QFont("Sanserif" , 8))
105 |
106 | #label
107 | label = QLabel(self)
108 | label.setText('learning Rate ')
109 | label.setFont(QtGui.QFont("Sanserif", 8))
110 | label.move(368, 144)
111 |
112 | #label
113 | label = QLabel(self)
114 | label.setText('epochs')
115 | label.setFont(QtGui.QFont("Sanserif", 8))
116 | label.move(368, 165)
117 |
118 | #label
119 | label = QLabel(self)
120 | label.setText('Training Parameters')
121 | label.setFont(QtGui.QFont("Sanserif", 8))
122 | label.move(365, 110)
123 |
124 | #label
125 | label = QLabel(self)
126 | label.setText('Training Result')
127 | label.setFont(QtGui.QFont("Sanserif", 8))
128 | label.move(10, 90)
129 |
130 | #text Box
131 | self.line_edit_1 = QLineEdit(self)
132 | self.line_edit_1.setReadOnly(True)
133 | self.line_edit_1.setFont(QtGui.QFont("Sanserif", 8))
134 | self.line_edit_1.setGeometry(QRect(80, 40, 365, 20))
135 | self.line_edit_1.setPlaceholderText("Browse Tampered images Directory")
136 |
137 | #text Box
138 | self.line_edit_2 = QLineEdit(self)
139 | self.line_edit_2.setReadOnly(True)
140 | self.line_edit_2.setFont(QtGui.QFont("Sanserif", 8))
141 | self.line_edit_2.setGeometry(QRect(80, 64, 365, 20))
142 | self.line_edit_2.setPlaceholderText("Browse ِAuthentic images Directory")
143 |
144 | #text Box
145 | self.lr = QLineEdit(self)
146 | self.lr.setFont(QtGui.QFont("Sanserif", 8))
147 | self.lr.setGeometry(QRect(436, 140, 70, 20))
148 | self.lr.setPlaceholderText("learning Rate")
149 |
150 | #text Box
151 | self.ep= QLineEdit(self)
152 | self.ep.setFont(QtGui.QFont("Sanserif", 8))
153 | self.ep.setGeometry(QRect(436, 165, 70, 20))
154 | self.ep.setPlaceholderText("epochs")
155 |
156 |
157 |
158 | #Button
159 | self.button_1 = QPushButton("Browse", self)
160 | self.button_1.setGeometry(QRect(450, 40, 90, 20))
161 | self.button_1.setToolTip("Browse image from your computer to start test!") # Notice using h2 tags From Html
162 | self.button_1.setIcon(QtGui.QIcon("698831-icon-105-folder-add-512.png")) #icon Pic File name
163 | self.button_1.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
164 | self.button_1.clicked.connect(self.getfiles_Tampered)
165 |
166 | # Button
167 | self.button_2 = QPushButton("Browse", self)
168 | self.button_2.setGeometry(QRect(450, 64, 90, 20))
169 | self.button_2.setToolTip(
170 | "Browse image from your computer to start test!") # Notice using h2 tags From Html
171 | self.button_2.setIcon(QtGui.QIcon("698831-icon-105-folder-add-512.png")) # icon Pic File name
172 | self.button_2.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
173 | self.button_2.clicked.connect(self.getfiles_Authentic )
174 |
175 | # Button
176 | self.button_3 = QPushButton("Create CSV file", self)
177 | self.button_3.setGeometry(QRect(440, 88, 100, 20))
178 | self.button_3.setToolTip("Browse image from your computer to start test!") # Notice using h2 tags From Html
179 | self.button_3.setIcon(QtGui.QIcon("create.png")) # icon Pic File name
180 | self.button_3.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
181 | self.button_3.clicked.connect(self.Make_CSV_file )
182 |
183 | #Button
184 | self.button = QPushButton("test", self)
185 | self.button.setGeometry(QRect(90, 360, 90, 20))
186 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
187 | self.button.setIcon(QtGui.QIcon("698827-icon-101-folder-search-512.png")) #icon Pic File name
188 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
189 | self.button.clicked.connect(self.go_to_test_window)
190 |
191 | #Button
192 | self.button = QPushButton("Back", self)
193 | self.button.setGeometry(QRect(180, 360, 90, 20))
194 | self.button.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
195 | self.button.setIcon(QtGui.QIcon("repeat-pngrepo-com.png")) #icon Pic File name
196 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
197 | self.button.clicked.connect(self.back_to_Main)
198 |
199 | #Button
200 | self.button_4 = QPushButton("Train", self)
201 | self.button_4.setGeometry(QRect(270, 360, 90, 20))
202 | self.button_4.setToolTip("test image either Forged or Not Forged!") # Notice using h2 tags From Html
203 | self.button_4.setIcon(QtGui.QIcon("Rocket-icon-blue.png")) #icon Pic File name
204 | self.button_4.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
205 | self.button_4.clicked.connect(self.on_click)
206 |
207 | #Button
208 | self.button = QPushButton(" Quit", self)
209 | self.button.setGeometry(QRect(360, 360, 90, 20))
210 | self.button.setToolTip("Close the program!") # Notice using h2 tags From Html
211 | self.button.setIcon(QtGui.QIcon("cancel-symbol-transparent-9.png")) #icon Pic File name
212 | self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
213 | self.button.clicked.connect(self.close_main_window)
214 |
215 | #Button
216 | #self.button = QPushButton("Help", self)
217 | #self.button.setGeometry(QRect(450, 360, 90, 20))
218 | #self.button.setToolTip("Help!") # Notice using h2 tags From Html
219 | #self.button.setIcon(QtGui.QIcon("icons8-faq-100 (1).png")) #icon Pic File name
220 | #self.button.setIconSize(QtCore.QSize(15, 15)) # to change icon Size
221 | #self.button.clicked.connect(self.on_click_help)
222 |
223 |
224 | label = QLabel(self)
225 | label.setText('Model ')
226 | label.setFont(QtGui.QFont("Sanserif", 8))
227 | label.move(10, 20)
228 |
229 |
230 | self.combo = QComboBox(self)
231 | self.combo.addItem("Error Level Analysis")
232 | self.combo.setToolTip("ELA")
233 | self.combo.addItem("VGG16")
234 | self.combo.setToolTip("VGG16")
235 | self.combo.addItem("VGG19")
236 | self.combo.setToolTip("VGG19")
237 |
238 | self.combo.setGeometry(QRect(80, 15,460 , 20))
239 |
240 |
241 |
242 | #topright = QFrame(self)
243 | #topright.setFrameShape(QFrame.StyledPanel)
244 | #topright.setGeometry(QRect(365, 125,150 , 230))
245 |
246 |
247 | topleft = QFrame(self)
248 | topleft.setFrameShape(QFrame.StyledPanel)
249 | topleft.setGeometry(QRect(10, 105,350 , 250))
250 | self.show()
251 |
252 | @pyqtSlot()
253 | def go_to_test_window(self):
254 | from Test_with_Retraind_Modules import Test_window
255 | head, tail = os.path.split(self.model)
256 | print("*"*50)
257 | print("Training_Window_Final ")
258 | print(tail)
259 | print(self.model)
260 | print("*"*50)
261 | self.Test_window = Test_window(self ,model_path= self.model , model_name=tail)
262 | self.Test_window.show()
263 | self.close()
264 |
265 | @pyqtSlot()
266 | def back_to_Main(self):
267 | from Main_window_Final import MainWindow
268 | self.Main_window = MainWindow()
269 | self.Main_window.show()
270 | self.close()
271 |
272 | @pyqtSlot()
273 | def getfiles_Authentic(self):
274 | fileName = QFileDialog.getExistingDirectory(self, 'Files', 'C:\'')
275 | self.file_path_Authentic = fileName
276 | self.line_edit_2.setText(fileName)
277 |
278 | @pyqtSlot()
279 | def getfiles_Tampered(self):
280 | fileName = QFileDialog.getExistingDirectory(self, 'Files', 'C:\'')
281 | self.file_path_Tampered = fileName
282 | self.line_edit_1.setText(fileName)
283 |
284 | @pyqtSlot()
285 | def Make_CSV_file(self):
286 | if self.file_path_Tampered == "" or self.file_path_Authentic == "":
287 | msg = QMessageBox()
288 | msg.setIcon(QMessageBox.Critical)
289 | msg.setText("Browse Another Authentic or Tampered Directory")
290 | msg.setWindowTitle("Error")
291 | msg.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
292 | msg.exec_()
293 | else:
294 | forged_images_path = self.file_path_Tampered
295 | Not_forged_images_path = self.file_path_Authentic
296 | forged = os.listdir(forged_images_path)
297 | Not_forged = os.listdir(Not_forged_images_path)
298 | file_number =random.randint(1, 1000000)
299 | CSV_file_name = self.combo.currentText()+"_"+str(file_number)+".csv"
300 | with open(CSV_file_name, "w", encoding="utf-8", newline='') as new_file:
301 | csv_writer = csv.writer(new_file)
302 | for (i, file) in enumerate(forged):
303 | csv_writer.writerow([ forged_images_path+"/" + file, 1])
304 | for (i, file) in enumerate(Not_forged):
305 | csv_writer.writerow([Not_forged_images_path+"/" + file, 0])
306 | new_file.close()
307 | shutil.move(self.current+"\\"+CSV_file_name, self.current + self.Dataset)
308 | self.csv_file = self.current+ self.Dataset+"\\"+CSV_file_name
309 | msg = QMessageBox()
310 | msg.setIcon(QMessageBox.Question)
311 | msg.setText("Dataset prepared click Train to train the Model")
312 | msg.setWindowTitle("Done")
313 | msg.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
314 | msg.exec_()
315 |
316 | def on_click(self):
317 | if self.file_path_Authentic == "" or self.file_path_Tampered == "" or self.csv_file == "":
318 | msg = QMessageBox()
319 | msg.setIcon(QMessageBox.Critical)
320 | msg.setText("Broswe Authentic Directory or Tampered Directory and Create Csv File")
321 | msg.setWindowTitle("Error")
322 | msg.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico"))
323 | msg.exec_()
324 | else:
325 | if str(self.combo.currentText()) == "Error Level Analysis" :
326 | self.button_1.setEnabled(False)
327 | self.button_2.setEnabled(False)
328 | self.button_3.setEnabled(False)
329 | self.button_4.setEnabled(False)
330 | lr = float(self.lr.text())
331 | ep = int(self.ep.text())
332 | self.myThread = thread()
333 | plot , model = self.myThread.train_model(self.csv_file , lr , ep , "ELA")
334 | self.myThread.start()
335 | self.model = model
336 |
337 | pixmap = QPixmap(plot)
338 | self.label.setPixmap(pixmap)
339 | self.label.resize(320, 240)
340 | self.label.move(10, 110)
341 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
342 | self.label.show()
343 |
344 | elif str(self.combo.currentText()) == "VGG16":
345 | self.button_1.setEnabled(False)
346 | self.button_2.setEnabled(False)
347 | self.button_3.setEnabled(False)
348 | self.button_4.setEnabled(False)
349 | lr = float(self.lr.text())
350 | ep = int(self.ep.text())
351 | self.myThread = thread()
352 | plot , model = self.myThread.train_model(self.csv_file, lr , ep , "VGG16")
353 | self.myThread.start()
354 | self.model = model
355 |
356 | pixmap = QPixmap(plot)
357 | self.label.setPixmap(pixmap)
358 | self.label.resize(320, 240)
359 | self.label.move(10, 110)
360 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
361 | self.label.show()
362 |
363 | elif str(self.combo.currentText()) == "VGG19":
364 | self.button_1.setEnabled(False)
365 | self.button_2.setEnabled(False)
366 | self.button_3.setEnabled(False)
367 | self.button_4.setEnabled(False)
368 | lr = float(self.lr.text())
369 | ep = int(self.ep.text())
370 | self.myThread = thread()
371 | plot , model = self.myThread.train_model(self.csv_file, lr , ep , "VGG19")
372 | self.myThread.start()
373 | self.model = model
374 |
375 | pixmap = QPixmap(plot)
376 | self.label.setPixmap(pixmap)
377 | self.label.resize(320, 240)
378 | self.label.move(10, 110)
379 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
380 | self.label.show()
381 |
382 | @pyqtSlot()
383 | def on_click_help(self):
384 | self.help_window = HelpWindow()
385 | self.help_window .show()
386 | self.showMinimized()
387 |
388 |
389 | @pyqtSlot()
390 | def closex(self):
391 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
392 | QMessageBox.Cancel | QMessageBox.Close)
393 | if reply== QMessageBox.Yes:
394 | self.close()
395 |
396 |
397 | @pyqtSlot()
398 | def keyPressEvent(self, event):
399 | """Close application from escape key.
400 |
401 | results in QMessageBox dialog from closeEvent, good but how/why?
402 | """
403 | if event.key() == Qt.Key_Escape:
404 | reply = QMessageBox.question(
405 | self, "Message",
406 | "Are you sure you want to quit?",
407 | QMessageBox.Close | QMessageBox.Cancel)
408 |
409 | if reply == QMessageBox.Close:
410 | self.close()
411 |
412 | @pyqtSlot()
413 | def close_main_window(self):
414 | """
415 | Generate 'question' dialog on clicking 'X' button in title bar.
416 | Reimplement the closeEvent() event handler to include a 'Question'
417 | dialog with options on how to proceed - Save, Close, Cancel buttons
418 | """
419 | reply = QMessageBox.question(self, "Quit", "Are you sure you want to quit?",
420 | QMessageBox.Cancel | QMessageBox.Close)
421 |
422 | if reply == QMessageBox.Close:
423 | self.close()
424 |
425 |
426 |
427 |
428 | if __name__ == "__main__":
429 | App = QApplication(sys.argv)
430 | App.setStyle('Fusion')
431 | window = Training_window()
432 | sys.exit(App.exec())
--------------------------------------------------------------------------------
/Source Code/VGG16_Training_Module_Final.py:
--------------------------------------------------------------------------------
1 | from sklearn.model_selection import train_test_split
2 | from keras.utils.np_utils import to_categorical
3 | from pylab import *
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 | from keras import models
7 | from keras import layers
8 | import itertools
9 | from sklearn.metrics import confusion_matrix
10 | from keras import optimizers
11 | from PIL import Image
12 | import pandas as pd
13 | from keras.applications.vgg16 import VGG16
14 | import os
15 | import random
16 |
17 | def train_VGG16_Model(csv_file , lr , ep):
18 | def Read_image(path):
19 | image = Image.open(path).convert('RGB')
20 | return image
21 |
22 | X = []
23 | Y = []
24 | dataset = pd.read_csv(csv_file)
25 | for index, row in dataset.iterrows():
26 | X.append(array(Read_image(row[0]).resize((100, 100))).flatten() / 255.0)
27 | Y.append(row[1])
28 |
29 | X = np.array(X)
30 | Y = to_categorical(Y, 2)
31 | X = X.reshape(-1, 100, 100, 3)
32 |
33 | X_train, X_val, Y_train, Y_val = train_test_split(X, Y, test_size=0.20, random_state=5)
34 |
35 | vgg_conv = VGG16(weights='imagenet', include_top=False, input_shape=(100, 100, 3))
36 |
37 | model = models.Sequential()
38 | #Note
39 | for layer in vgg_conv.layers[:-5]:
40 | layer.trainable = False
41 |
42 | for layer in vgg_conv.layers:
43 | print(layer, layer.trainable)
44 |
45 | model.add(vgg_conv)
46 | model.add(layers.Flatten())
47 | model.add(layers.Dense(1024, activation='relu'))
48 | model.add(layers.Dropout(0.25))
49 | model.add(layers.Dense(2, activation='softmax'))
50 |
51 | model.compile(loss='binary_crossentropy',
52 | optimizer=optimizers.RMSprop(lr=lr),
53 | metrics=['accuracy'])
54 | epochs = ep
55 | batch_size = 20
56 |
57 | history = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, validation_data=(X_val, Y_val),verbose=2)
58 | fig, ax = plt.subplots(3, 1)
59 | ax[0].plot(history.history['loss'], color='b', label="Training loss")
60 | ax[0].plot(history.history['val_loss'], color='r', label="validation loss", axes=ax[0])
61 | legend = ax[0].legend(loc='best', shadow=True)
62 |
63 | ax[1].plot(history.history['acc'], color='b', label="Training accuracy")
64 | ax[1].plot(history.history['val_acc'], color='r', label="Validation accuracy")
65 | legend = ax[1].legend(loc='best', shadow=True)
66 |
67 | def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues):
68 | plt.imshow(cm, interpolation='nearest', cmap=cmap)
69 | plt.title(title)
70 | plt.colorbar()
71 | tick_marks = np.arange(len(classes))
72 | plt.xticks(tick_marks, classes, rotation=45)
73 | plt.yticks(tick_marks, classes)
74 |
75 | if normalize:
76 | cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
77 |
78 | thresh = cm.max() / 2.
79 | for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
80 | plt.text(j, i, cm[i, j], horizontalalignment="center", color="white" if cm[i, j] > thresh else "black")
81 |
82 | plt.tight_layout()
83 | plt.ylabel('True label')
84 | plt.xlabel('Predicted label')
85 |
86 | # Predict the values from the validation dataset
87 | Y_pred = model.predict(X_val)
88 | # Convert predictions classes to one hot vectors
89 | Y_pred_classes = np.argmax(Y_pred, axis=1)
90 | # Convert validation observations to one hot vectors
91 | Y_true = np.argmax(Y_val, axis=1)
92 | # compute the confusion matrix
93 | confusion_mtx = confusion_matrix(Y_true, Y_pred_classes)
94 | # plot the confusion matrix
95 | plot_confusion_matrix(confusion_mtx, classes=range(2))
96 |
97 | image_path = os.getcwd()+"\\Figures"
98 | Models_path = os.getcwd()+"\\Re_Traind_Models"
99 | file_number =random.randint(1, 1000000)
100 | plot_Name = image_path+"\\VGG16_"+str(file_number)+".png"
101 | Model_Name = Models_path+"\\VGG16_"+str(file_number)+".h5"
102 | plt.savefig(plot_Name , transparent =True , bbox_incehs="tight" , pad_inches = 2 , dpi = 50)
103 | model.save(Model_Name)
104 | return plot_Name , Model_Name
105 |
106 |
--------------------------------------------------------------------------------
/Source Code/VGG19_Training_Module_Final.py:
--------------------------------------------------------------------------------
1 | from sklearn.model_selection import train_test_split
2 | from keras.utils.np_utils import to_categorical
3 | from pylab import *
4 | from keras.callbacks import LearningRateScheduler
5 | from keras import models
6 | from keras import layers
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | from keras.applications.vgg19 import VGG19
10 | import itertools
11 | from sklearn.metrics import confusion_matrix
12 | from keras import optimizers
13 | from PIL import Image
14 | import pandas as pd
15 | import os
16 | import random
17 |
18 | def train_VGG19_Model(csv_file , lr , ep):
19 | def step_decay_schedule(initial_lr=1e-3, decay_factor=0.75, step_size=10):
20 | def schedule(epoch):
21 | return initial_lr * (decay_factor ** np.floor(epoch / step_size))
22 | return LearningRateScheduler(schedule)
23 |
24 |
25 | def Read_image(path):
26 | im = Image.open(path).convert('RGB')
27 | return im
28 |
29 |
30 | X = []
31 | Y = []
32 | dataset = pd.read_csv(csv_file)
33 | for index, row in dataset.iterrows():
34 | X.append(array(Read_image(row[0]).resize((100, 100))).flatten() / 255.0)
35 | Y.append(row[1])
36 |
37 | X = np.array(X)
38 | Y = to_categorical(Y, 2)
39 | X = X.reshape(-1, 100, 100, 3)
40 | X_train, X_val, Y_train, Y_val = train_test_split(X, Y, test_size=0.20, random_state=5)
41 |
42 | # Load the VGG model
43 | vgg_conv = VGG19(weights='imagenet', include_top=False, input_shape=(100, 100, 3))
44 |
45 | # Create the model
46 | model = models.Sequential()
47 | # Freeze the layers the first layers
48 | for layer in vgg_conv.layers[:-5]:
49 | layer.trainable = False
50 |
51 | # Check the trainabl status of the individual layers
52 | for layer in vgg_conv.layers:
53 | print(layer, layer.trainable)
54 |
55 |
56 |
57 | model.add(vgg_conv)
58 | model.summary()
59 | model.add(layers.Flatten())
60 | model.add(layers.Dense(1024, activation='relu'))
61 | model.add(layers.Dropout(0.50))
62 | model.add(layers.Dense(1024, activation='relu'))
63 | model.add(layers.Dropout(0.50))
64 | model.add(layers.Dense(2, activation='softmax'))
65 |
66 | optimizer = optimizers.Adagrad(lr=lr, epsilon=None, decay=0.0)
67 | model.compile(optimizer=optimizer,
68 | loss="mean_squared_error",
69 | metrics=["accuracy"])
70 |
71 | lr_sched = step_decay_schedule(initial_lr=1e-4, decay_factor=0.75, step_size=2)
72 |
73 | epochs = ep
74 | batch_size = 20
75 |
76 | history = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, validation_data=(X_val, Y_val), verbose=2,callbacks=[lr_sched])
77 | # Plot the loss and accuracy curves for training and validation
78 | fig, ax = plt.subplots(3, 1)
79 | ax[0].plot(history.history['loss'], color='b', label="Training loss")
80 | ax[0].plot(history.history['val_loss'], color='r', label="validation loss", axes=ax[0])
81 | legend = ax[0].legend(loc='best', shadow=True)
82 |
83 | ax[1].plot(history.history['acc'], color='b', label="Training accuracy")
84 | ax[1].plot(history.history['val_acc'], color='r', label="Validation accuracy")
85 | legend = ax[1].legend(loc='best', shadow=True)
86 |
87 |
88 | def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues):
89 | plt.imshow(cm, interpolation='nearest', cmap=cmap)
90 | plt.title(title)
91 | plt.colorbar()
92 | tick_marks = np.arange(len(classes))
93 | plt.xticks(tick_marks, classes, rotation=45)
94 | plt.yticks(tick_marks, classes)
95 |
96 | if normalize:
97 | cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
98 |
99 | thresh = cm.max() / 2.
100 | for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
101 | plt.text(j, i, cm[i, j], horizontalalignment="center", color="white" if cm[i, j] > thresh else "black")
102 |
103 | plt.tight_layout()
104 | plt.ylabel('True label')
105 | plt.xlabel('Predicted label')
106 |
107 |
108 | # Predict the values from the validation dataset
109 | Y_pred = model.predict(X_val)
110 | # Convert predictions classes to one hot vectors
111 | Y_pred_classes = np.argmax(Y_pred, axis=1)
112 | # Convert validation observations to one hot vectors
113 | Y_true = np.argmax(Y_val, axis=1)
114 | # compute the confusion matrix
115 | confusion_mtx = confusion_matrix(Y_true, Y_pred_classes)
116 | # plot the confusion matrix
117 | plot_confusion_matrix(confusion_mtx, classes=range(2))
118 |
119 | image_path = os.getcwd()+"\\Figures"
120 | Models_path = os.getcwd()+"\\Re_Traind_Models"
121 | file_number =random.randint(1, 1000000)
122 | plot_Name = image_path+"\\VGG19_"+str(file_number)+".png"
123 | Model_Name = Models_path+"\\VGG19_"+str(file_number)+".h5"
124 | plt.savefig(plot_Name , transparent =True , bbox_incehs="tight" , pad_inches = 2 , dpi = 50)
125 | model.save(Model_Name)
126 | return plot_Name , Model_Name
127 |
128 |
--------------------------------------------------------------------------------
/Source Code/help_Window.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication , QFileDialog , QFrame,QComboBox, QLineEdit , QLabel, QHBoxLayout, QAction,QRadioButton , QMainWindow, QMenu, QVBoxLayout, QSizePolicy, QMessageBox, QWidget, QPushButton
2 | from PyQt5.QtCore import *
3 | from PyQt5 import QtGui
4 | from PyQt5 import QtCore
5 | from PyQt5.QtGui import QPixmap
6 |
7 | from PIL import Image
8 |
9 | import numpy as np
10 | import sys
11 | import os
12 |
13 | from Result_Window_Final import ResultWindow
14 | """
15 | import ELA_Module
16 | import VGG16_Module
17 | import VGG19_Module
18 | import SVM_Module
19 | """
20 | class HelpWindow(QWidget):
21 | def __init__(self, parent = None):
22 | """constructor to create a new window with charactersitis after create object from class window"""
23 |
24 | super().__init__()
25 | self.title = "IFD Application"
26 | self.top = 200
27 | self.left = 500
28 | self.width = 1086
29 | self.height = 680
30 | self.init_window()
31 |
32 | def init_window(self):
33 | """initialize window"""
34 |
35 | self.setWindowTitle(self.title)
36 | self.setWindowIcon(QtGui.QIcon("icons8-cbs-512.ico")) # icon Pic File name
37 | self.setGeometry(self.left, self.top, self.width, self.height)
38 | self.setFixedSize(self.width, self.height)
39 |
40 | pixmap = QPixmap("C:\\Users\\Mohamed-PC\\PycharmProjects\\graduation_project\\Final.png")
41 | self.label = QLabel(self)
42 | self.label.setPixmap(pixmap)
43 | self.label.resize(1086, 680)
44 | self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.IgnoreAspectRatio))
45 |
46 | self.show()
47 |
48 | if __name__ == "__main__":
49 | App = QApplication(sys.argv)
50 | App.setStyle('Fusion')
51 | window = HelpWindow()
52 | sys.exit(App.exec())
--------------------------------------------------------------------------------