Krish Patel
commited on
Commit
·
e728bee
1
Parent(s):
f3daa92
Uploaded model and UI
Browse files- .gitignore +1 -0
- app.py +111 -0
- deepfake2.py +207 -0
- deepfake_detector.h5 +3 -0
- testing2.py +174 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
__pycache__/
|
app.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
from tensorflow.keras.models import load_model
|
5 |
+
from PIL import Image
|
6 |
+
import io
|
7 |
+
import os
|
8 |
+
from testing2 import combined_prediction, predict_video
|
9 |
+
|
10 |
+
# Load the model
|
11 |
+
model = load_model("deepfake_detector.h5")
|
12 |
+
|
13 |
+
st.set_page_config(page_title="Deepfake Detection System", layout="wide")
|
14 |
+
|
15 |
+
def process_image_in_memory(file):
|
16 |
+
image = Image.open(file)
|
17 |
+
# Convert PIL Image to bytes
|
18 |
+
img_byte_arr = io.BytesIO()
|
19 |
+
image.save(img_byte_arr, format='JPEG')
|
20 |
+
img_byte_arr = img_byte_arr.getvalue()
|
21 |
+
|
22 |
+
# Create temporary file, process it, and delete immediately
|
23 |
+
temp_path = "temp_image.jpg"
|
24 |
+
with open(temp_path, "wb") as f:
|
25 |
+
f.write(img_byte_arr)
|
26 |
+
|
27 |
+
results = combined_prediction(temp_path)
|
28 |
+
|
29 |
+
# Clean up
|
30 |
+
if os.path.exists(temp_path):
|
31 |
+
os.remove(temp_path)
|
32 |
+
|
33 |
+
return results, image
|
34 |
+
|
35 |
+
def process_video_in_memory(file):
|
36 |
+
temp_path = "temp_video.mp4"
|
37 |
+
|
38 |
+
# Save temporarily for processing
|
39 |
+
with open(temp_path, "wb") as f:
|
40 |
+
f.write(file.read())
|
41 |
+
|
42 |
+
results = predict_video(temp_path)
|
43 |
+
|
44 |
+
# Clean up
|
45 |
+
if os.path.exists(temp_path):
|
46 |
+
os.remove(temp_path)
|
47 |
+
|
48 |
+
return results
|
49 |
+
|
50 |
+
def display_detailed_analysis(results):
|
51 |
+
st.subheader("🔍 Detailed Analysis")
|
52 |
+
|
53 |
+
# Main Metrics
|
54 |
+
col1, col2 = st.columns(2)
|
55 |
+
with col1:
|
56 |
+
st.metric("Final Verdict", results["Final Prediction"])
|
57 |
+
st.metric("CNN Analysis", results["CNN Prediction"])
|
58 |
+
with col2:
|
59 |
+
st.metric("Confidence Score", f"{results['Confidence Score']*100:.1f}%")
|
60 |
+
st.metric("Metadata Check", results["Metadata Analysis"])
|
61 |
+
|
62 |
+
# Technical Analysis
|
63 |
+
st.write("📊 Technical Analysis:")
|
64 |
+
st.write(f"- **Artifact Detection**: {results['Artifact Analysis']}")
|
65 |
+
st.write(f"- **Noise Pattern Analysis**: {results['Noise Pattern Analysis']}")
|
66 |
+
|
67 |
+
# Symmetry Analysis if available
|
68 |
+
if "Symmetry Analysis" in results:
|
69 |
+
st.write("🎯 Symmetry Measurements:")
|
70 |
+
symmetry = results["Symmetry Analysis"]
|
71 |
+
st.write(f"- **Vertical Symmetry**: {symmetry['Vertical Symmetry']*100:.1f}%")
|
72 |
+
st.write(f"- **Horizontal Symmetry**: {symmetry['Horizontal Symmetry']*100:.1f}%")
|
73 |
+
|
74 |
+
def main():
|
75 |
+
st.title("Deepfake Detection System")
|
76 |
+
st.write("Upload an image or video to detect if it's real or manipulated")
|
77 |
+
|
78 |
+
file = st.file_uploader("Choose a file", type=['jpg', 'jpeg', 'png', 'mp4', 'avi'])
|
79 |
+
|
80 |
+
if file:
|
81 |
+
file_type = file.type.split('/')[0]
|
82 |
+
|
83 |
+
if file_type == 'image':
|
84 |
+
results, image = process_image_in_memory(file)
|
85 |
+
st.image(image, caption="Uploaded Image", use_container_width=True, width=100)
|
86 |
+
|
87 |
+
display_detailed_analysis(results)
|
88 |
+
|
89 |
+
elif file_type == 'video':
|
90 |
+
st.video(file)
|
91 |
+
|
92 |
+
if st.button("Analyze Video"):
|
93 |
+
with st.spinner("Analyzing video frames..."):
|
94 |
+
results = process_video_in_memory(file)
|
95 |
+
|
96 |
+
# Display results
|
97 |
+
st.subheader("Video Analysis Results")
|
98 |
+
col1, col2 = st.columns(2)
|
99 |
+
|
100 |
+
with col1:
|
101 |
+
st.metric("Final Prediction", results["Final Video Prediction"])
|
102 |
+
st.metric("Confidence Score", f"{results['Confidence Score']*100:.2f}%")
|
103 |
+
|
104 |
+
with col2:
|
105 |
+
st.metric("Fake Frames", results["Fake Frames"])
|
106 |
+
st.metric("Real Frames", results["Real Frames"])
|
107 |
+
|
108 |
+
display_detailed_analysis(results)
|
109 |
+
|
110 |
+
if __name__ == "__main__":
|
111 |
+
main()
|
deepfake2.py
ADDED
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import shutil
|
3 |
+
import cv2
|
4 |
+
import numpy as np
|
5 |
+
from tensorflow.keras.models import Sequential
|
6 |
+
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
|
7 |
+
from tensorflow.keras.preprocessing.image import ImageDataGenerator
|
8 |
+
from tensorflow.keras.models import load_model
|
9 |
+
from tensorflow.keras.preprocessing import image
|
10 |
+
import random
|
11 |
+
|
12 |
+
# Paths to dataset directories
|
13 |
+
data_dir = "C:/Users/ramya/OneDrive - iiit-b/Desktop/data_deepfake/Dataset/"
|
14 |
+
train_dir = os.path.join(data_dir, "Train")
|
15 |
+
val_dir = os.path.join(data_dir, "Validation")
|
16 |
+
temp_train_dir = os.path.join(data_dir, "Temp_Train")
|
17 |
+
temp_val_dir = os.path.join(data_dir, "Temp_Validation")
|
18 |
+
|
19 |
+
# Image dimensions
|
20 |
+
img_height, img_width = 128, 128
|
21 |
+
|
22 |
+
# Limit the number of images for training and validation
|
23 |
+
max_images_per_class = 12000 # Adjust as needed
|
24 |
+
|
25 |
+
def count_images(directory):
|
26 |
+
"""Count the number of real and fake images in a directory."""
|
27 |
+
real_count = len(os.listdir(os.path.join(directory, 'Real')))
|
28 |
+
fake_count = len(os.listdir(os.path.join(directory, 'Fake')))
|
29 |
+
return real_count, fake_count
|
30 |
+
|
31 |
+
def prepare_limited_dataset(source_dir, target_dir, max_images):
|
32 |
+
"""Create a temporary dataset with a limited number of images per class."""
|
33 |
+
if os.path.exists(target_dir):
|
34 |
+
shutil.rmtree(target_dir)
|
35 |
+
os.makedirs(os.path.join(target_dir, 'Real'), exist_ok=True)
|
36 |
+
os.makedirs(os.path.join(target_dir, 'Fake'), exist_ok=True)
|
37 |
+
|
38 |
+
for class_dir in ['Real', 'Fake']:
|
39 |
+
class_path = os.path.join(source_dir, class_dir)
|
40 |
+
target_class_path = os.path.join(target_dir, class_dir)
|
41 |
+
all_images = os.listdir(class_path)
|
42 |
+
random.shuffle(all_images)
|
43 |
+
selected_images = all_images[:max_images]
|
44 |
+
|
45 |
+
for image_name in selected_images:
|
46 |
+
shutil.copy(os.path.join(class_path, image_name), target_class_path)
|
47 |
+
|
48 |
+
def get_processed_images_info(generator):
|
49 |
+
"""Calculate information about processed images from a generator."""
|
50 |
+
n_samples = generator.n
|
51 |
+
n_classes = len(generator.class_indices)
|
52 |
+
batch_size = generator.batch_size
|
53 |
+
steps_per_epoch = int(np.ceil(n_samples / batch_size))
|
54 |
+
|
55 |
+
class_distribution = {}
|
56 |
+
for class_name, class_index in generator.class_indices.items():
|
57 |
+
class_count = len(generator.classes[generator.classes == class_index])
|
58 |
+
class_distribution[class_name] = class_count
|
59 |
+
|
60 |
+
return {
|
61 |
+
'total_samples': n_samples,
|
62 |
+
'batch_size': batch_size,
|
63 |
+
'steps_per_epoch': steps_per_epoch,
|
64 |
+
'class_distribution': class_distribution
|
65 |
+
}
|
66 |
+
|
67 |
+
# Print initial image counts
|
68 |
+
print("\nInitial image counts:")
|
69 |
+
train_real, train_fake = count_images(train_dir)
|
70 |
+
val_real, val_fake = count_images(val_dir)
|
71 |
+
print(f"Training - Real: {train_real}, Fake: {train_fake}")
|
72 |
+
print(f"Validation - Real: {val_real}, Fake: {val_fake}")
|
73 |
+
|
74 |
+
# Prepare temporary directories with limited images
|
75 |
+
prepare_limited_dataset(train_dir, temp_train_dir, max_images_per_class)
|
76 |
+
prepare_limited_dataset(val_dir, temp_val_dir, max_images_per_class)
|
77 |
+
|
78 |
+
# Print filtered image counts
|
79 |
+
print("\nAfter filtering:")
|
80 |
+
train_real, train_fake = count_images(temp_train_dir)
|
81 |
+
val_real, val_fake = count_images(temp_val_dir)
|
82 |
+
print(f"Training - Real: {train_real}, Fake: {train_fake}")
|
83 |
+
print(f"Validation - Real: {val_real}, Fake: {val_fake}")
|
84 |
+
|
85 |
+
# Data generators for training and validation
|
86 |
+
datagen = ImageDataGenerator(rescale=1./255)
|
87 |
+
|
88 |
+
train_gen = datagen.flow_from_directory(
|
89 |
+
temp_train_dir,
|
90 |
+
target_size=(img_height, img_width),
|
91 |
+
batch_size=32,
|
92 |
+
class_mode='binary',
|
93 |
+
classes=['Real', 'Fake']
|
94 |
+
)
|
95 |
+
|
96 |
+
val_gen = datagen.flow_from_directory(
|
97 |
+
temp_val_dir,
|
98 |
+
target_size=(img_height, img_width),
|
99 |
+
batch_size=32,
|
100 |
+
class_mode='binary',
|
101 |
+
classes=['Real', 'Fake']
|
102 |
+
)
|
103 |
+
|
104 |
+
# Get training and validation information
|
105 |
+
train_info = get_processed_images_info(train_gen)
|
106 |
+
val_info = get_processed_images_info(val_gen)
|
107 |
+
|
108 |
+
print("\nTraining Data Processing Info:")
|
109 |
+
print(f"Total training samples: {train_info['total_samples']}")
|
110 |
+
print(f"Batch size: {train_info['batch_size']}")
|
111 |
+
print(f"Steps per epoch: {train_info['steps_per_epoch']}")
|
112 |
+
print("\nClass distribution in training:")
|
113 |
+
for class_name, count in train_info['class_distribution'].items():
|
114 |
+
print(f"{class_name}: {count} images")
|
115 |
+
|
116 |
+
print("\nValidation Data Processing Info:")
|
117 |
+
print(f"Total validation samples: {val_info['total_samples']}")
|
118 |
+
print(f"Batch size: {val_info['batch_size']}")
|
119 |
+
print(f"Steps per epoch: {val_info['steps_per_epoch']}")
|
120 |
+
print("\nClass distribution in validation:")
|
121 |
+
for class_name, count in val_info['class_distribution'].items():
|
122 |
+
print(f"{class_name}: {count} images")
|
123 |
+
|
124 |
+
# Define the CNN model
|
125 |
+
model = Sequential([
|
126 |
+
Conv2D(32, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)),
|
127 |
+
MaxPooling2D((2, 2)),
|
128 |
+
Conv2D(64, (3, 3), activation='relu'),
|
129 |
+
MaxPooling2D((2, 2)),
|
130 |
+
Conv2D(128, (3, 3), activation='relu'),
|
131 |
+
MaxPooling2D((2, 2)),
|
132 |
+
Flatten(),
|
133 |
+
Dense(128, activation='relu'),
|
134 |
+
Dropout(0.5),
|
135 |
+
Dense(1, activation='sigmoid')
|
136 |
+
])
|
137 |
+
|
138 |
+
# Compile the model
|
139 |
+
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
|
140 |
+
|
141 |
+
# Train the model
|
142 |
+
history = model.fit(
|
143 |
+
train_gen,
|
144 |
+
steps_per_epoch=train_info['steps_per_epoch'],
|
145 |
+
validation_data=val_gen,
|
146 |
+
validation_steps=val_info['steps_per_epoch'],
|
147 |
+
epochs=10
|
148 |
+
)
|
149 |
+
|
150 |
+
# Calculate total images processed
|
151 |
+
total_training_images_processed = train_info['total_samples'] * 10 # 10 epochs
|
152 |
+
total_validation_images_processed = val_info['total_samples'] * 10 # 10 epochs
|
153 |
+
|
154 |
+
print(f"\nTotal images processed during training: {total_training_images_processed}")
|
155 |
+
print(f"Total images processed during validation: {total_validation_images_processed}")
|
156 |
+
print(f"Combined total processed: {total_training_images_processed + total_validation_images_processed}")
|
157 |
+
|
158 |
+
# Save the model
|
159 |
+
model.save("deepfake_detector.h5")
|
160 |
+
|
161 |
+
# Functions for prediction
|
162 |
+
def predict_image(img_path):
|
163 |
+
"""Predict whether a single image is real or fake."""
|
164 |
+
img = image.load_img(img_path, target_size=(img_height, img_width))
|
165 |
+
img_array = image.img_to_array(img) / 255.0
|
166 |
+
img_array = np.expand_dims(img_array, axis=0)
|
167 |
+
prediction = model.predict(img_array)
|
168 |
+
return "Fake" if prediction[0][0] > 0.5 else "Real"
|
169 |
+
|
170 |
+
def predict_video(video_path):
|
171 |
+
"""Predict whether a video is real or fake by analyzing frames."""
|
172 |
+
cap = cv2.VideoCapture(video_path)
|
173 |
+
fake_count, real_count = 0, 0
|
174 |
+
|
175 |
+
while cap.isOpened():
|
176 |
+
ret, frame = cap.read()
|
177 |
+
if not ret:
|
178 |
+
break
|
179 |
+
|
180 |
+
# Preprocess the frame
|
181 |
+
frame_resized = cv2.resize(frame, (img_height, img_width))
|
182 |
+
frame_array = np.array(frame_resized) / 255.0
|
183 |
+
frame_array = np.expand_dims(frame_array, axis=0)
|
184 |
+
|
185 |
+
# Predict
|
186 |
+
prediction = model.predict(frame_array)
|
187 |
+
if prediction[0][0] > 0.5:
|
188 |
+
fake_count += 1
|
189 |
+
else:
|
190 |
+
real_count += 1
|
191 |
+
|
192 |
+
cap.release()
|
193 |
+
return "Fake" if fake_count > real_count else "Real"
|
194 |
+
|
195 |
+
# Example usage
|
196 |
+
if __name__ == "__main__":
|
197 |
+
# Test an image
|
198 |
+
test_image_path = "C:/Users/ramya/OneDrive - iiit-b/Desktop/test1.jpg"
|
199 |
+
if os.path.exists(test_image_path):
|
200 |
+
image_result = predict_image(test_image_path)
|
201 |
+
print(f"\nTest image prediction: {image_result}")
|
202 |
+
|
203 |
+
# Test a video (uncomment and modify path as needed)
|
204 |
+
# test_video_path = "example_video.mp4"
|
205 |
+
# if os.path.exists(test_video_path):
|
206 |
+
# video_result = predict_video(test_video_path)
|
207 |
+
# print(f"Test video prediction: {video_result}")
|
deepfake_detector.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1fb63513282ef336b9bd11ab762da260a4789913a6268246ff9e96a08344009e
|
3 |
+
size 39704352
|
testing2.py
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
import imghdr
|
5 |
+
from tensorflow.keras.models import load_model
|
6 |
+
from tensorflow.keras.preprocessing import image
|
7 |
+
from PIL import Image
|
8 |
+
from PIL.ExifTags import TAGS
|
9 |
+
|
10 |
+
# Load the saved model
|
11 |
+
model_path = "deepfake_detector.h5"
|
12 |
+
model = load_model(model_path)
|
13 |
+
|
14 |
+
# Image dimensions
|
15 |
+
img_height, img_width = 128, 128
|
16 |
+
|
17 |
+
# Trained model prediction
|
18 |
+
def predict_image(img_path):
|
19 |
+
if not os.path.exists(img_path):
|
20 |
+
return "Image path does not exist."
|
21 |
+
img = image.load_img(img_path, target_size=(img_height, img_width))
|
22 |
+
img_array = image.img_to_array(img) / 255.0
|
23 |
+
img_array = np.expand_dims(img_array, axis=0)
|
24 |
+
prediction = model.predict(img_array)
|
25 |
+
return "Fake" if prediction[0][0] > 0.5 else "Real"
|
26 |
+
|
27 |
+
def predict_video(video_path):
|
28 |
+
"""Predict whether a video is real or fake by analyzing frames."""
|
29 |
+
try:
|
30 |
+
cap = cv2.VideoCapture(video_path)
|
31 |
+
fake_count, real_count = 0, 0
|
32 |
+
total_frames = 0
|
33 |
+
results = {}
|
34 |
+
|
35 |
+
while cap.isOpened():
|
36 |
+
ret, frame = cap.read()
|
37 |
+
if not ret:
|
38 |
+
break
|
39 |
+
|
40 |
+
# Process every 5th frame to improve performance
|
41 |
+
if total_frames % 5 == 0:
|
42 |
+
# Analyze frame using all detection methods
|
43 |
+
frame_path = f"temp_frame_{total_frames}.jpg"
|
44 |
+
cv2.imwrite(frame_path, frame)
|
45 |
+
|
46 |
+
frame_results = combined_prediction(frame_path)
|
47 |
+
if frame_results["Final Prediction"] == "Fake":
|
48 |
+
fake_count += 1
|
49 |
+
else:
|
50 |
+
real_count += 1
|
51 |
+
|
52 |
+
os.remove(frame_path)
|
53 |
+
|
54 |
+
total_frames += 1
|
55 |
+
|
56 |
+
cap.release()
|
57 |
+
|
58 |
+
# Calculate final results
|
59 |
+
total_analyzed_frames = fake_count + real_count
|
60 |
+
fake_percentage = (fake_count / total_analyzed_frames * 100) if total_analyzed_frames > 0 else 0
|
61 |
+
|
62 |
+
results["Total Frames Analyzed"] = total_analyzed_frames
|
63 |
+
results["Fake Frames"] = fake_count
|
64 |
+
results["Real Frames"] = real_count
|
65 |
+
results["Fake Percentage"] = round(fake_percentage, 2)
|
66 |
+
results["Final Video Prediction"] = "Fake" if fake_percentage > 50 else "Real"
|
67 |
+
results["Confidence Score"] = round(abs(50 - fake_percentage) / 50, 2)
|
68 |
+
|
69 |
+
return results
|
70 |
+
|
71 |
+
except Exception as e:
|
72 |
+
return {"Error": f"Error analyzing video: {str(e)}"}
|
73 |
+
|
74 |
+
# Metadata analysis
|
75 |
+
def check_metadata(img_path):
|
76 |
+
try:
|
77 |
+
img = Image.open(img_path)
|
78 |
+
exif_data = img._getexif()
|
79 |
+
if not exif_data:
|
80 |
+
return "Fake (missing metadata)"
|
81 |
+
metadata = {TAGS.get(tag): value for tag, value in exif_data.items() if tag in TAGS}
|
82 |
+
return "Real (metadata present)" if metadata else "Fake (missing metadata)"
|
83 |
+
except Exception as e:
|
84 |
+
return f"Error analyzing metadata: {str(e)}"
|
85 |
+
|
86 |
+
# Artifact density analysis
|
87 |
+
def analyze_artifacts(img_path):
|
88 |
+
try:
|
89 |
+
img = cv2.imread(img_path)
|
90 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
91 |
+
laplacian = cv2.Laplacian(img_gray, cv2.CV_64F)
|
92 |
+
mean_var = np.mean(np.var(laplacian))
|
93 |
+
return "Fake (high artifact density)" if mean_var > 10 else "Real"
|
94 |
+
except Exception as e:
|
95 |
+
return f"Error analyzing artifacts: {str(e)}"
|
96 |
+
|
97 |
+
# Noise pattern detection
|
98 |
+
def detect_noise_patterns(img_path):
|
99 |
+
try:
|
100 |
+
img = cv2.imread(img_path)
|
101 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
102 |
+
noise_std = np.std(img_gray)
|
103 |
+
return "Fake (unnatural noise patterns)" if noise_std < 5 else "Real"
|
104 |
+
except Exception as e:
|
105 |
+
return f"Error analyzing noise patterns: {str(e)}"
|
106 |
+
|
107 |
+
# Symmetry analysis
|
108 |
+
def calculate_symmetry(img_path):
|
109 |
+
try:
|
110 |
+
img = cv2.imread(img_path)
|
111 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
112 |
+
img_flipped_v = cv2.flip(img_gray, 1)
|
113 |
+
img_flipped_h = cv2.flip(img_gray, 0)
|
114 |
+
vertical_symmetry = 1 - np.mean(np.abs(img_gray - img_flipped_v)) / 255
|
115 |
+
horizontal_symmetry = 1 - np.mean(np.abs(img_gray - img_flipped_h)) / 255
|
116 |
+
return {
|
117 |
+
"Vertical Symmetry": round(vertical_symmetry, 2),
|
118 |
+
"Horizontal Symmetry": round(horizontal_symmetry, 2)
|
119 |
+
}
|
120 |
+
except Exception as e:
|
121 |
+
return {"Error": str(e)}
|
122 |
+
|
123 |
+
# Combine all methods
|
124 |
+
def combined_prediction(img_path):
|
125 |
+
results = {}
|
126 |
+
cnn_prediction = predict_image(img_path)
|
127 |
+
results["CNN Prediction"] = cnn_prediction
|
128 |
+
cnn_score = 1 if cnn_prediction == "Fake" else 0
|
129 |
+
metadata_result = check_metadata(img_path)
|
130 |
+
results["Metadata Analysis"] = metadata_result
|
131 |
+
metadata_score = 1 if "Fake" in metadata_result else 0
|
132 |
+
artifact_result = analyze_artifacts(img_path)
|
133 |
+
results["Artifact Analysis"] = artifact_result
|
134 |
+
artifact_score = 1 if "Fake" in artifact_result else 0
|
135 |
+
noise_result = detect_noise_patterns(img_path)
|
136 |
+
results["Noise Pattern Analysis"] = noise_result
|
137 |
+
noise_score = 1 if "Fake" in noise_result else 0
|
138 |
+
symmetry_results = calculate_symmetry(img_path)
|
139 |
+
results["Symmetry Analysis"] = symmetry_results
|
140 |
+
vertical_symmetry = symmetry_results.get("Vertical Symmetry", 0)
|
141 |
+
horizontal_symmetry = symmetry_results.get("Horizontal Symmetry", 0)
|
142 |
+
symmetry_score = 0
|
143 |
+
if vertical_symmetry != "Unknown" and horizontal_symmetry != "Unknown":
|
144 |
+
if vertical_symmetry > 0.9 or horizontal_symmetry > 0.9:
|
145 |
+
symmetry_score = 1
|
146 |
+
total_score = (cnn_score * 0.4 + metadata_score * 0.1 +
|
147 |
+
artifact_score * 0.15 + noise_score * 0.15 +
|
148 |
+
symmetry_score * 0.2)
|
149 |
+
results["Final Prediction"] = "Fake" if total_score > 0.5 else "Real"
|
150 |
+
results["Confidence Score"] = round(total_score, 2)
|
151 |
+
return results
|
152 |
+
|
153 |
+
# Main function
|
154 |
+
if __name__ == "__main__":
|
155 |
+
test_image_path = "C:/Users/ramya/OneDrive - iiit-b/Desktop/test1.jpg"
|
156 |
+
if os.path.exists(test_image_path):
|
157 |
+
final_results = combined_prediction(test_image_path)
|
158 |
+
print("\nCombined Prediction Results:")
|
159 |
+
for key, value in final_results.items():
|
160 |
+
if isinstance(value, dict):
|
161 |
+
print(f"{key}:")
|
162 |
+
for sub_key, sub_value in value.items():
|
163 |
+
print(f" {sub_key}: {sub_value}")
|
164 |
+
else:
|
165 |
+
print(f"{key}: {value}")
|
166 |
+
|
167 |
+
# if __name__ == "__main__":
|
168 |
+
# # Test video
|
169 |
+
# test_video_path = "path/to/your/video.mp4"
|
170 |
+
# if os.path.exists(test_video_path):
|
171 |
+
# video_results = predict_video(test_video_path)
|
172 |
+
# print("\nVideo Analysis Results:")
|
173 |
+
# for key, value in video_results.items():
|
174 |
+
# print(f"{key}: {value}")
|