Skip to content

Commit 26efb0a

Browse files
committed
feat(validate_image): add scripts to generate coco files
- generate coco file from images in drive - generate coco file from images in dropbox
1 parent 92f21db commit 26efb0a

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function main() {
2+
const exportFileName = 'your_coco_export.json';
3+
const folderId = 'your_public_folder_id';
4+
const folder = DriveApp.getFolderById(folderId);
5+
const files = folder.getFiles();
6+
7+
const images = [];
8+
9+
let id = 1;
10+
while (files.hasNext()) {
11+
const file = files.next();
12+
const name = file.getName();
13+
const fileId = file.getId();
14+
// const url = https://drive.google.com/uc?export=view&id=" + fileId;
15+
const url = `https://drive.google.com/thumbnail?id=${fileId}&sz=w1000`;
16+
images.push({
17+
coco_url: url,
18+
file_name: name,
19+
id,
20+
});
21+
id += 1;
22+
}
23+
24+
const exportContent = JSON.stringify({ images });
25+
const exportFile = DriveApp.createFile(
26+
exportFileName,
27+
exportContent,
28+
MimeType.PLAIN_TEXT,
29+
);
30+
const exportFileUrl = exportFile.getUrl();
31+
32+
Logger.log(`COCO file available at: ${exportFileUrl}`);
33+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# /// script
2+
# dependencies = [
3+
# "requests<3",
4+
# ]
5+
# ///
6+
from pathlib import Path
7+
from argparse import ArgumentParser
8+
import requests
9+
import json
10+
import re
11+
12+
def dropbox_request(endpoint: str, data: object, *, access_token: str):
13+
url = f"https://api.dropboxapi.com/2/{endpoint}"
14+
headers = {
15+
"Authorization": f"Bearer {access_token}",
16+
"Content-Type": "application/json",
17+
}
18+
res = requests.post(
19+
url,
20+
headers=headers,
21+
data=json.dumps(data),
22+
)
23+
res.raise_for_status()
24+
return res.json()
25+
26+
def dropbox_content_request(endpoint: str, path: str, data: object, *, access_token: str):
27+
url = f"https://content.dropboxapi.com/2/{endpoint}"
28+
headers = {
29+
"Authorization": f"Bearer {access_token}",
30+
"Content-Type": "application/octet-stream",
31+
"Dropbox-API-Arg": json.dumps({
32+
"path": path,
33+
"mode": "overwrite", # overwrite if exists
34+
"autorename": False,
35+
"mute": False
36+
})
37+
}
38+
res = requests.post(
39+
url,
40+
headers=headers,
41+
data=json.dumps(data).encode("utf-8"),
42+
)
43+
res.raise_for_status()
44+
return res.json()
45+
46+
def list_all_files(folder_path: str, *, access_token: str):
47+
ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"}
48+
files = []
49+
50+
data = {"path": folder_path, "recursive": False}
51+
response = dropbox_request("files/list_folder", data, access_token=access_token)
52+
53+
files.extend(response.get("entries", []))
54+
55+
while response.get("has_more", False):
56+
cursor = response["cursor"]
57+
response = dropbox_request(
58+
"files/list_folder/continue",
59+
{"cursor": cursor},
60+
access_token=access_token,
61+
)
62+
files.extend(response.get("entries", []))
63+
64+
# Sort files by name (just in case)
65+
files = sorted(files, key=lambda file: file["name"].lower())
66+
# Filter out only files (not folders) that are supported
67+
files = [
68+
file for file in files
69+
if file[".tag"] == "file" and Path(file["name"]).suffix.lower() in ALLOWED_EXTENSIONS
70+
]
71+
return files
72+
73+
def share_file_and_get_links(files, *, access_token: str):
74+
total = len(files)
75+
images = []
76+
for i, file in enumerate(files):
77+
path = file["path_lower"]
78+
actual_path = file["path_display"]
79+
80+
# First try to list existing shared links
81+
data = {"path": path, "direct_only": True}
82+
print(f"{i + 1}/{total} Getting public URL")
83+
res = dropbox_request(
84+
"sharing/list_shared_links",
85+
data,
86+
access_token=access_token,
87+
)
88+
if res.get("links"):
89+
link = res["links"][0]["url"]
90+
else:
91+
data = {
92+
"path": path,
93+
"settings": {
94+
"requested_visibility": "public"
95+
}
96+
}
97+
res_create = dropbox_request(
98+
"sharing/create_shared_link_with_settings",
99+
data,
100+
access_token=access_token,
101+
)
102+
link = res_create["url"]
103+
104+
raw_url = re.sub(r'&dl=0\b', '', link) + '&raw=1'
105+
106+
images.append({
107+
"id": i + 1,
108+
"file_name": actual_path,
109+
"coco_url": raw_url,
110+
})
111+
return images
112+
113+
114+
def main():
115+
parser = ArgumentParser(description="Generate COCO file from images folder.")
116+
parser.add_argument("access_token", help="Access token for authentication")
117+
parser.add_argument("images_folder", help="Path to the images folder")
118+
parser.add_argument("export_file_name", help="Name of the export COCO file")
119+
120+
args = parser.parse_args()
121+
122+
access_token = args.access_token
123+
images_folder = args.images_folder
124+
export_file_name = args.export_file_name
125+
126+
# Get all the files on given path
127+
files = list_all_files(
128+
images_folder,
129+
access_token=access_token,
130+
)
131+
132+
# Share individual file publically and get public link
133+
public_images = share_file_and_get_links(
134+
files,
135+
access_token=access_token,
136+
)
137+
138+
# Upload coco format export to dropbox
139+
print("Uploading COCO file")
140+
absolute_export_file_name = str(Path(images_folder) / Path(export_file_name))
141+
dropbox_content_request(
142+
"files/upload",
143+
absolute_export_file_name,
144+
{ "images": public_images },
145+
access_token=access_token,
146+
)
147+
148+
# Get temporary link
149+
res = dropbox_request(
150+
"files/get_temporary_link",
151+
{ "path": absolute_export_file_name },
152+
access_token=access_token,
153+
)
154+
print(f"COCO file available at {res["link"]}")
155+
156+
if __name__ == "__main__":
157+
main()

0 commit comments

Comments
 (0)