-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrename.py
132 lines (105 loc) · 4.16 KB
/
rename.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import os
import sys
from base64 import b64encode
from io import BytesIO
import ollama
from PIL import Image
def load_image(image_path: str) -> Image.Image:
image = Image.open(image_path)
if image.mode == "P" and "transparency" in image.info:
image = image.convert("RGBA")
return image
def encode_image(image: Image.Image) -> str:
buffered = BytesIO()
image.save(buffered, format=image.format)
return b64encode(buffered.getvalue()).decode("utf-8")
def generate_filename_from_answer(answer: str) -> str:
# Remove file extensions if present
answer = answer.rsplit(".", 1)[0]
filename = "".join(char.lower() if char.isalnum() else "_" for char in answer)
words = filter(None, filename.split("_"))
filtered_words = []
for word in words:
if not word.isdigit():
filtered_words.append(word)
if not filtered_words:
return "unnamed_image" # Fallback if all words are numbers
return "_".join(filtered_words)
def generate_filename(image_path: str) -> str:
image = load_image(image_path)
encoded_image = encode_image(image)
response = ollama.chat(
model="llava-llama3",
messages=[
{
"role": "user",
"content": (
"Analyze the image and generate a concise, specific filename "
"that uniquely describes its content. Rules:\n"
"1. No special characters, only lowercase letters and underscores\n"
"2. Include only key elements\n"
"3. Prefer noun-verb format\n"
"4. Focus on main subject(s) and any notable action\n"
"5. Include distinctive visual elements or style if relevant\n"
"6. Avoid generic terms, numbers, or dates\n"
"The filename should clearly distinguish this image in a large collection. "
"Only output the filename and nothing else."
),
"images": [encoded_image],
}
],
)
answer = response["message"]["content"]
return generate_filename_from_answer(answer)
def get_new_path(image_path: str, filename: str) -> str:
directory = os.path.dirname(image_path)
base_path = os.path.join(directory, filename)
extension = os.path.splitext(image_path)[1]
new_path = base_path + extension
counter = 1
while os.path.exists(new_path):
new_path = f"{base_path}_{counter}{extension}"
counter += 1
return new_path
def rename_image(image_path: str, new_path: str) -> None:
try:
os.rename(image_path, new_path)
except Exception as e:
print(f"Error renaming image {image_path} to {new_path}: {e}")
def process_image(image_path: str, index: int, total: int) -> None:
try:
filename = generate_filename(image_path)
new_path = get_new_path(image_path, filename)
if new_path != image_path:
rename_image(image_path, new_path)
print(f"{index}/{total} Image renamed to: {new_path}")
else:
print(f"{index}/{total} Image already has the suggested name: {image_path}")
except Exception as e:
print(f"Error processing image {image_path}: {e}")
def process_folder(folder_path: str) -> None:
supported_extensions = (".jpg", ".jpeg", ".png", ".bmp", ".gif")
image_paths = [
os.path.join(root, file)
for root, _, files in os.walk(folder_path)
for file in files
if file.lower().endswith(supported_extensions)
]
image_count = len(image_paths)
print(f"Found {image_count} image{'s' if image_count != 1 else ''} in the folder.")
for index, image_path in enumerate(image_paths, start=1):
process_image(image_path, index, image_count)
def main(path: str) -> None:
if os.path.isfile(path):
process_image(path, 1, 1)
elif os.path.isdir(path):
process_folder(path)
else:
print(f"Invalid path: {path}")
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python test.py <image_path_or_folder_path>")
sys.exit(1)
path = sys.argv[1]
main(path)