Krish Patel
commited on
Commit
·
8c24dde
1
Parent(s):
3088d34
Added deepfake video detection
Browse files- .gitignore +2 -1
- app.py +39 -9
- deepfake2/testing2.py +40 -0
- nexus-frontend/src/pages/deepfake.tsx +57 -16
.gitignore
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
__pycache__/
|
2 |
node_modules/
|
3 |
-
.env
|
|
|
|
1 |
__pycache__/
|
2 |
node_modules/
|
3 |
+
.env
|
4 |
+
.venv/
|
app.py
CHANGED
@@ -31,23 +31,53 @@ async def analyze_news(news: NewsInput):
|
|
31 |
}
|
32 |
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
@app.post("/detect-deepfake")
|
35 |
-
async def detect_deepfake(
|
36 |
try:
|
37 |
-
# Save uploaded
|
38 |
-
with NamedTemporaryFile(delete=False, suffix=
|
39 |
-
contents = await
|
40 |
temp_file.write(contents)
|
41 |
temp_file_path = temp_file.name
|
42 |
|
43 |
-
#
|
44 |
-
from deepfake2.testing2 import predict_image
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
# Clean up temp file
|
48 |
os.remove(temp_file_path)
|
49 |
|
50 |
-
return
|
51 |
-
|
|
|
|
|
|
|
52 |
except Exception as e:
|
53 |
return {"error": str(e)}, 500
|
|
|
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 |
+
# except Exception as e:
|
52 |
+
# return {"error": str(e)}, 500
|
53 |
+
|
54 |
@app.post("/detect-deepfake")
|
55 |
+
async def detect_deepfake(file: UploadFile = File(...)):
|
56 |
try:
|
57 |
+
# Save uploaded file temporarily
|
58 |
+
with NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.filename)[1]) as temp_file:
|
59 |
+
contents = await file.read()
|
60 |
temp_file.write(contents)
|
61 |
temp_file_path = temp_file.name
|
62 |
|
63 |
+
# Import functions from testing2.py
|
64 |
+
from deepfake2.testing2 import predict_image, predict_video
|
65 |
+
|
66 |
+
# Use appropriate function based on file type
|
67 |
+
if file.filename.lower().endswith('.mp4'):
|
68 |
+
result = predict_video(temp_file_path)
|
69 |
+
file_type = "video"
|
70 |
+
else:
|
71 |
+
result = predict_image(temp_file_path)
|
72 |
+
file_type = "image"
|
73 |
|
74 |
# Clean up temp file
|
75 |
os.remove(temp_file_path)
|
76 |
|
77 |
+
return {
|
78 |
+
"result": result,
|
79 |
+
"file_type": file_type
|
80 |
+
}
|
81 |
+
|
82 |
except Exception as e:
|
83 |
return {"error": str(e)}, 500
|
deepfake2/testing2.py
CHANGED
@@ -24,6 +24,46 @@ def predict_image(img_path):
|
|
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:
|
|
|
24 |
prediction = model.predict(img_array)
|
25 |
return "Fake" if prediction[0][0] > 0.5 else "Real"
|
26 |
|
27 |
+
# Add this function for video analysis
|
28 |
+
def predict_video(video_path):
|
29 |
+
if not os.path.exists(video_path):
|
30 |
+
return "Video path does not exist."
|
31 |
+
|
32 |
+
cap = cv2.VideoCapture(video_path)
|
33 |
+
fake_frames = 0
|
34 |
+
total_frames = 0
|
35 |
+
|
36 |
+
while cap.isOpened():
|
37 |
+
ret, frame = cap.read()
|
38 |
+
if not ret:
|
39 |
+
break
|
40 |
+
|
41 |
+
# Convert frame to RGB and resize
|
42 |
+
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
43 |
+
frame_resized = cv2.resize(frame_rgb, (img_height, img_width))
|
44 |
+
|
45 |
+
# Prepare frame for prediction
|
46 |
+
frame_array = image.img_to_array(frame_resized) / 255.0
|
47 |
+
frame_array = np.expand_dims(frame_array, axis=0)
|
48 |
+
|
49 |
+
# Predict frame
|
50 |
+
prediction = model.predict(frame_array)
|
51 |
+
if prediction[0][0] > 0.5:
|
52 |
+
fake_frames += 1
|
53 |
+
total_frames += 1
|
54 |
+
|
55 |
+
cap.release()
|
56 |
+
|
57 |
+
# Calculate percentage of fake frames
|
58 |
+
fake_percentage = (fake_frames / total_frames) * 100 if total_frames > 0 else 0
|
59 |
+
|
60 |
+
return {
|
61 |
+
"prediction": "Fake" if fake_percentage > 50 else "Real",
|
62 |
+
"confidence_score": round(fake_percentage / 100, 2),
|
63 |
+
"frames_analyzed": total_frames,
|
64 |
+
"fake_frames_detected": fake_frames
|
65 |
+
}
|
66 |
+
|
67 |
# Metadata analysis
|
68 |
def check_metadata(img_path):
|
69 |
try:
|
nexus-frontend/src/pages/deepfake.tsx
CHANGED
@@ -60,6 +60,14 @@ const DeepfakeDetection = () => {
|
|
60 |
const [selectedImage, setSelectedImage] = useState(null);
|
61 |
const [result, setResult] = useState(null);
|
62 |
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
const handleImageSelect = (event) => {
|
65 |
const file = event.target.files[0];
|
@@ -67,10 +75,12 @@ const DeepfakeDetection = () => {
|
|
67 |
};
|
68 |
|
69 |
const handleUpload = async () => {
|
70 |
-
|
|
|
|
|
71 |
setLoading(true);
|
72 |
const formData = new FormData();
|
73 |
-
formData.append('
|
74 |
|
75 |
try {
|
76 |
const response = await fetch('http://localhost:8000/detect-deepfake', {
|
@@ -99,21 +109,39 @@ const DeepfakeDetection = () => {
|
|
99 |
|
100 |
<div className="space-y-6">
|
101 |
<div className="flex flex-col items-center">
|
102 |
-
<
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
</div>
|
114 |
-
</label>
|
115 |
|
116 |
-
{selectedImage && (
|
117 |
<div className="mt-4 text-center">
|
118 |
<p className="text-blue-300">Selected: {selectedImage.name}</p>
|
119 |
<img
|
@@ -123,10 +151,23 @@ const DeepfakeDetection = () => {
|
|
123 |
/>
|
124 |
</div>
|
125 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
<button
|
128 |
onClick={handleUpload}
|
129 |
-
disabled={!selectedImage || loading}
|
130 |
className="mt-4 px-6 py-2 rounded-lg bg-blue-500 hover:bg-blue-600 text-white disabled:opacity-50"
|
131 |
>
|
132 |
Analyze
|
|
|
60 |
const [selectedImage, setSelectedImage] = useState(null);
|
61 |
const [result, setResult] = useState(null);
|
62 |
const [loading, setLoading] = useState(false);
|
63 |
+
const [selectedVideo, setSelectedVideo] = useState(null);
|
64 |
+
const [fileType, setFileType] = useState(null);
|
65 |
+
|
66 |
+
const handleVideoSelect = (event) => {
|
67 |
+
const file = event.target.files[0];
|
68 |
+
setSelectedVideo(file);
|
69 |
+
setFileType('video');
|
70 |
+
};
|
71 |
|
72 |
const handleImageSelect = (event) => {
|
73 |
const file = event.target.files[0];
|
|
|
75 |
};
|
76 |
|
77 |
const handleUpload = async () => {
|
78 |
+
const fileToUpload = fileType === 'video' ? selectedVideo : selectedImage;
|
79 |
+
if (!fileToUpload) return;
|
80 |
+
|
81 |
setLoading(true);
|
82 |
const formData = new FormData();
|
83 |
+
formData.append('file', fileToUpload);
|
84 |
|
85 |
try {
|
86 |
const response = await fetch('http://localhost:8000/detect-deepfake', {
|
|
|
109 |
|
110 |
<div className="space-y-6">
|
111 |
<div className="flex flex-col items-center">
|
112 |
+
<div className="flex gap-4">
|
113 |
+
<input
|
114 |
+
accept="image/*"
|
115 |
+
className="hidden"
|
116 |
+
id="image-upload"
|
117 |
+
type="file"
|
118 |
+
onChange={(e) => {
|
119 |
+
handleImageSelect(e);
|
120 |
+
setFileType('image');
|
121 |
+
}}
|
122 |
+
/>
|
123 |
+
<label htmlFor="image-upload">
|
124 |
+
<div className="px-6 py-3 rounded-lg bg-blue-500 hover:bg-blue-600 text-white cursor-pointer flex items-center gap-2">
|
125 |
+
<CloudUploadIcon />
|
126 |
+
Upload Image
|
127 |
+
</div>
|
128 |
+
</label>
|
129 |
+
<input
|
130 |
+
accept="video/mp4"
|
131 |
+
className="hidden"
|
132 |
+
id="video-upload"
|
133 |
+
type="file"
|
134 |
+
onChange={handleVideoSelect}
|
135 |
+
/>
|
136 |
+
<label htmlFor="video-upload">
|
137 |
+
<div className="px-6 py-3 rounded-lg bg-green-500 hover:bg-green-600 text-white cursor-pointer flex items-center gap-2">
|
138 |
+
<CloudUploadIcon />
|
139 |
+
Upload MP4 Video
|
140 |
+
</div>
|
141 |
+
</label>
|
142 |
</div>
|
|
|
143 |
|
144 |
+
{selectedImage && fileType === 'image' && (
|
145 |
<div className="mt-4 text-center">
|
146 |
<p className="text-blue-300">Selected: {selectedImage.name}</p>
|
147 |
<img
|
|
|
151 |
/>
|
152 |
</div>
|
153 |
)}
|
154 |
+
|
155 |
+
{selectedVideo && fileType === 'video' && (
|
156 |
+
<div className="mt-4 text-center">
|
157 |
+
<p className="text-blue-300">Selected Video: {selectedVideo.name}</p>
|
158 |
+
<video
|
159 |
+
className="max-w-md mt-4 rounded-lg mx-auto"
|
160 |
+
controls
|
161 |
+
>
|
162 |
+
<source src={URL.createObjectURL(selectedVideo)} type={selectedVideo.type} />
|
163 |
+
Your browser does not support the video tag.
|
164 |
+
</video>
|
165 |
+
</div>
|
166 |
+
)}
|
167 |
|
168 |
<button
|
169 |
onClick={handleUpload}
|
170 |
+
disabled={!selectedImage && !selectedVideo || loading}
|
171 |
className="mt-4 px-6 py-2 rounded-lg bg-blue-500 hover:bg-blue-600 text-white disabled:opacity-50"
|
172 |
>
|
173 |
Analyze
|