|
|
|
""" |
|
Created on Mon Apr 29 17:46:18 2024 |
|
|
|
@author: beni |
|
""" |
|
|
|
import pandas as pd |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
import matplotlib.image as mpimg |
|
from PIL import Image |
|
import os |
|
from pylab import * |
|
import re |
|
from PIL import Image, ImageChops, ImageEnhance |
|
import tensorflow as tf |
|
from sklearn.model_selection import train_test_split |
|
from sklearn.metrics import confusion_matrix |
|
import itertools |
|
from tensorflow.keras.utils import to_categorical |
|
from keras.models import Sequential |
|
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D |
|
from tensorflow.keras.optimizers.legacy import RMSprop |
|
from keras.preprocessing.image import ImageDataGenerator |
|
from keras.callbacks import ReduceLROnPlateau, EarlyStopping |
|
from scipy.ndimage import gaussian_filter |
|
|
|
|
|
|
|
|
|
|
|
def convert_to_ela_image(path, quality, output_dir, resize=(256, 256)): |
|
filename = path |
|
resaved_filename = os.path.join(output_dir, os.path.splitext(os.path.basename(filename))[0] + '.resaved.jpg') |
|
ELA_filename = os.path.join(output_dir, os.path.splitext(os.path.basename(filename))[0] + '.ela.png') |
|
|
|
|
|
im = Image.open(filename).convert('RGB') |
|
im_resized = im.resize(resize) |
|
|
|
|
|
im_resized.save(resaved_filename, 'JPEG', quality=quality) |
|
resaved_im = Image.open(resaved_filename) |
|
|
|
ela_im = ImageChops.difference(im_resized, resaved_im) |
|
|
|
extrema = ela_im.getextrema() |
|
max_diff = max([ex[1] for ex in extrema]) |
|
if max_diff == 0: |
|
max_diff = 1 |
|
scale = 255.0 / max_diff |
|
|
|
ela_im = ImageEnhance.Brightness(ela_im).enhance(scale) |
|
|
|
ela_im.save(ELA_filename) |
|
|
|
return ela_im |
|
|
|
|
|
def shuffle_and_split_data(dataframe, test_size=0.2, random_state=59): |
|
|
|
shuffled_df = dataframe.sample(frac=1, random_state=random_state).reset_index(drop=True) |
|
|
|
|
|
train_df, val_df = train_test_split(shuffled_df, test_size=test_size, random_state=random_state) |
|
|
|
return train_df, val_df |
|
|
|
def labeling(path_real, path_fake): |
|
image_paths = [] |
|
labels = [] |
|
|
|
for filename in os.listdir(path_real): |
|
image_paths.append(os.path.join(path_real, filename)) |
|
labels.append(0) |
|
|
|
for filename in os.listdir(path_fake): |
|
image_paths.append(os.path.join(path_fake, filename)) |
|
labels.append(1) |
|
|
|
dataset = pd.DataFrame({'image_path': image_paths, 'label': labels}) |
|
|
|
return dataset |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
np.random.seed(22) |
|
tf.random.set_seed(9) |
|
|
|
traning_fake_folder = 'datasets/training_set/fake/' |
|
traning_real_folder = 'datasets/training_set/real/' |
|
|
|
|
|
traning_ela_output = 'datasets/training_set/ela_output/' |
|
traning_set = labeling(traning_real_folder, traning_fake_folder) |
|
|
|
|
|
X = [] |
|
Y = [] |
|
|
|
|
|
|
|
|
|
for index, row in traning_set.iterrows(): |
|
X.append(array(convert_to_ela_image(row[0], 90,traning_ela_output).resize((128, 128))).flatten() / 255.0) |
|
Y.append(row[1]) |
|
|
|
X = np.array(X) |
|
Y = to_categorical(Y, 2) |
|
X = X.reshape(-1, 128, 128, 3) |
|
X_train, X_val, Y_train, Y_val = train_test_split(X, Y, test_size = 0.2, random_state=1,shuffle=True) |
|
|
|
|
|
|
|
|
|
model = Sequential() |
|
model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'valid', |
|
activation ='relu', input_shape = (128,128,3))) |
|
print("Input: ", model.input_shape) |
|
print("Output: ", model.output_shape) |
|
|
|
model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'valid', |
|
activation ='relu')) |
|
print("Input: ", model.input_shape) |
|
print("Output: ", model.output_shape) |
|
|
|
model.add(MaxPool2D(pool_size=(2,2))) |
|
|
|
model.add(Dropout(0.25)) |
|
print("Input: ", model.input_shape) |
|
print("Output: ", model.output_shape) |
|
|
|
model.add(Flatten()) |
|
model.add(Dense(256, activation = "relu")) |
|
model.add(Dropout(0.5)) |
|
model.add(Dense(2, activation = "softmax")) |
|
|
|
model.summary() |
|
|
|
|
|
optimizer = RMSprop(lr=0.0005, rho=0.9, epsilon=1e-08, decay=0.0) |
|
|
|
model.compile(optimizer = optimizer , loss = "categorical_crossentropy", metrics=["accuracy"]) |
|
|
|
early_stopping = EarlyStopping(monitor='val_acc', |
|
min_delta=0, |
|
patience=2, |
|
verbose=0, mode='auto') |
|
|
|
|
|
epochs = 22 |
|
batch_size = 100 |
|
|
|
|
|
history = model.fit(X_train, Y_train, batch_size = batch_size, epochs = epochs, |
|
validation_data = (X_val, Y_val), verbose = 2, callbacks=[early_stopping]) |
|
|
|
|
|
|
|
|
|
plt.plot(history.history['accuracy']) |
|
plt.plot(history.history['val_accuracy']) |
|
plt.title('Model accuracy') |
|
plt.xlabel('Epoch') |
|
plt.ylabel('Accuracy') |
|
plt.legend(['Train', 'Validation'], loc='upper left') |
|
plt.show() |
|
|
|
|
|
plt.plot(history.history['loss']) |
|
plt.plot(history.history['val_loss']) |
|
plt.title('Model loss') |
|
plt.xlabel('Epoch') |
|
plt.ylabel('Loss') |
|
plt.legend(['Train', 'Validation'], loc='upper left') |
|
plt.show() |
|
|
|
|
|
model.save('ELA_CNN_ART_V2.h5') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|