RafidMehda commited on
Commit
f974716
·
verified ·
1 Parent(s): 6f6782e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -66
app.py CHANGED
@@ -6,14 +6,15 @@ from PIL import Image, ImageDraw
6
  import io
7
  import random
8
 
9
- # YOLOv10 import (installed via requirements.txt)
10
  try:
11
  from ultralytics 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):
@@ -24,7 +25,7 @@ def generate_key(seed, n):
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):
@@ -34,20 +35,20 @@ def shuffle_pixels(img_array, seed):
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
@@ -56,50 +57,46 @@ def encrypt_image(img_array, seed):
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
  # ------------------------
@@ -117,77 +114,67 @@ def main():
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)
@@ -195,7 +182,7 @@ def main():
195
  label="Download Encrypted Image",
196
  data=buf,
197
  file_name="encrypted_plate.png",
198
- mime="image/png",
199
  )
200
 
201
  if __name__ == "__main__":
 
6
  import io
7
  import random
8
 
9
+ # Attempt to import YOLOv10 from THU-MIG/yolov10, which installs 'ultralytics'.
10
  try:
11
  from ultralytics import YOLOv10
12
  except ImportError:
13
+ st.error("Could not import YOLOv10. Please confirm the library installation from THU-MIG/yolov10.")
14
+ st.stop()
15
 
16
  # ------------------------
17
+ # 1. Chaotic Logistic Map Encryption
18
  # ------------------------
19
 
20
  def logistic_map(r, x):
 
25
  x = seed
26
  for _ in range(n):
27
  x = logistic_map(3.9, x)
28
+ key.append(int(x * 255) % 256) # map float to 0-255
29
  return np.array(key, dtype=np.uint8)
30
 
31
  def shuffle_pixels(img_array, seed):
 
35
  indices = np.arange(num_pixels)
36
 
37
  random.seed(seed)
38
+ random.shuffle(indices)
39
+
40
  shuffled = flattened[indices]
41
  return shuffled.reshape(h, w, c), indices
42
 
43
  def encrypt_image(img_array, seed):
44
+ """Encrypt the given image array using a two-layer XOR + shuffle approach."""
45
  h, w, c = img_array.shape
46
  flat_image = img_array.flatten()
47
 
48
  # First chaotic key
49
  chaotic_key_1 = generate_key(seed, len(flat_image))
50
  # XOR-based encryption (first layer)
51
+ encrypted_flat_1 = [p ^ chaotic_key_1[i] for i, p in enumerate(flat_image)]
52
  encrypted_array_1 = np.array(encrypted_flat_1, dtype=np.uint8).reshape(h, w, c)
53
 
54
  # Shuffle
 
57
  # Second chaotic key
58
  chaotic_key_2 = generate_key(seed * 1.1, len(flat_image))
59
  shuffled_flat = shuffled_array.flatten()
60
+ encrypted_flat_2 = [p ^ chaotic_key_2[i] for i, p in enumerate(shuffled_flat)]
61
  doubly_encrypted_array = np.array(encrypted_flat_2, dtype=np.uint8).reshape(h, w, c)
62
 
63
  return doubly_encrypted_array
64
 
 
 
65
  # ------------------------
66
+ # 2. YOLOv10 License Plate Detection
67
  # ------------------------
68
 
69
+ @st.cache_data(show_spinner=False) # <-- Removed allow_output_mutation here
70
+ def load_model(weights_path):
71
+ """Loads the YOLOv10 model from local .pt weights."""
72
+ model = YOLOv10(weights_path) # from ultralytics
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 detected license plates
81
  """
 
82
  np_image = np.array(pil_image)
83
+ results = model.predict(np_image) # returns an object with .xyxy, etc.
84
+
85
+ # results.xyxy[0] -> [x1, y1, x2, y2, conf, class]
86
+ detections = results.xyxy[0] if len(results.xyxy) > 0 else []
87
+
 
 
88
  bboxes = []
89
  draw = ImageDraw.Draw(pil_image)
90
+
91
+ for *box, conf, cls_id in detections:
92
+ cls_id = int(cls_id)
93
+ # If your model has a single class (license plate) as class 0:
94
  if cls_id == 0:
95
  x1, y1, x2, y2 = map(int, box)
96
  bboxes.append((x1, y1, x2, y2))
97
+ # Draw bounding box for visualization
98
  draw.rectangle([x1, y1, x2, y2], outline="red", width=2)
99
+
100
  return pil_image, bboxes
101
 
102
  # ------------------------
 
114
  """
115
  )
116
 
117
+ # Model weights path
118
+ default_path = "best.pt" # Must exist in your repository if custom
119
+ model_path = st.sidebar.text_input("YOLOv10 Weights (.pt)", value=default_path)
 
120
 
121
  if not os.path.isfile(model_path):
122
+ st.warning(f"Model file '{model_path}' not found in this directory. Upload or provide a correct path.")
123
+ st.stop()
 
 
 
 
 
124
 
125
  with st.spinner("Loading YOLOv10 model..."):
126
+ model = load_model(model_path)
127
  st.success("Model loaded successfully!")
128
 
129
+ # Image input
130
+ st.subheader("Image Input")
131
  image_url = st.text_input("Image URL (optional)")
132
+ uploaded_file = st.file_uploader("Or upload an image file", type=["jpg","jpeg","png"])
 
 
133
 
134
  # Encryption seed slider
135
+ key_seed = st.slider("Encryption Key Seed (0 < seed < 1)", 0.001, 0.999, 0.5, step=0.001)
136
 
137
  if st.button("Detect & Encrypt"):
138
+ # 1. Load the image from URL or file
139
+ if image_url and not uploaded_file:
 
140
  try:
141
  response = requests.get(image_url, timeout=10)
142
+ image_bytes = io.BytesIO(response.content)
143
+ pil_image = Image.open(image_bytes).convert("RGB")
144
  except Exception as e:
145
+ st.error(f"Failed to load image from URL. Error: {str(e)}")
146
  return
147
  elif uploaded_file:
 
148
  pil_image = Image.open(uploaded_file).convert("RGB")
149
  else:
150
+ st.warning("Please either paste a valid URL or upload an image.")
151
  return
152
 
153
  st.image(pil_image, caption="Original Image", use_container_width=True)
154
 
155
+ # 2. Detect plates
156
  with st.spinner("Detecting license plates..."):
157
  image_with_boxes, bboxes = detect_license_plates(model, pil_image.copy())
 
 
158
 
159
+ st.image(image_with_boxes, caption="Detected Plate(s)", use_container_width=True)
160
  if not bboxes:
161
  st.warning("No license plates detected.")
162
  return
163
 
164
+ # 3. Encrypt bounding box regions
165
  with st.spinner("Encrypting license plates..."):
166
+ np_img = np.array(pil_image)
167
+ encrypted_np = np_img.copy()
 
168
  for (x1, y1, x2, y2) in bboxes:
169
  plate_region = encrypted_np[y1:y2, x1:x2]
170
+ encrypted_region = encrypt_image(plate_region, key_seed)
171
+ encrypted_np[y1:y2, x1:x2] = encrypted_region
172
 
173
  encrypted_image = Image.fromarray(encrypted_np)
174
 
175
  st.image(encrypted_image, caption="Encrypted Image", use_container_width=True)
176
 
177
+ # 4. Download link
178
  buf = io.BytesIO()
179
  encrypted_image.save(buf, format="PNG")
180
  buf.seek(0)
 
182
  label="Download Encrypted Image",
183
  data=buf,
184
  file_name="encrypted_plate.png",
185
+ mime="image/png"
186
  )
187
 
188
  if __name__ == "__main__":