devwildlifeai/wildlife_watcher_annotation_app_deva
0
1"""2TOC:30) IMPORTS 41) METADATA52) UPLOAD63) ANNOTATIONS7-1) MAIN8"""9 10# gradio run.py --demo-name=my_demo11 12##################################################13# 0) IMPORTS14##################################################15 16# baselayer17import os18from io import BytesIO19import argparse20 21# web22import gradio as gr23 24# image processing25from tkinter import Tk, filedialog26from pathlib import Path27from PIL import Image, ExifTags28from PIL.ExifTags import TAGS29 30# data science31import numpy as np32import pandas as pd33 34# export35import csv36 37 38# from transformers import AutoImageProcessor, AutoModelForImageClassification39# import torch40# Load model41# processor = AutoImageProcessor.from_pretrained("victor/animals-classifier")42# model = AutoModelForImageClassification.from_pretrained("victor/animals-classifier")43# model.eval()44 45##################################################46# 1) METADATA47##################################################48 49 50# this one works with PIL but we don't get all the metadata51def decode_utf16_little_endian(binary_data):52 try:53 # Decode the binary data as UTF-16 Little Endian54 # print(f"Test:{binary_data.decode('utf-16-le')}")55 # print(f"Type:{type(binary_data)}")56 decoded_text = binary_data.decode("utf-16-le").rstrip("\x00")57 except Exception as e:58 decoded_text = "Encoded"59 return decoded_text60 61 62'''63def get_exif(list_file_paths):64 metadata_all_file = {}65 df = pd.DataFrame()66 for file_path in list_file_paths:67 metadata = {}68 metadata["name"] = file_path.split("/")[-1]69 print(file_path)70 try:71 image = Image.open(file_path)72 exifdata = image._getexif()73 if exifdata is not None:74 print(len(exifdata.items()))75 for tagid, value in exifdata.items():76 # print(tagid, value)77 # print(f"Value:{value}")78 tagname = str(TAGS.get(tagid, tagid))79 # value = exifdata.get(tagid)80 # Handle binary data81 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 print(tagname)87 print(type(tagname))88 print(value)89 if type(tagname) is not str:90 print(">>>>>>>>>>>> here " + type(tagname))91 try:92 metadata[str(tagname)] = value93 except:94 try:95 metadata[repr(tagname)] = value96 except:97 pass98 else:99 metadata[tagname] = value100 """101 for key in metadata.keys():102 if type(key) is not str:103 try:104 metadata[str(key)] = metadata[key]105 except:106 try:107 metadata[repr(key)] = metadata[key]108 except:109 pass110 del metadata[key]111 """112 # print(f"\t{metadata}")113 print(metadata)114 print(pd.DataFrame([metadata]))115 df = pd.concat([df, pd.DataFrame([metadata])], ignore_index=True)116 # new_row = {"name": file_path, **metadata}117 # df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)118 # metadata_all_file[file_path] = metadata119 else:120 return "No EXIF metadata found."121 except Exception as e:122 return f"Error : {e}"123 print(pd.concat([df, pd.DataFrame([metadata])], ignore_index=True))124 print(f"FINAL DF \n \n \n {df}")125 return df126'''127import pandas as pd128from PIL import Image129from PIL.ExifTags import TAGS130 131 132def decode_utf16_little_endian(value):133 try:134 return value.decode("utf-16le").strip()135 except:136 return value # Fallback to the original value if decoding fails137 138 139def extract_particular_value_from_exif_file(metadata, tagname, value):140 pass141 142 143def get_exif(list_file_paths):144 df = pd.DataFrame()145 146 for file_path in list_file_paths:147 metadata = {"name": file_path.split("/")[-1]}148 print(file_path)149 150 try:151 image = Image.open(file_path)152 exifdata = image._getexif()153 154 if exifdata is not None:155 for tagid, value in exifdata.items():156 tagname = TAGS.get(tagid, str(tagid)) # Ensure tagname is a string157 print(type(tagname))158 if isinstance(value, bytes):159 value = decode_utf16_little_endian(value)160 if isinstance(value, dict):161 # for subkey, subvalue in value.items():162 # metadata[f"{tagname}_{subkey}"] = subvalue163 # else:164 # metadata[tagname] = value165 value = str(value)166 print(value)167 print(type(value))168 metadata[tagname] = value # All keys are now strings169 print(metadata)170 if all(isinstance(k, str) for k in metadata.keys()):171 df = pd.concat([df, pd.DataFrame([metadata])], ignore_index=True)172 else:173 print("Skipping metadata with non-string keys.")174 else:175 print(f"No EXIF metadata found for {file_path}")176 177 except Exception as e:178 print(f"Error processing {file_path}: {e}")179 180 print(f"FINAL DF:\n{df}")181 return df182 183 184##################################################185# 2) UPLOAD186##################################################187 188 189def get_file_names(files_):190 """191 Get a list of the name of files splitted to get only the proper name192 Input: Uploaded files193 Output: ['name of file 1', 'name of file 2']"""194 return [file.name for file in files_]195 196 197##################################################198# 3) ANNOTATIONS199##################################################200 201 202def get_annotation(files_):203 """204 Get the label and accuracy from pretrained (or futur custom model)205 Input: Uploaded files206 Output: Df that contains: file_name | label | accuracy207 """208 # df = pd.DataFrame(columns=["file_name", "label", "accuracy"])209 df_exif = get_exif(get_file_names(files_))210 return df_exif211 212 213def update_dataframe(df):214 return df # Simply return the modified dataframe215 216 217def df_to_csv(df_, encodings=None):218 """219 Get the df and convert it as an gradio file output ready for download220 Input: DF created221 Output: gr.File()222 """223 if encodings is None:224 encodings = ["utf-8", "utf-8-sig", "latin1", "iso-8859-1", "cp1252"]225 226 for encoding in encodings:227 try:228 df_.to_csv("output.csv", encoding=encoding, index=False)229 # print(f"File saved successfully with encoding: {encoding}")230 return gr.File(value="output.csv", visible=True)231 except Exception as e:232 print(f"Failed with encoding {encoding}: {e}")233 234 235##################################################236# -1) MAIN237##################################################238 239 240def process_files(files_):241 """242 Main function243 - Get uploaded files244 - Get annotations # TODO245 - Get the corresponding df246 - Get the csv output247 """248 df = get_annotation(files_)249 return df250 251 252with gr.Blocks() as interface:253 gr.Markdown("# Wildlife.ai Annotation tools")254 # Upload data255 with gr.Row():256 upload_btn = gr.UploadButton(257 "Upload raw data",258 file_types=["image", "video"],259 file_count="multiple",260 )261 update_btn = gr.Button("Modify raw data")262 download_raw_btn = gr.Button("Generate raw data as csv")263 download_modified_btn = gr.Button("Generate new data as a csv")264 # Get results265 gr.Markdown("## Results")266 df = gr.DataFrame(interactive=False)267 download_raw_btn.click(268 fn=df_to_csv,269 inputs=[df],270 outputs=gr.File(visible=False),271 )272 gr.Markdown("## Modified results")273 df_modified = gr.DataFrame(interactive=True)274 download_modified_btn.click(275 fn=df_to_csv,276 inputs=[df_modified],277 outputs=gr.File(visible=False),278 show_progress=False,279 )280 # gr.Markdown("## Extract as CSV")281 # Buttons282 upload_btn.upload(fn=process_files, inputs=upload_btn, outputs=df)283 update_btn.click(fn=update_dataframe, inputs=df, outputs=df_modified)284 285 286if __name__ == "__main__":287 interface.launch(debug=True)288 