AmirMoris commited on
Commit
5d09ff5
·
1 Parent(s): dbc336b
Files changed (4) hide show
  1. GoogleDrive_API.py +80 -0
  2. Kaggle_API.py +162 -0
  3. app.py +89 -0
  4. requirements.txt +3 -0
GoogleDrive_API.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from google.oauth2 import service_account
3
+ from googleapiclient.discovery import build
4
+ from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
5
+
6
+
7
+ class GoogleDrive_API:
8
+ def __init__(self):
9
+ self.SCOPES = ["https://www.googleapis.com/auth/drive"]
10
+ self.SERVICE_ACCOUNT_FILE = "service_account.json"
11
+ self.PARENT_FOLDER_ID = "1r-MlnEpWHx3b1fxHDnHcZ2-Wh_Y89676"
12
+ self.service = self.authenticate()
13
+ self.clear_files()
14
+
15
+ def authenticate(self):
16
+ credentials = service_account.Credentials.from_service_account_file(
17
+ self.SERVICE_ACCOUNT_FILE, scopes=self.SCOPES
18
+ )
19
+ service = build("drive", "v3", credentials=credentials)
20
+
21
+ return service
22
+
23
+ def get_files(self):
24
+ # List all files in the folder
25
+ results = (
26
+ self.service.files()
27
+ .list(
28
+ q=f"'{self.PARENT_FOLDER_ID}' in parents and trashed=false",
29
+ fields="files(id, name)",
30
+ )
31
+ .execute()
32
+ )
33
+ return results.get("files", [])
34
+
35
+ def clear_files(self):
36
+ items = self.get_files()
37
+
38
+ # Delete each file
39
+ for item in items:
40
+ file_id = item["id"]
41
+ self.service.files().delete(fileId=file_id).execute()
42
+
43
+ def upload_file(self, file_name, file_path):
44
+ file_metadata = {
45
+ "name": file_name,
46
+ "parents": [self.PARENT_FOLDER_ID],
47
+ }
48
+ media = MediaFileUpload(file_path)
49
+ file = (
50
+ self.service.files()
51
+ .create(body=file_metadata, media_body=media, fields="id")
52
+ .execute()
53
+ )
54
+ print(rf"{file_path} uploaded. ID:", file.get("id"))
55
+
56
+ def download_file(self, file_name, file_path):
57
+ results = (
58
+ self.service.files()
59
+ .list(
60
+ q=f"'{self.PARENT_FOLDER_ID}' in parents and name='{file_name}' and trashed=false",
61
+ fields="files(id)",
62
+ )
63
+ .execute()
64
+ )
65
+ items = results.get("files", [])
66
+
67
+ if items:
68
+ # Get the file ID
69
+ file_id = items[0]["id"]
70
+
71
+ request = self.service.files().get_media(fileId=file_id)
72
+
73
+ with open(file_path, "wb") as file:
74
+ downloader = MediaIoBaseDownload(file, request)
75
+ done = False
76
+ while not done:
77
+ status, done = downloader.next_chunk()
78
+ print(f"Download {int(status.progress() * 100)}%.")
79
+ else:
80
+ print(rf"Fine {file_name} is Not Found")
Kaggle_API.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+ import json
5
+ import time
6
+ from PIL import Image
7
+
8
+ from GoogleDrive_API import GoogleDrive_API
9
+
10
+
11
+ class API_Connection:
12
+ def __init__(self, kaggle_username: str = "", kaggle_key=""):
13
+ os.environ["KAGGLE_USERNAME"] = kaggle_username
14
+ os.environ["KAGGLE_KEY"] = kaggle_key
15
+
16
+ self.PROJECT_PATH = r""
17
+ self.NOTEBOOK_ID = "amirmoris/pix2pix"
18
+ self.DATASET_NAME = "dataset"
19
+
20
+ def execute_terminal_command(self, command: str):
21
+ try:
22
+ process = subprocess.Popen(
23
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
24
+ )
25
+ output, error = process.communicate()
26
+ output = str(output.decode("utf-8"))
27
+ error = str(error.decode("utf-8"))
28
+ print(rf"Command executed successfully: {command}")
29
+ return output
30
+ except Exception as e:
31
+ return None, str(e)
32
+
33
+ def correct_path(self, path: str):
34
+ return path[1:] if path.startswith("\\") else path
35
+
36
+ def create_folder(self, path: str):
37
+ path = self.correct_path(path)
38
+ if os.path.exists(path):
39
+ shutil.rmtree(path)
40
+ self.execute_terminal_command(rf"mkdir {path}")
41
+
42
+ def pull_kaggle_notebook(self, notebook_path: str):
43
+ command = rf"kaggle kernels pull {self.NOTEBOOK_ID} -p {notebook_path} -m"
44
+ return self.execute_terminal_command(command)
45
+
46
+ def push_kaggle_notebook(self, notebook_path: str):
47
+ command = rf"kaggle kernels push -p {notebook_path}"
48
+ return self.execute_terminal_command(command)
49
+
50
+ def get_notebook_status(self):
51
+ command = rf"kaggle kernels status {self.NOTEBOOK_ID}"
52
+ return self.execute_terminal_command(command)
53
+
54
+ def run(self, notebook_path: str):
55
+ notebook_path = self.correct_path(notebook_path)
56
+ self.pull_kaggle_notebook(notebook_path)
57
+ return self.push_kaggle_notebook(notebook_path)
58
+
59
+ def write_file(self, data: list, file_path: str, file_name: str = ""):
60
+ if len(file_name) > 0:
61
+ file_path = rf"{file_path}\{file_name}"
62
+
63
+ file_path = self.correct_path(file_path)
64
+ # Writing JSON data
65
+ with open(file_path, "w") as file:
66
+ for idx in range(len(data)):
67
+ json_string = json.dumps(data[idx]) + (
68
+ "\n" if idx < len(data) - 1 else ""
69
+ )
70
+ file.write(json_string)
71
+
72
+ def read_image(self, image_path: str):
73
+ try:
74
+ image = Image.open(image_path)
75
+ return image
76
+ except IOError:
77
+ print("Unable to load image")
78
+ return None
79
+
80
+ def get_notebook_output(self, output_path: str):
81
+ output_path = self.correct_path(output_path)
82
+ command = rf"kaggle kernels output {self.NOTEBOOK_ID} -p {output_path}"
83
+ return self.execute_terminal_command(command)
84
+
85
+ def generate_image(
86
+ self,
87
+ input_image_name: str,
88
+ edit_instruction: str,
89
+ output_image_name: str,
90
+ ):
91
+ if len(input_image_name) == 0 or len(edit_instruction) == 0:
92
+ return False, rf"Missing Input"
93
+
94
+ if len(output_image_name) == 0:
95
+ return False, rf"Missing Output"
96
+
97
+ GoogleDrive_connection = GoogleDrive_API()
98
+
99
+ dataset_path = self.correct_path(rf"{self.PROJECT_PATH}\{self.DATASET_NAME}")
100
+ notebook_path = self.correct_path(rf"{self.PROJECT_PATH}\notebook")
101
+
102
+ self.create_folder(dataset_path)
103
+
104
+ # copy image to the dataset
105
+ shutil.copyfile(
106
+ rf"local_dataset\{input_image_name}",
107
+ rf"{dataset_path}\{input_image_name}",
108
+ )
109
+
110
+ data = [
111
+ {
112
+ "edit": edit_instruction,
113
+ "input_image_path": input_image_name,
114
+ "output_image_path": output_image_name,
115
+ }
116
+ ]
117
+
118
+ self.write_file(data, dataset_path, "data.jsonl")
119
+ # update dataset
120
+ GoogleDrive_connection.upload_file(
121
+ "data.jsonl", rf"{self.DATASET_NAME}\data.jsonl"
122
+ )
123
+ GoogleDrive_connection.upload_file(
124
+ input_image_name, rf"{self.DATASET_NAME}\{input_image_name}"
125
+ )
126
+
127
+ # run notebook
128
+ print(self.run(notebook_path))
129
+
130
+ number_of_checks = 0
131
+ while True:
132
+ status = str(self.get_notebook_status()).replace("\n", "")
133
+ print(rf"- status no #{number_of_checks} : {status}")
134
+ number_of_checks += 1
135
+ if "complete" in status:
136
+ break
137
+
138
+ if "error" in status:
139
+ return False, "notebook status error"
140
+ if "cancelAcknowledged" in status:
141
+ return False, "notebook status cancelAcknowledged"
142
+ time.sleep(120)
143
+
144
+ # get output
145
+ GoogleDrive_connection.download_file(
146
+ output_image_name, rf"{dataset_path}\{output_image_name}"
147
+ )
148
+ output_image = self.read_image(rf"{dataset_path}\{output_image_name}")
149
+ # clear input and output
150
+
151
+ if output_image is None:
152
+ return False, "An error occured while running, no output image found"
153
+
154
+ return True, output_image
155
+
156
+
157
+ def main():
158
+ pass
159
+
160
+
161
+ if __name__ == "__main__":
162
+ main()
app.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ from PIL import Image
4
+ import gradio as gr
5
+
6
+ from Kaggle_API import API_Connection
7
+
8
+
9
+ def generate_button_clicked(input_image: Image = None, edit_instruction: str = ""):
10
+ if input_image is None:
11
+ raise gr.Error("Missing Input: input_image")
12
+ if edit_instruction == 0:
13
+ raise gr.Error("Missing Input: edit_instruction")
14
+
15
+ # set kaggle-api variables
16
+ kaggle_username = os.environ["kaggle_username"]
17
+ kaggle_key = os.environ["kaggle_key"]
18
+
19
+ api_connection = API_Connection(kaggle_username, kaggle_key)
20
+ api_connection.create_folder(rf"{api_connection.PROJECT_PATH}\local_dataset")
21
+
22
+ image_ID = ""
23
+ while len(image_ID) < 4:
24
+ image_ID += str(random.randint(0, 9))
25
+
26
+ input_image_name = rf"input_image_{image_ID}.png"
27
+ output_image_name = rf"output_image_{image_ID}.png"
28
+
29
+ input_image.save(rf"local_dataset\{input_image_name}")
30
+
31
+ status, img = api_connection.generate_image(
32
+ input_image_name, edit_instruction, output_image_name
33
+ )
34
+
35
+ if status == False:
36
+ raise gr.Error(img) # img represents the error
37
+
38
+ return img
39
+
40
+
41
+ def reset_button_clicked():
42
+ return None, "", None
43
+
44
+
45
+ SCOPES = ["https://www.googleapis.com/auth/drive"]
46
+ SERVICE_ACCOUNT_FILE = "service_account.json"
47
+ PARENT_FOLDER_ID = "1r-MlnEpWHx3b1fxHDnHcZ2-Wh_Y89676"
48
+
49
+
50
+ def main():
51
+ with gr.Blocks(css="footer {visibility: hidden}") as demo:
52
+ with gr.Row():
53
+ input_image = gr.Image(label="Input Image", type="pil", interactive=True)
54
+ edited_image = gr.Image(
55
+ label=f"Edited Image", type="pil", interactive=False
56
+ )
57
+
58
+ with gr.Row():
59
+ with gr.Column(scale=3):
60
+ instruction = gr.Textbox(
61
+ lines=1, label="Edit Instruction", interactive=True
62
+ )
63
+ with gr.Column(scale=1, min_width=100):
64
+ with gr.Row():
65
+ generate_button = gr.Button("Generate")
66
+ with gr.Row():
67
+ reset_button = gr.Button("Reset")
68
+
69
+ generate_button.click(
70
+ fn=generate_button_clicked,
71
+ inputs=[
72
+ input_image,
73
+ instruction,
74
+ ],
75
+ outputs=edited_image,
76
+ )
77
+ reset_button.click(
78
+ fn=reset_button_clicked,
79
+ outputs=[input_image, instruction, edited_image],
80
+ )
81
+
82
+ # Launch Gradio interface
83
+
84
+ demo.queue(max_size=1)
85
+ demo.launch(share=True)
86
+
87
+
88
+ if __name__ == "__main__":
89
+ main()
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio
2
+ kaggle
3
+ google-api-python-client