RafidMehda commited on
Commit
0ccc2f4
·
verified ·
1 Parent(s): a7f350d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -0
app.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import requests
4
+ import numpy as np
5
+ from PIL import Image, ImageDraw
6
+ import io
7
+ import random
8
+
9
+ # YOLOv10 import (installed via requirements.txt)
10
+ try:
11
+ from yolov10 import YOLOv10
12
+ except ImportError:
13
+ st.error("Could not import YOLOv10. Please confirm the library installation.")
14
+
15
+ # ------------------------
16
+ # 1. Chaotic Encryption Utilities
17
+ # ------------------------
18
+
19
+ def logistic_map(r, x):
20
+ return r * x * (1 - x)
21
+
22
+ def generate_key(seed, n):
23
+ key = []
24
+ x = seed
25
+ for _ in range(n):
26
+ x = logistic_map(3.9, x)
27
+ key.append(int(x * 255) % 256) # Map float to [0..255]
28
+ return np.array(key, dtype=np.uint8)
29
+
30
+ def shuffle_pixels(img_array, seed):
31
+ h, w, c = img_array.shape
32
+ num_pixels = h * w
33
+ flattened = img_array.reshape(-1, c)
34
+ indices = np.arange(num_pixels)
35
+
36
+ random.seed(seed)
37
+ random.shuffle(indices) # Shuffle indices
38
+
39
+ shuffled = flattened[indices]
40
+ return shuffled.reshape(h, w, c), indices
41
+
42
+ def encrypt_image(img_array, seed):
43
+ """Encrypt the given image array using a chaotic logistic map (two-layer XOR + shuffle)."""
44
+ h, w, c = img_array.shape
45
+ flat_image = img_array.flatten()
46
+
47
+ # First chaotic key
48
+ chaotic_key_1 = generate_key(seed, len(flat_image))
49
+ # XOR-based encryption (first layer)
50
+ encrypted_flat_1 = [pixel ^ chaotic_key_1[i] for i, pixel in enumerate(flat_image)]
51
+ encrypted_array_1 = np.array(encrypted_flat_1, dtype=np.uint8).reshape(h, w, c)
52
+
53
+ # Shuffle
54
+ shuffled_array, _ = shuffle_pixels(encrypted_array_1, seed)
55
+
56
+ # Second chaotic key
57
+ chaotic_key_2 = generate_key(seed * 1.1, len(flat_image))
58
+ shuffled_flat = shuffled_array.flatten()
59
+ encrypted_flat_2 = [pixel ^ chaotic_key_2[i] for i, pixel in enumerate(shuffled_flat)]
60
+ doubly_encrypted_array = np.array(encrypted_flat_2, dtype=np.uint8).reshape(h, w, c)
61
+
62
+ return doubly_encrypted_array
63
+
64
+ # (A decrypt_image function could be implemented if needed)
65
+
66
+ # ------------------------
67
+ # 2. YOLOv10 Detection Logic
68
+ # ------------------------
69
+
70
+ def load_model(model_path):
71
+ """Load YOLOv10 model from local .pt weights."""
72
+ model = YOLOv10(model_path)
73
+ return model
74
+
75
+ def detect_license_plates(model, pil_image):
76
+ """
77
+ Runs YOLOv10 detection on the PIL image.
78
+ Returns:
79
+ - image_with_boxes (PIL Image) with bounding boxes drawn
80
+ - bboxes (list of (x1, y1, x2, y2)) for each license plate
81
+ """
82
+ # Convert PIL image to np array
83
+ np_image = np.array(pil_image)
84
+
85
+ # YOLO inference
86
+ results = model.predict(np_image)
87
+
88
+ # Extract detections
89
+ detections = results.xyxy[0] # shape: (N, 6) -> [x1, y1, x2, y2, conf, class]
90
+
91
+ bboxes = []
92
+ draw = ImageDraw.Draw(pil_image)
93
+ for *box, conf, cls in detections:
94
+ cls_id = int(cls)
95
+ # Adjust class check if your model uses a different label for license plate
96
+ # e.g., if class 0 is 'license_plate'
97
+ if cls_id == 0:
98
+ x1, y1, x2, y2 = map(int, box)
99
+ bboxes.append((x1, y1, x2, y2))
100
+ # Draw bounding box
101
+ draw.rectangle([x1, y1, x2, y2], outline="red", width=2)
102
+
103
+ return pil_image, bboxes
104
+
105
+ # ------------------------
106
+ # 3. Streamlit App
107
+ # ------------------------
108
+
109
+ def main():
110
+ st.title("YOLOv10 + Chaotic Encryption Demo")
111
+ st.write(
112
+ """
113
+ **Instructions**:
114
+ 1. Provide an image (URL or file upload).
115
+ 2. If a license plate is detected, only that region will be **encrypted** using Chaotic Logistic Map.
116
+ 3. Download the final result.
117
+ """
118
+ )
119
+
120
+ # Sidebar: Model path
121
+ st.sidebar.header("Model Config")
122
+ default_path = "best.pt" # Make sure you've uploaded this file in your HF Space
123
+ model_path = st.sidebar.text_input("YOLOv10 Model Path", value=default_path)
124
+
125
+ if not os.path.isfile(model_path):
126
+ st.error(f"Model weights not found at {model_path}. Please upload best.pt!")
127
+ return
128
+
129
+ # Load model once
130
+ @st.cache_data(show_spinner=False, allow_output_mutation=True)
131
+ def cached_load_model(path):
132
+ return load_model(path)
133
+
134
+ with st.spinner("Loading YOLOv10 model..."):
135
+ model = cached_load_model(model_path)
136
+ st.success("Model loaded successfully!")
137
+
138
+ # Option 1: URL input
139
+ image_url = st.text_input("Image URL (optional)")
140
+
141
+ # Option 2: File upload
142
+ uploaded_file = st.file_uploader("OR Upload an Image", type=["png", "jpg", "jpeg"])
143
+
144
+ # Encryption seed slider
145
+ key_seed = st.slider("Encryption Key Seed (0 < seed < 1)", 0.001, 0.999, 0.5, 0.001)
146
+
147
+ if st.button("Detect & Encrypt"):
148
+ # 1) Load the image (from URL or uploaded file)
149
+ if image_url and (not uploaded_file):
150
+ # Download from URL
151
+ try:
152
+ response = requests.get(image_url, timeout=10)
153
+ pil_image = Image.open(io.BytesIO(response.content)).convert("RGB")
154
+ except Exception as e:
155
+ st.error(f"Failed to load image from URL. Error: {e}")
156
+ return
157
+ elif uploaded_file:
158
+ # Use uploaded file
159
+ pil_image = Image.open(uploaded_file).convert("RGB")
160
+ else:
161
+ st.warning("Please provide an image URL or upload an image.")
162
+ return
163
+
164
+ st.image(pil_image, caption="Original Image", use_container_width=True)
165
+
166
+ # 2) Detect license plates
167
+ with st.spinner("Detecting license plates..."):
168
+ image_with_boxes, bboxes = detect_license_plates(model, pil_image.copy())
169
+
170
+ st.image(image_with_boxes, caption="Detected Plate(s)", use_container_width=True)
171
+
172
+ if not bboxes:
173
+ st.warning("No license plates detected.")
174
+ return
175
+
176
+ # 3) Encrypt only the bounding box regions
177
+ with st.spinner("Encrypting license plates..."):
178
+ np_original = np.array(pil_image)
179
+ encrypted_np = np_original.copy()
180
+
181
+ for (x1, y1, x2, y2) in bboxes:
182
+ plate_region = encrypted_np[y1:y2, x1:x2]
183
+ plate_encrypted = encrypt_image(plate_region, key_seed)
184
+ encrypted_np[y1:y2, x1:x2] = plate_encrypted
185
+
186
+ encrypted_image = Image.fromarray(encrypted_np)
187
+
188
+ st.image(encrypted_image, caption="Encrypted Image", use_container_width=True)
189
+
190
+ # 4) Provide download button
191
+ buf = io.BytesIO()
192
+ encrypted_image.save(buf, format="PNG")
193
+ buf.seek(0)
194
+ st.download_button(
195
+ label="Download Encrypted Image",
196
+ data=buf,
197
+ file_name="encrypted_plate.png",
198
+ mime="image/png",
199
+ )
200
+
201
+ if __name__ == "__main__":
202
+ main()