Distilled from the
Desant CLIP-based phishing classifier by
Desant.ai for ultra-low-latency edge deployment.
Input Image (web page screenshot)
│
▼ Aspect-ratio-preserving resize + CLIP-mean padding → 224×224
┌──────────────────────────────┐
│ MobileNetV2 1.0 │ ← ImageNet-pretrained, fine-tuned
│ Depthwise Separable Convs │
│ Input: 224×224×3 (uint8) │
│ Inverted Residual Blocks │
└──────────┬───────────────────┘
│ 1280-dim feature map
▼
┌──────────────────────────────┐
│ GlobalAveragePooling2D │
│ Dropout(0.3) │
│ Dense(128, ReLU) │
│ Dropout(0.2) │
│ Dense(2, Softmax) │ ← [safe, malicious] probabilities
└──────────┬───────────────────┘
│
▼
uint8 output → dequantize → prediction
1 # 1. Load screenshot (any resolution)
2 # 2. Aspect-ratio-preserving resize to 224×224
3 # 3. Pad with CLIP-mean color: (123, 117, 104)
4 # 4. MobileNetV2 normalization: [0, 255] → [-1.0, 1.0]
5 # 5. INT8 quantization: scale=0.00784314, zero_point=127
1 import numpy as np
2 from PIL import Image
3 from pycoral . adapters import classify , common
4 from pycoral . utils . edgetpu import make_interpreter
5
6 CLIP_MEAN_PAD = ( 123 , 117 , 104 )
7
8 def preprocess ( image_path , size = 224 ) :
9 """Aspect-ratio-preserving resize with CLIP-mean padding."""
10 img = Image . open ( image_path ) . convert ( "RGB" )
11 w , h = img . size
12 scale = min ( size / w , size / h )
13 new_w , new_h = int ( w * scale ) , int ( h * scale )
14 img = img . resize ( ( new_w , new_h ) , Image . LANCZOS )
15 canvas = Image . new ( "RGB" , ( size , size ) , CLIP_MEAN_PAD )
16 canvas . paste ( img , ( ( size - new_w ) // 2 , ( size - new_h ) // 2 ) )
17 return np . array ( canvas , dtype = np . uint8 )
18
19 # Load Edge TPU model
20 interpreter = make_interpreter ( "student_best_int8_edgetpu_edgetpu.tflite" )
21 interpreter . allocate_tensors ( )
22
23 # Preprocess and run inference
24 image = preprocess ( "screenshot.png" )
25 common . set_input ( interpreter , image )
26 interpreter . invoke ( )
27
28 # Get results
29 output = common . output_tensor ( interpreter , 0 )
30 safe_score = output [ 0 ]
31 malicious_score = output [ 1 ]
32
33 label = "MALICIOUS" if malicious_score > safe_score else "SAFE"
34 print ( f" { label } — safe: { safe_score } , malicious: { malicious_score } " )
1 import numpy as np
2 from PIL import Image
3 import tflite_runtime . interpreter as tflite
4
5 CLIP_MEAN_PAD = ( 123 , 117 , 104 )
6
7 def preprocess ( image_path , size = 224 ) :
8 img = Image . open ( image_path ) . convert ( "RGB" )
9 w , h = img . size
10 scale = min ( size / w , size / h )
11 new_w , new_h = int ( w * scale ) , int ( h * scale )
12 img = img . resize ( ( new_w , new_h ) , Image . LANCZOS )
13 canvas = Image . new ( "RGB" , ( size , size ) , CLIP_MEAN_PAD )
14 canvas . paste ( img , ( ( size - new_w ) // 2 , ( size - new_h ) // 2 ) )
15 return np . expand_dims ( np . array ( canvas , dtype = np . uint8 ) , axis = 0 )
16
17 interpreter = tflite . Interpreter ( model_path = "student_best_int8_edgetpu.tflite" )
18 interpreter . allocate_tensors ( )
19
20 input_details = interpreter . get_input_details ( )
21 output_details = interpreter . get_output_details ( )
22
23 image = preprocess ( "screenshot.png" )
24 interpreter . set_tensor ( input_details [ 0 ] [ "index" ] , image )
25 interpreter . invoke ( )
26
27 output = interpreter . get_tensor ( output_details [ 0 ] [ "index" ] ) [ 0 ]
28 scale = output_details [ 0 ] [ "quantization_parameters" ] [ "scales" ] [ 0 ]
29 zero_point = output_details [ 0 ] [ "quantization_parameters" ] [ "zero_points" ] [ 0 ]
30 probs = ( output . astype ( np . float32 ) - zero_point ) * scale
31
32 label = "MALICIOUS" if probs [ 1 ] > probs [ 0 ] else "SAFE"
33 print ( f" { label } — safe: { probs [ 0 ] : .4f } , malicious: { probs [ 1 ] : .4f } " )
1 # Install Coral runtime
2 echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" \
3 | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
4 curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
5 sudo apt update && sudo apt install libedgetpu1-std python3-pycoral
6
7 # Run inference
8 python3 inference.py --model student_best_int8_edgetpu_edgetpu.tflite --image screenshot.png
1 @misc{desant2026phishing_edgetpu,
2 title={Desant Phishing Detector: MobileNetV2 INT8 for Google Coral Edge TPU},
3 author={Desant.ai},
4 year={2026},
5 url={https://huggingface.co/desant-ai/desant-phishing-detector-google-coral-int8}
6 }