Spaces:
Runtime error
Runtime error
Pruthul
commited on
Part-4 done (Streamlit)
Browse filesThe image similarity performed here is done using cosine similarity.Including Resnet model and Tensorflow created problems while running on streamlit
app.py
ADDED
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import cv2
|
3 |
+
from PIL import Image
|
4 |
+
import numpy as np
|
5 |
+
import os
|
6 |
+
import matplotlib.pyplot as plt
|
7 |
+
|
8 |
+
# Define a function to search for similar images
|
9 |
+
def search_similar_images(img_path, num_results=10):
|
10 |
+
# Load the query image
|
11 |
+
query_image = cv2.imread(img_path)
|
12 |
+
|
13 |
+
# Convert the query image to grayscale
|
14 |
+
query_image_gray = cv2.cvtColor(query_image, cv2.COLOR_BGR2GRAY)
|
15 |
+
|
16 |
+
# Resize the query image to a fixed size
|
17 |
+
query_image_resized = cv2.resize(query_image_gray, (300, 300))
|
18 |
+
|
19 |
+
# Calculate the histogram of the query image
|
20 |
+
query_hist = cv2.calcHist([query_image_resized], [0], None, [256], [0, 256])
|
21 |
+
|
22 |
+
# Normalize the histogram
|
23 |
+
query_hist_norm = cv2.normalize(query_hist, query_hist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
|
24 |
+
|
25 |
+
# Load all images from the 'images' directory
|
26 |
+
images_dir = "images"
|
27 |
+
image_files = os.listdir(images_dir)
|
28 |
+
images = []
|
29 |
+
for image_file in image_files:
|
30 |
+
if image_file.endswith(".jpg") or image_file.endswith(".png"):
|
31 |
+
image_path = os.path.join(images_dir, image_file)
|
32 |
+
image = cv2.imread(image_path)
|
33 |
+
images.append(image)
|
34 |
+
|
35 |
+
# Calculate the histograms and similarities for each image
|
36 |
+
similarities = []
|
37 |
+
for image in images:
|
38 |
+
# Convert the image to grayscale
|
39 |
+
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
40 |
+
|
41 |
+
# Resize the image to a fixed size
|
42 |
+
image_resized = cv2.resize(image_gray, (300, 300))
|
43 |
+
|
44 |
+
# Calculate the histogram of the image
|
45 |
+
image_hist = cv2.calcHist([image_resized], [0], None, [256], [0, 256])
|
46 |
+
|
47 |
+
# Normalize the histogram
|
48 |
+
image_hist_norm = cv2.normalize(image_hist, image_hist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
|
49 |
+
|
50 |
+
# Calculate the correlation between the histograms
|
51 |
+
similarity = cv2.compareHist(query_hist_norm, image_hist_norm, cv2.HISTCMP_CORREL)
|
52 |
+
|
53 |
+
# Add the similarity to the list
|
54 |
+
similarities.append(similarity)
|
55 |
+
|
56 |
+
# Get the indices of the top num_results most similar images
|
57 |
+
indices = np.argsort(similarities)[-num_results:]
|
58 |
+
|
59 |
+
# Create a list of the top num_results most similar images
|
60 |
+
results = []
|
61 |
+
for index in indices:
|
62 |
+
results.append(images[index])
|
63 |
+
|
64 |
+
# Return the list of results
|
65 |
+
return results
|
66 |
+
|
67 |
+
def display_results(similar_images):
|
68 |
+
# Create a figure with a grid of 10 subplots
|
69 |
+
fig, axs = plt.subplots(2, 5, figsize=(10, 4))
|
70 |
+
|
71 |
+
# Loop through the similar images and display each one in a subplot
|
72 |
+
for i,img in enumerate(similar_images):
|
73 |
+
# Load the image using OpenCV
|
74 |
+
# Convert to RGB for displaying with matplotlib
|
75 |
+
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
76 |
+
|
77 |
+
# Calculate the row and column index for the current subplot
|
78 |
+
row = i // 5
|
79 |
+
col = i % 5
|
80 |
+
|
81 |
+
# Display the image in the current subplot
|
82 |
+
axs[row, col].imshow(img)
|
83 |
+
axs[row, col].axis("off")
|
84 |
+
|
85 |
+
# Adjust the spacing between subplots and display the figure
|
86 |
+
plt.subplots_adjust(wspace=0.05, hspace=0.05)
|
87 |
+
st.pyplot(fig)
|
88 |
+
|
89 |
+
def app():
|
90 |
+
# Set the page title and icon
|
91 |
+
st.set_page_config(page_title="Similar Images Search", page_icon=":mag:")
|
92 |
+
# Add a title to the app
|
93 |
+
st.title("Find Similar Images")
|
94 |
+
|
95 |
+
# Add a description to the app
|
96 |
+
st.markdown("This app allows you to search for similar images.")
|
97 |
+
|
98 |
+
# Allow the user to choose between "Browse a single image" and "Select from test dataset"
|
99 |
+
option = st.radio("Select an option:", ("Browse a single image", "Select from test dataset"))
|
100 |
+
|
101 |
+
# If the user selects "Browse a single image"
|
102 |
+
if option == "Browse a single image":
|
103 |
+
# Allow the user to upload an image
|
104 |
+
uploaded_file = st.file_uploader("Choose an image:", type=["jpg", "jpeg", "png"])
|
105 |
+
|
106 |
+
# If the user has uploaded an image
|
107 |
+
if uploaded_file is not None:
|
108 |
+
# Load the image
|
109 |
+
image = Image.open(uploaded_file).convert("RGB")
|
110 |
+
|
111 |
+
# Display the uploaded image
|
112 |
+
st.image(image, caption="Uploaded Image", use_column_width=True)
|
113 |
+
|
114 |
+
# Search for similar images
|
115 |
+
# print("Uploaded file ==> ",uploaded_file)
|
116 |
+
# Save the image to a temporary file
|
117 |
+
temp_file_path = "temp.jpg"
|
118 |
+
image.save(temp_file_path)
|
119 |
+
|
120 |
+
results = search_similar_images(temp_file_path)
|
121 |
+
|
122 |
+
# Display the results as a grid of images
|
123 |
+
st.markdown("---")
|
124 |
+
st.subheader("Similar Images")
|
125 |
+
display_results(results)
|
126 |
+
|
127 |
+
# If the user selects "Select from test dataset"
|
128 |
+
else:
|
129 |
+
# Get a list of all test dataset image files
|
130 |
+
test_dataset_dir = "images"
|
131 |
+
test_dataset_files = os.listdir(test_dataset_dir)
|
132 |
+
test_dataset_images = []
|
133 |
+
|
134 |
+
# Display the list of test dataset image files in a sidebar
|
135 |
+
st.sidebar.title("Test Dataset")
|
136 |
+
for test_dataset_file in test_dataset_files:
|
137 |
+
if test_dataset_file.endswith(".jpg") or test_dataset_file.endswith(".png"):
|
138 |
+
test_dataset_image_path = os.path.join(test_dataset_dir, test_dataset_file)
|
139 |
+
test_dataset_image = Image.open(test_dataset_image_path)
|
140 |
+
test_dataset_images.append(test_dataset_image)
|
141 |
+
|
142 |
+
# Display the file name as a text instead of an image
|
143 |
+
st.sidebar.write(test_dataset_file)
|
144 |
+
|
145 |
+
# Allow the user to select an image from the test dataset
|
146 |
+
selected_image_path = st.sidebar.selectbox("Select an image:", test_dataset_files)
|
147 |
+
|
148 |
+
# Load the selected image
|
149 |
+
selected_image_path = os.path.join(test_dataset_dir, selected_image_path)
|
150 |
+
selected_image = Image.open(selected_image_path)
|
151 |
+
|
152 |
+
# Display the selected image
|
153 |
+
st.image(selected_image, caption="Selected Image", use_column_width=True)
|
154 |
+
|
155 |
+
# Search for similar images
|
156 |
+
results = search_similar_images(selected_image_path)
|
157 |
+
|
158 |
+
# Display the results as a grid of images
|
159 |
+
if selected_image_path != os.path.join(test_dataset_dir, test_dataset_files[0]):
|
160 |
+
st.markdown("---")
|
161 |
+
st.subheader("Similar Images")
|
162 |
+
display_results(results)
|
163 |
+
# for result in results:
|
164 |
+
# st.image(result, caption="Similar Image", use_column_width=True)
|
165 |
+
# print("result==> ",result)
|
166 |
+
|
167 |
+
# Add a footer to the app
|
168 |
+
st.markdown("---")
|
169 |
+
st.markdown("Created by Pruthul")
|
170 |
+
|
171 |
+
|
172 |
+
app()
|
173 |
+
|
174 |
+
|
175 |
+
|
176 |
+
#### == Image feature extraction using Resnet == (Failed when run using streamlit) ###
|
177 |
+
|
178 |
+
# from sklearn.neighbors import NearestNeighbors
|
179 |
+
# from tensorflow.keras.preprocessing.image import load_img, img_to_array
|
180 |
+
# from tensorflow.keras.applications.resnet50 import ResNet50,preprocess_input
|
181 |
+
|
182 |
+
# def extract_features(image_path, model):
|
183 |
+
# # Load and preprocess the image
|
184 |
+
# image = load_img(image_path, target_size=(224, 224))
|
185 |
+
# image_array = img_to_array(image)
|
186 |
+
# image_array = preprocess_input(image_array)
|
187 |
+
# # Extract the features using the ResNet50 model
|
188 |
+
# features = model.predict(image_array.reshape(1, 224, 224, 3))
|
189 |
+
|
190 |
+
# # Flatten the features and return them as a 1D array
|
191 |
+
# features = features.flatten()
|
192 |
+
# return features
|
193 |
+
|
194 |
+
|
195 |
+
# # Define a function to search for similar images
|
196 |
+
# def search_similar_images(img_path, num_results=10):
|
197 |
+
# #load feature dictionary
|
198 |
+
# with open("features.npy", "rb") as f:
|
199 |
+
# image_dict = np.load(f, allow_pickle=True).item()
|
200 |
+
|
201 |
+
# # Fit a nearest neighbor model on the features
|
202 |
+
# nn_model = NearestNeighbors(n_neighbors=num_results, metric='cosine')
|
203 |
+
|
204 |
+
# # Convert the dictionary to a matrix of feature vectors
|
205 |
+
# features_list = np.array(list(image_dict.values()))
|
206 |
+
|
207 |
+
# # Fit the model to the feature matrix
|
208 |
+
# nn_model.fit(features_list)
|
209 |
+
|
210 |
+
# # Define the file path to the test image
|
211 |
+
# test_image_path = img_path
|
212 |
+
|
213 |
+
# # Load all images from the 'images' directory
|
214 |
+
# images_dir = "images"
|
215 |
+
# image_files = os.listdir(images_dir)
|
216 |
+
# images = []
|
217 |
+
# for image_file in image_files:
|
218 |
+
# if image_file.endswith(".jpg") or image_file.endswith(".png"):
|
219 |
+
# image_path = os.path.join(images_dir, image_file)
|
220 |
+
# image = cv2.imread(image_path)
|
221 |
+
# images.append(image)
|
222 |
+
|
223 |
+
# model = ResNet50(weights='imagenet', include_top=False)
|
224 |
+
# # Extract features from the test image
|
225 |
+
# test_image_features = extract_features(test_image_path, model)
|
226 |
+
|
227 |
+
# # Reshape the test image features to match the shape of the feature vectors
|
228 |
+
# test_image_features = test_image_features.reshape(1, -1)
|
229 |
+
|
230 |
+
# # # Find the 10 most similar images to the test image
|
231 |
+
# distances, indices = nn_model.kneighbors(test_image_features)
|
232 |
+
|
233 |
+
# # Create a list of the top num_results most similar images
|
234 |
+
# results = []
|
235 |
+
# for index in indices[0]:
|
236 |
+
# results.append(images[index])
|
237 |
+
|
238 |
+
# # Return the list of results
|
239 |
+
# return results
|