| import streamlit as st |
| import os |
| from PIL import Image |
| import random |
| import string |
|
|
| def generate_access_code(): |
| """Generate a random access code consisting of 3 characters.""" |
| return ''.join(random.choices(string.ascii_uppercase + string.digits, k=3)) |
|
|
| def check_access_code(input_code): |
| """Check if the entered access code matches the generated access code.""" |
| return input_code == st.session_state.access_code |
|
|
| def initialize_session_state(): |
| """Initialize session state variables.""" |
| if 'coordinates' not in st.session_state: |
| st.session_state.coordinates = [] |
| if 'image' not in st.session_state: |
| st.session_state.image = None |
| if 'access_code' not in st.session_state: |
| st.session_state.access_code = generate_access_code() |
|
|
| def render_canvas(image_width, image_height): |
| """Render the HTML canvas for recording mouse coordinates.""" |
| canvas_html = f""" |
| <script> |
| let canvas = document.getElementById('canvas'); |
| let ctx = canvas.getContext('2d'); |
| let coordinates = []; |
| |
| canvas.addEventListener('mousedown', function(event) {{ |
| let rect = canvas.getBoundingClientRect(); |
| let x = event.clientX - rect.left; |
| let y = event.clientY - rect.top; |
| coordinates.push({{x: x, y: y}}); |
| updateCoordinates(); |
| ctx.fillStyle = "red"; |
| ctx.fillRect(x - 2, y - 2, 4, 4); |
| }}); |
| |
| function updateCoordinates() {{ |
| let coordsDiv = document.getElementById('coordinates'); |
| coordsDiv.innerHTML = ''; |
| coordinates.forEach((coord, index) => {{ |
| coordsDiv.innerHTML += `<li>${{index + 1}}. X: ${{coord.x}}, Y: ${{coord.y}}</li>`; |
| }}); |
| }} |
| |
| function clearCoordinates() {{ |
| coordinates = []; |
| ctx.clearRect(0, 0, canvas.width, canvas.height); |
| updateCoordinates(); |
| }} |
| |
| window.clearCoordinates = clearCoordinates; |
| </script> |
| """ |
| st.markdown(f""" |
| <canvas id="canvas" width="{image_width}" height="{image_height}" style="border:1px solid #000000;"></canvas> |
| {canvas_html} |
| <button onclick="window.clearCoordinates()">Clear Coordinates</button> |
| """, unsafe_allow_html=True) |
|
|
| def main(): |
| """Main function to run the Streamlit app.""" |
| st.title("Record XY Mouse Coordinates on an Uploaded Image") |
|
|
| |
| initialize_session_state() |
|
|
| |
| uploaded_file = st.file_uploader("Upload an image (Max 500 KB):", type=["jpg", "jpeg", "png"]) |
|
|
| |
| st.write("To prevent automated submissions, an Access Code has been implemented for this tool.") |
| st.image(f"https://dummyimage.com/60x30/000/fff&text={st.session_state.access_code}", caption="Access Code") |
| access_code_input = st.text_input("Enter Access Code:") |
| if st.button("Validate Access Code"): |
| if check_access_code(access_code_input): |
| st.success("Access Code is correct.") |
| else: |
| st.error("Access Code is incorrect.") |
|
|
| |
| if uploaded_file and check_access_code(access_code_input): |
| st.session_state.image = Image.open(uploaded_file) |
| st.image(st.session_state.image, caption="Uploaded Image") |
|
|
| |
| render_canvas(st.session_state.image.width, st.session_state.image.height) |
|
|
| |
| st.markdown("<h3>Recorded Coordinates:</h3>", unsafe_allow_html=True) |
| st.markdown("<ul id='coordinates'></ul>", unsafe_allow_html=True) |
|
|
| |
| st.write(f"Image width = {st.session_state.image.width} px") |
| st.write(f"Image height = {st.session_state.image.height} px") |
| st.write(f"Number of coordinates = {len(st.session_state.coordinates)}") |
|
|
| |
| st.markdown("<h3>Modify Coordinates:</h3>", unsafe_allow_html=True) |
| x_val = st.number_input("X-coord:", min_value=0, max_value=st.session_state.image.width if st.session_state.image else 0) |
| y_val = st.number_input("Y-coord:", min_value=0, max_value=st.session_state.image.height if st.session_state.image else 0) |
| action = st.selectbox("Action:", ["Add", "Change", "Delete"]) |
| if st.button("Execute"): |
| if action == "Add": |
| st.session_state.coordinates.append((x_val, y_val)) |
| elif action == "Change": |
| if len(st.session_state.coordinates) > 0: |
| st.session_state.coordinates[-1] = (x_val, y_val) |
| elif action == "Delete": |
| if len(st.session_state.coordinates) > 0: |
| st.session_state.coordinates.pop() |
| st.experimental_rerun() |
|
|
| if __name__ == "__main__": |
| main() |
|
|