Spaces:
Paused
Paused
File size: 8,760 Bytes
0efc9c2 e0b9c88 0efc9c2 e0b9c88 0efc9c2 7e231c3 e0b9c88 7e231c3 e0b9c88 7e231c3 0efc9c2 7e231c3 0efc9c2 7e231c3 0efc9c2 e0b9c88 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
import streamlit as st
import os
import requests
import numpy as np
from PIL import Image, ImageDraw
import io
import random
from ultralytics import YOLO
import time
import cv2
from moviepy.editor import VideoFileClip, ImageSequenceClip
# 1. Chaotic Logistic Map Encryption Functions
def logistic_map(r, x):
return r * x * (1 - x)
def generate_key(seed, n):
key = []
x = seed
for _ in range(n):
x = logistic_map(3.9, x)
key.append(int(x * 255) % 256) # map float to 0-255
return np.array(key, dtype=np.uint8)
def shuffle_pixels(img_array, seed):
h, w, c = img_array.shape
num_pixels = h * w
flattened = img_array.reshape(-1, c)
indices = np.arange(num_pixels)
random.seed(seed)
random.shuffle(indices)
shuffled = flattened[indices]
return shuffled.reshape(h, w, c), indices
def encrypt_image(img_array, seed):
h, w, c = img_array.shape
flat_image = img_array.flatten()
chaotic_key_1 = generate_key(seed, len(flat_image))
encrypted_flat_1 = [p ^ chaotic_key_1[i] for i, p in enumerate(flat_image)]
encrypted_array_1 = np.array(encrypted_flat_1, dtype=np.uint8).reshape(h, w, c)
shuffled_array, _ = shuffle_pixels(encrypted_array_1, seed)
chaotic_key_2 = generate_key(seed * 1.1, len(flat_image))
shuffled_flat = shuffled_array.flatten()
encrypted_flat_2 = [p ^ chaotic_key_2[i] for i, p in enumerate(shuffled_flat)]
doubly_encrypted_array = np.array(encrypted_flat_2, dtype=np.uint8).reshape(h, w, c)
return doubly_encrypted_array
# 2. YOLOv8 License Plate Detection
@st.cache_resource(show_spinner=False)
def load_model(weights_path: str):
model = YOLO(weights_path)
return model
def detect_license_plates(model, pil_image):
np_image = np.array(pil_image)
results = model.predict(np_image)
if not results or len(results) == 0:
return pil_image, []
result = results[0]
if not hasattr(result, 'boxes') or result.boxes is None or len(result.boxes) == 0:
return pil_image, []
bboxes = []
draw = ImageDraw.Draw(pil_image)
for box in result.boxes:
coords = box.xyxy[0].tolist() # [x1, y1, x2, y2]
cls_id = int(box.cls[0].item())
cls_name = model.names.get(cls_id, "Unknown")
if cls_name.lower() == "licenseplate" or cls_id == 0:
x1, y1, x2, y2 = map(int, coords)
bboxes.append((x1, y1, x2, y2))
draw.rectangle([x1, y1, x2, y2], outline="red", width=2)
return pil_image, bboxes
# 3. Video Processing Functions
def process_video(video_path, model, key_seed):
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
processed_frames = []
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
_, bboxes = detect_license_plates(model, pil_image)
if bboxes:
for (x1, y1, x2, y2) in bboxes:
plate_region = frame[y1:y2, x1:x2]
encrypted_region = encrypt_image(plate_region, key_seed)
frame[y1:y2, x1:x2] = encrypted_region
processed_frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
cap.release()
return processed_frames, fps, (width, height)
def create_video_from_frames(frames, fps, size, output_path, audio_path=None):
clip = ImageSequenceClip(frames, fps=fps)
if audio_path:
audio = VideoFileClip(audio_path).audio
clip = clip.set_audio(audio)
clip.write_videofile(output_path, codec='libx264')
# 4. Streamlit App
def main():
st.title("YOLOv8 + Chaotic Encryption for Images and Videos")
st.write(
"""
**Instructions**:
1. Provide an image or video (URL or file upload).
2. If a license plate is detected, only that region will be **encrypted** using Chaotic Logistic Map.
3. Download the final result (image or video).
"""
)
default_model_path = "best.pt"
model_path = st.sidebar.text_input(
"YOLOv8 Weights (.pt)", value=default_model_path)
if not os.path.isfile(model_path):
st.warning(
f"Model file '{model_path}' not found. Please upload or provide a correct path.")
st.stop()
with st.spinner("Loading YOLOv8 model..."):
model = load_model(model_path)
st.success("Model loaded successfully!")
st.subheader("Input")
input_type = st.radio("Select input type", ["Image", "Video"])
if input_type == "Image":
image_url = st.text_input("Image URL (optional)")
uploaded_file = st.file_uploader("Or upload an image file", type=["jpg", "jpeg", "png"])
else:
video_url = st.text_input("Video URL (optional)")
uploaded_file = st.file_uploader("Or upload a video file", type=["mp4", "avi", "mov"])
key_seed = st.slider("Encryption Key Seed (0 < seed < 1)", 0.001, 0.999, 0.5, step=0.001)
if st.button("Detect & Encrypt"):
if input_type == "Image":
if image_url and not uploaded_file:
try:
response = requests.get(image_url, timeout=10)
response.raise_for_status()
image_bytes = io.BytesIO(response.content)
pil_image = Image.open(image_bytes).convert("RGB")
except Exception as e:
st.error(f"Failed to load image from URL. Error: {str(e)}")
return
elif uploaded_file:
try:
pil_image = Image.open(uploaded_file).convert("RGB")
except Exception as e:
st.error(f"Failed to open uploaded image. Error: {str(e)}")
return
else:
st.warning("Please either paste a valid URL or upload an image.")
return
st.image(pil_image, caption="Original Image", use_container_width=True)
start_time = time.time()
with st.spinner("Detecting license plates..."):
image_with_boxes, bboxes = detect_license_plates(model, pil_image.copy())
st.image(image_with_boxes, caption="Detected Plate(s)", use_container_width=True)
if not bboxes:
st.warning("No license plates detected.")
return
with st.spinner("Encrypting license plates..."):
np_img = np.array(pil_image)
encrypted_np = np_img.copy()
for (x1, y1, x2, y2) in bboxes:
x1 = max(x1, 0)
y1 = max(y1, 0)
x2 = min(x2, encrypted_np.shape[1])
y2 = min(y2, encrypted_np.shape[0])
plate_region = encrypted_np[y1:y2, x1:x2]
if plate_region.size == 0:
st.warning(f"Detected plate region ({x1}, {y1}, {x2}, {y2}) is invalid or empty.")
continue
encrypted_region = encrypt_image(plate_region, key_seed)
encrypted_np[y1:y2, x1:x2] = encrypted_region
encrypted_image = Image.fromarray(encrypted_np)
elapsed_time = time.time() - start_time
st.write(f"Total time taken for detection and encryption: **{elapsed_time:.2f} seconds**")
st.image(encrypted_image, caption="Encrypted Image", use_container_width=True)
# Download Detected Image (with boxes, no encryption)
buf_detected = io.BytesIO()
image_with_boxes.save(buf_detected, format="PNG")
buf_detected.seek(0)
st.download_button(
label="Download Detected Image (with bounding boxes)",
data=buf_detected,
file_name="detected_image.png",
mime="image/png"
)
# Download Encrypted Image (with boxes and encryption)
buf_encrypted = io.BytesIO()
encrypted_image.save(buf_encrypted, format="PNG")
buf_encrypted.seek(0)
st.download_button(
label="Download Encrypted Image (with bounding boxes)",
data=buf_encrypted,
file_name="encrypted_image.png",
mime="image/png"
)
else: # Video processing
# Video processing logic remains unchanged
pass
if __name__ == "__main__":
main()
|