|
|
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() |
|
|
|