ABAO77 commited on
Commit
982b011
·
verified ·
1 Parent(s): f1973fa

Upload 161 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. Dockerfile +16 -0
  3. LICENSE +21 -0
  4. README.md +62 -7
  5. Screenshot 2025-01-02 at 22.48.01.png +0 -0
  6. Sea-chile.jpg +0 -0
  7. __pycache__/test.cpython-311.pyc +0 -0
  8. a.ipynb +0 -0
  9. app.py +54 -0
  10. data/.DS_Store +0 -0
  11. data/images/00000003_(7).jpg +0 -0
  12. data/images/00000004.jpg +0 -0
  13. data/images/00000007_(5).jpg +0 -0
  14. data/images/00000010.jpg +0 -0
  15. data/images/00000013_(7).jpg +0 -0
  16. data/images/00000017_(5).jpg +0 -0
  17. data/images/00000038.jpg +0 -0
  18. data/images/00000048_(2).jpg +0 -0
  19. data/images/00000058_(2).jpg +0 -0
  20. data/images/00000066_(3).jpg +0 -0
  21. data/images/00000071_(7).jpg +0 -0
  22. data/images/00000076_(3).jpg +0 -0
  23. data/images/00000080_(4).jpg +0 -0
  24. data/images/00000083_(2).jpg +0 -0
  25. data/images/00000084_(6).jpg +0 -0
  26. data/images/00000090_(4).jpg +0 -0
  27. data/images/00000093_(2).jpg +0 -0
  28. data/images/00000094_(6).jpg +0 -0
  29. data/images/00000123_(4).jpg +0 -0
  30. data/images/00000127_(6).jpg +0 -0
  31. data/images/00000130_(2).jpg +0 -0
  32. data/images/00000133_(4).jpg +0 -0
  33. data/images/00000137_(6).jpg +0 -0
  34. data/images/00000142_(2).jpg +0 -0
  35. data/images/00000145_(6).jpg +0 -0
  36. data/images/00000152_(2).jpg +0 -0
  37. data/images/00000155_(6).jpg +0 -0
  38. data/images/00000158.jpg +0 -0
  39. data/images/00000164.jpg +0 -0
  40. data/images/00000170.jpg +0 -0
  41. data/images/00000189_(2).jpg +0 -0
  42. data/images/00000199_(2).jpg +0 -0
  43. data/images/00000209_(5).jpg +0 -0
  44. data/images/00000219_(5).jpg +0 -0
  45. data/images/00000223_(6).jpg +0 -0
  46. data/images/00000224_(2).jpg +0 -0
  47. data/images/00000233_(6).jpg +0 -0
  48. data/images/00000234_(2).jpg +0 -0
  49. data/images/00000241_(6).jpg +0 -0
  50. data/images/00000245_(4).jpg +0 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ model/db_vit_b_16.index filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
2
+ # you will also find guides on how best to write your Dockerfile
3
+
4
+ FROM python:3.11-slim
5
+
6
+ RUN useradd -m -u 1000 user
7
+ USER user
8
+ ENV PATH="/home/user/.local/bin:$PATH"
9
+
10
+ WORKDIR /app
11
+
12
+ COPY --chown=user ./requirements.txt requirements.txt
13
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
14
+
15
+ COPY --chown=user . /app
16
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Samet Cetin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,10 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Image Retrieval
3
- emoji: 📉
4
- colorFrom: gray
5
- colorTo: gray
6
- sdk: docker
7
- pinned: false
8
  ---
 
 
 
 
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # image-retrieval
2
+
3
+ This repository presents an image retrieval pipeline that consists of a vector database storing image features extracted using a pre-trained ResNet/ViT model. Image retrieval pipeline consists of (1) a vector database building script that extracts image features of all images in the collection using a pre-trained ResNet/ViT model and stores them in a vector database by cosine similarity, (2) a search query script that extracts the features for a randomly selected image and returns the most similar images from the vector database.
4
+
5
+ The construction of the proposed image retrieval pipeline can be divided into three stages:
6
+
7
+ 1 - Place your images (a collection of images that you want to create an image retrieval pipeline on) under the data folders as ```data/images```. In this project, [Landscape Pictures Dataset](https://www.kaggle.com/datasets/arnaud58/landscape-pictures) is used but feel free to use your of own image collection.
8
+ 2 - Extract the features of all images using a pre-trained ResNet model and save all features into a vector database.
9
+ 3 - For a given query image, perform a similarity search by first extracting the features of the query image and then performing a search over the vector database.
10
+
11
+ ## Installation
12
+ 1. Clone the repository to your local first as follows
13
+ ```
14
+ $ git clone https://github.com/cetinsamet/image-retrieval.git
15
+ ```
16
+
17
+ 2. Then recreate the virtual environment on your local using the provided ```.yml``` file and activate the venv as follows
18
+ ```
19
+ $ cd image-retrieval
20
+ $ conda env create -f environment.yml
21
+ $ conda activate image-retrieval
22
+ ```
23
+
24
+ 3. Add the path of your own working directory as WORK_DIR in the configuration file ```src/config/settings.py```as follows
25
+ ```
26
+ $ cd src
27
+ $ nano config/settings.py # or use your favorite text editor and add the path of your own working directory
28
+
29
+ WORK_DIR = "PATH-TO-YOUR-OWN-WORKING-DIRECTORY"
30
+ ```
31
+
32
+ 4. Create a ```data``` folder as follows
33
+ ```
34
+ $ mkdir ../data
35
+ ```
36
+
37
+ 5. Download data from [here](https://www.kaggle.com/datasets/arnaud58/landscape-pictures) (Landscape Pictures Dataset) and place all image files under ```data/images``` folder.
38
+
39
+ ## Run
40
+ Please perform following steps sequentially to reproduce the image retrieval pipeline that gives the search query examples below.
41
+
42
+ ### Building vector database
43
+ Running ```build_vector_database.py``` extracts the features of all downloaded images by using the selected pre-trained ResNet model (please use ```--feat_extractor``` flag to customize) and save the features into a vector database that is stored under ```data/``` directory.
44
+
45
+ ```
46
+ $ python3 build_vector_database.py --feat_extractor vit_l_32
47
+ ```
48
+
49
+ ### Search query
50
+ Finally, running ```search_query.py``` selects random object images (the amount of the selected images can be customized using ```--n``` flag) and search the most similar object images (the amount of the similar images can be customized using ```--k``` flag) by querying the pre-built vector database.
51
+ ```
52
+ $ python3 search_query.py --feat_extractor vit_l_32 --n 10 --k 12
53
+ ```
54
+
55
+ Some examples of the resulting search queries are as follows;
56
+
57
+ ![img.png](results/results_vit_l_32/query_001.jpg)
58
  ---
59
+ ![img.png](results/results_vit_l_32/query_002.jpg)
 
 
 
 
 
60
  ---
61
+ ![img.png](results/results_vit_l_32/query_005.jpg)
62
+ ---
63
+ ![img.png](results/results_vit_l_32/query_006.jpg)
64
+
65
 
 
Screenshot 2025-01-02 at 22.48.01.png ADDED
Sea-chile.jpg ADDED
__pycache__/test.cpython-311.pyc ADDED
Binary file (3.73 kB). View file
 
a.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import faiss
4
+ from PIL import Image
5
+ from fastapi import FastAPI, UploadFile, File
6
+ from fastapi.responses import FileResponse, JSONResponse
7
+ from src.modules import FeatureExtractor
8
+ from src.config import DATA_DIR
9
+ from io import BytesIO
10
+
11
+ app = FastAPI(docs_url="/")
12
+
13
+ # Load FAISS index and feature extractor
14
+ index = faiss.read_index("./model/db_vit_b_16.index")
15
+ feature_extractor = FeatureExtractor(base_model="vit_b_16")
16
+
17
+ # Use MPS (Apple Silicon) if available, otherwise fallback to CPU
18
+ if torch.has_mps:
19
+ torch.set_default_device("mps")
20
+
21
+ # Helper function to load image from uploaded file
22
+ def load_image(uploaded_file):
23
+ image = Image.open(BytesIO(uploaded_file)).convert("RGB")
24
+ return image
25
+
26
+ @app.post("/search-image/")
27
+ async def search_image(file: UploadFile = File(...)):
28
+ try:
29
+ # Load the uploaded image
30
+ image = load_image(await file.read())
31
+
32
+ # Extract features
33
+ with torch.no_grad():
34
+ output = feature_extractor.extract_features(image)
35
+ output = output.view(output.size(0), -1)
36
+ output = output / output.norm(p=2, dim=1, keepdim=True)
37
+
38
+ # Perform FAISS search for the top 1 similar image
39
+ D, I = index.search(output.cpu().numpy(), 1) # Changed from 5 to 1
40
+
41
+ # Load the list of image filenames (assuming you have image_list)
42
+ image_list = sorted(os.listdir(os.path.join(DATA_DIR, "images")))
43
+
44
+ # Get the path of the most similar image
45
+ similar_image_path = os.path.join(DATA_DIR, "images", image_list[int(I[0][0])])
46
+
47
+ # Return the image file itself
48
+ return FileResponse(similar_image_path, media_type="image/jpeg")
49
+ except Exception as e:
50
+ return JSONResponse(content={"error": str(e)}, status_code=500)
51
+
52
+ if __name__ == "__main__":
53
+ import uvicorn
54
+ uvicorn.run(app, host="0.0.0.0", port=8000)
data/.DS_Store ADDED
Binary file (6.15 kB). View file
 
data/images/00000003_(7).jpg ADDED
data/images/00000004.jpg ADDED
data/images/00000007_(5).jpg ADDED
data/images/00000010.jpg ADDED
data/images/00000013_(7).jpg ADDED
data/images/00000017_(5).jpg ADDED
data/images/00000038.jpg ADDED
data/images/00000048_(2).jpg ADDED
data/images/00000058_(2).jpg ADDED
data/images/00000066_(3).jpg ADDED
data/images/00000071_(7).jpg ADDED
data/images/00000076_(3).jpg ADDED
data/images/00000080_(4).jpg ADDED
data/images/00000083_(2).jpg ADDED
data/images/00000084_(6).jpg ADDED
data/images/00000090_(4).jpg ADDED
data/images/00000093_(2).jpg ADDED
data/images/00000094_(6).jpg ADDED
data/images/00000123_(4).jpg ADDED
data/images/00000127_(6).jpg ADDED
data/images/00000130_(2).jpg ADDED
data/images/00000133_(4).jpg ADDED
data/images/00000137_(6).jpg ADDED
data/images/00000142_(2).jpg ADDED
data/images/00000145_(6).jpg ADDED
data/images/00000152_(2).jpg ADDED
data/images/00000155_(6).jpg ADDED
data/images/00000158.jpg ADDED
data/images/00000164.jpg ADDED
data/images/00000170.jpg ADDED
data/images/00000189_(2).jpg ADDED
data/images/00000199_(2).jpg ADDED
data/images/00000209_(5).jpg ADDED
data/images/00000219_(5).jpg ADDED
data/images/00000223_(6).jpg ADDED
data/images/00000224_(2).jpg ADDED
data/images/00000233_(6).jpg ADDED
data/images/00000234_(2).jpg ADDED
data/images/00000241_(6).jpg ADDED
data/images/00000245_(4).jpg ADDED