Deva commited on
Commit
d01f802
·
1 Parent(s): 2ceb61b

Feature Get exif readable and modifiable and extract

Browse files
Files changed (2) hide show
  1. .gitignore +2 -1
  2. app.py +143 -28
.gitignore CHANGED
@@ -1,2 +1,3 @@
1
- test_images/*
 
2
  *.csv
 
1
+ data/*
2
+ notebooks/*
3
  *.csv
app.py CHANGED
@@ -1,28 +1,119 @@
1
- import gradio as gr
2
- import numpy as np
3
- import pandas as pd
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import os
5
- from tkinter import Tk, filedialog
 
 
 
6
  import gradio as gr
 
 
 
7
  from pathlib import Path
8
- from io import BytesIO
 
9
 
10
- # from transformers import AutoImageProcessor, AutoModelForImageClassification
11
- # import torch
 
12
 
13
 
 
 
14
  # Load model
15
  # processor = AutoImageProcessor.from_pretrained("victor/animals-classifier")
16
  # model = AutoModelForImageClassification.from_pretrained("victor/animals-classifier")
17
  # model.eval()
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  def get_file_names(files_):
21
  """
22
  Get a list of the name of files splitted to get only the proper name
23
  Input: Uploaded files
24
  Output: ['name of file 1', 'name of file 2']"""
25
- return [file.name.split("/")[-1] for file in files_]
 
 
 
 
 
26
 
27
 
28
  def get_annotation(files_):
@@ -31,11 +122,14 @@ def get_annotation(files_):
31
  Input: Uploaded files
32
  Output: Df that contains: file_name | label | accuracy
33
  """
34
- df = pd.DataFrame(columns=["file_name", "label", "accuracy"])
35
- df["file_name"] = get_file_names(files_)
36
- df["label"] = "incoming" # TODO
37
- df["accuracy"] = 100 # TODO
38
- return df
 
 
 
39
 
40
 
41
  def df_to_csv(df_):
@@ -48,6 +142,11 @@ def df_to_csv(df_):
48
  return gr.File(value="output.csv", visible=True)
49
 
50
 
 
 
 
 
 
51
  def process_files(files_):
52
  """
53
  Main function
@@ -57,29 +156,45 @@ def process_files(files_):
57
  - Get the csv output
58
  """
59
  df = get_annotation(files_)
60
- output_csv = df_to_csv(df)
61
- print(df)
62
- print(output_csv)
63
- print("test")
64
- return [df, output_csv]
65
-
66
-
67
- title = "Demo: zero-shot depth estimation with DPT + 3D Point Cloud"
68
- description = "This demo is a variation from the original <a href='https://huggingface.co/spaces/nielsr/dpt-depth-estimation' target='_blank'>DPT Demo</a>. It uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object."
69
 
70
 
71
  with gr.Blocks() as interface:
 
 
72
  with gr.Row():
73
  upload_btn = gr.UploadButton(
74
- "Click to Upload a File",
75
  file_types=["image", "video"],
76
  file_count="multiple",
77
  )
78
- # file_output = gr.File()
79
- # output_df = gr.DataFrame()
80
- upload_btn.upload(
81
- fn=process_files, inputs=upload_btn, outputs=[gr.DataFrame(), gr.Files()]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  )
 
 
 
 
83
 
84
 
85
- interface.launch(debug=True)
 
 
 
 
1
+ """
2
+ TOC:
3
+ 0) IMPORTS
4
+ 1) METADATA
5
+ 2) UPLOAD
6
+ 3) ANNOTATIONS
7
+ -1) MAIN
8
+ """
9
+
10
+ # gradio run.py --demo-name=my_demo
11
+
12
+ ##################################################
13
+ # 0) IMPORTS
14
+ ##################################################
15
+
16
+ # baselayer
17
  import os
18
+ from io import BytesIO
19
+ import argparse
20
+
21
+ # web
22
  import gradio as gr
23
+
24
+ # image processing
25
+ from tkinter import Tk, filedialog
26
  from pathlib import Path
27
+ from PIL import Image, ExifTags
28
+ from PIL.ExifTags import TAGS
29
 
30
+ # data science
31
+ import numpy as np
32
+ import pandas as pd
33
 
34
 
35
+ # from transformers import AutoImageProcessor, AutoModelForImageClassification
36
+ # import torch
37
  # Load model
38
  # processor = AutoImageProcessor.from_pretrained("victor/animals-classifier")
39
  # model = AutoModelForImageClassification.from_pretrained("victor/animals-classifier")
40
  # model.eval()
41
 
42
+ ##################################################
43
+ # 1) METADATA
44
+ ##################################################
45
+
46
+
47
+ # this one works with PIL but we don't get all the metadata
48
+ def decode_utf16_little_endian(binary_data):
49
+ try:
50
+ # Decode the binary data as UTF-16 Little Endian
51
+ # print(f"Test:{binary_data.decode('utf-16-le')}")
52
+ # print(f"Type:{type(binary_data)}")
53
+ decoded_text = binary_data.decode("utf-16-le").rstrip("\x00")
54
+ return decoded_text
55
+ except Exception as e:
56
+ return f"Error decoding UTF-16 LE: {e}"
57
+
58
+
59
+ def get_exif(list_file_paths):
60
+ metadata_all_file = {}
61
+ df = pd.DataFrame()
62
+ for file_path in list_file_paths:
63
+ metadata = {}
64
+ print(file_path)
65
+ try:
66
+ # file_path = file_path_.split("/")[-1]
67
+ # df = pd.DataFrame()
68
+ # df['file_name'] = [file_path]
69
+ # print(df)
70
+ # print("inside the tryin")
71
+ image = Image.open(file_path)
72
+ exifdata = image._getexif()
73
+ if exifdata is not None:
74
+ # print(metadata)
75
+ for tagid, value in exifdata.items():
76
+ # print(tagid, value)
77
+ # print(f"Value:{value}")
78
+ tagname = TAGS.get(tagid, tagid)
79
+ # value = exifdata.get(tagid)
80
+ # Handle binary data
81
+ if isinstance(value, bytes):
82
+ # print(f"Value bytes {value}")
83
+ # print(f"Value bytes {type(value)}")
84
+ # print(f"Value str {decode_utf16_little_endian(value)}")
85
+ value = decode_utf16_little_endian(value)
86
+ metadata[tagname] = value
87
+ # print(f"\t{metadata}")
88
+ new_row = {"name": file_path, **metadata}
89
+ df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)
90
+ # metadata_all_file[file_path] = metadata
91
+ else:
92
+ return "No EXIF metadata found."
93
+ except Exception as e:
94
+ return f"Error : {e}"
95
+ print(df)
96
+ df["name"] = df["name"].apply(lambda filepath: filepath.split("/")[-1])
97
+ print(df)
98
+ return df
99
+
100
+
101
+ ##################################################
102
+ # 2) UPLOAD
103
+ ##################################################
104
+
105
 
106
  def get_file_names(files_):
107
  """
108
  Get a list of the name of files splitted to get only the proper name
109
  Input: Uploaded files
110
  Output: ['name of file 1', 'name of file 2']"""
111
+ return [file.name for file in files_]
112
+
113
+
114
+ ##################################################
115
+ # 3) ANNOTATIONS
116
+ ##################################################
117
 
118
 
119
  def get_annotation(files_):
 
122
  Input: Uploaded files
123
  Output: Df that contains: file_name | label | accuracy
124
  """
125
+ # df = pd.DataFrame(columns=["file_name", "label", "accuracy"])
126
+ df_exif = get_exif(get_file_names(files_))
127
+ print(df_exif)
128
+ return df_exif
129
+
130
+
131
+ def update_dataframe(df):
132
+ return df # Simply return the modified dataframe
133
 
134
 
135
  def df_to_csv(df_):
 
142
  return gr.File(value="output.csv", visible=True)
143
 
144
 
145
+ ##################################################
146
+ # -1) MAIN
147
+ ##################################################
148
+
149
+
150
  def process_files(files_):
151
  """
152
  Main function
 
156
  - Get the csv output
157
  """
158
  df = get_annotation(files_)
159
+ return df
 
 
 
 
 
 
 
 
160
 
161
 
162
  with gr.Blocks() as interface:
163
+ gr.Markdown("# Wildlife.ai Annotation tools")
164
+ # Upload data
165
  with gr.Row():
166
  upload_btn = gr.UploadButton(
167
+ "Upload raw data",
168
  file_types=["image", "video"],
169
  file_count="multiple",
170
  )
171
+ update_btn = gr.Button("Modify raw data")
172
+ download_raw_btn = gr.Button("Generate raw data as csv")
173
+ download_modified_btn = gr.Button("Generate new data as a csv")
174
+ # Get results
175
+ gr.Markdown("## Results")
176
+ df = gr.DataFrame(interactive=False)
177
+ download_raw_btn.click(
178
+ fn=df_to_csv,
179
+ inputs=df,
180
+ outputs=gr.File(visible=False),
181
+ show_progress=False,
182
+ )
183
+ gr.Markdown("## Modified results")
184
+ df_modified = gr.DataFrame(interactive=True)
185
+ download_modified_btn.click(
186
+ fn=df_to_csv,
187
+ inputs=df_modified,
188
+ outputs=gr.File(visible=False),
189
+ show_progress=False,
190
  )
191
+ # gr.Markdown("## Extract as CSV")
192
+ # Buttons
193
+ upload_btn.upload(fn=process_files, inputs=upload_btn, outputs=df)
194
+ update_btn.click(fn=update_dataframe, inputs=df, outputs=df_modified)
195
 
196
 
197
+ if __name__ == "__main__":
198
+ # file_path = "../data/rat1.jpg"
199
+ # get_exif(file_path)
200
+ interface.launch(debug=True)