├── 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 | IFD 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()) --------------------------------------------------------------------------------