File size: 11,586 Bytes
dca0165
 
 
 
 
 
1713300
dca0165
 
 
 
 
 
 
 
 
 
 
 
1713300
 
 
 
 
 
 
 
 
dca0165
 
 
 
 
 
 
 
 
1713300
dca0165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1713300
dca0165
 
1713300
 
dca0165
 
 
1713300
 
 
dca0165
 
 
 
1713300
 
 
9ae8c1b
1713300
 
 
 
 
 
 
 
 
 
 
9ae8c1b
1713300
9ae8c1b
dca0165
 
1713300
9ae8c1b
1713300
dca0165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1713300
 
 
 
 
 
 
 
 
 
 
 
d2609c3
1713300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dca0165
 
 
1713300
 
dca0165
 
 
 
1713300
dca0165
1713300
dca0165
 
 
 
 
 
 
 
 
 
1713300
3e54650
9ae8c1b
1713300
6a5b8c1
dca0165
 
 
 
9ae8c1b
dca0165
 
1713300
dca0165
1713300
dca0165
 
 
 
 
 
 
1713300
 
 
 
dca0165
 
 
1713300
dca0165
1713300
 
 
 
 
dca0165
1713300
 
 
 
 
dca0165
1713300
dca0165
 
 
 
 
 
 
1713300
dca0165
1713300
dca0165
 
1713300
 
 
dca0165
 
 
 
 
 
 
 
 
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
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()