saakshigupta commited on
Commit
36eda57
·
verified ·
1 Parent(s): 388d161

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +293 -274
app.py CHANGED
@@ -178,20 +178,80 @@ def check_gpu():
178
  return False
179
 
180
  # Sidebar components
181
- st.sidebar.title("About")
182
- st.sidebar.markdown("""
183
- This tool detects deepfakes using three AI models:
184
- - **Xception**: Initial Real/Fake classification
185
- - **BLIP**: Describes image content
186
- - **Llama 3.2**: Explains potential manipulations
187
 
188
- ### Quick Start
189
- 1. **Load Models** - Start with Xception, add others as needed
190
- 2. **Upload Image** - View classification and heat map
191
- 3. **Analyze** - Get explanations and ask questions
192
-
193
- *GPU recommended for better performance*
194
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
  # Fixed values for temperature and max tokens
197
  temperature = 0.7
@@ -296,7 +356,7 @@ def process_image_with_xception_gradcam(image, model, device, pred_class):
296
  _, _, _, _, face_box, _ = dataset[0]
297
 
298
  return raw_cam, overlay, comparison, face_box
299
- else:
300
  st.error("Failed to generate GradCAM visualization")
301
  return None, None, None, None
302
 
@@ -375,18 +435,18 @@ def generate_gradcam_caption(image, processor, model, max_length=60):
375
  # Try to parse the caption based on different possible formats
376
  try:
377
  # Original format with "high activation:" etc.
378
- formatted_text = ""
379
  if "high activation :" in caption:
380
  high_match = caption.split("high activation :")[1].split("moderate")[0]
381
- formatted_text += f"**High activation**:\n{high_match.strip()}\n\n"
382
 
383
  if "moderate activation :" in caption:
384
  moderate_match = caption.split("moderate activation :")[1].split("low")[0]
385
- formatted_text += f"**Moderate activation**:\n{moderate_match.strip()}\n\n"
386
 
387
  if "low activation :" in caption:
388
  low_match = caption.split("low activation :")[1]
389
- formatted_text += f"**Low activation**:\n{low_match.strip()}"
390
 
391
  # If nothing was extracted using the original format, try alternative formats
392
  if not formatted_text.strip():
@@ -663,7 +723,7 @@ def preprocess_image_xception(image):
663
 
664
  # Main app
665
  def main():
666
- # Initialize session state variables
667
  if 'xception_model_loaded' not in st.session_state:
668
  st.session_state.xception_model_loaded = False
669
  st.session_state.xception_model = None
@@ -687,276 +747,240 @@ def main():
687
  # Create multi-tab interface
688
  tab1, tab2, tab3 = st.tabs(["Deepfake Detection", "Image Captions", "LLM Analysis"])
689
 
690
- # Tab 1: Deepfake Detection with Model Loading and Image Upload
691
  with tab1:
692
  st.header("Deepfake Detection")
693
 
694
- # Model Loading section
695
- with st.expander("Load Detection Model", expanded=True):
696
- st.write("Please load the Xception model for deepfake detection:")
697
- if not st.session_state.xception_model_loaded:
698
- if st.button("📥 Load Xception Model", type="primary"):
699
- # Load Xception model
700
- model, device = load_detection_model_xception()
701
- if model is not None:
702
- st.session_state.xception_model = model
703
- st.session_state.device = device
704
- st.session_state.xception_model_loaded = True
705
- st.success("✅ Xception model loaded successfully!")
706
- else:
707
- st.error("❌ Failed to load Xception model.")
708
- else:
709
- st.success("✅ Xception model loaded and ready!")
710
-
711
  # Image upload section
712
- with st.expander("Upload and Analyze Image", expanded=True):
713
- st.subheader("Upload an Image")
714
-
715
- # Add alternative upload methods
716
- upload_tab1, upload_tab2 = st.tabs(["File Upload", "URL Input"])
717
-
718
- uploaded_image = None
719
-
720
- with upload_tab1:
721
- uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
722
- if uploaded_file is not None:
723
- try:
724
- # Simple direct approach - load the image directly
725
- image = Image.open(uploaded_file).convert("RGB")
726
- uploaded_image = image
727
- st.session_state.upload_method = "file"
728
- except Exception as e:
729
- st.error(f"Error loading image: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730
  import traceback
731
  st.error(traceback.format_exc())
 
 
 
 
 
 
 
 
732
 
733
- with upload_tab2:
734
- url = st.text_input("Enter image URL:")
735
- if url and url.strip():
736
- try:
737
- import requests
738
- # Simplified URL handling with more robust approach
739
- headers = {
740
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
741
- 'Accept': 'image/jpeg, image/png, image/*, */*',
742
- 'Referer': 'https://huggingface.co/'
743
- }
744
 
745
- # Try three different methods to handle various API restrictions
746
- try_methods = True
 
 
 
 
 
747
 
748
- # Method 1: Direct requests
749
- if try_methods:
750
- try:
751
- response = requests.get(url, stream=True, headers=headers, timeout=10)
752
- if response.status_code == 200 and 'image' in response.headers.get('Content-Type', ''):
753
- try:
754
- image = Image.open(io.BytesIO(response.content)).convert("RGB")
755
- uploaded_image = image
756
- st.session_state.upload_method = "url_direct"
757
- try_methods = False
758
- st.success("✅ Image loaded via direct request")
759
- except Exception as e:
760
- st.warning(f"Direct method received data but couldn't process as image: {str(e)}")
761
- else:
762
- st.info(f"Direct method failed: Status {response.status_code}, trying alternative method...")
763
- except Exception as e:
764
- st.info(f"Direct method error: {str(e)}, trying alternative method...")
765
 
766
- # Method 2: Use Python's urllib as fallback
767
- if try_methods:
768
- try:
769
- import urllib.request
770
- from urllib.error import HTTPError
771
-
772
- opener = urllib.request.build_opener()
773
- opener.addheaders = [('User-agent', headers['User-Agent'])]
774
- urllib.request.install_opener(opener)
775
-
776
- with urllib.request.urlopen(url, timeout=10) as response:
777
- image_data = response.read()
778
- image = Image.open(io.BytesIO(image_data)).convert("RGB")
779
- uploaded_image = image
780
- st.session_state.upload_method = "url_urllib"
781
- try_methods = False
782
- st.success("✅ Image loaded via urllib")
783
- except HTTPError as e:
784
- st.info(f"urllib method failed: HTTP error {e.code}, trying next method...")
785
- except Exception as e:
786
- st.info(f"urllib method error: {str(e)}, trying next method...")
787
 
788
- # Method 3: Use a proxy service as last resort
789
- if try_methods:
790
- try:
791
- # This uses an image proxy service to bypass CORS issues
792
- # Only as last resort since it depends on external service
793
- proxy_url = f"https://images.weserv.nl/?url={url}"
794
- response = requests.get(proxy_url, stream=True, timeout=10)
795
- if response.status_code == 200:
796
- image = Image.open(io.BytesIO(response.content)).convert("RGB")
797
- uploaded_image = image
798
- st.session_state.upload_method = "url_proxy"
799
- try_methods = False
800
- st.success("✅ Image loaded via proxy service")
801
- else:
802
- st.error(f"All methods failed to load the image from URL. Last status: {response.status_code}")
803
- except Exception as e:
804
- st.error(f"All methods failed. Final error: {str(e)}")
805
-
806
- if not uploaded_image:
807
- st.error("Failed to load image using all available methods.")
808
-
809
- except Exception as e:
810
- st.error(f"Error processing URL: {str(e)}")
811
- if st.session_state.debug:
812
  import traceback
813
  st.error(traceback.format_exc())
814
-
815
- # If we have an uploaded image, process it
816
- if uploaded_image is not None:
817
- # Display the image
818
- image = uploaded_image
819
- col1, col2 = st.columns([1, 2])
820
- with col1:
821
- st.image(image, caption="Uploaded Image", width=300)
822
-
823
- # Continue with Xception model analysis
824
- if st.session_state.xception_model_loaded:
825
- try:
826
- with st.spinner("Analyzing image with Xception model..."):
827
- # Preprocess image for Xception
828
- input_tensor, original_image, face_box = preprocess_image_xception(image)
829
-
830
- if input_tensor is None:
831
- st.error("Failed to preprocess image. Please try another image.")
832
- st.stop()
833
-
834
- # Get device and model
835
- device = st.session_state.device
836
- model = st.session_state.xception_model
837
-
838
- # Ensure model is in eval mode
839
- model.eval()
840
-
841
- # Move tensor to device
842
- input_tensor = input_tensor.to(device)
843
-
844
- # Forward pass with proper error handling
845
- try:
846
- with torch.no_grad():
847
- logits = model(input_tensor)
848
- probabilities = torch.softmax(logits, dim=1)[0]
849
- pred_class = torch.argmax(probabilities).item()
850
- confidence = probabilities[pred_class].item()
851
-
852
- # Explicit class mapping - adjust if needed based on your model
853
- pred_label = "Fake" if pred_class == 0 else "Real"
854
- except Exception as e:
855
- st.error(f"Error in model inference: {str(e)}")
856
- import traceback
857
- st.error(traceback.format_exc())
858
- # Set default values
859
- pred_class = 0
860
- confidence = 0.5
861
- pred_label = "Error in prediction"
862
 
863
- # Display results
864
- with col2:
865
- st.markdown("### Detection Result")
866
- st.markdown(f"**Classification:** {pred_label} (Confidence: {confidence:.2%})")
867
-
868
- # Display face box on image if detected
869
- if face_box:
870
- img_to_show = original_image.copy()
871
- img_draw = np.array(img_to_show)
872
- x, y, w, h = face_box
873
- cv2.rectangle(img_draw, (x, y), (x + w, y + h), (0, 255, 0), 2)
874
- st.image(Image.fromarray(img_draw), caption="Detected Face", width=300)
 
 
875
 
876
- # GradCAM visualization with error handling
877
- st.subheader("GradCAM Visualization")
878
- try:
879
- cam, overlay, comparison, detected_face_box = process_image_with_xception_gradcam(
880
- image, model, device, pred_class
881
- )
882
 
883
- if comparison:
884
- # Display GradCAM results (controlled size)
885
- st.image(comparison, caption="Original | CAM | Overlay", width=700)
 
 
 
 
 
 
 
 
 
 
 
886
 
887
- # Save for later use
888
- st.session_state.comparison_image = comparison
889
- else:
890
- st.error("GradCAM visualization failed - comparison image not generated")
891
-
892
- # Generate caption for GradCAM overlay image if BLIP model is loaded
893
- if st.session_state.blip_model_loaded and overlay:
894
- with st.spinner("Analyzing GradCAM visualization..."):
895
- gradcam_caption = generate_gradcam_caption(
896
- overlay,
897
- st.session_state.finetuned_processor,
898
- st.session_state.finetuned_model
899
- )
900
- st.session_state.gradcam_caption = gradcam_caption
901
-
902
- # Display the caption directly here as well for immediate feedback
903
- st.markdown("### GradCAM Analysis")
904
- st.markdown(gradcam_caption)
905
- except Exception as e:
906
- st.error(f"Error generating GradCAM: {str(e)}")
907
- import traceback
908
- st.error(traceback.format_exc())
909
-
910
- # Save results in session state for use in other tabs
911
- st.session_state.current_image = image
912
- st.session_state.current_overlay = overlay if 'overlay' in locals() else None
913
- st.session_state.current_face_box = detected_face_box if 'detected_face_box' in locals() else None
914
- st.session_state.current_pred_label = pred_label
915
- st.session_state.current_confidence = confidence
916
-
917
- st.success("✅ Initial detection and GradCAM visualization complete!")
918
- except Exception as e:
919
- st.error(f"Overall error in Xception processing: {str(e)}")
920
- import traceback
921
- st.error(traceback.format_exc())
922
- else:
923
- st.warning("⚠️ Please load the Xception model first to perform initial detection.")
924
 
925
  # Tab 2: Image Captions with BLIP models
926
  with tab2:
927
  st.header("Image Captions")
928
 
929
- # Model Loading section
930
- with st.expander("Load Captioning Models", expanded=True):
931
- if not st.session_state.blip_model_loaded:
932
- if st.button("📥 Load BLIP for Captioning", type="primary"):
933
- # Load BLIP models
934
- original_processor, original_model, finetuned_processor, finetuned_model = load_blip_models()
935
- if all([original_processor, original_model, finetuned_processor, finetuned_model]):
936
- st.session_state.original_processor = original_processor
937
- st.session_state.original_model = original_model
938
- st.session_state.finetuned_processor = finetuned_processor
939
- st.session_state.finetuned_model = finetuned_model
940
- st.session_state.blip_model_loaded = True
941
- st.success("✅ BLIP captioning models loaded successfully!")
942
- else:
943
- st.error("❌ Failed to load BLIP models.")
944
- else:
945
- st.success("✅ BLIP captioning models loaded and ready!")
946
-
947
  # Image Caption Display
948
  if hasattr(st.session_state, 'current_image'):
949
  col1, col2 = st.columns([1, 2])
950
 
951
  with col1:
952
- st.image(st.session_state.current_image, caption="Image", width=300)
953
 
954
  if hasattr(st.session_state, 'current_overlay'):
955
  st.image(st.session_state.current_overlay, caption="GradCAM Visualization", width=300)
956
 
957
  with col2:
958
  if not st.session_state.blip_model_loaded:
959
- st.warning("⚠️ Please load the BLIP models first to see captions.")
960
  else:
961
  # Button to generate captions if not already generated
962
  if not hasattr(st.session_state, 'image_caption') or st.button("Regenerate Image Caption"):
@@ -990,7 +1014,18 @@ def main():
990
  st.session_state.gradcam_caption = gradcam_caption
991
  st.rerun()
992
  else:
993
- st.info("GradCAM caption not available. Visit the Detection tab to generate it.")
 
 
 
 
 
 
 
 
 
 
 
994
  else:
995
  st.info("Please upload and analyze an image in the Detection tab first.")
996
 
@@ -998,22 +1033,6 @@ def main():
998
  with tab3:
999
  st.header("LLM Analysis")
1000
 
1001
- # Model Loading section
1002
- with st.expander("Load LLM Model", expanded=True):
1003
- if not st.session_state.llm_model_loaded:
1004
- if st.button("📥 Load Vision LLM", type="primary"):
1005
- # Load LLM model
1006
- model, tokenizer = load_llm_model()
1007
- if model is not None and tokenizer is not None:
1008
- st.session_state.llm_model = model
1009
- st.session_state.tokenizer = tokenizer
1010
- st.session_state.llm_model_loaded = True
1011
- st.success("✅ Vision LLM loaded successfully!")
1012
- else:
1013
- st.error("❌ Failed to load Vision LLM.")
1014
- else:
1015
- st.success("✅ Vision LLM loaded and ready!")
1016
-
1017
  # Chat Interface
1018
  if hasattr(st.session_state, 'current_image') and st.session_state.llm_model_loaded:
1019
  st.subheader("Deepfake Analysis Chat")
@@ -1140,7 +1159,7 @@ def main():
1140
  if not hasattr(st.session_state, 'current_image'):
1141
  st.warning("⚠️ Please upload an image in the Detection tab first.")
1142
  else:
1143
- st.warning("⚠️ Please load the Vision LLM to perform detailed analysis.")
1144
 
1145
  # Footer
1146
  st.markdown("---")
 
178
  return False
179
 
180
  # Sidebar components
181
+ st.sidebar.title("Model Controls")
 
 
 
 
 
182
 
183
+ # Model loading buttons in sidebar
184
+ with st.sidebar:
185
+ st.write("### Load Models")
186
+
187
+ # Xception model loading
188
+ if 'xception_model_loaded' not in st.session_state:
189
+ st.session_state.xception_model_loaded = False
190
+ st.session_state.xception_model = None
191
+
192
+ if not st.session_state.xception_model_loaded:
193
+ if st.button("📥 Load Xception Model", type="primary"):
194
+ # Load Xception model
195
+ model, device = load_detection_model_xception()
196
+ if model is not None:
197
+ st.session_state.xception_model = model
198
+ st.session_state.device = device
199
+ st.session_state.xception_model_loaded = True
200
+ st.success("✅ Xception model loaded!")
201
+ else:
202
+ st.error("❌ Failed to load Xception model.")
203
+ else:
204
+ st.success("✅ Xception model loaded")
205
+
206
+ # BLIP model loading
207
+ if 'blip_model_loaded' not in st.session_state:
208
+ st.session_state.blip_model_loaded = False
209
+ st.session_state.original_processor = None
210
+ st.session_state.original_model = None
211
+ st.session_state.finetuned_processor = None
212
+ st.session_state.finetuned_model = None
213
+
214
+ if not st.session_state.blip_model_loaded:
215
+ if st.button("📥 Load BLIP Models", type="primary"):
216
+ # Load BLIP models
217
+ original_processor, original_model, finetuned_processor, finetuned_model = load_blip_models()
218
+ if all([original_processor, original_model, finetuned_processor, finetuned_model]):
219
+ st.session_state.original_processor = original_processor
220
+ st.session_state.original_model = original_model
221
+ st.session_state.finetuned_processor = finetuned_processor
222
+ st.session_state.finetuned_model = finetuned_model
223
+ st.session_state.blip_model_loaded = True
224
+ st.success("✅ BLIP models loaded!")
225
+ else:
226
+ st.error("❌ Failed to load BLIP models.")
227
+ else:
228
+ st.success("✅ BLIP models loaded")
229
+
230
+ # LLM model loading
231
+ if 'llm_model_loaded' not in st.session_state:
232
+ st.session_state.llm_model_loaded = False
233
+ st.session_state.llm_model = None
234
+ st.session_state.tokenizer = None
235
+
236
+ if not st.session_state.llm_model_loaded:
237
+ if st.button("📥 Load Vision LLM", type="primary"):
238
+ # Load LLM model
239
+ model, tokenizer = load_llm_model()
240
+ if model is not None and tokenizer is not None:
241
+ st.session_state.llm_model = model
242
+ st.session_state.tokenizer = tokenizer
243
+ st.session_state.llm_model_loaded = True
244
+ st.success("✅ Vision LLM loaded!")
245
+ else:
246
+ st.error("❌ Failed to load Vision LLM.")
247
+ else:
248
+ st.success("✅ Vision LLM loaded")
249
+
250
+ # Debug toggle
251
+ st.session_state.debug = st.toggle("Enable Debug Mode", value=debug_mode)
252
+
253
+ # Display model info
254
+ st.info("Using Xception + deepfake-explainer-new models")
255
 
256
  # Fixed values for temperature and max tokens
257
  temperature = 0.7
 
356
  _, _, _, _, face_box, _ = dataset[0]
357
 
358
  return raw_cam, overlay, comparison, face_box
359
+ else:
360
  st.error("Failed to generate GradCAM visualization")
361
  return None, None, None, None
362
 
 
435
  # Try to parse the caption based on different possible formats
436
  try:
437
  # Original format with "high activation:" etc.
438
+ formatted_text = ""
439
  if "high activation :" in caption:
440
  high_match = caption.split("high activation :")[1].split("moderate")[0]
441
+ formatted_text += f"**High activation**:\n{high_match.strip()}\n\n"
442
 
443
  if "moderate activation :" in caption:
444
  moderate_match = caption.split("moderate activation :")[1].split("low")[0]
445
+ formatted_text += f"**Moderate activation**:\n{moderate_match.strip()}\n\n"
446
 
447
  if "low activation :" in caption:
448
  low_match = caption.split("low activation :")[1]
449
+ formatted_text += f"**Low activation**:\n{low_match.strip()}"
450
 
451
  # If nothing was extracted using the original format, try alternative formats
452
  if not formatted_text.strip():
 
723
 
724
  # Main app
725
  def main():
726
+ # Initialize session state variables if not present
727
  if 'xception_model_loaded' not in st.session_state:
728
  st.session_state.xception_model_loaded = False
729
  st.session_state.xception_model = None
 
747
  # Create multi-tab interface
748
  tab1, tab2, tab3 = st.tabs(["Deepfake Detection", "Image Captions", "LLM Analysis"])
749
 
750
+ # Tab 1: Deepfake Detection
751
  with tab1:
752
  st.header("Deepfake Detection")
753
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
754
  # Image upload section
755
+ st.subheader("Upload an Image")
756
+
757
+ # Add alternative upload methods
758
+ upload_tab1, upload_tab2 = st.tabs(["File Upload", "URL Input"])
759
+
760
+ uploaded_image = None
761
+
762
+ with upload_tab1:
763
+ uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
764
+ if uploaded_file is not None:
765
+ try:
766
+ # Simple direct approach - load the image directly
767
+ image = Image.open(uploaded_file).convert("RGB")
768
+ uploaded_image = image
769
+ st.session_state.upload_method = "file"
770
+ except Exception as e:
771
+ st.error(f"Error loading image: {str(e)}")
772
+ import traceback
773
+ st.error(traceback.format_exc())
774
+
775
+ with upload_tab2:
776
+ url = st.text_input("Enter image URL:")
777
+ if url and url.strip():
778
+ try:
779
+ import requests
780
+ # Simplified URL handling with more robust approach
781
+ headers = {
782
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
783
+ 'Accept': 'image/jpeg, image/png, image/*, */*',
784
+ 'Referer': 'https://huggingface.co/'
785
+ }
786
+
787
+ # Try three different methods to handle various API restrictions
788
+ try_methods = True
789
+
790
+ # Method 1: Direct requests
791
+ if try_methods:
792
+ try:
793
+ response = requests.get(url, stream=True, headers=headers, timeout=10)
794
+ if response.status_code == 200 and 'image' in response.headers.get('Content-Type', ''):
795
+ try:
796
+ image = Image.open(io.BytesIO(response.content)).convert("RGB")
797
+ uploaded_image = image
798
+ st.session_state.upload_method = "url_direct"
799
+ try_methods = False
800
+ st.success("✅ Image loaded via direct request")
801
+ except Exception as e:
802
+ st.warning(f"Direct method received data but couldn't process as image: {str(e)}")
803
+ else:
804
+ st.info(f"Direct method failed: Status {response.status_code}, trying alternative method...")
805
+ except Exception as e:
806
+ st.info(f"Direct method error: {str(e)}, trying alternative method...")
807
+
808
+ # Method 2: Use Python's urllib as fallback
809
+ if try_methods:
810
+ try:
811
+ import urllib.request
812
+ from urllib.error import HTTPError
813
+
814
+ opener = urllib.request.build_opener()
815
+ opener.addheaders = [('User-agent', headers['User-Agent'])]
816
+ urllib.request.install_opener(opener)
817
+
818
+ with urllib.request.urlopen(url, timeout=10) as response:
819
+ image_data = response.read()
820
+ image = Image.open(io.BytesIO(image_data)).convert("RGB")
821
+ uploaded_image = image
822
+ st.session_state.upload_method = "url_urllib"
823
+ try_methods = False
824
+ st.success("✅ Image loaded via urllib")
825
+ except HTTPError as e:
826
+ st.info(f"urllib method failed: HTTP error {e.code}, trying next method...")
827
+ except Exception as e:
828
+ st.info(f"urllib method error: {str(e)}, trying next method...")
829
+
830
+ # Method 3: Use a proxy service as last resort
831
+ if try_methods:
832
+ try:
833
+ # This uses an image proxy service to bypass CORS issues
834
+ # Only as last resort since it depends on external service
835
+ proxy_url = f"https://images.weserv.nl/?url={url}"
836
+ response = requests.get(proxy_url, stream=True, timeout=10)
837
+ if response.status_code == 200:
838
+ image = Image.open(io.BytesIO(response.content)).convert("RGB")
839
+ uploaded_image = image
840
+ st.session_state.upload_method = "url_proxy"
841
+ try_methods = False
842
+ st.success("✅ Image loaded via proxy service")
843
+ else:
844
+ st.error(f"All methods failed to load the image from URL. Last status: {response.status_code}")
845
+ except Exception as e:
846
+ st.error(f"All methods failed. Final error: {str(e)}")
847
+
848
+ if not uploaded_image:
849
+ st.error("Failed to load image using all available methods.")
850
+
851
+ except Exception as e:
852
+ st.error(f"Error processing URL: {str(e)}")
853
+ if st.session_state.debug:
854
  import traceback
855
  st.error(traceback.format_exc())
856
+
857
+ # If we have an uploaded image, process it
858
+ if uploaded_image is not None:
859
+ # Display the image
860
+ image = uploaded_image
861
+ col1, col2 = st.columns([1, 2])
862
+ with col1:
863
+ st.image(image, caption="Uploaded Image", width=300)
864
 
865
+ # Continue with Xception model analysis
866
+ if st.session_state.xception_model_loaded:
867
+ try:
868
+ with st.spinner("Analyzing image with Xception model..."):
869
+ # Preprocess image for Xception
870
+ input_tensor, original_image, face_box = preprocess_image_xception(image)
 
 
 
 
 
871
 
872
+ if input_tensor is None:
873
+ st.error("Failed to preprocess image. Please try another image.")
874
+ st.stop()
875
+
876
+ # Get device and model
877
+ device = st.session_state.device
878
+ model = st.session_state.xception_model
879
 
880
+ # Ensure model is in eval mode
881
+ model.eval()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
 
883
+ # Move tensor to device
884
+ input_tensor = input_tensor.to(device)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
 
886
+ # Forward pass with proper error handling
887
+ try:
888
+ with torch.no_grad():
889
+ logits = model(input_tensor)
890
+ probabilities = torch.softmax(logits, dim=1)[0]
891
+ pred_class = torch.argmax(probabilities).item()
892
+ confidence = probabilities[pred_class].item()
893
+
894
+ # Explicit class mapping - adjust if needed based on your model
895
+ pred_label = "Fake" if pred_class == 0 else "Real"
896
+ except Exception as e:
897
+ st.error(f"Error in model inference: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
898
  import traceback
899
  st.error(traceback.format_exc())
900
+ # Set default values
901
+ pred_class = 0
902
+ confidence = 0.5
903
+ pred_label = "Error in prediction"
904
+
905
+ # Display results
906
+ with col2:
907
+ st.markdown("### Detection Result")
908
+ st.markdown(f"**Classification:** {pred_label} (Confidence: {confidence:.2%})")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
 
910
+ # Display face box on image if detected
911
+ if face_box:
912
+ img_to_show = original_image.copy()
913
+ img_draw = np.array(img_to_show)
914
+ x, y, w, h = face_box
915
+ cv2.rectangle(img_draw, (x, y), (x + w, y + h), (0, 255, 0), 2)
916
+ st.image(Image.fromarray(img_draw), caption="Detected Face", width=300)
917
+
918
+ # GradCAM visualization with error handling
919
+ st.subheader("GradCAM Visualization")
920
+ try:
921
+ cam, overlay, comparison, detected_face_box = process_image_with_xception_gradcam(
922
+ image, model, device, pred_class
923
+ )
924
 
925
+ if comparison:
926
+ # Display GradCAM results (controlled size)
927
+ st.image(comparison, caption="Original | CAM | Overlay", width=700)
 
 
 
928
 
929
+ # Save for later use
930
+ st.session_state.comparison_image = comparison
931
+ else:
932
+ st.error("GradCAM visualization failed - comparison image not generated")
933
+
934
+ # Generate caption for GradCAM overlay image if BLIP model is loaded
935
+ if st.session_state.blip_model_loaded and overlay:
936
+ with st.spinner("Analyzing GradCAM visualization..."):
937
+ gradcam_caption = generate_gradcam_caption(
938
+ overlay,
939
+ st.session_state.finetuned_processor,
940
+ st.session_state.finetuned_model
941
+ )
942
+ st.session_state.gradcam_caption = gradcam_caption
943
 
944
+ # Display the caption directly here
945
+ st.markdown("### GradCAM Analysis")
946
+ st.markdown(gradcam_caption)
947
+ except Exception as e:
948
+ st.error(f"Error generating GradCAM: {str(e)}")
949
+ import traceback
950
+ st.error(traceback.format_exc())
951
+
952
+ # Save results in session state for use in other tabs
953
+ st.session_state.current_image = image
954
+ st.session_state.current_overlay = overlay if 'overlay' in locals() else None
955
+ st.session_state.current_face_box = detected_face_box if 'detected_face_box' in locals() else None
956
+ st.session_state.current_pred_label = pred_label
957
+ st.session_state.current_confidence = confidence
958
+
959
+ st.success("✅ Initial detection and GradCAM visualization complete!")
960
+ except Exception as e:
961
+ st.error(f"Overall error in Xception processing: {str(e)}")
962
+ import traceback
963
+ st.error(traceback.format_exc())
964
+ else:
965
+ st.warning("⚠️ Please load the Xception model from the sidebar first.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
 
967
  # Tab 2: Image Captions with BLIP models
968
  with tab2:
969
  st.header("Image Captions")
970
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
971
  # Image Caption Display
972
  if hasattr(st.session_state, 'current_image'):
973
  col1, col2 = st.columns([1, 2])
974
 
975
  with col1:
976
+ st.image(st.session_state.current_image, caption="Original Image", width=300)
977
 
978
  if hasattr(st.session_state, 'current_overlay'):
979
  st.image(st.session_state.current_overlay, caption="GradCAM Visualization", width=300)
980
 
981
  with col2:
982
  if not st.session_state.blip_model_loaded:
983
+ st.warning("⚠️ Please load the BLIP models from the sidebar first.")
984
  else:
985
  # Button to generate captions if not already generated
986
  if not hasattr(st.session_state, 'image_caption') or st.button("Regenerate Image Caption"):
 
1014
  st.session_state.gradcam_caption = gradcam_caption
1015
  st.rerun()
1016
  else:
1017
+ if hasattr(st.session_state, 'current_overlay'):
1018
+ if st.button("Generate GradCAM Caption"):
1019
+ with st.spinner("Analyzing GradCAM visualization..."):
1020
+ gradcam_caption = generate_gradcam_caption(
1021
+ st.session_state.current_overlay,
1022
+ st.session_state.finetuned_processor,
1023
+ st.session_state.finetuned_model
1024
+ )
1025
+ st.session_state.gradcam_caption = gradcam_caption
1026
+ st.rerun()
1027
+ else:
1028
+ st.info("GradCAM visualization not available. Visit the Detection tab to generate it.")
1029
  else:
1030
  st.info("Please upload and analyze an image in the Detection tab first.")
1031
 
 
1033
  with tab3:
1034
  st.header("LLM Analysis")
1035
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1036
  # Chat Interface
1037
  if hasattr(st.session_state, 'current_image') and st.session_state.llm_model_loaded:
1038
  st.subheader("Deepfake Analysis Chat")
 
1159
  if not hasattr(st.session_state, 'current_image'):
1160
  st.warning("⚠️ Please upload an image in the Detection tab first.")
1161
  else:
1162
+ st.warning("⚠️ Please load the Vision LLM from the sidebar to perform detailed analysis.")
1163
 
1164
  # Footer
1165
  st.markdown("---")