Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import sqlite3 | |
| import hashlib | |
| from datetime import datetime | |
| from localization_eval import evaluate_submission | |
| from PIL import Image | |
| # --- CONFIGURATION & SETUP --- | |
| st.set_page_config( | |
| page_title="AI Benchmark Arena", | |
| page_icon="๐", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| DB_NAME = "./benchmark.db" | |
| def see_entire_table(): | |
| conn = sqlite3.connect(DB_NAME) | |
| c = conn.cursor() | |
| c.execute('SELECT * FROM submissions') | |
| conn.commit() | |
| conn.close() | |
| def init_db(): | |
| conn = sqlite3.connect(DB_NAME) | |
| c = conn.cursor() | |
| # User Table | |
| c.execute('''CREATE TABLE IF NOT EXISTS users | |
| (username TEXT PRIMARY KEY, password TEXT)''') | |
| # Submissions Table | |
| c.execute('''CREATE TABLE IF NOT EXISTS submissions | |
| (id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| username TEXT, bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 , timestamp DATETIME)''') | |
| conn.commit() | |
| conn.close() | |
| def make_hashes(password): | |
| return hashlib.sha256(str.encode(password)).hexdigest() | |
| def check_hashes(password, hashed_text): | |
| if make_hashes(password) == hashed_text: | |
| return hashed_text | |
| return False | |
| def add_user(username, password): | |
| conn = sqlite3.connect(DB_NAME) | |
| c = conn.cursor() | |
| try: | |
| c.execute('INSERT INTO users(username, password) VALUES (?,?)', | |
| (username, make_hashes(password))) | |
| conn.commit() | |
| return True | |
| except sqlite3.IntegrityError: | |
| return False | |
| finally: | |
| conn.close() | |
| def login_user(username, password): | |
| conn = sqlite3.connect(DB_NAME) | |
| c = conn.cursor() | |
| c.execute('SELECT * FROM users WHERE username =? AND password = ?', | |
| (username, make_hashes(password))) | |
| data = c.fetchall() | |
| conn.close() | |
| return data | |
| def save_submission(username, bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 ): | |
| conn = sqlite3.connect(DB_NAME) | |
| c = conn.cursor() | |
| c.execute('INSERT INTO submissions(username, bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 , timestamp) VALUES (?,?, ?, ? ,? ,?)', | |
| (username, bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 , datetime.now())) | |
| conn.commit() | |
| conn.close() | |
| def get_leaderboard_data(): | |
| conn = sqlite3.connect(DB_NAME) | |
| # Get the BEST score for each user | |
| query = """ | |
| WITH BestScores AS ( | |
| SELECT | |
| username, | |
| MAX(segm_mAP) as max_segm_mAP | |
| FROM submissions | |
| GROUP BY username | |
| ) | |
| SELECT | |
| s.username, | |
| s.bbox_mAP, | |
| s.bbox_AP50, | |
| s.segm_mAP, | |
| s.segm_AP50, | |
| MAX(s.timestamp) as last_submission -- MAX(timestamp) to get the most recent best submission | |
| FROM submissions s | |
| INNER JOIN BestScores b ON s.username = b.username AND s.segm_mAP = b.max_segm_mAP | |
| GROUP BY s.username | |
| ORDER BY s.segm_mAP DESC, s.timestamp ASC | |
| """ | |
| df = pd.read_sql_query(query, conn) | |
| # Rename the column for display clarity | |
| df = df.rename(columns={'segm_mAP': 'Best_segm_mAP'}) | |
| conn.close() | |
| return df | |
| # --- User Interface --- | |
| def ui_login_signup(): | |
| st.title("Welcome to Benchmark Arena ๐") | |
| tab1, tab2 = st.tabs(["Login", "Sign Up"]) | |
| with tab1: | |
| st.subheader("Sign In") | |
| username = st.text_input("Username", key="login_user") | |
| password = st.text_input("Password", type='password', key="login_pass") | |
| if st.button("Login"): | |
| if login_user(username, password): | |
| st.session_state['logged_in'] = True | |
| st.session_state['username'] = username | |
| st.rerun() | |
| else: | |
| st.error("Username or Password incorrect") | |
| with tab2: | |
| st.subheader("Create New Account") | |
| new_user = st.text_input("Username", key="new_user") | |
| new_pass = st.text_input("Password", type='password', key="new_pass") | |
| if st.button("Sign Up"): | |
| if add_user(new_user, new_pass): | |
| st.success("Account created! Please navigate to Login.") | |
| else: | |
| st.warning("Username already exists.") | |
| def main_app(): | |
| # Sidebar Navigation | |
| st.sidebar.title(f"Hi, {st.session_state['username']}!") | |
| menu = ["Submit Model", "Leaderboard"] | |
| choice = st.sidebar.radio("Navigation", menu) | |
| st.sidebar.markdown("---") | |
| if st.sidebar.button("Logout"): | |
| st.session_state['logged_in'] = False | |
| st.session_state['username'] = None | |
| st.rerun() | |
| # --- NEW: Overview Expander --- | |
| with st.expander("โน๏ธ Overview of the AI Benchmark Arena"): | |
| # Placeholder for an informative image | |
| st.markdown( | |
| """ | |
| A natural application of computer vision is to assist blind people, whether that may be to overcome their daily visual challenges or break down their social accessibility barriers. BIV-Priv is proposed to preserve a blind person's visual privacy to ensure they can access visual-related tools safely. | |
| VizWiz Challenge 2025 is the 1th edition of the Few-Shot Private Object Localization Challenge on the BIV-Priv dataset. To participate in the challenge, you can find instructions on the Challenge website. | |
| Note: All the timings on the EvalAI platform are local to your timezone. | |
| """ | |
| ) | |
| overview_image = Image.open("src/overview_image.png").resize((600, 600)) | |
| st.image(overview_image, caption="Example of an object localization task", ) | |
| # --- NEW: Evaluation Expander --- | |
| with st.expander("๐ How is the Score Calculated?"): | |
| st.markdown( | |
| """ | |
| Terms and Conditions | |
| The images and annotations in this dataset belong to the VizWiz team and are licensed under a Commons Attribution 4.0 International License. | |
| Copyright ยฉ 2015, VizWiz team. All rights reserved. Redistribution and use software in source and binary form, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the VizWiz team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND ANNOTATIONS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| """ | |
| ) | |
| st.markdown("---") # Visual separator | |
| # --- PAGE: SUBMIT MODEL (Existing Code) --- | |
| if choice == "Submit Model": | |
| st.header("๐ Submit your Predictions") | |
| # ... (rest of the Submit Model code) | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| # st.info("Upload your CSV file. It must contain `id` and `prediction` columns.") | |
| uploaded_file = st.file_uploader("Choose a JSON file", type="json") # Corrected type to 'json' based on localization_eval | |
| # ... (rest of the submission logic) | |
| if uploaded_file is not None: | |
| save_path = f"./{uploaded_file.name}" | |
| # Write the file to the current directory | |
| with open(save_path, "wb") as f: | |
| f.write(uploaded_file.getbuffer()) | |
| if st.button("Evaluate"): | |
| with st.spinner('Calculating score against Ground Truth...'): | |
| # Ensure the ground truth path is correct | |
| bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 = evaluate_submission("src/biv_query.json", save_path) | |
| st.success(f"bbox_mAP, bbox_AP50, segm_mAP, segm_AP50 : {bbox_mAP:.2f, bbox_AP50:.2f, segm_mAP:.2f, segm_AP50:.2f}") | |
| if bbox_mAP is not None and bbox_AP50 is not None and segm_mAP is not None and segm_AP50 is not None: | |
| save_submission(st.session_state['username'], bbox_mAP, bbox_AP50, segm_mAP, segm_AP50) | |
| st.balloons() | |
| st.success("Submission Successful!") | |
| # Display Metrics | |
| # st.metric(label="Result : ", value=f"{bbox_mAP:.4f, bbox_AP50:.4f, segm_mAP:.4f, segm_AP50:.4f}") | |
| # --- PAGE: LEADERBOARD (Existing Code) --- | |
| elif choice == "Leaderboard": | |
| # ... (rest of the Leaderboard code) | |
| st.header("๐ Leaderboard") | |
| st.write("Rankings based on the highest accuracy score achieved.") | |
| df_leaderboard = get_leaderboard_data() | |
| if not df_leaderboard.empty: | |
| # Add a Rank column | |
| df_leaderboard.insert(0, 'Rank', range(1, len(df_leaderboard) + 1)) | |
| # Apply formatting and configuration | |
| st.dataframe( | |
| df_leaderboard, | |
| column_config={ | |
| "Rank": st.column_config.Column("Rank", width="small"), | |
| "username": "Participant", | |
| # The main ranking metric (bbox_mAP), formatted to 4 decimal places | |
| "Best_bbox_mAP": st.column_config.NumberColumn( | |
| "bbox_mAP (Primary)", | |
| format="%.4f", | |
| help="Best Bounding Box Mean Average Precision achieved." | |
| ), | |
| # Other metrics, formatted as numbers without a progress bar | |
| "bbox_AP50": st.column_config.NumberColumn("bbox_AP50", format="%.4f"), | |
| "segm_mAP": st.column_config.NumberColumn("segm_mAP", format="%.4f"), | |
| "segm_AP50": st.column_config.NumberColumn("segm_AP50", format="%.4f"), | |
| # Datetime column configuration remains the same | |
| "last_submission": st.column_config.DatetimeColumn( | |
| "Last Active Submission", | |
| format="D MMM YYYY, h:mm a", | |
| ), | |
| }, | |
| use_container_width=True, | |
| hide_index=True, | |
| ) | |
| else: | |
| st.info("No submissions yet. Be the first to submit your model!") | |
| if __name__ == '__main__': | |
| init_db() | |
| print("see entire table") | |
| see_entire_table() | |
| print("---------------------------") | |
| # Session State Initialization | |
| if 'logged_in' not in st.session_state: | |
| st.session_state['logged_in'] = False | |
| st.session_state['username'] = None | |
| if not st.session_state['logged_in']: | |
| ui_login_signup() | |
| else: | |
| main_app() |