Skip to content

Commit 62cf17c

Browse files
committed
updaging fastdup to 1.85
1 parent 12ce82f commit 62cf17c

23 files changed

+1894
-193
lines changed

fastdup/__init__.py

+199-56
Large diffs are not rendered by default.

fastdup/ascii_art.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import random
2+
3+
ascii_arts = [
4+
"""
5+
:++. ...
6+
;&&$+. ;x: ;;;
7+
.$&+ X&x ;;;
8+
X$&&&$$; :$&&$+. ;$x .x&&&X: ;$&&&$$$: :;;;;:. ;;; :;;. .;;. :;; :;;;;;.
9+
+x&&Xxx: :$&&Xx++X&&$&$ .&&$+;+$&&; :x&&$xxx: .;;;;;:;;;;;;; :;;. .;;: :;;;;;;:;;;;;:
10+
.$&; :$&X +&&$ ;&$. ;XX X&x .;;; ;;;; :;;. .;;: :;;;. :;;:
11+
.$&; +&&. x&$ .$&&$+. X&x ;;; ;;; :;;. .;;: :;;. ;;;
12+
.$&; +&&. x&$ ;X&&&&$. X&x ;;; ;;; :;;. .;;: :;; ;;;
13+
.$&; :&&; :&&$ .:. x&& X&x :;;; :;;; .;;: :;;: :;;; .;;;
14+
.$&; +&&$; :X&&&$ ;&&+. .X&& X&&. :;;;: :;;;;; ;;;;. .;;;;: :;;;;:. .;;;;
15+
.$&; +&&&&&&X.+&$ .X&&&&&&+ X&&&&; :;;;;;;;.;;; .;;;;;;;:;;: :;; :;;;;;;;.
16+
:;;
17+
:;;
18+
:;;
19+
.::
20+
""",
21+
"""
22+
23+
ad88 88
24+
d8" ,d 88
25+
88 88 88
26+
MM88MMM ,adPPYYba, ,adPPYba, MM88MMM ,adPPYb,88 88 88 8b,dPPYba,
27+
88 "" `Y8 I8[ "" 88 a8" `Y88 88 88 88P' "8a
28+
88 ,adPPPPP88 `"Y8ba, 88 8b 88 88 88 88 d8
29+
88 88, ,88 aa ]8I 88, "8a, ,d88 "8a, ,a88 88b, ,a8"
30+
88 `"8bbdP"Y8 `"YbbdP"' "Y888 `"8bbdP"Y8 `"YbbdP'Y8 88`YbbdP"'
31+
88
32+
88
33+
"""
34+
35+
]
36+
37+
38+
def get_ascii_art():
39+
choice = random.randint(0, len(ascii_arts) - 1)
40+
return ascii_arts[choice]

fastdup/captions.py

+63-28
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
import torch
12
from fastdup.sentry import fastdup_capture_exception
23
from fastdup.definitions import MISSING_LABEL
34
from fastdup.galleries import fastdup_imread
45
import cv2
6+
from tqdm import tqdm
57

8+
device_to_captioner = {}
9+
10+
def init_captioning(model_name='automatic', device='cpu', batch_size=8, max_new_tokens=20,
11+
use_float_16=True):
612

7-
def generate_labels(filenames, model_name='automatic', device = 'cpu', batch_size=8):
813
'''
914
This function generates captions for a given set of images, and takes the following arguments:
1015
- filenames: the list of images passed to the function
@@ -15,64 +20,82 @@ def generate_labels(filenames, model_name='automatic', device = 'cpu', batch_siz
1520
- BLIP: 'blip'
1621
- batch_size: the size of image batches to caption (default: 8)
1722
- device: whether to use a GPU (default: -1, CPU only ; set to 0 for GPU)
23+
- max_bew_tokens: set the number of allowed tokens
1824
'''
25+
26+
global device_to_captioner
1927
# use GPU if device is specified
2028
if device == 'gpu':
2129
device = 0
2230
elif device == 'cpu':
2331
device = -1
32+
use_float_16 = False
2433
else:
25-
assert False, "Incompatible device name entered. Available device names are gpu and cpu."
34+
assert False, "Incompatible device name entered {device}. Available device names are gpu and cpu."
2635

2736
# confirm necessary dependencies are installed, and import them
2837
try:
2938
from transformers import pipeline
3039
from transformers.utils import logging
31-
logging.set_verbosity_info()
32-
import torch
33-
from PIL import Image
34-
from tqdm import tqdm
40+
logging.set_verbosity(50)
41+
3542
except Exception as e:
3643
fastdup_capture_exception("Auto generate labels", e)
3744
print("Auto captioning requires an installation of the following libraries:\n")
38-
print(" huggingface transformers\n pytorch\n pillow\n tqdm\n")
39-
print("to install, use `pip install transformers torch pillow tqdm`")
40-
return [MISSING_LABEL] * len(filenames)
45+
print(" huggingface transformers\n pytorch\n")
46+
print(" to install, use `pip3 install transformers torch`")
47+
raise
4148

4249
# dictionary of captioning models
4350
models = {
4451
'automatic': "nlpconnect/vit-gpt2-image-captioning",
4552
'vitgpt2': "nlpconnect/vit-gpt2-image-captioning",
46-
'blip2': "Salesforce/blip2-opt-2.7b",
53+
'blip-2': "Salesforce/blip2-opt-2.7b",
4754
'blip': "Salesforce/blip-image-captioning-large"
4855
}
49-
56+
assert model_name in models.keys(), f"Unknown captioning model {model_name} allowed models are {models.keys()}"
5057
model = models[model_name]
58+
has_gpu = torch.cuda.is_available()
59+
captioner = pipeline("image-to-text", model=model, device=device if has_gpu else "cpu", max_new_tokens=max_new_tokens,
60+
torch_dtype=torch.float16 if use_float_16 else torch.float32)
61+
device_to_captioner[device] = captioner
5162

52-
# generate captions
53-
try:
54-
captioner = pipeline("image-to-text", model=model, device=device)
55-
56-
captions = []
57-
58-
for pred in captioner(filenames, batch_size=batch_size):
59-
#caption = pred['generated_text']
60-
caption = ''.join([d['generated_text'] for d in pred])
61-
captions.append(caption)
63+
return captioner
6264

65+
def generate_labels(filenames, model_name='automatic', device = 'cpu', batch_size=8, max_new_tokens=20, use_float_16=True):
66+
global device_to_captioner
67+
if device not in device_to_captioner:
68+
captioner = init_captioning(model_name, device, batch_size, max_new_tokens, use_float_16)
69+
else:
70+
captioner = device_to_captioner[device]
6371

64-
'''for image_path in tqdm(filenames):
65-
img = Image.open(image_path)
66-
pred = captioner(img)
67-
caption = pred[0]['generated_text']
68-
captions.append(caption)'''
69-
return captions
70-
72+
captions = []
73+
# generate captions
74+
try:
75+
for i in tqdm(range(0, len(filenames), batch_size)):
76+
chunk = filenames[i:i + batch_size]
77+
try:
78+
for pred in captioner(chunk, batch_size=batch_size):
79+
charstring = '' if model_name != 'blip' else ' '
80+
caption = charstring.join([d['generated_text'] for d in pred])
81+
# Split the sentence into words
82+
words = caption.split()
83+
# Filter out words containing '#'
84+
filtered_words = [word for word in words if '#' not in word]
85+
# Join the filtered words back into a sentence
86+
caption = ' '.join(filtered_words)
87+
caption = caption.strip()
88+
captions.append(caption)
89+
except Exception as ex:
90+
print("Failed to caption chunk", chunk[:5], ex)
91+
captions.extend([MISSING_LABEL] * len(chunk))
7192

7293
except Exception as e:
7394
fastdup_capture_exception("Auto caption image", e)
7495
return [MISSING_LABEL] * len(filenames)
7596

97+
return captions
98+
7699

77100
def generate_vqa_labels(filenames, text, kwargs):
78101
# confirm necessary dependencies are installed, and import them
@@ -156,3 +179,15 @@ def generate_age_labels(filenames, kwargs):
156179
fastdup_capture_exception("Age label", e)
157180
return [MISSING_LABEL] * len(filenames)
158181

182+
if __name__ == "__main__":
183+
import fastdup
184+
from fastdup.captions import generate_labels
185+
file = "/Users/dannybickson/visual_database/cxx/unittests/two_images/"
186+
import os
187+
files = os.listdir(file)
188+
files = [os.path.join(file, f) for f in files]
189+
ret = generate_labels(files, model_name='blip')
190+
assert(len(ret) == 2)
191+
print(ret)
192+
for r in ret:
193+
assert "shelf" in r or "shelves" in r or "store" in r

fastdup/coco.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# FastDup Software, (C) copyright 2022 Dr. Amir Alush and Dr. Danny Bickson.
33
# This software is free for non-commercial and academic usage under the Creative Common Attribution-NonCommercial-NoDerivatives
44
# 4.0 International license. Please reach out to [email protected] for licensing options.
5-
5+
from fastdup.sentry import fastdup_capture_exception
66

77
import os
88
cat = {0: u'__background__',
@@ -103,8 +103,8 @@ def read_coco_labels(path):
103103
#print('cat is', cat[int_cat])
104104
label_dict[os.path.join(path.replace('labels','images'),f).replace('.txt','.jpg')] = cat[int_cat]
105105
except Exception as ex:
106-
print('Failed to read file ', os.path.join(path, f), ' with error: ', ex)
107-
106+
fastdup_capture_exception(f'Failed to read coco file {os.path.join(path, f)}', ex)
107+
108108
return label_dict
109109

110110

fastdup/cvat.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ def copy_images_and_zip(files, save_path):
277277
rel_path = os.path.relpath(f, save_path)
278278
zip_path = os.path.join('data', rel_path)
279279
zipf.write(f, zip_path)
280-
assert os.path.exists(local_file)
281-
print('Zipped file:', local_file, ' for cvat')
280+
assert os.path.exists(zip_path)
281+
print('Zipped file:', zip_path, ' for cvat')
282282
return 0
283283

284284

fastdup/datasets.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import logging
88
from typing import Optional, Any
99
from concurrent.futures import ThreadPoolExecutor
10-
10+
from fastdup.sentry import fastdup_capture_exception
1111

1212
# Configure logging
1313
logging.basicConfig(level=logging.INFO)
@@ -67,7 +67,7 @@ def __init__(
6767
dataset_name, split=split, cache_dir=self.cache_dir, **kwargs
6868
)
6969
except Exception as e:
70-
logging.error(f"Error loading dataset: {e}")
70+
fastdup_capture_exception(f"dataset/__init__", e)
7171
return
7272

7373
super().__init__(
@@ -87,7 +87,7 @@ def __init__(
8787
current_hash: str = self._generate_img_folder_hash()
8888
previous_hash: Optional[str] = self._retrieve_cached_metadata()
8989
except Exception as e:
90-
logging.error(f"Error generating or retrieving hash: {e}")
90+
fastdup_capture_exception(f"Error generating or retrieving hash:", e)
9191
return
9292

9393
if (current_hash != previous_hash) or reconvert_jpg:
@@ -122,6 +122,7 @@ def _cache_metadata(self, cache_hash: str) -> None:
122122
with open(cache_file, "w") as f:
123123
f.write(cache_hash)
124124
except Exception as e:
125+
fastdup_capture_exception("error extracting metadata", e)
125126
logging.error(f"Error caching metadata: {e}")
126127

127128
def _retrieve_cached_metadata(self) -> Optional[str]:
@@ -131,6 +132,7 @@ def _retrieve_cached_metadata(self) -> Optional[str]:
131132
with open(cache_file, "r") as f:
132133
return f.read()
133134
except Exception as e:
135+
fastdup_capture_exception("Error opening cache file ", e)
134136
logging.error(f"Error reading cached metadata: {e}")
135137
return None
136138

@@ -150,6 +152,7 @@ def _save_single_image(self, idx: int, item: dict, pbar) -> None:
150152
image.save(os.path.join(label_dir, f"{idx}.jpg"))
151153
pbar.update(1)
152154
except Exception as e:
155+
fastdup_capture_exception("Error saving an image", e)
153156
logging.error(f"Error in saving image at index {idx}: {e}")
154157

155158
def _save_as_image_files(self) -> None:
@@ -177,6 +180,7 @@ def annotations(self) -> pd.DataFrame:
177180
filenames.append(subentry.path)
178181
labels.append(label)
179182
except Exception as e:
183+
fastdup_capture_exception("Error generating annotation", e)
180184
logging.error(f"Error in generating annotations: {e}")
181185
return pd.DataFrame()
182186

fastdup/definitions.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import tempfile
55

66
FILENAME_SIMILARITY = "similarity.csv"
7+
FILENAME_SEARCH = "search.csv"
78
FILENAME_OUTLIERS = "outliers.csv"
89
FILENAME_NNF_INDEX = "nnf.index"
910
FILENAME_FEATURES = "features.dat"
@@ -49,7 +50,7 @@
4950

5051
DEFUALT_METRIC_ZERO = 0
5152
DEFAULT_METRIC_MINUS_ONE = -1
52-
VERSION__ = "1.39"
53+
VERSION__ = "1.86"
5354

5455
GITHUB_URL = "https://github.com/visual-layer/fastdup/issues"
5556

@@ -58,8 +59,8 @@
5859
"and special care needs to select the right backend for your OS/Hardware combination. You can install matplot lib using "
5960
"python3.8 -m pip install matplotlib matplotlib-inline. (change the python3.8 to your python version). "
6061

61-
SUPPORTED_IMG_FORMATS = [".png", ".jpg", ".jpeg", ".giff", ".jpeg", ".tif", ".tiff", ".heic", ".heif", ".bmp", ".webp"]
62-
SUPPORTED_VID_FORMATS = ["mp4", ".avi"]
62+
SUPPORTED_IMG_FORMATS = [".png", ".jpg", ".jpeg", ".giff", ".jpeg", ".tif", ".tiff", ".heic", ".heif", ".bmp", ".webp", ".jp2"]
63+
SUPPORTED_VID_FORMATS = [".mp4", ".avi", ".dav", ".m4a", ".m4v", ".mov"]
6364

6465
RUN_ALL = 0
6566
RUN_EXTRACT = 1

0 commit comments

Comments
 (0)