Spaces:
Sleeping
Sleeping
import streamlit as st | |
import cv2 | |
import numpy as np | |
from PIL import Image | |
from io import BytesIO | |
from cvzone.ClassificationModule import Classifier | |
import pandas as pd | |
# Set page configuration | |
st.set_page_config(page_title="Infrastructure Grading & Facility Verification", page_icon="π", layout="wide") | |
# Initialize session state variables if they don't exist | |
if 'total_score' not in st.session_state: | |
st.session_state.total_score = 0 | |
if 'facility_results' not in st.session_state: | |
st.session_state.facility_results = [] | |
if 'deficiencies' not in st.session_state: | |
st.session_state.deficiencies = [] | |
if 'verified_facilities' not in st.session_state: | |
st.session_state.verified_facilities = set() | |
if 'facility_status' not in st.session_state: | |
st.session_state.facility_status = {} | |
# Streamlit app title with subheader | |
st.title("π Infrastructure Grading & Facility Verification System") | |
# Create tabs | |
tab1, tab2, tab3, tab4 = st.tabs(["π College Info", "π’ Facility Verification", "π Results", "β Help"]) | |
# Define models dictionary | |
models = { | |
"Restroom Model": ('Models/Restroom model/keras_model.h5', | |
'Models/Restroom model/labels.txt'), | |
"Dispenser Model": ('Models/Dispenser model/keras_model.h5', | |
'Models/Dispenser model/labels.txt'), | |
"Safety Equipment Model": ('Models/safety equipment model/keras_model.h5', | |
'Models/safety equipment model/labels.txt'), | |
"Computer Lab Model": ('Models/computer lab model/keras_model.h5', | |
'Models/computer lab model/labels.txt'), | |
"Server Room Model": ('Models/Server Room model/keras_model.h5', | |
'Models/Server Room model/labels.txt'), | |
"Lab Equipment Model": ('Models/lab equipment model/keras_model.h5', | |
'Models/lab equipment model/labels.txt'), | |
"Sports Equipment Model": ('Models/sports equipment model/keras_model.h5', | |
'Models/sports equipment model/labels.txt'), | |
"Bicycle Stand Model": ('Models/bicycle stand model/keras_model.h5', | |
'Models/bicycle stand model/labels.txt'), | |
"Medical Room Model": ('Models/Medical Room Model/keras_model.h5', | |
'Models/Medical Room Model/labels.txt'), | |
"Workshop/Mechanical Lab Model": ('Models/workshop model/keras_model.h5', | |
'Models/workshop model/labels.txt'), | |
"Bus/Transport Model": ('Models/bus transport model/keras_model.h5', | |
'Models/bus transport model/labels.txt'), | |
"COVID-19 Protocol Model": ('Models/COVID-19 protocol model/keras_model.h5', | |
'Models/COVID-19 protocol model/labels.txt'), | |
"Canteen Model": ('Models/canteen model/keras_model.h5', | |
'Models/canteen model/labels.txt'), | |
"CCTV Model": ('Models/CCTV model/keras_model.h5', | |
'Models/CCTV model/labels.txt'), | |
"Classroom Model": ('Models/classroom model/keras_model.h5', | |
'Models/classroom model/labels.txt'), | |
"Elearning Model": ('Models/elearning model/keras_model.h5', | |
'Models/elearning model/labels.txt'), | |
"Faculty Cabin Model": ('Models/faculty cabin model/keras_model.h5', | |
'Models/faculty cabin model/labels.txt'), | |
"Fire Extinguisher Model": ('Models/fire extinguisher model/keras_model.h5', | |
'Models/fire extinguisher model/labels.txt'), | |
"Generator Model": ('Models/generator model/keras_model.h5', | |
'Models/generator model/labels.txt'), | |
"Ground Model": ('Models/ground model (1)/keras_model.h5', | |
'Models/ground model (1)/labels.txt'), | |
"Laptop Model": ('Models/laptop model/keras_model.h5', | |
'Models/laptop model/labels.txt'), | |
"Library Model": ('Models/library model/keras_model.h5', | |
'Models/library model/labels.txt'), | |
"Parking Model": ('Models/parking model/keras_model.h5', | |
'Models/parking model/labels.txt'), | |
"Pothole Model": ('Models/pothole model/keras_model.h5', | |
'Models/pothole model/labels.txt'), | |
"Seminar Hall Model": ('Models/seminar hall model/keras_model.h5', | |
'Models/seminar hall model/labels.txt'), | |
"TPO Model": ('Models/tpo model/keras_model.h5', | |
'Models/tpo model/labels.txt'), | |
"Audi Model": ('Models/Audi model/keras_model.h5', | |
'Models/Audi model/labels.txt'), | |
"Conference Halls Model": ('Models/conference halls model/keras_model.h5', | |
'Models/conference halls model/labels.txt'), | |
"Drawing Halls Model": ('Models/Drawing halls model/keras_model.h5', | |
'Models/Drawing halls model/labels.txt'), | |
} | |
# Function to handle input and image upload | |
def input_and_upload(label, min_value, default_value, model_name, model_path, labels_path): | |
col1, col2 = st.columns(2) | |
with col1: | |
if isinstance(default_value, int): | |
user_value = st.number_input(f"Number of {label}", min_value=min_value, value=int(default_value), step=1) | |
else: | |
user_value = st.number_input(f"Number of {label}", min_value=float(min_value), value=float(default_value), step=0.1) | |
with col2: | |
uploaded_files = st.file_uploader(f"Upload images for {label} (max {int(user_value)})", | |
type=["jpg", "jpeg", "png"], | |
accept_multiple_files=True) | |
# Limit the number of processed files to user_value | |
uploaded_files = uploaded_files[:int(user_value)] if uploaded_files else [] | |
score = 0 | |
if uploaded_files: | |
score = classify_image(model_path, labels_path, uploaded_files, model_name) | |
# Update the facility status immediately after classification | |
if label not in st.session_state.verified_facilities and score > 0: | |
st.session_state.verified_facilities.add(label) | |
st.session_state.total_score = sum( | |
data["Score"] | |
for data in st.session_state.facility_status.values() | |
) | |
return user_value, score | |
# Function to classify image | |
def classify_image(model_path, labels_path, uploaded_files, model_name): | |
try: | |
classifier = Classifier(model_path, labels_path) | |
class_names = open(labels_path).read().splitlines() | |
except FileNotFoundError: | |
st.error(f"Model files for {model_name} not found. Please check the model path.") | |
return 0 | |
except Exception as e: | |
st.error(f"Error loading model {model_name}: {str(e)}") | |
return 0 | |
score = 0 | |
# Create a grid layout for images | |
cols = st.columns(3) # Adjust the number of columns as needed | |
for idx, uploaded_file in enumerate(uploaded_files): | |
try: | |
img = Image.open(BytesIO(uploaded_file.read())) | |
img_array = np.array(img) | |
# Convert to BGR if the image is RGB | |
if img_array.shape[-1] == 3: | |
img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) | |
# Resize for prediction (but don't display this resized version) | |
img_resized = cv2.resize(img_array, (224, 224)) | |
prediction = classifier.getPrediction(img_resized) | |
class_id = prediction[1] | |
class_name = class_names[class_id] if class_id < len(class_names) else "Unknown" | |
# Display image and results in a compact format | |
with cols[idx % 3]: | |
st.image(img, use_column_width=True) | |
if "no" in class_name.lower() or "not" in class_name.lower(): | |
st.warning(f"{model_name} not verified.") | |
else: | |
st.success(f"{model_name} is verified.") | |
score += 10 | |
except Exception as e: | |
st.error(f"An error occurred: {e}") | |
return score | |
# Grade calculation function | |
def calculate_grade(total_score, max_score): | |
percentage = (total_score / max_score) * 100 | |
if percentage >= 80: | |
return "A" | |
elif percentage >= 60: | |
return "B" | |
elif percentage >= 40: | |
return "C" | |
else: | |
return "D" | |
with tab1: | |
st.markdown("### College Information") | |
st.markdown("Enter the basic information about the college below:") | |
# Create columns for a more compact layout | |
col1, col2 = st.columns(2) | |
with col1: | |
num_divisions = st.number_input("Number of Divisions", min_value=1, value=1, help="Total number of divisions across all years") | |
num_courses = st.number_input("Number of Courses", min_value=1, value=1, help="Total number of distinct courses offered") | |
with col2: | |
num_students = st.number_input("Total Students", min_value=1, value=100, help="Total number of students enrolled") | |
course_duration = st.number_input("Course Duration (years)", min_value=1, value=4, help="Average duration of courses in years") | |
# Calculations | |
classroom_requirement = num_divisions * course_duration * 0.5 | |
# Lab logic based on student intake | |
if num_students <= 600: | |
first_year_labs = 4 | |
else: | |
first_year_labs = 4 + (num_students - 600) // 150 | |
if num_students <= 180 * num_courses: | |
labs_other_years = 2 * num_courses * (course_duration - 1) | |
else: | |
extra_students_per_course = (num_students - 180 * num_courses) // 50 | |
labs_other_years = 2 * num_courses * (course_duration - 1) + extra_students_per_course | |
total_labs = first_year_labs + labs_other_years | |
# Other facility requirements | |
workshop_requirement = 1 + (num_students - 600) // 600 if num_students > 600 else 1 | |
cad_centre_requirement = 1 + (num_students - 600) // 600 if num_students > 600 else 1 | |
computer_centre_requirement = 1 + (num_students - 600) // 600 if num_students > 600 else 1 | |
seminar_hall_requirement = 1 | |
library_requirement = 1 | |
language_lab_requirement = 1 | |
pc_requirement = max(20, num_students // 10) | |
st.markdown("### π Calculated Facility Requirements") | |
# Create three columns for a more compact display of requirements | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
st.metric("Classrooms", f"{classroom_requirement:.1f}") | |
st.metric("Total Labs", f"{total_labs}") | |
st.metric("Workshops", f"{workshop_requirement}") | |
with col2: | |
st.metric("CAD Centres", f"{cad_centre_requirement}") | |
st.metric("Computer Centres", f"{computer_centre_requirement}") | |
st.metric("Seminar Halls", f"{seminar_hall_requirement}") | |
with col3: | |
st.metric("Libraries", f"{library_requirement}") | |
st.metric("Language Labs", f"{language_lab_requirement}") | |
st.metric("PC/Laptops", f"{pc_requirement}") | |
st.info("βΉ These calculations are based on standard educational infrastructure guidelines.") | |
# Input fields and image upload for each facility | |
facilities = [ | |
("Classrooms", classroom_requirement, "Classroom Model"), | |
("Computer Labs", computer_centre_requirement, "Computer Lab Model"), #Done | |
("Workshops", workshop_requirement, "Workshop/Mechanical Lab Model"), # Done | |
("Drawing Halls", cad_centre_requirement, "Drawing Halls Model"), # Done | |
("Seminar Halls", seminar_hall_requirement, "Seminar Hall Model"), # Done | |
("Conference Halls", 1, "Conference Halls Model"), # done | |
("Auditorium", 1, "Audi Model"), | |
("Faculty Cabins", 1, "Faculty Cabin Model"), | |
("Security/CCTV", 1, "CCTV Model"), | |
("House Keeping", 1, "Safety Equipment Model"), # to be done / store rooms can be done but not added yet | |
("Restrooms", 1, "Restroom Model"), # Done | |
("Canteens", 1, "Canteen Model"), | |
("Server Room", 1, "Server Room Model"), # Done | |
("First Aid/Medical Room", 1, "Medical Room Model"), # done | |
("Gym/Sports Facilities", 1, "Sports Equipment Model"), # done | |
("Language Labs", language_lab_requirement, "Computer Lab Model"), #done | |
("Water Coolers/Dispensers", 1, "Dispenser Model"), # done | |
("Generators", 1, "Generator Model"), | |
("TPO Office", 1, "TPO Model"), | |
# Other supporting facilities | |
("Libraries", library_requirement, "Library Model"), | |
("PCs/Laptops", pc_requirement, "Laptop Model"), | |
("Bicycle Stands", 1, "Bicycle Stand Model"), | |
("Bus/Transport Facilities", 1, "Bus/Transport Model"), | |
("COVID-19 Protocol Measures", 1, "COVID-19 Protocol Model"), | |
("E-learning Facilities", 1, "Elearning Model"), | |
("Fire Extinguishers", 1, "Fire Extinguisher Model"), | |
("Grounds/Playgrounds", 1, "Ground Model"), | |
("Parking Areas", 1, "Parking Model"), | |
("Road Condition (Potholes)", 1, "Pothole Model"), | |
] | |
with tab2: | |
st.markdown("### Facility Verification") | |
st.markdown("Upload images for each facility to verify their existence and compliance.") | |
# Reset scores and results when starting verification | |
if st.button("π Reset Verification"): | |
# Reset all session state variables | |
st.session_state.total_score = 0 | |
st.session_state.facility_results = [] | |
st.session_state.deficiencies = [] | |
st.session_state.verified_facilities = set() | |
st.session_state.facility_status = {} | |
# Add a rerun to refresh the page | |
st.rerun() | |
# Create subtabs for different facility categories | |
facility_tabs = st.tabs(["π« Academic", "π¬ Labs & Workshops", "π Support Facilities", "π₯ Essential Services"]) | |
# Define facility categories | |
academic_facilities = [ | |
f for f in facilities | |
if any(name in f[0] for name in ["Classroom", "Faculty", "Drawing", "Seminar", "Conference", "Auditorium"]) | |
] | |
lab_facilities = [ | |
f for f in facilities | |
if any(name in f[0] for name in ["Computer Lab", "Workshop", "Language Lab", "Server"]) | |
] | |
support_facilities = [ | |
f for f in facilities | |
if any(name in f[0] for name in ["Library", "TPO", "E-learning", "Sport", "Ground"]) | |
] | |
essential_facilities = [ | |
f for f in facilities | |
if any(name in f[0] for name in ["Restroom", "Security", "CCTV", "Medical", "Water", "Fire", "Generator"]) | |
] | |
# Process facilities in each tab | |
with facility_tabs[0]: # Academic Facilities | |
for facility, requirement, model_name in academic_facilities: | |
st.markdown(f"#### {facility}") | |
user_value, score = input_and_upload(facility, 0, requirement, model_name, *models[model_name]) | |
# Update facility status | |
st.session_state.facility_status[facility] = { | |
"Verified": int(user_value), | |
"Required": int(requirement), | |
"Score": score, | |
"Status": "β Met" if user_value >= requirement and score > 0 else "β Not Met" | |
} | |
# Only add score if not already verified | |
if facility not in st.session_state.verified_facilities and score > 0: | |
st.session_state.total_score += score | |
st.session_state.verified_facilities.add(facility) | |
if user_value < requirement: | |
st.session_state.deficiencies.append(f"{facility} requires {int(requirement - user_value)} more.") | |
st.markdown("---") | |
with facility_tabs[1]: # Labs & Workshops | |
for facility, requirement, model_name in lab_facilities: | |
st.markdown(f"#### {facility}") | |
user_value, score = input_and_upload(facility, 0, requirement, model_name, *models[model_name]) | |
# Update facility status | |
st.session_state.facility_status[facility] = { | |
"Verified": int(user_value), | |
"Required": int(requirement), | |
"Score": score, | |
"Status": "β Met" if user_value >= requirement and score > 0 else "β Not Met" | |
} | |
# Only add score if not already verified | |
if facility not in st.session_state.verified_facilities and score > 0: | |
st.session_state.total_score += score | |
st.session_state.verified_facilities.add(facility) | |
if user_value < requirement: | |
st.session_state.deficiencies.append(f"{facility} requires {int(requirement - user_value)} more.") | |
st.markdown("---") | |
with facility_tabs[2]: # Support Facilities | |
for facility, requirement, model_name in support_facilities: | |
st.markdown(f"#### {facility}") | |
user_value, score = input_and_upload(facility, 0, requirement, model_name, *models[model_name]) | |
# Update facility status | |
st.session_state.facility_status[facility] = { | |
"Verified": int(user_value), | |
"Required": int(requirement), | |
"Score": score, | |
"Status": "β Met" if user_value >= requirement and score > 0 else "β Not Met" | |
} | |
# Only add score if not already verified | |
if facility not in st.session_state.verified_facilities and score > 0: | |
st.session_state.total_score += score | |
st.session_state.verified_facilities.add(facility) | |
if user_value < requirement: | |
st.session_state.deficiencies.append(f"{facility} requires {int(requirement - user_value)} more.") | |
st.markdown("---") | |
with facility_tabs[3]: # Essential Services | |
for facility, requirement, model_name in essential_facilities: | |
st.markdown(f"#### {facility}") | |
user_value, score = input_and_upload(facility, 0, requirement, model_name, *models[model_name]) | |
# Update facility status | |
st.session_state.facility_status[facility] = { | |
"Verified": int(user_value), | |
"Required": int(requirement), | |
"Score": score, | |
"Status": "β Met" if user_value >= requirement and score > 0 else "β Not Met" | |
} | |
# Only add score if not already verified | |
if facility not in st.session_state.verified_facilities and score > 0: | |
st.session_state.total_score += score | |
st.session_state.verified_facilities.add(facility) | |
if user_value < requirement: | |
st.session_state.deficiencies.append(f"{facility} requires {int(requirement - user_value)} more.") | |
st.markdown("---") | |
with tab3: | |
st.markdown("### π Results Summary") | |
# Calculate max possible score and verification progress | |
max_score = len(facilities) * 10 | |
verified_count = len(st.session_state.verified_facilities) | |
verification_progress = (verified_count / len(facilities)) * 100 | |
# Calculate grade based on total score | |
current_grade = calculate_grade(st.session_state.total_score, max_score) | |
# Create three columns for key metrics | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
st.markdown("#### Grade") | |
st.markdown(f"<h2 style='text-align: center; color: {'green' if current_grade == 'A' else 'orange' if current_grade == 'B' else 'red'};'>{current_grade}</h2>", unsafe_allow_html=True) | |
with col2: | |
st.markdown("#### Score") | |
st.markdown(f"<h2 style='text-align: center;'>{st.session_state.total_score}/{max_score}</h2>", unsafe_allow_html=True) | |
st.progress(st.session_state.total_score / max_score) | |
with col3: | |
st.markdown("#### Verification Progress") | |
st.markdown(f"<h2 style='text-align: center;'>{verification_progress:.1f}%</h2>", unsafe_allow_html=True) | |
st.progress(verification_progress / 100) | |
# Display facility status metrics | |
if st.session_state.facility_status: | |
st.markdown("### π Facility Status Overview") | |
# Calculate metrics | |
total_facilities = len(st.session_state.facility_status) | |
compliant_facilities = sum(1 for data in st.session_state.facility_status.values() if data["Status"] == "β Met") | |
non_compliant_facilities = total_facilities - compliant_facilities | |
# Display metrics in columns | |
metric_col1, metric_col2, metric_col3 = st.columns(3) | |
with metric_col1: | |
st.metric("Total Facilities", total_facilities) | |
with metric_col2: | |
st.metric("Compliant", compliant_facilities, delta=f"{(compliant_facilities/total_facilities)*100:.1f}%") | |
with metric_col3: | |
st.metric("Non-Compliant", non_compliant_facilities, delta=f"-{(non_compliant_facilities/total_facilities)*100:.1f}%") | |
# Create tabs for different views of the results | |
results_tab1, results_tab2 = st.tabs(["π Summary Table", "β οΈ Deficiencies"]) | |
with results_tab1: | |
# Create DataFrame from facility_status | |
summary_data = [ | |
{ | |
"Facility": facility, | |
"Verified": data["Verified"], | |
"Required": data["Required"], | |
"Score": data["Score"], | |
"Status": data["Status"] | |
} | |
for facility, data in st.session_state.facility_status.items() | |
] | |
summary_df = pd.DataFrame(summary_data) | |
summary_df = summary_df[["Facility", "Verified", "Required", "Score", "Status"]] | |
# Add color coding to the dataframe | |
st.dataframe( | |
summary_df.style | |
.set_properties(**{ | |
'background-color': 'white', | |
'color': 'black', | |
'border-color': 'lightgrey', | |
'text-align': 'center' | |
}) | |
.apply(lambda x: ['background-color: #e6ffe6' if v == 'β Met' else 'background-color: #ffe6e6' for v in x], subset=['Status']) | |
.format({'Score': '{:.0f}'}) | |
) | |
with results_tab2: | |
# Display deficiencies with better formatting | |
current_deficiencies = [ | |
(facility, data['Required'] - data['Verified'], data['Score']) | |
for facility, data in st.session_state.facility_status.items() | |
if data['Verified'] < data['Required'] or data['Score'] == 0 | |
] | |
if current_deficiencies: | |
st.markdown("#### π¨ Areas Needing Improvement") | |
for facility, shortage, score in current_deficiencies: | |
if score == 0: | |
st.error(f"**{facility}**: Needs verification with proper images") | |
else: | |
st.error(f"**{facility}**: Requires {shortage} more unit{'s' if shortage > 1 else ''}") | |
# Add recommendations | |
st.markdown("#### π‘ Recommendations") | |
st.info(""" | |
To improve your grade: | |
1. Focus on addressing critical deficiencies first | |
2. Prioritize essential facilities | |
3. Document improvements with clear photographs | |
4. Ensure all verifications are complete | |
""") | |
else: | |
st.success("π Congratulations! All required facilities are met and verified.") | |
else: | |
# Show empty state | |
st.info("π No facilities have been verified yet. Please complete the verification process in the Facility Verification tab.") | |
st.markdown(""" | |
#### Getting Started: | |
1. Go to the Facility Verification tab | |
2. Upload images for each facility | |
3. Complete the verification process | |
4. Return here to view your results | |
""") | |
with tab4: | |
st.markdown("### How to Use This System") | |
st.write(""" | |
1. **College Information Tab** | |
- Enter basic college details | |
- View calculated facility requirements | |
2. **Facility Verification Tab** | |
- Navigate through facility categories | |
- Upload images for verification | |
- Get instant verification results | |
3. **Results Tab** | |
- View overall grade and score | |
- Check facility verification summary | |
- Review any deficiencies | |
""") | |
st.markdown("### Grading Criteria") | |
st.write(""" | |
**Grade A:** β₯ 80% (Excellent infrastructure and verification) | |
**Grade B:** β₯ 60% (Good infrastructure with minor improvements needed) | |
**Grade C:** β₯ 40% (Basic infrastructure present but needs significant improvements) | |
**Grade D:** < 40% (Major infrastructure improvements required) | |
""") | |
st.markdown("### Note") | |
st.info("This system uses machine learning models to verify facilities from uploaded images. Ensure that the images clearly show the relevant facility for accurate verification.") | |
st.markdown("### Disclaimer") | |
st.warning("This tool is for assessment purposes only. The final evaluation and accreditation of educational institutions should be conducted by authorized bodies following official guidelines and on-site inspections.") | |
# Footer | |
st.markdown("---") | |
st.markdown("Developed for educational infrastructure assessment purposes. For support or inquiries, please contact the system administrator.") |