Spaces:
Running
Running
admin
commited on
Commit
•
b3e0d76
1
Parent(s):
70a4862
upl base code
Browse files- .gitignore +5 -0
- README.md +2 -2
- app.py +170 -0
- requirements.txt +4 -0
.gitignore
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
data/*
|
2 |
+
test.py
|
3 |
+
__pycache__/*
|
4 |
+
flagged/*
|
5 |
+
rename.sh
|
README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
colorFrom: purple
|
5 |
colorTo: purple
|
6 |
sdk: gradio
|
|
|
1 |
---
|
2 |
+
title: EXIF Cleaner
|
3 |
+
emoji: 📷️
|
4 |
colorFrom: purple
|
5 |
colorTo: purple
|
6 |
sdk: gradio
|
app.py
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import imghdr
|
3 |
+
import shutil
|
4 |
+
import hashlib
|
5 |
+
import zipfile
|
6 |
+
import exifread
|
7 |
+
import gradio as gr
|
8 |
+
import pandas as pd
|
9 |
+
from PIL import Image
|
10 |
+
|
11 |
+
TMP_DIR = "./__pycache__"
|
12 |
+
|
13 |
+
|
14 |
+
def get_exif_data(origin_file_path):
|
15 |
+
with open(origin_file_path, "rb") as image_file:
|
16 |
+
tags = exifread.process_file(image_file)
|
17 |
+
|
18 |
+
output = ""
|
19 |
+
for key in tags.keys():
|
20 |
+
value = str(tags[key])
|
21 |
+
output += "{0}:{1}\n".format(key, value)
|
22 |
+
|
23 |
+
return output
|
24 |
+
|
25 |
+
|
26 |
+
def clear_exif_data(image_path: str, img_mode=None, outdir=""):
|
27 |
+
save_path = f"{TMP_DIR}/{outdir}output." + image_path.split(".")[-1]
|
28 |
+
try:
|
29 |
+
img = Image.open(image_path)
|
30 |
+
data = list(img.getdata())
|
31 |
+
if img_mode:
|
32 |
+
save_path = (
|
33 |
+
f"{TMP_DIR}/{outdir}{hashlib.md5(image_path.encode()).hexdigest()}.jpg"
|
34 |
+
)
|
35 |
+
else:
|
36 |
+
img_mode = img.mode
|
37 |
+
|
38 |
+
img_without_exif = Image.new(img_mode, img.size)
|
39 |
+
img_without_exif.putdata(data)
|
40 |
+
img_without_exif.save(save_path)
|
41 |
+
|
42 |
+
except Exception as e:
|
43 |
+
print(f"\n{image_path} Error: {e}")
|
44 |
+
|
45 |
+
return save_path
|
46 |
+
|
47 |
+
|
48 |
+
def unzip_file(zip_path: str, extract_to=f"{TMP_DIR}/inputs"):
|
49 |
+
if not os.path.exists(extract_to):
|
50 |
+
os.makedirs(extract_to)
|
51 |
+
|
52 |
+
# 打开ZIP文件
|
53 |
+
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
54 |
+
# 解压文件
|
55 |
+
zip_ref.extractall(extract_to)
|
56 |
+
|
57 |
+
return extract_to
|
58 |
+
|
59 |
+
|
60 |
+
def find_files(directory: str):
|
61 |
+
found_files = []
|
62 |
+
for root, _, files in os.walk(directory):
|
63 |
+
for file in files:
|
64 |
+
fpath = os.path.join(root, file).replace("\\", "/")
|
65 |
+
if imghdr.what(fpath) != None:
|
66 |
+
found_files.append(fpath)
|
67 |
+
|
68 |
+
return found_files
|
69 |
+
|
70 |
+
|
71 |
+
def compress(folder_path=f"{TMP_DIR}/outputs", zip_file_path=f"{TMP_DIR}/outputs.zip"):
|
72 |
+
if not os.path.exists(folder_path):
|
73 |
+
print(f"Error: Folder '{folder_path}' does not exist.")
|
74 |
+
return
|
75 |
+
|
76 |
+
with zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_DEFLATED) as zipf:
|
77 |
+
for root, _, files in os.walk(folder_path):
|
78 |
+
for file in files:
|
79 |
+
file_path = os.path.join(root, file)
|
80 |
+
relative_path = os.path.relpath(file_path, folder_path)
|
81 |
+
zipf.write(
|
82 |
+
file_path,
|
83 |
+
arcname=os.path.join(os.path.basename(folder_path), relative_path),
|
84 |
+
)
|
85 |
+
|
86 |
+
return zip_file_path
|
87 |
+
|
88 |
+
|
89 |
+
def infer(image_path: str, original_ext: bool):
|
90 |
+
if not image_path or imghdr.what(image_path) == None:
|
91 |
+
return None, "Please input a picture!"
|
92 |
+
|
93 |
+
if os.path.exists(TMP_DIR):
|
94 |
+
shutil.rmtree(TMP_DIR)
|
95 |
+
|
96 |
+
os.makedirs(TMP_DIR, exist_ok=True)
|
97 |
+
return clear_exif_data(
|
98 |
+
image_path, img_mode="RGB" if not original_ext else None
|
99 |
+
), get_exif_data(image_path)
|
100 |
+
|
101 |
+
|
102 |
+
def batch_infer(imgs_zip: str, original_ext: bool):
|
103 |
+
if not imgs_zip:
|
104 |
+
return None, pd.DataFrame([{"Warning": "Please upload pictures zip!"}])
|
105 |
+
|
106 |
+
if os.path.exists(TMP_DIR):
|
107 |
+
shutil.rmtree(TMP_DIR)
|
108 |
+
|
109 |
+
os.makedirs(f"{TMP_DIR}/outputs", exist_ok=True)
|
110 |
+
extract_to = unzip_file(imgs_zip)
|
111 |
+
imgs = find_files(extract_to)
|
112 |
+
mode = "RGB" if not original_ext else None
|
113 |
+
exifs = []
|
114 |
+
for img in imgs:
|
115 |
+
clear_exif_data(img, img_mode=mode, outdir="outputs/")
|
116 |
+
exifs.append({"filename": os.path.basename(img), "exif": get_exif_data(img)})
|
117 |
+
|
118 |
+
if not exifs:
|
119 |
+
exifs = [{"Warning": "No picture in the zip"}]
|
120 |
+
|
121 |
+
return compress(), pd.DataFrame(exifs)
|
122 |
+
|
123 |
+
|
124 |
+
if __name__ == "__main__":
|
125 |
+
with gr.Blocks() as iface:
|
126 |
+
with gr.Tab("Process single picture"):
|
127 |
+
gr.Interface(
|
128 |
+
fn=infer,
|
129 |
+
inputs=[
|
130 |
+
gr.File(label="Upload picture", file_types=["image/*"]),
|
131 |
+
gr.Checkbox(
|
132 |
+
label="Export original format",
|
133 |
+
value=False,
|
134 |
+
),
|
135 |
+
],
|
136 |
+
outputs=[
|
137 |
+
gr.Image(
|
138 |
+
label="Download cleaned picture",
|
139 |
+
type="filepath",
|
140 |
+
),
|
141 |
+
gr.Textbox(label="EXIF", show_copy_button=True),
|
142 |
+
],
|
143 |
+
allow_flagging="never",
|
144 |
+
)
|
145 |
+
|
146 |
+
with gr.Tab("Batch processor"):
|
147 |
+
gr.Interface(
|
148 |
+
fn=batch_infer,
|
149 |
+
inputs=[
|
150 |
+
gr.File(
|
151 |
+
label="Upload pictures zip",
|
152 |
+
file_types=[".zip"],
|
153 |
+
),
|
154 |
+
gr.Checkbox(
|
155 |
+
label="Export original format",
|
156 |
+
value=False,
|
157 |
+
),
|
158 |
+
],
|
159 |
+
outputs=[
|
160 |
+
gr.File(
|
161 |
+
label="Download cleaned pictures",
|
162 |
+
type="filepath",
|
163 |
+
),
|
164 |
+
gr.Dataframe(label="EXIF list"),
|
165 |
+
],
|
166 |
+
description="When uploading pictures zip, please make sure the zip is completely uploaded before clicking Submit",
|
167 |
+
allow_flagging="never",
|
168 |
+
)
|
169 |
+
|
170 |
+
iface.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Pillow
|
2 |
+
gradio
|
3 |
+
exifread
|
4 |
+
tqdm
|