Krish Patel
commited on
Commit
·
b6597a0
1
Parent(s):
990f77e
Added deepfake
Browse files- .env.example +1 -0
- .gitignore +2 -1
- app.py +50 -110
- deepfake2/deepfake2.py +207 -0
- deepfake2/deepfake_detector.h5 +3 -0
- deepfake2/testing2.py +118 -0
- final.py +5 -52
.env.example
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
GEMINI_API=
|
.gitignore
CHANGED
|
@@ -1,2 +1,3 @@
|
|
| 1 |
__pycache__/
|
| 2 |
-
node_modules/
|
|
|
|
|
|
| 1 |
__pycache__/
|
| 2 |
+
node_modules/
|
| 3 |
+
.env
|
app.py
CHANGED
|
@@ -1,113 +1,53 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
#
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
#
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
# # @app.get("/health")
|
| 24 |
-
# # async def health_check():
|
| 25 |
-
# # return {"status": "healthy"}
|
| 26 |
|
| 27 |
-
# from fastapi import FastAPI
|
| 28 |
-
# from fastapi.middleware.cors import CORSMiddleware
|
| 29 |
-
# from pydantic import BaseModel
|
| 30 |
-
# from final import predict_news, get_gemini_analysis
|
| 31 |
-
|
| 32 |
-
# app = FastAPI()
|
| 33 |
-
|
| 34 |
-
# # Add CORS middleware
|
| 35 |
-
# app.add_middleware(
|
| 36 |
-
# CORSMiddleware,
|
| 37 |
-
# allow_origins=["http://localhost:5173"], # Your React app's URL
|
| 38 |
-
# allow_credentials=True,
|
| 39 |
-
# allow_methods=["*"],
|
| 40 |
-
# allow_headers=["*"],
|
| 41 |
-
# )
|
| 42 |
-
|
| 43 |
-
# # Rest of your code remains the same
|
| 44 |
-
# class NewsInput(BaseModel):
|
| 45 |
-
# text: str
|
| 46 |
-
|
| 47 |
-
# @app.post("/analyze")
|
| 48 |
-
# async def analyze_news(news: NewsInput):
|
| 49 |
-
# prediction = predict_news(news.text)
|
| 50 |
-
# gemini_analysis = get_gemini_analysis(news.text)
|
| 51 |
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
gemini_analysis = get_gemini_analysis(news_text)
|
| 73 |
-
|
| 74 |
-
# Display results
|
| 75 |
-
st.header("Analysis Results")
|
| 76 |
-
|
| 77 |
-
# Main prediction with color coding
|
| 78 |
-
prediction_color = "green" if prediction == "REAL" else "red"
|
| 79 |
-
st.markdown(f"### Prediction: <span style='color:{prediction_color}'>{prediction}</span>", unsafe_allow_html=True)
|
| 80 |
-
|
| 81 |
-
# Detailed Gemini Analysis
|
| 82 |
-
st.subheader("Detailed Analysis")
|
| 83 |
-
|
| 84 |
-
# Display structured analysis
|
| 85 |
-
col1, col2 = st.columns(2)
|
| 86 |
-
|
| 87 |
-
with col1:
|
| 88 |
-
st.markdown("#### Content Classification")
|
| 89 |
-
st.write(f"Category: {gemini_analysis['text_classification']['category']}")
|
| 90 |
-
st.write(f"Writing Style: {gemini_analysis['text_classification']['writing_style']}")
|
| 91 |
-
st.write(f"Content Type: {gemini_analysis['text_classification']['content_type']}")
|
| 92 |
-
|
| 93 |
-
with col2:
|
| 94 |
-
st.markdown("#### Sentiment Analysis")
|
| 95 |
-
st.write(f"Primary Emotion: {gemini_analysis['sentiment_analysis']['primary_emotion']}")
|
| 96 |
-
st.write(f"Emotional Intensity: {gemini_analysis['sentiment_analysis']['emotional_intensity']}/10")
|
| 97 |
-
st.write(f"Sensationalism Level: {gemini_analysis['sentiment_analysis']['sensationalism_level']}")
|
| 98 |
-
|
| 99 |
-
# Fact checking section
|
| 100 |
-
st.markdown("#### Fact Checking")
|
| 101 |
-
st.write(f"Evidence Present: {gemini_analysis['fact_checking']['evidence_present']}")
|
| 102 |
-
st.write(f"Fact Check Score: {gemini_analysis['fact_checking']['fact_check_score']}/100")
|
| 103 |
-
|
| 104 |
-
# Verifiable claims
|
| 105 |
-
st.markdown("#### Verifiable Claims")
|
| 106 |
-
for claim in gemini_analysis['fact_checking']['verifiable_claims']:
|
| 107 |
-
st.write(f"- {claim}")
|
| 108 |
-
|
| 109 |
-
else:
|
| 110 |
-
st.warning("Please enter some text to analyze")
|
| 111 |
-
|
| 112 |
-
if __name__ == "__main__":
|
| 113 |
-
main()
|
|
|
|
| 1 |
+
from fastapi import FastAPI, UploadFile, File
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from final import predict_news, get_gemini_analysis
|
| 5 |
+
import os
|
| 6 |
+
from tempfile import NamedTemporaryFile
|
| 7 |
+
|
| 8 |
+
app = FastAPI()
|
| 9 |
+
|
| 10 |
+
# Add CORS middleware
|
| 11 |
+
app.add_middleware(
|
| 12 |
+
CORSMiddleware,
|
| 13 |
+
allow_origins=["http://localhost:5173"], # Your React app's URL
|
| 14 |
+
allow_credentials=True,
|
| 15 |
+
allow_methods=["*"],
|
| 16 |
+
allow_headers=["*"],
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
# Rest of your code remains the same
|
| 20 |
+
class NewsInput(BaseModel):
|
| 21 |
+
text: str
|
| 22 |
+
|
| 23 |
+
@app.post("/analyze")
|
| 24 |
+
async def analyze_news(news: NewsInput):
|
| 25 |
+
prediction = predict_news(news.text)
|
| 26 |
+
gemini_analysis = get_gemini_analysis(news.text)
|
| 27 |
|
| 28 |
+
return {
|
| 29 |
+
"prediction": prediction,
|
| 30 |
+
"detailed_analysis": gemini_analysis
|
| 31 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
+
@app.post("/detect-deepfake")
|
| 35 |
+
async def detect_deepfake(image: UploadFile = File(...)):
|
| 36 |
+
try:
|
| 37 |
+
# Save uploaded image temporarily
|
| 38 |
+
with NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file:
|
| 39 |
+
contents = await image.read()
|
| 40 |
+
temp_file.write(contents)
|
| 41 |
+
temp_file_path = temp_file.name
|
| 42 |
+
|
| 43 |
+
# Use your existing deepfake detection function
|
| 44 |
+
from deepfake2.testing2 import predict_image # Use your existing function
|
| 45 |
+
result = predict_image(temp_file_path)
|
| 46 |
+
|
| 47 |
+
# Clean up temp file
|
| 48 |
+
os.remove(temp_file_path)
|
| 49 |
+
|
| 50 |
+
return result
|
| 51 |
+
|
| 52 |
+
except Exception as e:
|
| 53 |
+
return {"error": str(e)}, 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deepfake2/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}")
|
deepfake2/deepfake_detector.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1fb63513282ef336b9bd11ab762da260a4789913a6268246ff9e96a08344009e
|
| 3 |
+
size 39704352
|
deepfake2/testing2.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 = "C:/Users/krish/OneDrive - iiit-b/IIITB/Hackathons/Truthtell/complete_nlp_stuff/deepfake2/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 |
+
# Metadata analysis
|
| 28 |
+
def check_metadata(img_path):
|
| 29 |
+
try:
|
| 30 |
+
img = Image.open(img_path)
|
| 31 |
+
exif_data = img._getexif()
|
| 32 |
+
if not exif_data:
|
| 33 |
+
return "Fake (missing metadata)"
|
| 34 |
+
metadata = {TAGS.get(tag): value for tag, value in exif_data.items() if tag in TAGS}
|
| 35 |
+
return "Real (metadata present)" if metadata else "Fake (missing metadata)"
|
| 36 |
+
except Exception as e:
|
| 37 |
+
return f"Error analyzing metadata: {str(e)}"
|
| 38 |
+
|
| 39 |
+
# Artifact density analysis
|
| 40 |
+
def analyze_artifacts(img_path):
|
| 41 |
+
try:
|
| 42 |
+
img = cv2.imread(img_path)
|
| 43 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
| 44 |
+
laplacian = cv2.Laplacian(img_gray, cv2.CV_64F)
|
| 45 |
+
mean_var = np.mean(np.var(laplacian))
|
| 46 |
+
return "Fake (high artifact density)" if mean_var > 10 else "Real"
|
| 47 |
+
except Exception as e:
|
| 48 |
+
return f"Error analyzing artifacts: {str(e)}"
|
| 49 |
+
|
| 50 |
+
# Noise pattern detection
|
| 51 |
+
def detect_noise_patterns(img_path):
|
| 52 |
+
try:
|
| 53 |
+
img = cv2.imread(img_path)
|
| 54 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
| 55 |
+
noise_std = np.std(img_gray)
|
| 56 |
+
return "Fake (unnatural noise patterns)" if noise_std < 5 else "Real"
|
| 57 |
+
except Exception as e:
|
| 58 |
+
return f"Error analyzing noise patterns: {str(e)}"
|
| 59 |
+
|
| 60 |
+
# Symmetry analysis
|
| 61 |
+
def calculate_symmetry(img_path):
|
| 62 |
+
try:
|
| 63 |
+
img = cv2.imread(img_path)
|
| 64 |
+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
| 65 |
+
img_flipped_v = cv2.flip(img_gray, 1)
|
| 66 |
+
img_flipped_h = cv2.flip(img_gray, 0)
|
| 67 |
+
vertical_symmetry = 1 - np.mean(np.abs(img_gray - img_flipped_v)) / 255
|
| 68 |
+
horizontal_symmetry = 1 - np.mean(np.abs(img_gray - img_flipped_h)) / 255
|
| 69 |
+
return {
|
| 70 |
+
"Vertical Symmetry": round(vertical_symmetry, 2),
|
| 71 |
+
"Horizontal Symmetry": round(horizontal_symmetry, 2)
|
| 72 |
+
}
|
| 73 |
+
except Exception as e:
|
| 74 |
+
return {"Error": str(e)}
|
| 75 |
+
|
| 76 |
+
# Combine all methods
|
| 77 |
+
def combined_prediction(img_path):
|
| 78 |
+
results = {}
|
| 79 |
+
cnn_prediction = predict_image(img_path)
|
| 80 |
+
results["CNN Prediction"] = cnn_prediction
|
| 81 |
+
cnn_score = 1 if cnn_prediction == "Fake" else 0
|
| 82 |
+
metadata_result = check_metadata(img_path)
|
| 83 |
+
results["Metadata Analysis"] = metadata_result
|
| 84 |
+
metadata_score = 1 if "Fake" in metadata_result else 0
|
| 85 |
+
artifact_result = analyze_artifacts(img_path)
|
| 86 |
+
results["Artifact Analysis"] = artifact_result
|
| 87 |
+
artifact_score = 1 if "Fake" in artifact_result else 0
|
| 88 |
+
noise_result = detect_noise_patterns(img_path)
|
| 89 |
+
results["Noise Pattern Analysis"] = noise_result
|
| 90 |
+
noise_score = 1 if "Fake" in noise_result else 0
|
| 91 |
+
symmetry_results = calculate_symmetry(img_path)
|
| 92 |
+
results["Symmetry Analysis"] = symmetry_results
|
| 93 |
+
vertical_symmetry = symmetry_results.get("Vertical Symmetry", 0)
|
| 94 |
+
horizontal_symmetry = symmetry_results.get("Horizontal Symmetry", 0)
|
| 95 |
+
symmetry_score = 0
|
| 96 |
+
if vertical_symmetry != "Unknown" and horizontal_symmetry != "Unknown":
|
| 97 |
+
if vertical_symmetry > 0.9 or horizontal_symmetry > 0.9:
|
| 98 |
+
symmetry_score = 1
|
| 99 |
+
total_score = (cnn_score * 0.4 + metadata_score * 0.1 +
|
| 100 |
+
artifact_score * 0.15 + noise_score * 0.15 +
|
| 101 |
+
symmetry_score * 0.2)
|
| 102 |
+
results["Final Prediction"] = "Fake" if total_score > 0.5 else "Real"
|
| 103 |
+
results["Confidence Score"] = round(total_score, 2)
|
| 104 |
+
return results
|
| 105 |
+
|
| 106 |
+
# Main function
|
| 107 |
+
# if __name__ == "__main__":
|
| 108 |
+
# test_image_path = "C:/Users/ramya/OneDrive - iiit-b/Desktop/test1.jpg"
|
| 109 |
+
# if os.path.exists(test_image_path):
|
| 110 |
+
# final_results = combined_prediction(test_image_path)
|
| 111 |
+
# print("\nCombined Prediction Results:")
|
| 112 |
+
# for key, value in final_results.items():
|
| 113 |
+
# if isinstance(value, dict):
|
| 114 |
+
# print(f"{key}:")
|
| 115 |
+
# for sub_key, sub_value in value.items():
|
| 116 |
+
# print(f" {sub_key}: {sub_value}")
|
| 117 |
+
# else:
|
| 118 |
+
# print(f"{key}: {value}")
|
final.py
CHANGED
|
@@ -6,6 +6,10 @@ import pickle
|
|
| 6 |
import pandas as pd
|
| 7 |
import google.generativeai as genai
|
| 8 |
import json
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# Load spaCy for NER
|
| 11 |
nlp = spacy.load("en_core_web_sm")
|
|
@@ -18,7 +22,7 @@ model.eval()
|
|
| 18 |
|
| 19 |
#########################
|
| 20 |
def setup_gemini():
|
| 21 |
-
genai.configure(api_key=
|
| 22 |
model = genai.GenerativeModel('gemini-pro')
|
| 23 |
return model
|
| 24 |
#########################
|
|
@@ -114,57 +118,6 @@ def predict_news(text):
|
|
| 114 |
# You can enhance this by combining the scores from both predictions
|
| 115 |
return ml_prediction if ml_prediction == kg_prediction else "UNCERTAIN"
|
| 116 |
|
| 117 |
-
#########################
|
| 118 |
-
# def analyze_content_gemini(model, text):
|
| 119 |
-
# prompt = f"""Analyze this news text and provide results in the following JSON-like format:
|
| 120 |
-
|
| 121 |
-
# TEXT: {text}
|
| 122 |
-
|
| 123 |
-
# Please provide analysis in these specific sections:
|
| 124 |
-
|
| 125 |
-
# 1. GEMINI ANALYSIS:
|
| 126 |
-
# - Predicted Classification: [Real/Fake]
|
| 127 |
-
# - Confidence Score: [0-100%]
|
| 128 |
-
# - Reasoning: [Key points for classification]
|
| 129 |
-
|
| 130 |
-
# 2. TEXT CLASSIFICATION:
|
| 131 |
-
# - Content category/topic
|
| 132 |
-
# - Writing style: [Formal/Informal/Clickbait]
|
| 133 |
-
# - Target audience
|
| 134 |
-
# - Content type: [news/opinion/editorial]
|
| 135 |
-
|
| 136 |
-
# 3. SENTIMENT ANALYSIS:
|
| 137 |
-
# - Primary emotion
|
| 138 |
-
# - Emotional intensity (1-10)
|
| 139 |
-
# - Sensationalism Level: [High/Medium/Low]
|
| 140 |
-
# - Bias Indicators: [List if any]
|
| 141 |
-
# - Tone: (formal/informal), [Professional/Emotional/Neutral]
|
| 142 |
-
# - Key emotional triggers
|
| 143 |
-
|
| 144 |
-
# 4. ENTITY RECOGNITION:
|
| 145 |
-
# - Source Credibility: [High/Medium/Low]
|
| 146 |
-
# - People mentioned
|
| 147 |
-
# - Organizations
|
| 148 |
-
# - Locations
|
| 149 |
-
# - Dates/Time references
|
| 150 |
-
# - Key numbers/statistics
|
| 151 |
-
|
| 152 |
-
# 5. CONTEXT EXTRACTION:
|
| 153 |
-
# - Main narrative/story
|
| 154 |
-
# - Supporting elements
|
| 155 |
-
# - Key claims
|
| 156 |
-
# - Narrative structure
|
| 157 |
-
|
| 158 |
-
# 6. FACT CHECKING:
|
| 159 |
-
# - Verifiable Claims: [List main claims]
|
| 160 |
-
# - Evidence Present: [Yes/No]
|
| 161 |
-
# - Fact Check Score: [0-100%]
|
| 162 |
-
|
| 163 |
-
# Format the response clearly with distinct sections."""
|
| 164 |
-
|
| 165 |
-
# response = model.generate_content(prompt)
|
| 166 |
-
# return response.text
|
| 167 |
-
|
| 168 |
def analyze_content_gemini(model, text):
|
| 169 |
prompt = f"""Analyze this news text and return a JSON object with the following structure:
|
| 170 |
{{
|
|
|
|
| 6 |
import pandas as pd
|
| 7 |
import google.generativeai as genai
|
| 8 |
import json
|
| 9 |
+
import os
|
| 10 |
+
import dotenv
|
| 11 |
+
|
| 12 |
+
dotenv.load_dotenv()
|
| 13 |
|
| 14 |
# Load spaCy for NER
|
| 15 |
nlp = spacy.load("en_core_web_sm")
|
|
|
|
| 22 |
|
| 23 |
#########################
|
| 24 |
def setup_gemini():
|
| 25 |
+
genai.configure(api_key=os.getenv("GEMINI_API"))
|
| 26 |
model = genai.GenerativeModel('gemini-pro')
|
| 27 |
return model
|
| 28 |
#########################
|
|
|
|
| 118 |
# You can enhance this by combining the scores from both predictions
|
| 119 |
return ml_prediction if ml_prediction == kg_prediction else "UNCERTAIN"
|
| 120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
def analyze_content_gemini(model, text):
|
| 122 |
prompt = f"""Analyze this news text and return a JSON object with the following structure:
|
| 123 |
{{
|