Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app.py +150 -0
- requirements.txt +4 -3
app.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import requests
|
3 |
+
import pandas as pd
|
4 |
+
from PIL import Image
|
5 |
+
import io
|
6 |
+
from io import BytesIO
|
7 |
+
|
8 |
+
def check_image_accessibility(url):
|
9 |
+
try:
|
10 |
+
response = requests.get(url, timeout=5)
|
11 |
+
if response.status_code == 200:
|
12 |
+
try:
|
13 |
+
image = Image.open(BytesIO(response.content))
|
14 |
+
# Verify if image can be displayed by checking its mode and size
|
15 |
+
if image.mode in ['RGB', 'RGBA', 'L'] and image.size[0] > 0 and image.size[1] > 0:
|
16 |
+
return "Accessible", image
|
17 |
+
else:
|
18 |
+
return "Not Accessible", None
|
19 |
+
except Exception:
|
20 |
+
return "Not Accessible", None
|
21 |
+
else:
|
22 |
+
return "Not Accessible", None
|
23 |
+
except Exception:
|
24 |
+
return "Not Accessible", None
|
25 |
+
|
26 |
+
def analyze_image(image_file):
|
27 |
+
# TinEye API endpoint
|
28 |
+
URL = "https://tineye.com/api/v1/result_json/?sort=score&order=desc"
|
29 |
+
|
30 |
+
# Read image file
|
31 |
+
#image_data = image_file.read()
|
32 |
+
image_data = image_file.getvalue()
|
33 |
+
# Prepare files for API request
|
34 |
+
files = {'image': ("test.png", image_data)}
|
35 |
+
|
36 |
+
# Make API request
|
37 |
+
response = requests.post(URL, files=files)
|
38 |
+
output = response.json()
|
39 |
+
|
40 |
+
# Extract data from response
|
41 |
+
urls = []
|
42 |
+
backlinks = []
|
43 |
+
crawl_dates = []
|
44 |
+
image_urls = []
|
45 |
+
image_statuses = []
|
46 |
+
images = []
|
47 |
+
|
48 |
+
for match in output['matches']:
|
49 |
+
for backlink in match['backlinks']:
|
50 |
+
urls.append(backlink['url'])
|
51 |
+
backlinks.append(backlink['backlink'])
|
52 |
+
crawl_dates.append(backlink['crawl_date'])
|
53 |
+
image_urls.append(match['image_url'])
|
54 |
+
|
55 |
+
# Check image accessibility
|
56 |
+
status, image = check_image_accessibility(match['image_url'])
|
57 |
+
image_statuses.append(status)
|
58 |
+
images.append(image)
|
59 |
+
|
60 |
+
# Create DataFrame
|
61 |
+
df = pd.DataFrame({
|
62 |
+
'URL': urls,
|
63 |
+
'Backlink': backlinks,
|
64 |
+
'Crawl Date': crawl_dates,
|
65 |
+
'Image URL': image_urls,
|
66 |
+
'Image Status': image_statuses
|
67 |
+
})
|
68 |
+
|
69 |
+
# Sort by crawl date
|
70 |
+
df = df.sort_values(by='Crawl Date', ascending=True)
|
71 |
+
|
72 |
+
return df, output['first_crawl_date'], images
|
73 |
+
|
74 |
+
def main():
|
75 |
+
st.title("Image Analysis Tool")
|
76 |
+
|
77 |
+
st.header("Image Analysis")
|
78 |
+
uploaded_file = st.file_uploader("Choose an image file", type=['png', 'jpg', 'jpeg'])
|
79 |
+
|
80 |
+
if uploaded_file is not None:
|
81 |
+
# Display the uploaded image
|
82 |
+
image = Image.open(uploaded_file)
|
83 |
+
st.image(image, caption='Uploaded Image', use_column_width=True)
|
84 |
+
|
85 |
+
if st.button("Analyze Image"):
|
86 |
+
with st.spinner("Analyzing image..."):
|
87 |
+
try:
|
88 |
+
df, first_crawl_date, images = analyze_image(uploaded_file)
|
89 |
+
|
90 |
+
# Display first crawl date
|
91 |
+
st.subheader("First Found Date")
|
92 |
+
st.write(f"This image was first found on: {first_crawl_date}")
|
93 |
+
|
94 |
+
# Display matches with images and details
|
95 |
+
st.subheader("Matched Images")
|
96 |
+
|
97 |
+
for idx, row in df.iterrows():
|
98 |
+
# Create a container for each match
|
99 |
+
with st.container():
|
100 |
+
# Display the matched image if available and accessible
|
101 |
+
if row['Image Status'] == "Accessible" and images[idx] is not None:
|
102 |
+
try:
|
103 |
+
st.image(images[idx], use_column_width=True)
|
104 |
+
except Exception:
|
105 |
+
# If image display fails, update status
|
106 |
+
df.at[idx, 'Image Status'] = "Not Accessible"
|
107 |
+
st.warning("Image not accessible")
|
108 |
+
else:
|
109 |
+
st.warning("Image not accessible")
|
110 |
+
|
111 |
+
# Display details in a clean format
|
112 |
+
st.markdown("---")
|
113 |
+
st.markdown(f"**Match {idx + 1} Details:**")
|
114 |
+
st.markdown(f"**URL:** {row['URL']}")
|
115 |
+
st.markdown(f"**Backlink:** {row['Backlink']}")
|
116 |
+
st.markdown(f"**Crawl Date:** {row['Crawl Date']}")
|
117 |
+
st.markdown(f"**Image Status:** {row['Image Status']}")
|
118 |
+
st.markdown("---")
|
119 |
+
|
120 |
+
# Add a separator before the DataFrame
|
121 |
+
st.markdown("---")
|
122 |
+
st.markdown("### Complete Results Table")
|
123 |
+
|
124 |
+
# Display the DataFrame with clickable links
|
125 |
+
st.dataframe(
|
126 |
+
df,
|
127 |
+
use_container_width=True,
|
128 |
+
hide_index=True,
|
129 |
+
column_config={
|
130 |
+
"URL": st.column_config.LinkColumn("URL"),
|
131 |
+
"Backlink": st.column_config.LinkColumn("Backlink"),
|
132 |
+
"Crawl Date": st.column_config.DateColumn("Crawl Date"),
|
133 |
+
"Image URL": st.column_config.LinkColumn("Image URL"),
|
134 |
+
"Image Status": st.column_config.TextColumn("Image Status")
|
135 |
+
}
|
136 |
+
)
|
137 |
+
|
138 |
+
# Download button for results
|
139 |
+
csv = df.to_csv(index=False)
|
140 |
+
st.download_button(
|
141 |
+
label="Download Results as CSV",
|
142 |
+
data=csv,
|
143 |
+
file_name="image_analysis_results.csv",
|
144 |
+
mime="text/csv"
|
145 |
+
)
|
146 |
+
except Exception as e:
|
147 |
+
st.error(f"An error occurred: {str(e)}")
|
148 |
+
|
149 |
+
if __name__ == "__main__":
|
150 |
+
main()
|
requirements.txt
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
1 |
+
streamlit==1.32.0
|
2 |
+
requests==2.31.0
|
3 |
+
pandas==2.2.0
|
4 |
+
Pillow==10.2.0
|