|
|
import streamlit as st |
|
|
import numpy as np |
|
|
import cv2 |
|
|
from keras.models import load_model |
|
|
from keras.preprocessing.image import img_to_array |
|
|
from PIL import Image |
|
|
|
|
|
|
|
|
st.set_page_config( |
|
|
page_title="Smart Face Mask Scanner π·", |
|
|
layout="centered", |
|
|
page_icon="π·" |
|
|
) |
|
|
|
|
|
|
|
|
@st.cache_resource |
|
|
def load_model_cached(): |
|
|
return load_model("Face_Detector.keras", compile=False) |
|
|
|
|
|
model = load_model_cached() |
|
|
|
|
|
|
|
|
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") |
|
|
|
|
|
|
|
|
def detect_and_predict(image_input): |
|
|
image_np = np.array(image_input.convert("RGB")) |
|
|
gray = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY) |
|
|
faces = face_cascade.detectMultiScale(gray, 1.1, 4) |
|
|
|
|
|
if len(faces) == 0: |
|
|
return image_input, None, "No face detected" |
|
|
|
|
|
x, y, w, h = faces[0] |
|
|
face_roi = image_np[y:y+h, x:x+w] |
|
|
face_pil = Image.fromarray(face_roi).resize((200, 200)) |
|
|
img_array = img_to_array(face_pil) / 255.0 |
|
|
img_array = np.expand_dims(img_array, axis=0) |
|
|
|
|
|
prediction = model.predict(img_array)[0][0] |
|
|
confidence = (1 - prediction) if prediction < 0.5 else prediction |
|
|
label = "β
Mask Detected" if prediction < 0.5 else "π« No Mask Detected" |
|
|
|
|
|
color = (0, 255, 0) if prediction < 0.5 else (255, 0, 0) |
|
|
cv2.rectangle(image_np, (x, y), (x + w, y + h), color, 2) |
|
|
cv2.putText(image_np, f"{label} ({confidence*100:.2f}%)", (x, y - 10), |
|
|
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) |
|
|
|
|
|
return Image.fromarray(image_np), confidence, label |
|
|
|
|
|
|
|
|
st.markdown(""" |
|
|
<style> |
|
|
.main { |
|
|
background-color: #f0f4f8; |
|
|
padding: 1rem; |
|
|
border-radius: 15px; |
|
|
} |
|
|
h2 { |
|
|
text-align: center; |
|
|
color: #2c3e50; |
|
|
} |
|
|
.stTabs [data-baseweb="tab"] { |
|
|
background-color: #e3f2fd; |
|
|
border-radius: 10px; |
|
|
padding: 10px; |
|
|
} |
|
|
.stTabs [aria-selected="true"] { |
|
|
background-color: #1976d2; |
|
|
color: white; |
|
|
} |
|
|
</style> |
|
|
""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
st.markdown("<h2>π‘οΈ Smart Face Mask Scanner</h2>", unsafe_allow_html=True) |
|
|
st.markdown("<p style='text-align:center;'>Upload an image or use your webcam to check if a person is wearing a face mask.</p>", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
tab1, tab2 = st.tabs(["π€ Upload Image", "π· Use Webcam"]) |
|
|
|
|
|
|
|
|
with tab1: |
|
|
st.subheader("π€ Upload a photo") |
|
|
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"]) |
|
|
if uploaded_file: |
|
|
image_input = Image.open(uploaded_file) |
|
|
st.image(image_input, caption="π· Uploaded Image", use_column_width=True) |
|
|
|
|
|
with st.spinner("π Analyzing..."): |
|
|
result_img, confidence, label = detect_and_predict(image_input) |
|
|
|
|
|
st.image(result_img, caption="π Detection Result", use_column_width=True) |
|
|
|
|
|
if confidence is not None: |
|
|
st.metric("π§ Confidence", f"{confidence*100:.2f}%") |
|
|
if "Mask" in label: |
|
|
st.success(label) |
|
|
else: |
|
|
st.error(label) |
|
|
else: |
|
|
st.warning(label) |
|
|
|
|
|
|
|
|
with tab2: |
|
|
st.subheader("π· Use your cam") |
|
|
camera_image = st.camera_input("Take a snapshot") |
|
|
if camera_image: |
|
|
image_input = Image.open(camera_image) |
|
|
st.image(image_input, caption="πΈ Captured Image", use_column_width=True) |
|
|
|
|
|
with st.spinner("π Analyzing..."): |
|
|
result_img, confidence, label = detect_and_predict(image_input) |
|
|
|
|
|
st.image(result_img, caption="π Detection Result", use_column_width=True) |
|
|
|
|
|
if confidence is not None: |
|
|
st.metric("π§ Confidence", f"{confidence*100:.2f}%") |
|
|
if "Mask" in label: |
|
|
st.success(label) |
|
|
else: |
|
|
st.error(label) |
|
|
else: |
|
|
st.warning(label) |
|
|
|