Create st.py
Browse files
st.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import os
|
| 3 |
+
from PIL import Image
|
| 4 |
+
import random
|
| 5 |
+
import string
|
| 6 |
+
|
| 7 |
+
def generate_access_code():
|
| 8 |
+
"""Generate a random access code consisting of 3 characters."""
|
| 9 |
+
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=3))
|
| 10 |
+
|
| 11 |
+
def check_access_code(input_code):
|
| 12 |
+
"""Check if the entered access code matches the generated access code."""
|
| 13 |
+
return input_code == st.session_state.access_code
|
| 14 |
+
|
| 15 |
+
def initialize_session_state():
|
| 16 |
+
"""Initialize session state variables."""
|
| 17 |
+
if 'coordinates' not in st.session_state:
|
| 18 |
+
st.session_state.coordinates = []
|
| 19 |
+
if 'image' not in st.session_state:
|
| 20 |
+
st.session_state.image = None
|
| 21 |
+
if 'access_code' not in st.session_state:
|
| 22 |
+
st.session_state.access_code = generate_access_code()
|
| 23 |
+
|
| 24 |
+
def render_canvas(image_width, image_height):
|
| 25 |
+
"""Render the HTML canvas for recording mouse coordinates."""
|
| 26 |
+
canvas_html = f"""
|
| 27 |
+
<script>
|
| 28 |
+
let canvas = document.getElementById('canvas');
|
| 29 |
+
let ctx = canvas.getContext('2d');
|
| 30 |
+
let coordinates = [];
|
| 31 |
+
|
| 32 |
+
canvas.addEventListener('mousedown', function(event) {{
|
| 33 |
+
let rect = canvas.getBoundingClientRect();
|
| 34 |
+
let x = event.clientX - rect.left;
|
| 35 |
+
let y = event.clientY - rect.top;
|
| 36 |
+
coordinates.push({{x: x, y: y}});
|
| 37 |
+
updateCoordinates();
|
| 38 |
+
ctx.fillStyle = "red";
|
| 39 |
+
ctx.fillRect(x - 2, y - 2, 4, 4);
|
| 40 |
+
}});
|
| 41 |
+
|
| 42 |
+
function updateCoordinates() {{
|
| 43 |
+
let coordsDiv = document.getElementById('coordinates');
|
| 44 |
+
coordsDiv.innerHTML = '';
|
| 45 |
+
coordinates.forEach((coord, index) => {{
|
| 46 |
+
coordsDiv.innerHTML += `<li>${{index + 1}}. X: ${{coord.x}}, Y: ${{coord.y}}</li>`;
|
| 47 |
+
}});
|
| 48 |
+
}}
|
| 49 |
+
|
| 50 |
+
function clearCoordinates() {{
|
| 51 |
+
coordinates = [];
|
| 52 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 53 |
+
updateCoordinates();
|
| 54 |
+
}}
|
| 55 |
+
|
| 56 |
+
window.clearCoordinates = clearCoordinates;
|
| 57 |
+
</script>
|
| 58 |
+
"""
|
| 59 |
+
st.markdown(f"""
|
| 60 |
+
<canvas id="canvas" width="{image_width}" height="{image_height}" style="border:1px solid #000000;"></canvas>
|
| 61 |
+
{canvas_html}
|
| 62 |
+
<button onclick="window.clearCoordinates()">Clear Coordinates</button>
|
| 63 |
+
""", unsafe_allow_html=True)
|
| 64 |
+
|
| 65 |
+
def main():
|
| 66 |
+
"""Main function to run the Streamlit app."""
|
| 67 |
+
st.title("Record XY Mouse Coordinates on an Uploaded Image")
|
| 68 |
+
|
| 69 |
+
# Initialize session state variables
|
| 70 |
+
initialize_session_state()
|
| 71 |
+
|
| 72 |
+
# Image upload section
|
| 73 |
+
uploaded_file = st.file_uploader("Upload an image (Max 500 KB):", type=["jpg", "jpeg", "png"])
|
| 74 |
+
|
| 75 |
+
# Access code section
|
| 76 |
+
st.write("To prevent automated submissions, an Access Code has been implemented for this tool.")
|
| 77 |
+
st.image(f"https://dummyimage.com/60x30/000/fff&text={st.session_state.access_code}", caption="Access Code")
|
| 78 |
+
access_code_input = st.text_input("Enter Access Code:")
|
| 79 |
+
if st.button("Validate Access Code"):
|
| 80 |
+
if check_access_code(access_code_input):
|
| 81 |
+
st.success("Access Code is correct.")
|
| 82 |
+
else:
|
| 83 |
+
st.error("Access Code is incorrect.")
|
| 84 |
+
|
| 85 |
+
# Display canvas if image is uploaded and access code is correct
|
| 86 |
+
if uploaded_file and check_access_code(access_code_input):
|
| 87 |
+
st.session_state.image = Image.open(uploaded_file)
|
| 88 |
+
st.image(st.session_state.image, caption="Uploaded Image")
|
| 89 |
+
|
| 90 |
+
# Display the canvas for coordinate recording
|
| 91 |
+
render_canvas(st.session_state.image.width, st.session_state.image.height)
|
| 92 |
+
|
| 93 |
+
# Display coordinates list
|
| 94 |
+
st.markdown("<h3>Recorded Coordinates:</h3>", unsafe_allow_html=True)
|
| 95 |
+
st.markdown("<ul id='coordinates'></ul>", unsafe_allow_html=True)
|
| 96 |
+
|
| 97 |
+
# Show image details
|
| 98 |
+
st.write(f"Image width = {st.session_state.image.width} px")
|
| 99 |
+
st.write(f"Image height = {st.session_state.image.height} px")
|
| 100 |
+
st.write(f"Number of coordinates = {len(st.session_state.coordinates)}")
|
| 101 |
+
|
| 102 |
+
# Add, Change, and Delete coordinates sections
|
| 103 |
+
st.markdown("<h3>Modify Coordinates:</h3>", unsafe_allow_html=True)
|
| 104 |
+
x_val = st.number_input("X-coord:", min_value=0, max_value=st.session_state.image.width if st.session_state.image else 0)
|
| 105 |
+
y_val = st.number_input("Y-coord:", min_value=0, max_value=st.session_state.image.height if st.session_state.image else 0)
|
| 106 |
+
action = st.selectbox("Action:", ["Add", "Change", "Delete"])
|
| 107 |
+
if st.button("Execute"):
|
| 108 |
+
if action == "Add":
|
| 109 |
+
st.session_state.coordinates.append((x_val, y_val))
|
| 110 |
+
elif action == "Change":
|
| 111 |
+
if len(st.session_state.coordinates) > 0:
|
| 112 |
+
st.session_state.coordinates[-1] = (x_val, y_val)
|
| 113 |
+
elif action == "Delete":
|
| 114 |
+
if len(st.session_state.coordinates) > 0:
|
| 115 |
+
st.session_state.coordinates.pop()
|
| 116 |
+
st.experimental_rerun()
|
| 117 |
+
|
| 118 |
+
if __name__ == "__main__":
|
| 119 |
+
main()
|