stereoid commited on
Commit
6d35aff
·
verified ·
1 Parent(s): 3f3265f

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. approach/ape_stage.py +150 -0
  2. approach/llm/__init__.py +0 -0
  3. approach/llm/gpt.py +90 -0
  4. approach/llm/gpt_polling.py +268 -0
  5. approach/method.py +732 -0
  6. approach/method_claude.py +656 -0
  7. approach/method_fastuse.py +736 -0
  8. approach/ovod/APE/demo/__init__.py +0 -0
  9. approach/ovod/APE/demo/pre-requirements.txt +4 -0
  10. approach/ovod/APE/demo/predictor_lazy.py +429 -0
  11. approach/ovod/APE/demo/requirements.txt +11 -0
  12. approach/ovod/GroundingDINO/.gitignore +146 -0
  13. approach/ovod/GroundingDINO/LICENSE +201 -0
  14. approach/ovod/GroundingDINO/README.md +367 -0
  15. approach/ovod/GroundingDINO/gdino.py +23 -0
  16. approach/ovod/GroundingDINO/requirements.txt +10 -0
  17. approach/ovod/GroundingDINO/setup.py +208 -0
  18. approach/ovod/GroundingDINO/test.ipynb +55 -0
  19. approach/ovod/d-cube/.gitignore +164 -0
  20. approach/ovod/d-cube/README.md +134 -0
  21. approach/ovod/d-cube/qa.md +24 -0
  22. approach/ovod/d-cube/requirements.txt +4 -0
  23. approach/ovod/d-cube/setup.py +30 -0
  24. approach/ovod/detectron2/.clang-format +85 -0
  25. approach/ovod/detectron2/.flake8 +15 -0
  26. approach/ovod/detectron2/.gitignore +53 -0
  27. approach/ovod/detectron2/GETTING_STARTED.md +79 -0
  28. approach/ovod/detectron2/INSTALL.md +261 -0
  29. approach/ovod/detectron2/LICENSE +202 -0
  30. approach/ovod/detectron2/MODEL_ZOO.md +1052 -0
  31. approach/ovod/detectron2/README.md +68 -0
  32. approach/ovod/detectron2/setup.cfg +26 -0
  33. approach/ovod/detectron2/setup.py +212 -0
  34. approach/ovod/gdino.py +23 -0
  35. approach/pipeline_utils.py +176 -0
  36. approach/run_ape.py +291 -0
  37. approach/util/test.py +35 -0
  38. approach/vlm/LLaVA/.gitignore +29 -0
  39. approach/vlm/LLaVA/LICENSE +201 -0
  40. approach/vlm/LLaVA/README.md +366 -0
  41. approach/vlm/LLaVA/pyproject.toml +39 -0
  42. approach/vlm/gpt4v/cu_gpt4v.py +25 -0
  43. approach/vlm/gpt4v/gpt4v.py +148 -0
  44. configs/model_profiles.yaml +31 -0
  45. dataset/statistics/app_genre.csv +101 -0
  46. dataset/statistics/app_tag.csv +101 -0
  47. dataset/statistics/plot.py +179 -0
  48. docs/ASSETS.md +59 -0
  49. docs/ENVIRONMENT.md +93 -0
  50. docs/MODEL_MANIFEST.md +11 -0
approach/ape_stage.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import string
3
+ from pathlib import Path
4
+ from typing import Callable, Dict, Iterable, List, Mapping, Optional, Tuple
5
+
6
+ from approach.pipeline_utils import (
7
+ enrich_ape_results,
8
+ parse_orienter_image_name,
9
+ resolve_image_path,
10
+ write_json_atomic,
11
+ )
12
+
13
+
14
+ InferenceFn = Callable[..., List[dict]]
15
+
16
+
17
+ def extract_image_id(image_name: str) -> int:
18
+ return parse_orienter_image_name(Path(image_name).name)[2]
19
+
20
+
21
+ def build_referring_expressions(objects: Mapping[str, object]) -> List[str]:
22
+ translator = str.maketrans("", "", string.punctuation)
23
+ expressions = []
24
+ for name, description in objects.items():
25
+ if isinstance(description, str):
26
+ text = description
27
+ elif isinstance(description, Mapping):
28
+ text = " ".join(str(value) for value in description.values())
29
+ else:
30
+ text = str(description)
31
+ expressions.append(f"{name}: {text.translate(translator)}")
32
+ return expressions
33
+
34
+
35
+ def _load_existing(output_path: Path) -> List[dict]:
36
+ if not output_path.exists():
37
+ return []
38
+ with output_path.open() as file:
39
+ data = json.load(file)
40
+ if not isinstance(data, list):
41
+ raise ValueError(f"Existing prediction file must contain a list: {output_path}")
42
+ return data
43
+
44
+
45
+ def _completed_image_ids(results: Iterable[dict]) -> set:
46
+ return {item["image_id"] for item in results if "image_id" in item}
47
+
48
+
49
+ def _progress_path(output_path: Path) -> Path:
50
+ return output_path.with_name(f"{output_path.stem}.progress.json")
51
+
52
+
53
+ def _load_progress(output_path: Path) -> set:
54
+ path = _progress_path(output_path)
55
+ if not path.exists():
56
+ return set()
57
+ with path.open() as file:
58
+ data = json.load(file)
59
+ return set(data.get("completed_image_ids", []))
60
+
61
+
62
+ def _get_question(questions: Mapping[object, Mapping[str, object]], question_id):
63
+ if question_id in questions:
64
+ return questions[question_id]
65
+ question_id_str = str(question_id)
66
+ if question_id_str in questions:
67
+ return questions[question_id_str]
68
+ try:
69
+ question_id_int = int(question_id)
70
+ except (TypeError, ValueError):
71
+ question_id_int = None
72
+ if question_id_int in questions:
73
+ return questions[question_id_int]
74
+ raise KeyError(question_id)
75
+
76
+
77
+ def run_ape_stage(
78
+ records: Iterable[dict],
79
+ questions: Mapping[object, Mapping[str, object]],
80
+ images_dir,
81
+ output_path,
82
+ inference: InferenceFn,
83
+ inference_kwargs: Optional[Dict[str, object]] = None,
84
+ error_path=None,
85
+ resume: bool = True,
86
+ ) -> Tuple[List[dict], List[dict]]:
87
+ output_path = Path(output_path)
88
+ error_path = Path(error_path) if error_path is not None else None
89
+ images_dir = Path(images_dir)
90
+ inference_kwargs = dict(inference_kwargs or {})
91
+ results = _load_existing(output_path) if resume else []
92
+ completed = _completed_image_ids(results)
93
+ if resume:
94
+ completed.update(_load_progress(output_path))
95
+ errors = []
96
+ write_json_atomic(str(output_path), results)
97
+ write_json_atomic(
98
+ str(_progress_path(output_path)),
99
+ {"completed_image_ids": sorted(completed)},
100
+ )
101
+
102
+ for record in records:
103
+ question_id = record["question_id"]
104
+ question = _get_question(questions, question_id)
105
+ image_name = question["image"]
106
+ image_id = extract_image_id(image_name)
107
+ if image_id in completed:
108
+ continue
109
+
110
+ text = record.get("text")
111
+ if not text:
112
+ continue
113
+ objects = text["objects"]
114
+ expressions = build_referring_expressions(objects)
115
+ image_path = resolve_image_path(images_dir, image_name)
116
+
117
+ try:
118
+ ape_results = inference(
119
+ input_path=str(image_path),
120
+ text_prompt=", ".join(expressions),
121
+ **inference_kwargs,
122
+ )
123
+ enriched = enrich_ape_results(ape_results, image_name, extract_image_id)
124
+ results.extend(enriched)
125
+ completed.add(image_id)
126
+ write_json_atomic(str(output_path), results)
127
+ write_json_atomic(
128
+ str(_progress_path(output_path)),
129
+ {"completed_image_ids": sorted(completed)},
130
+ )
131
+ except Exception as exc:
132
+ errors.append(
133
+ {
134
+ "question_id": question_id,
135
+ "image": image_name,
136
+ "error_type": type(exc).__name__,
137
+ "message": str(exc),
138
+ }
139
+ )
140
+ if error_path is not None:
141
+ write_json_atomic(str(error_path), errors)
142
+
143
+ write_json_atomic(str(output_path), results)
144
+ write_json_atomic(
145
+ str(_progress_path(output_path)),
146
+ {"completed_image_ids": sorted(completed)},
147
+ )
148
+ if error_path is not None:
149
+ write_json_atomic(str(error_path), errors)
150
+ return results, errors
approach/llm/__init__.py ADDED
File without changes
approach/llm/gpt.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import time
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+ from approach.config import get_model_profile
7
+ from approach.pipeline_utils import write_json_atomic
8
+ from approach.providers import OpenAICompatibleChatClient
9
+
10
+ DEFAULT_PROFILE = os.environ.get("ORIENT_MODEL_PROFILE", "default")
11
+
12
+
13
+ def get_steam_app_data(app_id, image_name):
14
+ url = f"https://store.steampowered.com/app/{app_id}"
15
+
16
+ try:
17
+ response = requests.get(url, timeout=30)
18
+ response.raise_for_status() # Raise an HTTPError if the HTTP request returned an unsuccessful status code
19
+
20
+ soup = BeautifulSoup(response.content, "html.parser")
21
+
22
+ app_name = soup.find("div", {"id": "appHubAppName"}).get_text(strip=True)
23
+ short_desc = soup.find("div", class_="game_description_snippet").get_text(strip=True)
24
+ long_desc = soup.find("div", {"id": "game_area_description"}).get_text(strip=True)
25
+
26
+ return app_name, short_desc + " " + long_desc
27
+ except Exception as e:
28
+ print(f"Error fetching app data for app_id {app_id} of image {image_name}. Error: {e}")
29
+ return "", ""
30
+
31
+ def generate_prompt(app_name, app_description, app_current_view):
32
+ return (f"You are a virtual reality game player. Currently, you are playing a game named {app_name} "
33
+ f"with the following description: {app_description}. Now in your field of view, you can see that: {app_current_view}. "
34
+ "Please infer what virtual objects you can see currently based on the current view and the app description.")
35
+
36
+ def infer_object_candidates(
37
+ vlm_question_path,
38
+ vlm_answer_path,
39
+ llm_candidate_path,
40
+ model_profile=DEFAULT_PROFILE,
41
+ ):
42
+ profile = get_model_profile(model_profile)
43
+ client = OpenAICompatibleChatClient(profile)
44
+ # Read and process the two jsonl files
45
+ with open(vlm_answer_path, "r") as f_a:
46
+ file_a_data = [json.loads(line) for line in f_a.readlines()]
47
+
48
+ with open(vlm_question_path, "r") as f_b:
49
+ file_b_data = {json.loads(line)["question_id"]: json.loads(line) for line in f_b.readlines()}
50
+ # file_b_dict = {json.loads(line)["question_id"]: json.loads(line)["image"].split("_")[0] for line in f_b.readlines()}
51
+
52
+ results = {}
53
+
54
+ index = 0
55
+ for line_data_a in file_a_data:
56
+ print(index)
57
+ index += 1
58
+
59
+ question_id = line_data_a["question_id"]
60
+ app_current_view = line_data_a["text"]
61
+
62
+ line_data_b = file_b_data.get(question_id, {})
63
+ app_id = line_data_b.get("image", "").split("_")[0]
64
+ # app_id = file_b_dict.get(question_id, "")
65
+ # line_data_b = file_b_dict.get(question_id, {})
66
+
67
+ if app_id:
68
+ app_name, app_description = get_steam_app_data(app_id, line_data_b.get("image", ""))
69
+ message_content = generate_prompt(app_name, app_description, app_current_view)
70
+ try:
71
+ payload = client.build_payload(message_content)
72
+ completion = client.chat_completion(payload)
73
+ content = completion["choices"][0]["message"]["content"].strip()
74
+ inferred_objects = [item.strip() for item in content.split(";") if item.strip()]
75
+
76
+ results[question_id] = {
77
+ "vlm_question": line_data_a,
78
+ "vlm_answer": line_data_b,
79
+ "app_name": app_name,
80
+ "app_description": app_description,
81
+ "app_current_view": app_current_view,
82
+ "inferred_object_candidates": inferred_objects
83
+ }
84
+ except Exception as e:
85
+ print(f"Error generating completion for question_id {question_id}. Error: {e}")
86
+
87
+ time.sleep(20)
88
+
89
+ # Save the results to a json file
90
+ write_json_atomic(llm_candidate_path, results)
approach/llm/gpt_polling.py ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import time
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+ from approach.config import get_model_profile
7
+ from approach.providers import OpenAICompatibleChatClient
8
+
9
+ DEFAULT_PROFILE = os.environ.get("ORIENT_MODEL_PROFILE", "default")
10
+
11
+
12
+ def get_steam_app_data(app_id, image_name):
13
+ url = f"https://store.steampowered.com/app/{app_id}"
14
+
15
+ try:
16
+ response = requests.get(url, timeout=30)
17
+ response.raise_for_status()
18
+
19
+ soup = BeautifulSoup(response.content, "html.parser")
20
+
21
+ app_name = soup.find("div", {"id": "appHubAppName"}).get_text(strip=True)
22
+ short_desc = soup.find("div", class_="game_description_snippet").get_text(strip=True)
23
+ long_desc = soup.find("div", {"id": "game_area_description"}).get_text(strip=True)
24
+
25
+ return app_name, short_desc + " " + long_desc
26
+ except Exception as e:
27
+ print(f"Error fetching app data for app_id {app_id} of image {image_name}. Error: {e}")
28
+ return "", ""
29
+
30
+
31
+ def save_results_to_file(llm_candidate_path, results):
32
+ """Utility function to save results to a file."""
33
+ with open(llm_candidate_path, "w") as out_file:
34
+ json.dump(results, out_file, indent=4)
35
+
36
+
37
+ def generate_prompt(app_name, app_description, app_current_view, ablation):
38
+ # return (f"You are a virtual reality game player. Currently, you are playing a game named {app_name} "
39
+ # f"with the following description: . Now in your field of view, you can see that: {app_current_view}. "
40
+ # "Please infer what virtual objects you can see currently based on the current view and the app description. Let's think step by step.\n"
41
+ # "List the virtual objects one by one, seperated by semicolons"
42
+ # f"App description: {app_description}")
43
+
44
+ # return f'''
45
+ # ** Context and Task **
46
+ # You are a virtual reality game player. Currently, you are playing a game named {app_name} with the following description. Now in your field of view from the VR headset, you can see that: {app_current_view}. Please infer what virtual objects you can see currently based on the current view and the app description.\n
47
+ # Output the inferred objects one by one, seperated by semicolons, strictly following the format: object1;object2. E.g., "door;desk"\n
48
+ # NO DOT OUTPUT any other content.\n
49
+
50
+ # ** Chain-of-Thought Reasoning Demonstration **
51
+ # (1) For a tree object in a tree-planting game, the users need to pick up and plant the tree, thus the object is interactable.
52
+ # (2) But for a tree object appeard in the background scenery of a fishing-only game, the object is highly likely non-interactable.\n
53
+
54
+ # ** Data **
55
+ # The description of the app:
56
+ # <app_description>.
57
+ # '''
58
+
59
+ # return f'''
60
+ # ** Context and Task **
61
+ # You are a virtual reality game player. Currently, you are playing a game named {app_name} with the following description. Now in your field of view from the VR headset, you can see that: {app_current_view}. Please extract information and infer what virtual objects you can see currently based on the current view and the app description.\n
62
+ # Output the inferred objects one by one, seperated by semicolons, strictly following the format: object1;object2. E.g., "door;desk"\n
63
+ # NO DOT OUTPUT any other content.\n
64
+
65
+ # ** Data **
66
+ # The description of the app:
67
+ # <app_description>.
68
+ # '''
69
+
70
+ if ablation:
71
+ return f'''
72
+ Please extract objects from the following description: {app_current_view}
73
+ Output the extracted objects in JSON format: {{"objects": ["object1", "object2"]}}. E.g., {{"objects": ["door", "desk"]}}\n
74
+ NO DOT OUTPUT any other content besides JSON.\n
75
+ '''
76
+ elif not ablation:
77
+ return f'''
78
+ --- Context and Task ---
79
+ You are a virtual reality game player. Currently, you are playing a game named {app_name} with the following description. Now in your field of view from the VR headset, you can see the current VR scenario: {app_current_view}. Please extract information and infer what virtual objects you can see currently based on the current view and the app description.\n
80
+
81
+ --- Instructions and Demonstrations ---
82
+ (1) If there are multiple similar objects, please output all objects one by one. E.g., if there are several pens on the table, please output several "pen" instead of a single "pens".
83
+ (2) Provide detailed object description with texts on them (if any). For example, for a button or option with text on it (e.g., begin), you need to output "begin button" or "begin option".
84
+ (3) Ignore the virtual objects of user-controlled VR devices, e.g., controllers, hands and gloves, which are near the users in screenshot.
85
+ (4) Format: Output the inferred objects in JSON format: {{"objects": ["object1", "object2"]}}. E.g., {{"objects": ["door", "desk"]}}\n
86
+ NO DOT OUTPUT any other content besides JSON.\n
87
+
88
+ --- Data ---
89
+ The description of the app:
90
+ {app_description}.
91
+ '''
92
+
93
+ def generate_i_prompt(inferred_objects, app_current_view, ablation):
94
+ if ablation:
95
+ return f'''
96
+ For the following objects: {inferred_objects}. Please identify those user-interactable objects in VR games.
97
+ Output the extracted objects in JSON format: {{"objects": ["object1", "object2"]}}. E.g., {{"objects": ["door", "desk"]}}\n
98
+ NO DOT OUTPUT any other content besides JSON.\n
99
+ '''
100
+ elif not ablation:
101
+ return f'''
102
+ --- Context and Task ---
103
+ You are a virtual reality game player. From your previous response, you find that the following objects exist in the screenshot: {inferred_objects}.
104
+ Please perform reasoning to identify the user-interactable objects, with which users can use VR devices like handheld controllers to interact, in the current VR scene screenshot. Please perform reasoning based on the app description and current VR scenario.\n
105
+
106
+ --- Instructions and Demonstrations ---
107
+ (1) For a tree object in a tree-planting game, the users need to pick up and plant the tree, thus the object is interactable.
108
+ (2) But for a tree object appeard in the background scenery of a fishing-only game, the object is highly likely non-interactable.\n
109
+ Output the interactable objects in JSON format: {{"objects": ["object1", "object2"]}}. E.g., {{"objects": ["door", "desk"]}}\n
110
+ NO DOT OUTPUT any other content besides JSON.\n
111
+
112
+ --- Data ---
113
+ The current VR scenario in the screenshot:
114
+ {app_current_view}
115
+ '''
116
+
117
+
118
+ # def infer_object_candidates(vlm_question_path, vlm_answer_path, llm_candidate_path):
119
+ def infer_objects(vlm_question_path, vlm_answer_path, llm_candidate_path, ablation, model_profile=DEFAULT_PROFILE):
120
+ profile = get_model_profile(model_profile)
121
+ client = OpenAICompatibleChatClient(profile)
122
+
123
+ with open(vlm_answer_path, "r") as f_a:
124
+ file_a_data = [json.loads(line) for line in f_a.readlines()]
125
+
126
+ with open(vlm_question_path, "r") as f_b:
127
+ file_b_data = {json.loads(line)["question_id"]: json.loads(line) for line in f_b.readlines()}
128
+
129
+ results = {}
130
+ index = 0
131
+
132
+ for line_data_a in file_a_data:
133
+ print(index)
134
+ index += 1
135
+
136
+ # TODO: Proxy pool
137
+ # proxy = get_proxy()
138
+ # if not proxy:
139
+ # print("Failed to fetch proxy.")
140
+ # continue
141
+
142
+ question_id = line_data_a["question_id"]
143
+ app_current_view = line_data_a["text"]
144
+ line_data_b = file_b_data.get(question_id, {})
145
+ app_id = line_data_b.get("image", "").split("_")[0]
146
+
147
+ if app_id:
148
+ app_name, app_description = get_steam_app_data(app_id, line_data_b.get("image", ""))
149
+ message_content = generate_prompt(app_name, app_description, app_current_view, ablation)
150
+ # switch_api_key() # Use the next API key in the list
151
+ try:
152
+ # TODO: Proxy pool (f"http://{proxy}")
153
+ completion = client.complete_json(message_content)
154
+ inferred_objects = completion["objects"]
155
+ inferred_objects = [io.strip() for io in inferred_objects]
156
+
157
+ # wrong_flag = False
158
+ # for io in inferred_objects:
159
+ # if io.startswith('Based on') or len(io) > 70:
160
+ # print('Based on')
161
+ # wrong_flag = True
162
+ # break
163
+ # if wrong_flag:
164
+ # continue
165
+ print(inferred_objects)
166
+
167
+ i_completion = client.complete_json_messages([
168
+ {'role': 'user', 'content': message_content},
169
+ {'role': 'assistant', 'content': json.dumps(completion)},
170
+ {'role': 'user', 'content': generate_i_prompt(inferred_objects, app_current_view, ablation)}
171
+ ])
172
+ interactable_objects = i_completion["objects"]
173
+ interactable_objects = [io.strip() for io in interactable_objects]
174
+ # TODO: !!
175
+ if len(interactable_objects) == 0:
176
+ interactable_objects = ['\n']
177
+ print(interactable_objects)
178
+
179
+ results[question_id] = {
180
+ "vlm_question": line_data_a,
181
+ "vlm_answer": line_data_b,
182
+ "app_name": app_name,
183
+ "app_description": app_description,
184
+ "app_current_view": app_current_view,
185
+ "inferred_object_candidates": inferred_objects,
186
+ "interactable_objects": interactable_objects
187
+ }
188
+
189
+ # Save the updated results to file after each successful API call
190
+ save_results_to_file(llm_candidate_path, results)
191
+
192
+ except Exception as e:
193
+ print(f"Error generating completion for question_id {question_id}. Error: {e}")
194
+
195
+ time.sleep(3) # Sleep for 2 seconds before switching to the next API key
196
+
197
+
198
+ # def infer_interactable_object(vlm_question_path, vlm_answer_path, llm_candidate_path):
199
+ # with open(vlm_answer_path, "r") as f_a:
200
+ # file_a_data = [json.loads(line) for line in f_a.readlines()]
201
+
202
+ # with open(vlm_question_path, "r") as f_b:
203
+ # file_b_data = {json.loads(line)["question_id"]: json.loads(line) for line in f_b.readlines()}
204
+
205
+ # results = {}
206
+ # index = 0
207
+
208
+ # for line_data_a in file_a_data:
209
+ # print(index)
210
+ # index += 1
211
+
212
+ # # TODO: Proxy pool
213
+ # # proxy = get_proxy()
214
+ # # if not proxy:
215
+ # # print("Failed to fetch proxy.")
216
+ # # continue
217
+
218
+ # question_id = line_data_a["question_id"]
219
+ # app_current_view = line_data_a["text"]
220
+ # line_data_b = file_b_data.get(question_id, {})
221
+ # app_id = line_data_b.get("image", "").split("_")[0]
222
+
223
+ # if app_id:
224
+ # app_name, app_description = get_steam_app_data(app_id, line_data_b.get("image", ""))
225
+ # message_content = generate_prompt(app_name, app_description, app_current_view)
226
+ # # switch_api_key() # Use the next API key in the list
227
+ # try:
228
+ # # TODO: Proxy pool (f"http://{proxy}")
229
+ # completion = openai.ChatCompletion.create(
230
+ # model='gemini-3-flash-preview-nothinking',
231
+ # temperature=0,
232
+ # messages=[{'role': 'user', 'content': message_content}]
233
+ # )
234
+ # print(completion)
235
+ # # inferred_objects = completion['choices'][0]['message']['content'].strip().split(";")
236
+ # inferred_objects = json.loads(completion['choices'][0]['message']['content'].strip())['objects']
237
+ # inferred_objects = [io.strip() for io in inferred_objects]
238
+
239
+ # # wrong_flag = False
240
+ # # for io in inferred_objects:
241
+ # # if io.startswith('Based on') or len(io) > 70:
242
+ # # print('Based on')
243
+ # # wrong_flag = True
244
+ # # break
245
+ # # if wrong_flag:
246
+ # # continue
247
+ # print(inferred_objects)
248
+
249
+ # results[question_id] = {
250
+ # "vlm_question": line_data_a,
251
+ # "vlm_answer": line_data_b,
252
+ # "app_name": app_name,
253
+ # "app_description": app_description,
254
+ # "app_current_view": app_current_view,
255
+ # "inferred_object_candidates": inferred_objects
256
+ # }
257
+
258
+ # # Save the updated results to file after each successful API call
259
+ # save_results_to_file(llm_candidate_path, results)
260
+
261
+ # except Exception as e:
262
+ # print(f"Error generating completion for question_id {question_id}. Error: {e}")
263
+
264
+ # time.sleep(0.5) # Sleep for 2 seconds before switching to the next API key
265
+
266
+
267
+ if __name__ == "__main__":
268
+ infer_object_candidates("path_to_vlm_question", "path_to_vlm_answer", "path_to_llm_candidate")
approach/method.py ADDED
@@ -0,0 +1,732 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import random
6
+ import string
7
+ import argparse
8
+ import copy
9
+ import logging
10
+ from tqdm import tqdm
11
+ import PIL
12
+ from PIL import ImageFile
13
+ PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
14
+
15
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16
+ sys.path.append(BASE_DIR)
17
+ from approach.pipeline_utils import (
18
+ enrich_ape_results,
19
+ output_path_for_selection,
20
+ run_optional_reflection,
21
+ select_jsonl_lines,
22
+ write_json_atomic,
23
+ )
24
+
25
+ os.environ['TORCH_HOME'] = './.cache'
26
+ os.environ['HF_HOME'] = './.cache'
27
+
28
+
29
+ vlm = 'llava7b'
30
+ llm = 'gpt_3.5_turbo'
31
+ ovod = 'grounding_dino'
32
+
33
+ vlm_prompt = ''
34
+
35
+ ### Configurable
36
+ host_device = os.getenv('ORIENTER_LEGACY_HOST', 'local')
37
+ perspective = 'all_perspective'
38
+ # perspective = 'direct_back'
39
+ # perspective = 'direct_front'
40
+ # perspective = 'direct_side'
41
+ # perspective = 'direct_top'
42
+ # perspective = 'eyelevel'
43
+ # perspective = 'overlook'
44
+ ### Configurable
45
+
46
+ llava_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/llava/eval')
47
+ grounding_dino_path = os.path.join(BASE_DIR, 'approach/ovod/GroundingDINO')
48
+ ape_path = os.path.join(BASE_DIR, 'approach/ovod/APE')
49
+ # TODO: data on the CUHK server
50
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/interactable')
51
+ # icse
52
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/test_set_merged')
53
+ # icse_rebuttal
54
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_angleview/images/all_perspective')
55
+ # fse
56
+ images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_det/images/union3')
57
+
58
+
59
+ # def generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates):
60
+ # gdino_object_str = ' . '.join(ovod_candidates)
61
+
62
+ # gdino_command = f'''
63
+ # python demo/inference_on_a_image.py \
64
+ # -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
65
+ # -p weights/groundingdino_swint_ogc.pth \
66
+ # -i {ovod_image_path} \
67
+ # -o "{ovod_output_dir}" \
68
+ # -t "{gdino_object_str}"
69
+ # '''
70
+ # return gdino_command
71
+
72
+
73
+ def generate_question_file(img_folder, dst_path):
74
+ # Ensure the directory exists
75
+ if not os.path.exists(img_folder):
76
+ print(f"Error: Directory {img_folder} does not exist.")
77
+ return
78
+
79
+ # List all files in the directory
80
+ all_files = os.listdir(img_folder)
81
+
82
+ # Filter out files that are not images (based on extension). You can add more if needed.
83
+ image_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff"]
84
+ image_files = [f for f in all_files if any(f.lower().endswith(ext) for ext in image_extensions)]
85
+
86
+ # Open the output file for writing
87
+ with open(dst_path, 'w') as out_file:
88
+ for index, img_file in enumerate(image_files):
89
+ data = {
90
+ "question_id": index,
91
+ "image": img_file,
92
+ "text": vlm_prompt,
93
+ "category": "detail"
94
+ }
95
+ out_file.write(json.dumps(data) + '\n')
96
+
97
+ print(f"Processed {len(image_files)} images. Output saved to {dst_path}.")
98
+
99
+
100
+ def generate_answer_id(length=20):
101
+ # Define the characters that can be used in the string
102
+ characters = string.ascii_letters + string.digits
103
+ # Generate a random string of the specified length
104
+ answer_id = ''.join(random.choice(characters) for _ in range(length))
105
+ return answer_id
106
+
107
+
108
+ def method(
109
+ vlm=vlm,
110
+ llm=llm,
111
+ ovod=ovod,
112
+ start_index=None,
113
+ end_index=None,
114
+ shard_index=None,
115
+ num_shards=None,
116
+ enable_reflection=False,
117
+ reflection_profile="default",
118
+ max_reflection_iterations=10,
119
+ questions_path=None,
120
+ candidates_path=None,
121
+ images_path=None,
122
+ output_path=None,
123
+ ape_root=None,
124
+ ape_checkpoint=None,
125
+ ):
126
+ images_dir = images_path or globals()["images_dir"]
127
+ active_ape_path = ape_root or globals()["ape_path"]
128
+ active_ape_checkpoint = ape_checkpoint or "./ape_d_model_final.pth"
129
+ # vlm_question_path = os.path.join(BASE_DIR, 'approach/vlm/sampled_vlm_questions.jsonl')
130
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_vlm_questions_from671.jsonl')
131
+ # icse
132
+ # complete_vlm_question_abl_i_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions_ablation_interactability.jsonl')
133
+
134
+ # icse
135
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions.jsonl')
136
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
137
+ # icse_rebuttal
138
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_vlm_questions.jsonl')
139
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_complete_vlm_questions.jsonl')
140
+ # fse
141
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/fse_union3_{vlm}_questions.jsonl')
142
+ complete_vlm_question_path = questions_path or os.path.join(BASE_DIR, f'approach/vlm/realfse_union3_complete_{vlm}_questions.jsonl')
143
+ vlm_question_path = complete_vlm_question_path
144
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
145
+ # playground/data/coco2014_val_qa_eval/qa90_questions.jsonl
146
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_slowerspeed_1.jsonl')
147
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_higherspeed_r3_1_from195.jsonl')
148
+
149
+ # icse
150
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/cuhk_icse_test_set_merged_{vlm}_answer.jsonl')
151
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer.jsonl')
152
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_ablation_no_interactability_r1_0.jsonl')
153
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_cuhk_icse_test_set_merged_gpt4v_answer_higherspeed_r3_0.jsonl')
154
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_hit_icse_test_set_merged_gemini_answer_ablation_no_interactability_r1_0.jsonl')
155
+ # icse_rebuttal
156
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer.jsonl')
157
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
158
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
159
+ # fse
160
+ vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_uninon3_{vlm}_answer.jsonl')
161
+ llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_fse_uninon3_{vlm}_answer.jsonl')
162
+ gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_union3_{vlm}_answer.jsonl')
163
+
164
+ # icse
165
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_gpt4v_answer.jsonl')
166
+ # icse_rebuttal
167
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer_265_528.jsonl')
168
+ # fse
169
+ gpt4_results_answer_path = candidates_path or os.path.join(BASE_DIR, f'approach/vlm/realfse_uninon3_gpt4v_answer.jsonl')
170
+ # print(gpt4_results_answer_path)
171
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_answer.jsonl')
172
+
173
+ # icse
174
+ # # /path/to/answer-file-our.jsonl
175
+ # # llm_candidate_path = os.path.join(BASE_DIR, f'approach/llm/{vlm}_{llm}_cancidate_objects.json')
176
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_test_set_merged_{vlm}_{llm}_interactable_objects.json')
177
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_test_set_merged_{ovod}')
178
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
179
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
180
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_feedback_object_bbox_gpu2.json')
181
+
182
+ # icse_rebuttal
183
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_rbt_{perspective}_{vlm}_{llm}_interactable_objects.json')
184
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_rbt_{perspective}_{ovod}')
185
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
186
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
187
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_rbt_{perspective}_{vlm}_{llm}_{ovod}_object_bbox_gpu3_265_528.json')
188
+
189
+ gpu = '1-3'
190
+ # fse
191
+ interactable_object_path = candidates_path or os.path.join(BASE_DIR, f'approach/llm/realfse_union3_{vlm}_{llm}_interactable_objects.json') # TODO: Tentatively unused
192
+ ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/realfse_union3_{ovod}')
193
+ # GPU 0
194
+ base_output_path = output_path or os.path.join(BASE_DIR, f'approach/ovod/realfse_union3_{vlm}_{ovod}_object_bbox_gpu{gpu}.json')
195
+ oovd_object_bbox_path = output_path_for_selection(
196
+ base_output_path,
197
+ start_index=start_index,
198
+ end_index=end_index,
199
+ shard_index=shard_index,
200
+ num_shards=num_shards,
201
+ )
202
+
203
+ llava7b_model_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/checkpoints/llava-v1.5-7b')
204
+ llava7b_cmd = f'''
205
+ python model_vqa.py \
206
+ --model-path {llava7b_model_path} \
207
+ --question-file \
208
+ {complete_vlm_question_path} \
209
+ --image-folder \
210
+ {images_dir} \
211
+ --answers-file \
212
+ {llava_vlm_answer_path}
213
+ '''
214
+
215
+ # STEP #0
216
+ # First time of running
217
+ # TODO: Check whether it is first-time running
218
+ # generate_question_file(images_dir, vlm_question_path)
219
+
220
+ # STEP #1
221
+ # VLM - Get local context
222
+ # print(f'VLM {vlm} analysis begins ...')
223
+ # vlm_start_time = time.time()
224
+ # logging.info(f'STEP #1 VLM {vlm} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
225
+ # if vlm == 'llava7b':
226
+ # original_path = os.path.dirname(__file__)
227
+ # os.chdir(llava_path)
228
+ # os.system(llava7b_cmd)
229
+ # os.chdir(original_path)
230
+ # elif vlm == 'generate_q_file':
231
+ # from approach.vlm.gpt4v.gpt4v import process_image_q
232
+ # with open(vlm_question_path, 'r') as q_file, open(complete_vlm_question_path, 'w') as cq_file: # Open answer file in append mode
233
+ # qfile_lines = q_file.readlines()
234
+ # key_idx = 0
235
+ # for line in tqdm(qfile_lines):
236
+ # key_idx = (key_idx + 1) % 4
237
+
238
+ # ans_item = {}
239
+
240
+ # line_data = json.loads(line)
241
+ # image_path = os.path.join(images_dir, line_data['image'])
242
+ # image_question = line_data['text']
243
+
244
+ # if vlm == 'gpt4v_abl':
245
+ # gpt4v_ablation = True
246
+ # elif vlm == 'gpt4v':
247
+ # gpt4v_ablation = False
248
+ # gpt4v_q = process_image_q(image_question, image_path, key_idx)
249
+ # data = {
250
+ # "question_id": line_data['question_id'],
251
+ # "image": line_data['image'],
252
+ # "text": gpt4v_q,
253
+ # "category": "detail"
254
+ # }
255
+ # cq_file.write(json.dumps(data) + '\n')
256
+ # elif vlm == 'gpt4v' or vlm == 'gpt4v_abl' or vlm == 'claude35sonnet' or vlm == 'gemini15pro':
257
+ # from approach.vlm.gpt4v.gpt4v import process_image
258
+ # with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'a') as a_file: # Open answer file in append mode
259
+ # qfile_lines = q_file.readlines()
260
+ # key_idx = 0
261
+ # for line in tqdm(qfile_lines):
262
+ # key_idx = (key_idx + 1) % 4
263
+
264
+ # ans_item = {}
265
+
266
+ # line_data = json.loads(line)
267
+ # image_path = os.path.join(images_dir, line_data['image'])
268
+ # image_question = line_data['text']
269
+
270
+ # gpt4v_ablation = False
271
+ # if vlm == 'gpt4v_abl':
272
+ # gpt4v_ablation = True
273
+ # elif vlm == 'gpt4v':
274
+ # gpt4v_ablation = False
275
+ # gpt4v_res = process_image(vlm, image_question, image_path, gpt4v_ablation, key_idx)
276
+ # print(gpt4v_res)
277
+ # # time.sleep(3)
278
+
279
+ # ans_item = {
280
+ # "question_id": line_data['question_id'],
281
+ # "prompt": '',
282
+ # "text": gpt4v_res,
283
+ # "answer_id": generate_answer_id(),
284
+ # "model_id": vlm,
285
+ # "metadata": {}
286
+ # }
287
+
288
+ # a_file.write(json.dumps(ans_item) + '\n')
289
+ # a_file.flush()
290
+ # elif vlm == 'bing':
291
+ # from approach.vlm.bing.bing import context_conversation
292
+ # with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'a') as a_file: # Open answer file in append mode
293
+ # for line in tqdm(q_file):
294
+ # ans_item = {}
295
+
296
+ # line_data = json.loads(line)
297
+ # image_path = os.path.join(images_dir, line_data['image'])
298
+ # image_question = line_data['text']
299
+
300
+ # bing_res = context_conversation(image_question, image_path)
301
+ # print(bing_res)
302
+ # time.sleep(15)
303
+
304
+ # ans_item = {
305
+ # "question_id": line_data['question_id'],
306
+ # "prompt": image_question,
307
+ # "text": bing_res,
308
+ # "answer_id": generate_answer_id(),
309
+ # "model_id": vlm,
310
+ # "metadata": {}
311
+ # }
312
+
313
+ # a_file.write(json.dumps(ans_item) + '\n')
314
+ # elif vlm == 'gemini':
315
+ # import pathlib
316
+ # import textwrap
317
+
318
+ # import google.generativeai as genai
319
+
320
+ # GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY", "[GOOGLE_API_KEY]")
321
+ # genai.configure(api_key=GOOGLE_API_KEY)
322
+
323
+ # safety_settings = [
324
+ # {
325
+ # "category": "HARM_CATEGORY_DANGEROUS",
326
+ # "threshold": "BLOCK_NONE",
327
+ # },
328
+ # {
329
+ # "category": "HARM_CATEGORY_HARASSMENT",
330
+ # "threshold": "BLOCK_NONE",
331
+ # },
332
+ # {
333
+ # "category": "HARM_CATEGORY_HATE_SPEECH",
334
+ # "threshold": "BLOCK_NONE",
335
+ # },
336
+ # {
337
+ # "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
338
+ # "threshold": "BLOCK_NONE",
339
+ # },
340
+ # {
341
+ # "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
342
+ # "threshold": "BLOCK_NONE",
343
+ # },
344
+ # ]
345
+
346
+ # # before fse
347
+ # # model = genai.GenerativeModel('gemini-pro-vision')
348
+ # # fse
349
+ # model = genai.GenerativeModel('gemini-1.5-pro')
350
+
351
+ # with open(vlm_question_path, 'r') as q_file, open(gemini_vlm_answer_path, 'a') as a_file: # Open answer file in append mode
352
+ # qfile_lines = q_file.readlines()[0:2]
353
+ # for line in tqdm(qfile_lines):
354
+
355
+ # ans_item = {}
356
+
357
+ # line_data = json.loads(line)
358
+ # image_path = os.path.join(images_dir, line_data['image'])
359
+ # image_question = line_data['text']
360
+
361
+ # gemini_response = model.generate_content([image_question, PIL.Image.open(image_path)], safety_settings=safety_settings)
362
+ # gemini_response.resolve()
363
+ # try:
364
+ # gemini_response = gemini_response.text
365
+ # ans_item = {
366
+ # "question_id": line_data['question_id'],
367
+ # "prompt": image_question,
368
+ # "text": gemini_response,
369
+ # "answer_id": generate_answer_id(),
370
+ # "model_id": vlm,
371
+ # "metadata": {}
372
+ # }
373
+
374
+ # a_file.write(json.dumps(ans_item) + '\n')
375
+ # a_file.flush()
376
+ # except Exception as e:
377
+ # print(f"Error for image {image_path}. Error: {e}")
378
+ # # print(gemini_response)
379
+ # time.sleep(30)
380
+
381
+
382
+
383
+ # elif vlm.endswith('_pass'):
384
+ # print(f'Passing VLM {vlm} ...')
385
+ # else:
386
+ # raise Exception('Unrecognized VLM!')
387
+
388
+ # logging.info(f'STEP #1 VLM {vlm} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
389
+ # logging.info(f'STEP #1 VLM {vlm} analysis total time taken: {time.time() - vlm_start_time} seconds')
390
+
391
+
392
+
393
+
394
+
395
+ # Get label candidates
396
+ # if llm == 'gpt_3.5_turbo':
397
+ # from approach.llm.gpt_polling import infer_object_candidates
398
+ # elif llm == 'llama2':
399
+ # from approach.llm.llama import infer_object_candidates
400
+
401
+
402
+ # STEP #3
403
+ # if llm == 'gpt_3.5_turbo' or llm == 'gpt_3.5_turbo_abl':
404
+ # from approach.llm.gpt_polling import infer_objects
405
+
406
+ # if llm == 'gpt_3.5_turbo_abl':
407
+ # gpt35_ablation = True
408
+ # elif llm == 'gpt_3.5_turbo':
409
+ # gpt35_ablation = False
410
+ # infer_objects(vlm_question_path, vlm_answer_path, interactable_object_path, gpt35_ablation)
411
+ # elif llm == 'llama2':
412
+ # from approach.llm.llama import infer_objects
413
+ # exit(0)
414
+ # elif llm.endswith('_pass'):
415
+ # print(f'Passing LLM {llm} ...')
416
+ # else:
417
+ # raise Exception('Unrecognized LLM!')
418
+
419
+
420
+
421
+
422
+
423
+
424
+ # STEP #2
425
+ # Open-vocabulary object detection
426
+ ovod_start_time = time.time()
427
+ logging.info(f'STEP #2 OVOD {ovod} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
428
+ vlm_questions = {}
429
+ with open(complete_vlm_question_path, 'r') as q_file:
430
+ for line in q_file:
431
+ line_data = json.loads(line)
432
+ vlm_questions[line_data['question_id']] = line_data
433
+ # print(line_data['question_id'])
434
+
435
+ if ovod == 'grounding_dino':
436
+ from approach.ovod.GroundingDINO.demo.inference_on_a_image import process_grounding_dino
437
+
438
+ original_path = os.path.dirname(__file__)
439
+ os.chdir(grounding_dino_path)
440
+
441
+ # with open(llm_candidate_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
442
+ with open(interactable_object_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
443
+ llm_candidate = json.load(llm_candidate_file)
444
+ all_oovd_res = {}
445
+ for image_index in llm_candidate.keys():
446
+ print(image_index)
447
+ # TODO:
448
+ if (image_index != '1160'):
449
+ ovod_image_path = os.path.join(images_dir, vlm_questions[int(image_index)]["image"])
450
+ ovod_candidates = llm_candidate[image_index]['interactable_objects']
451
+ # grounding_dino_command = generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates)
452
+ # print(grounding_dino_command)
453
+ # os.system(grounding_dino_command)
454
+
455
+ gdino_res = process_grounding_dino(
456
+ config_file='groundingdino/config/GroundingDINO_SwinT_OGC.py',
457
+ checkpoint_path='weights/groundingdino_swint_ogc.pth',
458
+ image_path=ovod_image_path,
459
+ ovod_candidates=ovod_candidates,
460
+ output_dir=ovod_output_dir,
461
+ box_threshold=0.3,
462
+ text_threshold=0.25,
463
+ token_spans=None,
464
+ cpu_only=False
465
+ )
466
+ # print(gdino_res)
467
+
468
+ object_oovd_item = copy.deepcopy(llm_candidate[image_index])
469
+ object_oovd_item['oovd_result'] = gdino_res
470
+ print(object_oovd_item)
471
+ all_oovd_res[image_index] = object_oovd_item
472
+
473
+ json.dump(all_oovd_res, oovd_file, indent=4)
474
+
475
+
476
+ os.chdir(original_path)
477
+
478
+ elif ovod == 'ape_d' or ovod == 'ape_d_abl':
479
+ from approach.ovod.APE.demo.ape_inference import run_ape_model_inference
480
+
481
+ original_path = os.path.dirname(__file__)
482
+ os.chdir(active_ape_path)
483
+
484
+ all_ape_res = []
485
+ reflection_traces = []
486
+ # General
487
+ # with open(vlm_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
488
+ # GPT-4 eval
489
+ with open(gpt4_results_answer_path, 'r') as llm_candidate_file:
490
+ # Gemini abl i eval
491
+ # with open(interactability_abl_results_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
492
+
493
+ # llm_candidate = json.load(llm_candidate_file)
494
+ all_oovd_res = {}
495
+
496
+ candidate_lines = select_jsonl_lines(
497
+ llm_candidate_file.readlines(),
498
+ start_index=start_index,
499
+ end_index=end_index,
500
+ shard_index=shard_index,
501
+ num_shards=num_shards,
502
+ )
503
+
504
+ for line in tqdm(candidate_lines):
505
+ ans_item = {}
506
+
507
+ line_data = json.loads(line)
508
+
509
+ # for image_index in llm_candidate.keys():
510
+ # print(image_index)
511
+ # TODO:
512
+ # if (image_index != '1160'):
513
+ # image_index = line_data['question_id']
514
+
515
+ image_name = vlm_questions[line_data['question_id']]["image"]
516
+ ovod_image_path = os.path.join(images_dir, image_name)
517
+
518
+ # General
519
+ # try:
520
+ # if line_data['text'].startswith(" ```json"):
521
+ # ovod_candidates = json.loads(line_data['text'][8:-4])['objects']
522
+ # elif line_data['text'].startswith(' {\"objects\"'):
523
+ # ovod_candidates = json.loads(line_data['text'])['objects']
524
+ # else:
525
+ # print(f"Error for decoding IVO json for {image_name}.")
526
+ # except Exception as e:
527
+ # print(f"Error for decoding IVO json for image {image_name}. Error: {e}")
528
+ # continue
529
+
530
+
531
+ # GPT-4v
532
+ if line_data['text']:
533
+ ovod_candidates = line_data['text']['objects']
534
+ else:
535
+ continue
536
+ all_res = []
537
+ for ocd in ovod_candidates.keys():
538
+ referring_expr_str = ovod_candidates[ocd]
539
+
540
+ translator = str.maketrans('', '', string.punctuation)
541
+ if type(referring_expr_str) is str:
542
+ referring_expr_str = referring_expr_str.translate(translator)
543
+ else:
544
+ # dict
545
+ referring_expr_str = ' '.join(referring_expr_str.values())
546
+ referring_expr_str = referring_expr_str.translate(translator)
547
+ referring_expr_str = f'{ocd}: {referring_expr_str}'
548
+ # print(image_name, referring_expr_str)
549
+ all_res.append(referring_expr_str)
550
+
551
+ if ovod == 'ape_d':
552
+ ape_threshold = 0.15
553
+ elif ovod == 'ape_d_abl':
554
+ ape_threshold = 0.1
555
+
556
+ ape_res = []
557
+ try:
558
+ ape_res = run_ape_model_inference(
559
+ config_file='configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k.py',
560
+ input_path=ovod_image_path,
561
+ # GPU 0
562
+ output_path=f'./realfse_{vlm}_{ovod}_gpu0123',
563
+ confidence_threshold=ape_threshold,
564
+ text_prompt=', '.join(all_res),
565
+ with_box=True,
566
+ with_mask=False,
567
+ with_sseg=False,
568
+ opts=[
569
+ f"train.init_checkpoint='{active_ape_checkpoint}'",
570
+ "model.model_language.cache_dir=''",
571
+ "model.model_vision.select_box_nums_for_evaluation=500",
572
+ "model.model_vision.text_feature_bank_reset=True",
573
+ "model.model_vision.backbone.net.xattn=False",
574
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
575
+ "model.model_vision.transformer.decoder.pytorch_attn=True"
576
+ ]
577
+ )
578
+ except Exception as e:
579
+ print(f"Error for image {image_name}. Error: {e}")
580
+
581
+ def reflection_detector(candidates, previous):
582
+ if not candidates:
583
+ return previous
584
+ try:
585
+ refined = run_ape_model_inference(
586
+ config_file='configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k.py',
587
+ input_path=ovod_image_path,
588
+ output_path=f'./realfse_{vlm}_{ovod}_gpu0123',
589
+ confidence_threshold=ape_threshold,
590
+ text_prompt=', '.join(candidates),
591
+ with_box=True,
592
+ with_mask=False,
593
+ with_sseg=False,
594
+ opts=[
595
+ f"train.init_checkpoint='{active_ape_checkpoint}'",
596
+ "model.model_language.cache_dir=''",
597
+ "model.model_vision.select_box_nums_for_evaluation=500",
598
+ "model.model_vision.text_feature_bank_reset=True",
599
+ "model.model_vision.backbone.net.xattn=False",
600
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
601
+ "model.model_vision.transformer.decoder.pytorch_attn=True"
602
+ ]
603
+ )
604
+ return previous + refined
605
+ except Exception as e:
606
+ print(f"Error during reflection redetection for {image_name}. Error: {e}")
607
+ return previous
608
+
609
+ reflection_result = run_optional_reflection(
610
+ ovod_image_path,
611
+ ape_res,
612
+ detector=reflection_detector,
613
+ enabled=enable_reflection,
614
+ model_profile=reflection_profile,
615
+ max_iterations=max_reflection_iterations,
616
+ )
617
+ if reflection_result is not None:
618
+ ape_res = reflection_result["detections"]
619
+ reflection_traces.append(
620
+ {
621
+ "image": image_name,
622
+ "image_id": extract_image_id(image_name),
623
+ "trace": reflection_result["trace"],
624
+ "max_iterations_reached": reflection_result["max_iterations_reached"],
625
+ }
626
+ )
627
+
628
+ all_ape_res.extend(enrich_ape_results(ape_res, image_name, extract_image_id))
629
+ # object_oovd_item = copy.deepcopy(llm_candidate[image_index])
630
+ # object_oovd_item['ape_result'] = all_ape_res
631
+ # # print(object_oovd_item)
632
+ # all_oovd_res[image_index] = object_oovd_item
633
+
634
+ write_json_atomic(oovd_object_bbox_path, all_ape_res)
635
+ if enable_reflection:
636
+ write_json_atomic(f"{oovd_object_bbox_path}.reflection.json", reflection_traces)
637
+
638
+
639
+ os.chdir(original_path)
640
+
641
+ elif ovod.endswith('_pass'):
642
+ print(f'Passing OVOD {ovod} ...')
643
+ else:
644
+ raise Exception('Unrecognized OVOD!')
645
+
646
+ logging.info(f'STEP #2 OVOD {ovod} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
647
+ logging.info(f'STEP #2 OVOD {ovod} analysis total time taken: {time.time() - ovod_start_time} seconds')
648
+ # icse & fse
649
+ def extract_image_id(image_name):
650
+ # Split the image name into parts and form the image_id accordingly
651
+ parts = image_name.split('_')
652
+ print(image_name)
653
+ base, extension = parts[1].split('.')
654
+ return int(parts[0] + base.zfill(3))
655
+ # icse_rebuttal
656
+ # def extract_image_id(image_name):
657
+ # # Split the image name into parts by underscore
658
+ # parts = image_name.split('_')
659
+ # # Extracting the first part as the base and the numeric portion of the third part before the file extension
660
+ # base = parts[0] # This will give '625470'
661
+ # numeric_part = parts[2].split('.')[0] # This will give 'b3'
662
+ # # Removing non-numeric characters from 'b3'
663
+ # numeric_part = ''.join(filter(str.isdigit, numeric_part))
664
+ # # Zfill is used to ensure the numeric part has at least 3 digits, then combining with base
665
+ # print(int(base + numeric_part.zfill(3)))
666
+ # return int(base + numeric_part.zfill(3))
667
+
668
+
669
+ def main():
670
+ vlms = ['llava7b', 'bing', 'gpt4v']
671
+ llms = ['llama2', 'gpt_3.5_turbo']
672
+ ovods = ['grounding_dino', 'glip', 'ape_d']
673
+
674
+
675
+ # python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d
676
+ # python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d_abl
677
+ # python method.py -v claude35sonnet -l gpt_3.5_turbo -o ape_d
678
+ # python method.py -v gemini -l gpt_3.5_turbo -o ape_d
679
+ if __name__=='__main__':
680
+ # main()
681
+
682
+ parser = argparse.ArgumentParser("Method", add_help=True)
683
+ parser.add_argument("--vlm", "-v", type=str, required=True, help="vlm")
684
+ parser.add_argument("--llm", "-l", type=str, required=True, help="llm")
685
+ parser.add_argument("--ovod", "-o", type=str, required=True, help="ovod")
686
+ parser.add_argument("--start-index", type=int, default=None, help="first JSONL row to process")
687
+ parser.add_argument("--end-index", type=int, default=None, help="exclusive JSONL row end")
688
+ parser.add_argument("--shard-index", type=int, default=None, help="zero-based shard index")
689
+ parser.add_argument("--num-shards", type=int, default=None, help="total number of shards")
690
+ parser.add_argument("--enable-reflection", action="store_true", help="run PII.5/PII.6 advisor reflection loop")
691
+ parser.add_argument("--reflection-profile", default="default", help="model profile for the reflection advisor")
692
+ parser.add_argument("--max-reflection-iterations", type=int, default=10, help="max advisor reflection rounds")
693
+ parser.add_argument("--questions", dest="questions_path", help="question manifest JSONL")
694
+ parser.add_argument("--candidates", dest="candidates_path", help="candidate JSON/JSONL for the selected detector")
695
+ parser.add_argument("--images-dir", dest="images_path", help="directory containing XR screenshots")
696
+ parser.add_argument("--output", dest="output_path", help="prediction JSON path; selection suffixes are added automatically")
697
+ parser.add_argument("--ape-root", help="APE repository directory")
698
+ parser.add_argument("--ape-checkpoint", help="APE checkpoint path")
699
+ parser.add_argument("--log-file", help="optional log file; defaults to stderr")
700
+ args = parser.parse_args()
701
+
702
+ gpu = '1-3'
703
+ stage = '1'
704
+ idx = '0001'
705
+ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
706
+ datefmt='%m/%d/%Y %H:%M:%S',
707
+ level=logging.INFO,
708
+ filename=args.log_file,
709
+ )
710
+
711
+ method(
712
+ args.vlm,
713
+ args.llm,
714
+ args.ovod,
715
+ start_index=args.start_index,
716
+ end_index=args.end_index,
717
+ shard_index=args.shard_index,
718
+ num_shards=args.num_shards,
719
+ enable_reflection=args.enable_reflection,
720
+ reflection_profile=args.reflection_profile,
721
+ max_reflection_iterations=args.max_reflection_iterations,
722
+ questions_path=args.questions_path,
723
+ candidates_path=args.candidates_path,
724
+ images_path=args.images_path,
725
+ output_path=args.output_path,
726
+ ape_root=args.ape_root,
727
+ ape_checkpoint=args.ape_checkpoint,
728
+ )
729
+
730
+ # CUDA_VISIBLE_DEVICES=0 python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d > ../log/realfse/240910_gpt4v_2_g0_0001.txt
731
+ # CUDA_VISIBLE_DEVICES=3 python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d_abl > ../log/realfse/240910_gpt4v_ape_d_abl_2_g3_0001.txt
732
+ # CUDA_VISIBLE_DEVICES=3 python method.py -v gpt4v_abl -l gpt_3.5_turbo -o ape_d > ../log/realfse/240912_gpt4v_abl_1_g1-3_0001.txt
approach/method_claude.py ADDED
@@ -0,0 +1,656 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import sys
4
+ import json
5
+ import time
6
+ import random
7
+ import string
8
+ import argparse
9
+ import pandas as pd
10
+ import copy
11
+ import logging
12
+ from tqdm import tqdm
13
+ import PIL
14
+ from PIL import ImageFile
15
+ PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
16
+
17
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18
+ sys.path.append(BASE_DIR)
19
+ from approach.pipeline_utils import (
20
+ enrich_ape_results,
21
+ output_path_for_selection,
22
+ select_jsonl_lines,
23
+ write_json_atomic,
24
+ )
25
+
26
+ os.environ['TORCH_HOME'] = './.cache'
27
+ os.environ['HF_HOME'] = './.cache'
28
+
29
+
30
+ vlm = 'llava7b'
31
+ llm = 'gpt_3.5_turbo'
32
+ ovod = 'grounding_dino'
33
+
34
+ vlm_prompt = ''
35
+
36
+ ### Configurable
37
+ host_device = os.getenv('ORIENTER_LEGACY_HOST', 'local')
38
+ perspective = 'all_perspective'
39
+ # perspective = 'direct_back'
40
+ # perspective = 'direct_front'
41
+ # perspective = 'direct_side'
42
+ # perspective = 'direct_top'
43
+ # perspective = 'eyelevel'
44
+ # perspective = 'overlook'
45
+ ### Configurable
46
+
47
+ llava_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/llava/eval')
48
+ grounding_dino_path = os.path.join(BASE_DIR, 'approach/ovod/GroundingDINO')
49
+ ape_path = os.path.join(BASE_DIR, 'approach/ovod/APE')
50
+ # TODO: data on the CUHK server
51
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/interactable')
52
+ # icse
53
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/test_set_merged')
54
+ # icse_rebuttal
55
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_angleview/images/all_perspective')
56
+ # fse
57
+ images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_det/images/union3')
58
+
59
+
60
+ # def generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates):
61
+ # gdino_object_str = ' . '.join(ovod_candidates)
62
+
63
+ # gdino_command = f'''
64
+ # python demo/inference_on_a_image.py \
65
+ # -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
66
+ # -p weights/groundingdino_swint_ogc.pth \
67
+ # -i {ovod_image_path} \
68
+ # -o "{ovod_output_dir}" \
69
+ # -t "{gdino_object_str}"
70
+ # '''
71
+ # return gdino_command
72
+
73
+
74
+ def generate_question_file(img_folder, dst_path):
75
+ # Ensure the directory exists
76
+ if not os.path.exists(img_folder):
77
+ print(f"Error: Directory {img_folder} does not exist.")
78
+ return
79
+
80
+ # List all files in the directory
81
+ all_files = os.listdir(img_folder)
82
+
83
+ # Filter out files that are not images (based on extension). You can add more if needed.
84
+ image_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff"]
85
+ image_files = [f for f in all_files if any(f.lower().endswith(ext) for ext in image_extensions)]
86
+
87
+ # Open the output file for writing
88
+ with open(dst_path, 'w') as out_file:
89
+ for index, img_file in enumerate(image_files):
90
+ data = {
91
+ "question_id": index,
92
+ "image": img_file,
93
+ "text": vlm_prompt,
94
+ "category": "detail"
95
+ }
96
+ out_file.write(json.dumps(data) + '\n')
97
+
98
+ print(f"Processed {len(image_files)} images. Output saved to {dst_path}.")
99
+
100
+
101
+ def generate_answer_id(length=20):
102
+ # Define the characters that can be used in the string
103
+ characters = string.ascii_letters + string.digits
104
+ # Generate a random string of the specified length
105
+ answer_id = ''.join(random.choice(characters) for _ in range(length))
106
+ return answer_id
107
+
108
+
109
+ def method(vlm=vlm, llm=llm, ovod=ovod, start_index=None, end_index=None, shard_index=None, num_shards=None):
110
+ # vlm_question_path = os.path.join(BASE_DIR, 'approach/vlm/sampled_vlm_questions.jsonl')
111
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_vlm_questions_from671.jsonl')
112
+ # icse
113
+ # complete_vlm_question_abl_i_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions_ablation_interactability.jsonl')
114
+
115
+ # icse
116
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions.jsonl')
117
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
118
+ # icse_rebuttal
119
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_vlm_questions.jsonl')
120
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_complete_vlm_questions.jsonl')
121
+ # fse
122
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/fse_union3_{vlm}_questions.jsonl')
123
+ complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_union3_complete_{vlm}_questions.jsonl')
124
+ vlm_question_path = complete_vlm_question_path
125
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
126
+ # playground/data/coco2014_val_qa_eval/qa90_questions.jsonl
127
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_slowerspeed_1.jsonl')
128
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_higherspeed_r3_1_from195.jsonl')
129
+
130
+ # icse
131
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/cuhk_icse_test_set_merged_{vlm}_answer.jsonl')
132
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer.jsonl')
133
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_ablation_no_interactability_r1_0.jsonl')
134
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_cuhk_icse_test_set_merged_gpt4v_answer_higherspeed_r3_0.jsonl')
135
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_hit_icse_test_set_merged_gemini_answer_ablation_no_interactability_r1_0.jsonl')
136
+ # icse_rebuttal
137
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer.jsonl')
138
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
139
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
140
+ # fse
141
+ vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_uninon3_{vlm}_answer.jsonl')
142
+ llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_fse_uninon3_{vlm}_answer.jsonl')
143
+ gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_union3_{vlm}_answer.jsonl')
144
+
145
+ # icse
146
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_gpt4v_answer.jsonl')
147
+ # icse_rebuttal
148
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer_265_528.jsonl')
149
+ # fse
150
+ gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_uninon3_gpt4v_answer.jsonl')
151
+ # print(gpt4_results_answer_path)
152
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_answer.jsonl')
153
+
154
+ # icse
155
+ # # /path/to/answer-file-our.jsonl
156
+ # # llm_candidate_path = os.path.join(BASE_DIR, f'approach/llm/{vlm}_{llm}_cancidate_objects.json')
157
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_test_set_merged_{vlm}_{llm}_interactable_objects.json')
158
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_test_set_merged_{ovod}')
159
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
160
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
161
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_feedback_object_bbox_gpu2.json')
162
+
163
+ # icse_rebuttal
164
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_rbt_{perspective}_{vlm}_{llm}_interactable_objects.json')
165
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_rbt_{perspective}_{ovod}')
166
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
167
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
168
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_rbt_{perspective}_{vlm}_{llm}_{ovod}_object_bbox_gpu3_265_528.json')
169
+
170
+ gpu = '2'
171
+ # fse
172
+ interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/realfse_union3_{vlm}_{llm}_interactable_objects.json') # TODO: Tentatively unused
173
+ ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/realfse_union3_{ovod}')
174
+ # GPU 0
175
+ oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/realfse_union3_{vlm}_{ovod}_object_bbox_gpu{gpu}.json')
176
+ oovd_object_bbox_path = output_path_for_selection(
177
+ oovd_object_bbox_path,
178
+ start_index=start_index,
179
+ end_index=end_index,
180
+ shard_index=shard_index,
181
+ num_shards=num_shards,
182
+ )
183
+
184
+ llava7b_model_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/checkpoints/llava-v1.5-7b')
185
+ llava7b_cmd = f'''
186
+ python model_vqa.py \
187
+ --model-path {llava7b_model_path} \
188
+ --question-file \
189
+ {complete_vlm_question_path} \
190
+ --image-folder \
191
+ {images_dir} \
192
+ --answers-file \
193
+ {llava_vlm_answer_path}
194
+ '''
195
+
196
+ # STEP #0
197
+ # First time of running
198
+ # TODO: Check whether it is first-time running
199
+ # generate_question_file(images_dir, vlm_question_path)
200
+
201
+ # STEP #1
202
+ # VLM - Get local context
203
+ # print(f'VLM {vlm} analysis begins ...')
204
+ # vlm_start_time = time.time()
205
+ # logging.info(f'STEP #1 VLM {vlm} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
206
+ # if vlm == 'llava7b':
207
+ # original_path = os.path.dirname(__file__)
208
+ # os.chdir(llava_path)
209
+ # os.system(llava7b_cmd)
210
+ # os.chdir(original_path)
211
+ # elif vlm == 'generate_q_file':
212
+ # from approach.vlm.gpt4v.gpt4v import process_image_q
213
+ # with open(vlm_question_path, 'r') as q_file, open(complete_vlm_question_path, 'w') as cq_file: # Open answer file in append mode
214
+ # qfile_lines = q_file.readlines()
215
+ # key_idx = 0
216
+ # for line in tqdm(qfile_lines):
217
+ # key_idx = (key_idx + 1) % 4
218
+
219
+ # ans_item = {}
220
+
221
+ # line_data = json.loads(line)
222
+ # image_path = os.path.join(images_dir, line_data['image'])
223
+ # image_question = line_data['text']
224
+
225
+ # if vlm == 'gpt4v_abl':
226
+ # gpt4v_ablation = True
227
+ # elif vlm == 'gpt4v':
228
+ # gpt4v_ablation = False
229
+ # gpt4v_q = process_image_q(image_question, image_path, key_idx)
230
+ # data = {
231
+ # "question_id": line_data['question_id'],
232
+ # "image": line_data['image'],
233
+ # "text": gpt4v_q,
234
+ # "category": "detail"
235
+ # }
236
+ # cq_file.write(json.dumps(data) + '\n')
237
+ # elif vlm == 'gpt4v' or vlm == 'gpt4v_abl' or vlm == 'claude35sonnet' or vlm == 'gemini15pro':
238
+ # from approach.vlm.gpt4v.gpt4v import process_image
239
+ # with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'a') as a_file: # Open answer file in append mode
240
+ # qfile_lines = q_file.readlines()
241
+ # key_idx = 0
242
+ # for line in tqdm(qfile_lines):
243
+ # key_idx = (key_idx + 1) % 4
244
+
245
+ # ans_item = {}
246
+
247
+ # line_data = json.loads(line)
248
+ # image_path = os.path.join(images_dir, line_data['image'])
249
+ # image_question = line_data['text']
250
+
251
+ # gpt4v_ablation = False
252
+ # if vlm == 'gpt4v_abl':
253
+ # gpt4v_ablation = True
254
+ # elif vlm == 'gpt4v':
255
+ # gpt4v_ablation = False
256
+ # gpt4v_res = process_image(vlm, image_question, image_path, gpt4v_ablation, key_idx)
257
+ # print(gpt4v_res)
258
+ # # time.sleep(3)
259
+
260
+ # ans_item = {
261
+ # "question_id": line_data['question_id'],
262
+ # "prompt": '',
263
+ # "text": gpt4v_res,
264
+ # "answer_id": generate_answer_id(),
265
+ # "model_id": vlm,
266
+ # "metadata": {}
267
+ # }
268
+
269
+ # a_file.write(json.dumps(ans_item) + '\n')
270
+ # a_file.flush()
271
+ # elif vlm == 'bing':
272
+ # from approach.vlm.bing.bing import context_conversation
273
+ # with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'a') as a_file: # Open answer file in append mode
274
+ # for line in tqdm(q_file):
275
+ # ans_item = {}
276
+
277
+ # line_data = json.loads(line)
278
+ # image_path = os.path.join(images_dir, line_data['image'])
279
+ # image_question = line_data['text']
280
+
281
+ # bing_res = context_conversation(image_question, image_path)
282
+ # print(bing_res)
283
+ # time.sleep(15)
284
+
285
+ # ans_item = {
286
+ # "question_id": line_data['question_id'],
287
+ # "prompt": image_question,
288
+ # "text": bing_res,
289
+ # "answer_id": generate_answer_id(),
290
+ # "model_id": vlm,
291
+ # "metadata": {}
292
+ # }
293
+
294
+ # a_file.write(json.dumps(ans_item) + '\n')
295
+ # elif vlm == 'gemini':
296
+ # import pathlib
297
+ # import textwrap
298
+
299
+ # import google.generativeai as genai
300
+
301
+ # GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY", "[GOOGLE_API_KEY]")
302
+ # genai.configure(api_key=GOOGLE_API_KEY)
303
+
304
+ # safety_settings = [
305
+ # {
306
+ # "category": "HARM_CATEGORY_DANGEROUS",
307
+ # "threshold": "BLOCK_NONE",
308
+ # },
309
+ # {
310
+ # "category": "HARM_CATEGORY_HARASSMENT",
311
+ # "threshold": "BLOCK_NONE",
312
+ # },
313
+ # {
314
+ # "category": "HARM_CATEGORY_HATE_SPEECH",
315
+ # "threshold": "BLOCK_NONE",
316
+ # },
317
+ # {
318
+ # "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
319
+ # "threshold": "BLOCK_NONE",
320
+ # },
321
+ # {
322
+ # "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
323
+ # "threshold": "BLOCK_NONE",
324
+ # },
325
+ # ]
326
+
327
+ # # before fse
328
+ # # model = genai.GenerativeModel('gemini-pro-vision')
329
+ # # fse
330
+ # model = genai.GenerativeModel('gemini-1.5-pro')
331
+
332
+ # with open(vlm_question_path, 'r') as q_file, open(gemini_vlm_answer_path, 'a') as a_file: # Open answer file in append mode
333
+ # qfile_lines = q_file.readlines()[0:2]
334
+ # for line in tqdm(qfile_lines):
335
+
336
+ # ans_item = {}
337
+
338
+ # line_data = json.loads(line)
339
+ # image_path = os.path.join(images_dir, line_data['image'])
340
+ # image_question = line_data['text']
341
+
342
+ # gemini_response = model.generate_content([image_question, PIL.Image.open(image_path)], safety_settings=safety_settings)
343
+ # gemini_response.resolve()
344
+ # try:
345
+ # gemini_response = gemini_response.text
346
+ # ans_item = {
347
+ # "question_id": line_data['question_id'],
348
+ # "prompt": image_question,
349
+ # "text": gemini_response,
350
+ # "answer_id": generate_answer_id(),
351
+ # "model_id": vlm,
352
+ # "metadata": {}
353
+ # }
354
+
355
+ # a_file.write(json.dumps(ans_item) + '\n')
356
+ # a_file.flush()
357
+ # except Exception as e:
358
+ # print(f"Error for image {image_path}. Error: {e}")
359
+ # # print(gemini_response)
360
+ # time.sleep(30)
361
+
362
+
363
+
364
+ # elif vlm.endswith('_pass'):
365
+ # print(f'Passing VLM {vlm} ...')
366
+ # else:
367
+ # raise Exception('Unrecognized VLM!')
368
+
369
+ # logging.info(f'STEP #1 VLM {vlm} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
370
+ # logging.info(f'STEP #1 VLM {vlm} analysis total time taken: {time.time() - vlm_start_time} seconds')
371
+
372
+
373
+
374
+
375
+
376
+ # Get label candidates
377
+ # if llm == 'gpt_3.5_turbo':
378
+ # from approach.llm.gpt_polling import infer_object_candidates
379
+ # elif llm == 'llama2':
380
+ # from approach.llm.llama import infer_object_candidates
381
+
382
+
383
+ # STEP #3
384
+ # if llm == 'gpt_3.5_turbo' or llm == 'gpt_3.5_turbo_abl':
385
+ # from approach.llm.gpt_polling import infer_objects
386
+
387
+ # if llm == 'gpt_3.5_turbo_abl':
388
+ # gpt35_ablation = True
389
+ # elif llm == 'gpt_3.5_turbo':
390
+ # gpt35_ablation = False
391
+ # infer_objects(vlm_question_path, vlm_answer_path, interactable_object_path, gpt35_ablation)
392
+ # elif llm == 'llama2':
393
+ # from approach.llm.llama import infer_objects
394
+ # exit(0)
395
+ # elif llm.endswith('_pass'):
396
+ # print(f'Passing LLM {llm} ...')
397
+ # else:
398
+ # raise Exception('Unrecognized LLM!')
399
+
400
+
401
+
402
+
403
+
404
+
405
+ # STEP #2
406
+ # Open-vocabulary object detection
407
+ ovod_start_time = time.time()
408
+ logging.info(f'STEP #2 OVOD {ovod} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
409
+ vlm_questions = {}
410
+ with open(complete_vlm_question_path, 'r') as q_file:
411
+ for line in q_file:
412
+ line_data = json.loads(line)
413
+ vlm_questions[line_data['question_id']] = line_data
414
+ # print(line_data['question_id'])
415
+
416
+ if ovod == 'grounding_dino':
417
+ from approach.ovod.GroundingDINO.demo.inference_on_a_image import process_grounding_dino
418
+
419
+ original_path = os.path.dirname(__file__)
420
+ os.chdir(grounding_dino_path)
421
+
422
+ # with open(llm_candidate_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
423
+ with open(interactable_object_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
424
+ llm_candidate = json.load(llm_candidate_file)
425
+ all_oovd_res = {}
426
+ for image_index in llm_candidate.keys():
427
+ print(image_index)
428
+ # TODO:
429
+ if (image_index != '1160'):
430
+ ovod_image_path = os.path.join(images_dir, vlm_questions[int(image_index)]["image"])
431
+ ovod_candidates = llm_candidate[image_index]['interactable_objects']
432
+ # grounding_dino_command = generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates)
433
+ # print(grounding_dino_command)
434
+ # os.system(grounding_dino_command)
435
+
436
+ gdino_res = process_grounding_dino(
437
+ config_file='groundingdino/config/GroundingDINO_SwinT_OGC.py',
438
+ checkpoint_path='weights/groundingdino_swint_ogc.pth',
439
+ image_path=ovod_image_path,
440
+ ovod_candidates=ovod_candidates,
441
+ output_dir=ovod_output_dir,
442
+ box_threshold=0.3,
443
+ text_threshold=0.25,
444
+ token_spans=None,
445
+ cpu_only=False
446
+ )
447
+ # print(gdino_res)
448
+
449
+ object_oovd_item = copy.deepcopy(llm_candidate[image_index])
450
+ object_oovd_item['oovd_result'] = gdino_res
451
+ print(object_oovd_item)
452
+ all_oovd_res[image_index] = object_oovd_item
453
+
454
+ json.dump(all_oovd_res, oovd_file, indent=4)
455
+
456
+
457
+ os.chdir(original_path)
458
+
459
+ elif ovod == 'ape_d' or ovod == 'ape_d_abl':
460
+ from approach.ovod.APE.demo.ape_inference import run_ape_model_inference
461
+
462
+ original_path = os.path.dirname(__file__)
463
+ os.chdir(ape_path)
464
+
465
+ # with open(llm_candidate_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
466
+
467
+ all_ape_res = []
468
+ # General
469
+ with open(vlm_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
470
+ # GPT-4 eval
471
+ # with open(gpt4_results_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
472
+ # Gemini abl i eval
473
+ # with open(interactability_abl_results_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
474
+
475
+ # llm_candidate = json.load(llm_candidate_file)
476
+ all_oovd_res = {}
477
+
478
+
479
+ # candidate_lines = llm_candidate_file.readlines()[265:528]
480
+ # GPU 0
481
+ # candidate_lines = llm_candidate_file.readlines()[0:230]
482
+ # candidate_lines = llm_candidate_file.readlines()[230:460]
483
+ candidate_lines = select_jsonl_lines(
484
+ llm_candidate_file.readlines(),
485
+ start_index=start_index,
486
+ end_index=end_index,
487
+ shard_index=shard_index,
488
+ num_shards=num_shards,
489
+ )
490
+ # candidate_lines = llm_candidate_file.readlines()[690:919]
491
+ # candidate_lines = llm_candidate_file.readlines()
492
+ for line in tqdm(candidate_lines):
493
+ ans_item = {}
494
+
495
+ line_data = json.loads(line)
496
+
497
+ # for image_index in llm_candidate.keys():
498
+ # print(image_index)
499
+ # TODO:
500
+ # if (image_index != '1160'):
501
+ # image_index = line_data['question_id']
502
+
503
+ image_name = vlm_questions[line_data['question_id']]["image"]
504
+ ovod_image_path = os.path.join(images_dir, image_name)
505
+
506
+ # General
507
+ # try:
508
+ # if line_data['text'].startswith(" ```json"):
509
+ # ovod_candidates = json.loads(line_data['text'][8:-4])['objects']
510
+ # elif line_data['text'].startswith(' {\"objects\"'):
511
+ # ovod_candidates = json.loads(line_data['text'])['objects']
512
+ # else:
513
+ # print(f"Error for decoding IVO json for {image_name}.")
514
+ # except Exception as e:
515
+ # print(f"Error for decoding IVO json for image {image_name}. Error: {e}")
516
+ # continue
517
+
518
+
519
+ # GPT-4v
520
+ if line_data['text']:
521
+ ovod_candidates = line_data['text']['objects']
522
+ else:
523
+ continue
524
+
525
+
526
+ all_res = []
527
+ for ocd in ovod_candidates.keys():
528
+ referring_expr_str = ovod_candidates[ocd]
529
+
530
+ translator = str.maketrans('', '', string.punctuation)
531
+ if type(referring_expr_str) is str:
532
+ referring_expr_str = referring_expr_str.translate(translator)
533
+ else:
534
+ # dict
535
+ referring_expr_str = ' '.join(referring_expr_str.values())
536
+ referring_expr_str = referring_expr_str.translate(translator)
537
+ referring_expr_str = f'{ocd}: {referring_expr_str}'
538
+ # print(image_name, referring_expr_str)
539
+ all_res.append(referring_expr_str)
540
+
541
+ if ovod == 'ape_d':
542
+ ape_threshold = 0.15
543
+ elif ovod == 'ape_d_abl':
544
+ ape_threshold = 0.1
545
+
546
+ ape_res = []
547
+ try:
548
+ ape_res = run_ape_model_inference(
549
+ config_file='configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k.py',
550
+ input_path=ovod_image_path,
551
+ # GPU 0
552
+ output_path=f'./realfse_{vlm}_{ovod}_gpu0123',
553
+ confidence_threshold=ape_threshold,
554
+ text_prompt=', '.join(all_res),
555
+ with_box=True,
556
+ with_mask=False,
557
+ with_sseg=False,
558
+ opts=[
559
+ "train.init_checkpoint='./ape_d_model_final.pth'",
560
+ "model.model_language.cache_dir=''",
561
+ "model.model_vision.select_box_nums_for_evaluation=500",
562
+ "model.model_vision.text_feature_bank_reset=True",
563
+ "model.model_vision.backbone.net.xattn=False",
564
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
565
+ "model.model_vision.transformer.decoder.pytorch_attn=True"
566
+ ]
567
+ )
568
+ except Exception as e:
569
+ print(f"Error for image {image_name}. Error: {e}")
570
+
571
+ all_ape_res.extend(enrich_ape_results(ape_res, image_name, extract_image_id))
572
+ # object_oovd_item = copy.deepcopy(llm_candidate[image_index])
573
+ # object_oovd_item['ape_result'] = all_ape_res
574
+ # # print(object_oovd_item)
575
+ # all_oovd_res[image_index] = object_oovd_item
576
+
577
+ write_json_atomic(oovd_object_bbox_path, all_ape_res)
578
+
579
+
580
+ os.chdir(original_path)
581
+
582
+ elif ovod.endswith('_pass'):
583
+ print(f'Passing OVOD {ovod} ...')
584
+ else:
585
+ raise Exception('Unrecognized OVOD!')
586
+
587
+ logging.info(f'STEP #2 OVOD {ovod} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
588
+ logging.info(f'STEP #2 OVOD {ovod} analysis total time taken: {time.time() - ovod_start_time} seconds')
589
+
590
+ # icse & fse
591
+ def extract_image_id(image_name):
592
+ # Split the image name into parts and form the image_id accordingly
593
+ parts = image_name.split('_')
594
+ print(image_name)
595
+ base, extension = parts[1].split('.')
596
+ return int(parts[0] + base.zfill(3))
597
+ # icse_rebuttal
598
+ # def extract_image_id(image_name):
599
+ # # Split the image name into parts by underscore
600
+ # parts = image_name.split('_')
601
+ # # Extracting the first part as the base and the numeric portion of the third part before the file extension
602
+ # base = parts[0] # This will give '625470'
603
+ # numeric_part = parts[2].split('.')[0] # This will give 'b3'
604
+ # # Removing non-numeric characters from 'b3'
605
+ # numeric_part = ''.join(filter(str.isdigit, numeric_part))
606
+ # # Zfill is used to ensure the numeric part has at least 3 digits, then combining with base
607
+ # print(int(base + numeric_part.zfill(3)))
608
+ # return int(base + numeric_part.zfill(3))
609
+
610
+
611
+ def main():
612
+ vlms = ['llava7b', 'bing', 'gpt4v']
613
+ llms = ['llama2', 'gpt_3.5_turbo']
614
+ ovods = ['grounding_dino', 'glip', 'ape_d']
615
+
616
+
617
+ # python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d
618
+ # python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d_abl
619
+ # python method.py -v claude35sonnet -l gpt_3.5_turbo -o ape_d
620
+ # python method.py -v gemini -l gpt_3.5_turbo -o ape_d
621
+ if __name__=='__main__':
622
+ # main()
623
+
624
+ parser = argparse.ArgumentParser("Method", add_help=True)
625
+ parser.add_argument("--vlm", "-v", type=str, required=True, help="vlm")
626
+ parser.add_argument("--llm", "-l", type=str, required=True, help="llm")
627
+ parser.add_argument("--ovod", "-o", type=str, required=True, help="ovod")
628
+ parser.add_argument("--start-index", type=int, default=None, help="first JSONL row to process")
629
+ parser.add_argument("--end-index", type=int, default=None, help="exclusive JSONL row end")
630
+ parser.add_argument("--shard-index", type=int, default=None, help="zero-based shard index")
631
+ parser.add_argument("--num-shards", type=int, default=None, help="total number of shards")
632
+ args = parser.parse_args()
633
+
634
+ gpu = '2'
635
+ stage = '2'
636
+ idx = '0001'
637
+ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
638
+ datefmt='%m/%d/%Y %H:%M:%S',
639
+ level=logging.INFO,
640
+ # gpu
641
+ filename=f'../log/realfse/240910_{args.vlm}_{stage}_g{gpu}_{idx}.log'
642
+ )
643
+
644
+ method(
645
+ args.vlm,
646
+ args.llm,
647
+ args.ovod,
648
+ start_index=args.start_index,
649
+ end_index=args.end_index,
650
+ shard_index=args.shard_index,
651
+ num_shards=args.num_shards,
652
+ )
653
+
654
+ # CUDA_VISIBLE_DEVICES=0 python method.py -v gpt4v -l gpt_3.5_turbo -o ape_d > ../log/realfse/240910_gpt4v_2_g0_0001.txt
655
+ # CUDA_VISIBLE_DEVICES=3 python method_gemini.py -v gemini15pro -l gpt_3.5_turbo -o ape_d > ../log/realfse/240910_gemini15pro_2_g3_0001.txt
656
+ # CUDA_VISIBLE_DEVICES=2 python method_claude.py -v claude35sonnet -l gpt_3.5_turbo -o ape_d > ../log/realfse/240910_claude35sonnet_2_g2_0001.txt
approach/method_fastuse.py ADDED
@@ -0,0 +1,736 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import random
6
+ import string
7
+ import argparse
8
+ import copy
9
+ import logging
10
+ from tqdm import tqdm
11
+ import PIL
12
+ from PIL import ImageFile
13
+ PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
14
+
15
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17
+ sys.path.append(BASE_DIR)
18
+ from approach.pipeline_utils import (
19
+ enrich_ape_results,
20
+ output_path_for_selection,
21
+ run_optional_reflection,
22
+ select_jsonl_lines,
23
+ write_json_atomic,
24
+ )
25
+
26
+ os.environ['TORCH_HOME'] = './.cache'
27
+ os.environ['HF_HOME'] = './.cache'
28
+
29
+
30
+ vlm = 'llava7b'
31
+ llm = 'gemini-3-flash-preview-nothinking'
32
+ ovod = 'ape_d'
33
+
34
+ vlm_prompt = ''
35
+
36
+ ### Configurable
37
+ host_device = os.getenv('ORIENTER_LEGACY_HOST', 'local')
38
+ perspective = 'all_perspective'
39
+ # perspective = 'direct_back'
40
+ # perspective = 'direct_front'
41
+ # perspective = 'direct_side'
42
+ # perspective = 'direct_top'
43
+ # perspective = 'eyelevel'
44
+ # perspective = 'overlook'
45
+ ### Configurable
46
+
47
+ llava_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/llava/eval')
48
+ grounding_dino_path = os.path.join(BASE_DIR, 'approach/ovod/GroundingDINO')
49
+ ape_path = os.path.join(BASE_DIR, 'approach/ovod/APE')
50
+ # TODO: data on the CUHK server
51
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/interactable')
52
+ # icse
53
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_merged/images/test_set_merged')
54
+ # icse_rebuttal
55
+ # images_dir = os.path.join(BASE_DIR, 'dataset/data/coco_angleview/images/all_perspective')
56
+ # fse
57
+ images_dir = os.path.join(BASE_DIR, 'fastimg')
58
+
59
+
60
+ # def generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates):
61
+ # gdino_object_str = ' . '.join(ovod_candidates)
62
+
63
+ # gdino_command = f'''
64
+ # python demo/inference_on_a_image.py \
65
+ # -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
66
+ # -p weights/groundingdino_swint_ogc.pth \
67
+ # -i {ovod_image_path} \
68
+ # -o "{ovod_output_dir}" \
69
+ # -t "{gdino_object_str}"
70
+ # '''
71
+ # return gdino_command
72
+
73
+
74
+ def generate_question_file(img_folder, dst_path):
75
+ # Ensure the directory exists
76
+ if not os.path.exists(img_folder):
77
+ print(f"Error: Directory {img_folder} does not exist.")
78
+ return
79
+
80
+ # List all files in the directory
81
+ all_files = os.listdir(img_folder)
82
+
83
+ # Filter out files that are not images (based on extension). You can add more if needed.
84
+ image_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff"]
85
+ image_files = [f for f in all_files if any(f.lower().endswith(ext) for ext in image_extensions)]
86
+
87
+ # Open the output file for writing
88
+ with open(dst_path, 'w') as out_file:
89
+ for index, img_file in enumerate(image_files):
90
+ data = {
91
+ "question_id": index,
92
+ "image": img_file,
93
+ "text": vlm_prompt,
94
+ "category": "detail"
95
+ }
96
+ out_file.write(json.dumps(data) + '\n')
97
+
98
+ print(f"Processed {len(image_files)} images. Output saved to {dst_path}.")
99
+
100
+
101
+ def generate_answer_id(length=20):
102
+ # Define the characters that can be used in the string
103
+ characters = string.ascii_letters + string.digits
104
+ # Generate a random string of the specified length
105
+ answer_id = ''.join(random.choice(characters) for _ in range(length))
106
+ return answer_id
107
+
108
+
109
+ def method(
110
+ vlm=vlm,
111
+ llm=llm,
112
+ ovod=ovod,
113
+ start_index=None,
114
+ end_index=None,
115
+ shard_index=None,
116
+ num_shards=None,
117
+ enable_reflection=False,
118
+ reflection_profile="default",
119
+ max_reflection_iterations=10,
120
+ questions_path=None,
121
+ candidates_path=None,
122
+ images_path=None,
123
+ output_path=None,
124
+ ape_root=None,
125
+ ape_checkpoint=None,
126
+ ):
127
+ images_dir = images_path or globals()["images_dir"]
128
+ active_ape_path = ape_root or globals()["ape_path"]
129
+ active_ape_checkpoint = ape_checkpoint or "./ape_d_model_final.pth"
130
+ # vlm_question_path = os.path.join(BASE_DIR, 'approach/vlm/sampled_vlm_questions.jsonl')
131
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_vlm_questions_from671.jsonl')
132
+ # icse
133
+ # complete_vlm_question_abl_i_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions_ablation_interactability.jsonl')
134
+
135
+ # icse
136
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_test_set_merged_complete_vlm_questions.jsonl')
137
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
138
+ # icse_rebuttal
139
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_vlm_questions.jsonl')
140
+ # complete_vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_complete_vlm_questions.jsonl')
141
+ # fse
142
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/fse_fastuse_{vlm}_questions.jsonl')
143
+ complete_vlm_question_path = questions_path or os.path.join(BASE_DIR, f'approach/vlm/realfse_fastuse_complete_{vlm}_questions.jsonl')
144
+ vlm_question_path = complete_vlm_question_path
145
+ # vlm_question_path = os.path.join(BASE_DIR, f'approach/vlm/gpt4v_failure_questions.jsonl')
146
+ # playground/data/coco2014_val_qa_eval/qa90_questions.jsonl
147
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_slowerspeed_1.jsonl')
148
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_higherspeed_r3_1_from195.jsonl')
149
+
150
+ # icse
151
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/cuhk_icse_test_set_merged_{vlm}_answer.jsonl')
152
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer.jsonl')
153
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_test_set_merged_{vlm}_answer_ablation_no_interactability_r1_0.jsonl')
154
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_cuhk_icse_test_set_merged_gpt4v_answer_higherspeed_r3_0.jsonl')
155
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_hit_icse_test_set_merged_gemini_answer_ablation_no_interactability_r1_0.jsonl')
156
+ # icse_rebuttal
157
+ # vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer.jsonl')
158
+ # llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
159
+ # gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_icse_rbt_{perspective}_{vlm}_answer.jsonl')
160
+ # fse
161
+ vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_fastuse_{vlm}_answer.jsonl')
162
+ llava_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/{host_device}_fse_fastuse_{vlm}_answer.jsonl')
163
+ gemini_vlm_answer_path = os.path.join(BASE_DIR, f'approach/vlm/realfse_fastuse_{vlm}_answer.jsonl')
164
+
165
+ # icse
166
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_gpt4v_answer.jsonl')
167
+ # icse_rebuttal
168
+ # gpt4_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/icse_rbt_{perspective}_{vlm}_answer_265_528.jsonl')
169
+ # fse
170
+ gpt4_results_answer_path = candidates_path or os.path.join(BASE_DIR, f'approach/vlm/realfse_fastuse_gpt4v_answer.jsonl')
171
+ # print(gpt4_results_answer_path)
172
+ # interactability_abl_results_answer_path = os.path.join(BASE_DIR, f'approach/vlm/aaa_icse_rbt_{perspective}_answer.jsonl')
173
+
174
+ # icse
175
+ # # /path/to/answer-file-our.jsonl
176
+ # # llm_candidate_path = os.path.join(BASE_DIR, f'approach/llm/{vlm}_{llm}_cancidate_objects.json')
177
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_test_set_merged_{vlm}_{llm}_interactable_objects.json')
178
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_test_set_merged_{ovod}')
179
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
180
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
181
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_feedback_object_bbox_gpu2.json')
182
+
183
+ # icse_rebuttal
184
+ # interactable_object_path = os.path.join(BASE_DIR, f'approach/llm/icse_rbt_{perspective}_{vlm}_{llm}_interactable_objects.json')
185
+ # ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/icse_rbt_{perspective}_{ovod}')
186
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_object_bbox_gpu3_2.json')
187
+ # # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_test_set_merged_{vlm}_{llm}_{ovod}_ablation_no_interactability_object_bbox_gpu0.json')
188
+ # oovd_object_bbox_path = os.path.join(BASE_DIR, f'approach/ovod/icse_rbt_{perspective}_{vlm}_{llm}_{ovod}_object_bbox_gpu3_265_528.json')
189
+
190
+ gemini31_results_answer_path = candidates_path or os.path.join(BASE_DIR, f'approach/vlm/realfse_fastuse_gemini31pro_answer.jsonl')
191
+ gpu = '1-3'
192
+ # fse
193
+ interactable_object_path = candidates_path or os.path.join(BASE_DIR, f'approach/llm/realfse_fastuse_{vlm}_{llm}_interactable_objects.json') # TODO: Tentatively unused
194
+ ovod_output_dir = os.path.join(BASE_DIR, f'approach/ovod/output/realfse_fastuse_{ovod}')
195
+ # GPU 0
196
+ base_output_path = output_path or os.path.join(BASE_DIR, f'approach/ovod/realfse_fastuse_{vlm}_{ovod}_object_bbox_gpu{gpu}.json')
197
+ oovd_object_bbox_path = output_path_for_selection(
198
+ base_output_path,
199
+ start_index=start_index,
200
+ end_index=end_index,
201
+ shard_index=shard_index,
202
+ num_shards=num_shards,
203
+ )
204
+
205
+ os.makedirs(ovod_output_dir, exist_ok=True)
206
+ llava7b_model_path = os.path.join(BASE_DIR, 'approach/vlm/LLaVA/checkpoints/llava-v1.5-7b')
207
+ llava7b_cmd = f'''
208
+ python model_vqa.py \
209
+ --model-path {llava7b_model_path} \
210
+ --question-file \
211
+ {complete_vlm_question_path} \
212
+ --image-folder \
213
+ {images_dir} \
214
+ --answers-file \
215
+ {llava_vlm_answer_path}
216
+ '''
217
+
218
+ # # STEP #0
219
+ # # First time of running
220
+ # # TODO: Check whether it is first-time running
221
+ generate_question_file(images_dir, vlm_question_path)
222
+
223
+ # STEP #1
224
+ # VLM - Get local context
225
+ print(f'VLM {vlm} analysis begins ...')
226
+ vlm_start_time = time.time()
227
+ logging.info(f'STEP #1 VLM {vlm} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
228
+ if vlm == 'llava7b':
229
+ original_path = os.path.dirname(__file__)
230
+ os.chdir(llava_path)
231
+ os.system(llava7b_cmd)
232
+ os.chdir(original_path)
233
+ elif vlm == 'generate_q_file':
234
+ from approach.vlm.gpt4v.gpt4v import process_image_q
235
+ with open(vlm_question_path, 'r') as q_file, open(complete_vlm_question_path, 'w') as cq_file: # Open answer file in append mode
236
+ qfile_lines = q_file.readlines()
237
+ key_idx = 0
238
+ for line in tqdm(qfile_lines):
239
+ key_idx = (key_idx + 1) % 4
240
+
241
+ ans_item = {}
242
+
243
+ line_data = json.loads(line)
244
+ image_path = os.path.join(images_dir, line_data['image'])
245
+ image_question = line_data['text']
246
+
247
+ if vlm == 'gpt4v_abl':
248
+ gpt4v_ablation = True
249
+ elif vlm == 'gpt4v':
250
+ gpt4v_ablation = False
251
+ gpt4v_q = process_image_q(image_question, image_path, key_idx)
252
+ data = {
253
+ "question_id": line_data['question_id'],
254
+ "image": line_data['image'],
255
+ "text": gpt4v_q,
256
+ "category": "detail"
257
+ }
258
+ cq_file.write(json.dumps(data) + '\n')
259
+ elif vlm == 'gpt4v' or vlm == 'gpt4v_abl' or vlm == 'claude35sonnet' or vlm == 'gemini15pro' or vlm == 'gemini31pro':
260
+ from approach.vlm.gpt4v.gpt4v import process_image
261
+ with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'w') as a_file: # Open answer file in append mode
262
+ qfile_lines = q_file.readlines()
263
+ key_idx = 0
264
+ for line in tqdm(qfile_lines):
265
+ key_idx = (key_idx + 1) % 4
266
+
267
+ ans_item = {}
268
+
269
+ line_data = json.loads(line)
270
+ image_path = os.path.join(images_dir, line_data['image'])
271
+ image_question = line_data['text']
272
+
273
+ gpt4v_ablation = False
274
+ if vlm == 'gpt4v_abl':
275
+ gpt4v_ablation = True
276
+ elif vlm == 'gpt4v':
277
+ gpt4v_ablation = False
278
+ gpt4v_res = process_image(vlm, image_question, image_path, gpt4v_ablation, key_idx)
279
+ print(gpt4v_res)
280
+ # time.sleep(3)
281
+
282
+ ans_item = {
283
+ "question_id": line_data['question_id'],
284
+ "prompt": '',
285
+ "text": gpt4v_res,
286
+ "answer_id": generate_answer_id(),
287
+ "model_id": vlm,
288
+ "metadata": {}
289
+ }
290
+
291
+ a_file.write(json.dumps(ans_item) + '\n')
292
+ a_file.flush()
293
+ elif vlm == 'bing':
294
+ from approach.vlm.bing.bing import context_conversation
295
+ with open(vlm_question_path, 'r') as q_file, open(vlm_answer_path, 'a') as a_file: # Open answer file in append mode
296
+ for line in tqdm(q_file):
297
+ ans_item = {}
298
+
299
+ line_data = json.loads(line)
300
+ image_path = os.path.join(images_dir, line_data['image'])
301
+ image_question = line_data['text']
302
+
303
+ bing_res = context_conversation(image_question, image_path)
304
+ print(bing_res)
305
+ time.sleep(15)
306
+
307
+ ans_item = {
308
+ "question_id": line_data['question_id'],
309
+ "prompt": image_question,
310
+ "text": bing_res,
311
+ "answer_id": generate_answer_id(),
312
+ "model_id": vlm,
313
+ "metadata": {}
314
+ }
315
+
316
+ a_file.write(json.dumps(ans_item) + '\n')
317
+ elif vlm == 'gemini':
318
+ import pathlib
319
+ import textwrap
320
+
321
+ import google.generativeai as genai
322
+
323
+ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY", "[GOOGLE_API_KEY]")
324
+ genai.configure(api_key=GOOGLE_API_KEY)
325
+
326
+ safety_settings = [
327
+ {
328
+ "category": "HARM_CATEGORY_DANGEROUS",
329
+ "threshold": "BLOCK_NONE",
330
+ },
331
+ {
332
+ "category": "HARM_CATEGORY_HARASSMENT",
333
+ "threshold": "BLOCK_NONE",
334
+ },
335
+ {
336
+ "category": "HARM_CATEGORY_HATE_SPEECH",
337
+ "threshold": "BLOCK_NONE",
338
+ },
339
+ {
340
+ "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
341
+ "threshold": "BLOCK_NONE",
342
+ },
343
+ {
344
+ "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
345
+ "threshold": "BLOCK_NONE",
346
+ },
347
+ ]
348
+
349
+ # before fse
350
+ # model = genai.GenerativeModel('gemini-pro-vision')
351
+ # fse
352
+ model = genai.GenerativeModel('gemini-1.5-pro')
353
+
354
+ with open(vlm_question_path, 'r') as q_file, open(gemini_vlm_answer_path, 'w') as a_file: # Open answer file in append mode
355
+ qfile_lines = q_file.readlines()[0:2]
356
+ for line in tqdm(qfile_lines):
357
+
358
+ ans_item = {}
359
+
360
+ line_data = json.loads(line)
361
+ image_path = os.path.join(images_dir, line_data['image'])
362
+ image_question = line_data['text']
363
+
364
+ gemini_response = model.generate_content([image_question, PIL.Image.open(image_path)], safety_settings=safety_settings)
365
+ gemini_response.resolve()
366
+ try:
367
+ gemini_response = gemini_response.text
368
+ ans_item = {
369
+ "question_id": line_data['question_id'],
370
+ "prompt": image_question,
371
+ "text": gemini_response,
372
+ "answer_id": generate_answer_id(),
373
+ "model_id": vlm,
374
+ "metadata": {}
375
+ }
376
+
377
+ a_file.write(json.dumps(ans_item) + '\n')
378
+ a_file.flush()
379
+ except Exception as e:
380
+ print(f"Error for image {image_path}. Error: {e}")
381
+ # print(gemini_response)
382
+ time.sleep(30)
383
+
384
+
385
+
386
+ elif vlm.endswith('_pass'):
387
+ print(f'Passing VLM {vlm} ...')
388
+ else:
389
+ raise Exception('Unrecognized VLM!')
390
+
391
+ logging.info(f'STEP #1 VLM {vlm} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
392
+ logging.info(f'STEP #1 VLM {vlm} analysis total time taken: {time.time() - vlm_start_time} seconds')
393
+
394
+
395
+
396
+
397
+
398
+ # Get label candidates
399
+ # if llm == 'gemini-3-flash-preview-nothinking':
400
+ # from approach.llm.gpt_polling import infer_object_candidates
401
+ # elif llm == 'llama2':
402
+ # from approach.llm.llama import infer_object_candidates
403
+
404
+
405
+ # STEP #3
406
+ if llm == 'gemini-3-flash-preview-nothinking' or llm == 'gemini-3-flash-preview-nothinking_abl':
407
+ from approach.llm.gpt_polling import infer_objects
408
+
409
+ if llm == 'gemini-3-flash-preview-nothinking_abl':
410
+ gpt35_ablation = True
411
+ elif llm == 'gemini-3-flash-preview-nothinking':
412
+ gpt35_ablation = False
413
+ infer_objects(vlm_question_path, vlm_answer_path, interactable_object_path, gpt35_ablation)
414
+ elif llm == 'llama2':
415
+ from approach.llm.llama import infer_objects
416
+ exit(0)
417
+ elif llm.endswith('_pass'):
418
+ print(f'Passing LLM {llm} ...')
419
+ else:
420
+ raise Exception('Unrecognized LLM!')
421
+
422
+
423
+
424
+
425
+
426
+
427
+ # STEP #2
428
+ # Open-vocabulary object detection
429
+ ovod_start_time = time.time()
430
+ logging.info(f'STEP #2 OVOD {ovod} analysis started at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
431
+ vlm_questions = {}
432
+ with open(complete_vlm_question_path, 'r') as q_file:
433
+ for line in q_file:
434
+ line_data = json.loads(line)
435
+ vlm_questions[line_data['question_id']] = line_data
436
+ # print(line_data['question_id'])
437
+
438
+ if ovod == 'grounding_dino':
439
+ from approach.ovod.GroundingDINO.demo.inference_on_a_image import process_grounding_dino
440
+
441
+ original_path = os.path.dirname(__file__)
442
+ os.chdir(grounding_dino_path)
443
+
444
+ # with open(llm_candidate_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
445
+ with open(interactable_object_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
446
+ llm_candidate = json.load(llm_candidate_file)
447
+ all_oovd_res = {}
448
+ for image_index in llm_candidate.keys():
449
+ print(image_index)
450
+ # TODO:
451
+ if (image_index != '1160'):
452
+ ovod_image_path = os.path.join(images_dir, vlm_questions[int(image_index)]["image"])
453
+ ovod_candidates = llm_candidate[image_index]['interactable_objects']
454
+ # grounding_dino_command = generate_grounding_dino_command(ovod_image_path, ovod_output_dir, ovod_candidates)
455
+ # print(grounding_dino_command)
456
+ # os.system(grounding_dino_command)
457
+
458
+ gdino_res = process_grounding_dino(
459
+ config_file='groundingdino/config/GroundingDINO_SwinT_OGC.py',
460
+ checkpoint_path='weights/groundingdino_swint_ogc.pth',
461
+ image_path=ovod_image_path,
462
+ ovod_candidates=ovod_candidates,
463
+ output_dir=ovod_output_dir,
464
+ box_threshold=0.3,
465
+ text_threshold=0.25,
466
+ token_spans=None,
467
+ cpu_only=False
468
+ )
469
+ # print(gdino_res)
470
+
471
+ object_oovd_item = copy.deepcopy(llm_candidate[image_index])
472
+ object_oovd_item['oovd_result'] = gdino_res
473
+ print(object_oovd_item)
474
+ all_oovd_res[image_index] = object_oovd_item
475
+
476
+ json.dump(all_oovd_res, oovd_file, indent=4)
477
+
478
+
479
+ os.chdir(original_path)
480
+
481
+ elif ovod == 'ape_d' or ovod == 'ape_d_abl':
482
+ from approach.ovod.APE.demo.ape_inference import run_ape_model_inference
483
+
484
+ original_path = os.path.dirname(__file__)
485
+ os.chdir(active_ape_path)
486
+
487
+ all_ape_res = []
488
+ reflection_traces = []
489
+ # General
490
+ # with open(vlm_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
491
+ # GPT-4 eval
492
+ with open(gemini31_results_answer_path, 'r') as llm_candidate_file:
493
+ # Gemini abl i eval
494
+ # with open(interactability_abl_results_answer_path, 'r') as llm_candidate_file, open(oovd_object_bbox_path, 'w') as oovd_file:
495
+
496
+ # llm_candidate = json.load(llm_candidate_file)
497
+ all_oovd_res = {}
498
+
499
+ candidate_lines = select_jsonl_lines(
500
+ llm_candidate_file.readlines(),
501
+ start_index=start_index,
502
+ end_index=end_index,
503
+ shard_index=shard_index,
504
+ num_shards=num_shards,
505
+ )
506
+
507
+ for line in tqdm(candidate_lines):
508
+ ans_item = {}
509
+
510
+ line_data = json.loads(line)
511
+
512
+ # for image_index in llm_candidate.keys():
513
+ # print(image_index)
514
+ # TODO:
515
+ # if (image_index != '1160'):
516
+ # image_index = line_data['question_id']
517
+
518
+ image_name = vlm_questions[line_data['question_id']]["image"]
519
+ ovod_image_path = os.path.join(images_dir, image_name)
520
+
521
+ # General
522
+ # try:
523
+ # if line_data['text'].startswith(" ```json"):
524
+ # ovod_candidates = json.loads(line_data['text'][8:-4])['objects']
525
+ # elif line_data['text'].startswith(' {\"objects\"'):
526
+ # ovod_candidates = json.loads(line_data['text'])['objects']
527
+ # else:
528
+ # print(f"Error for decoding IVO json for {image_name}.")
529
+ # except Exception as e:
530
+ # print(f"Error for decoding IVO json for image {image_name}. Error: {e}")
531
+ # continue
532
+
533
+
534
+ # GPT-4v
535
+ if line_data['text']:
536
+ ovod_candidates = line_data['text']['objects']
537
+ else:
538
+ continue
539
+ all_res = []
540
+ for ocd in ovod_candidates.keys():
541
+ referring_expr_str = ovod_candidates[ocd]
542
+
543
+ translator = str.maketrans('', '', string.punctuation)
544
+ if type(referring_expr_str) is str:
545
+ referring_expr_str = referring_expr_str.translate(translator)
546
+ else:
547
+ # dict
548
+ referring_expr_str = ' '.join(referring_expr_str.values())
549
+ referring_expr_str = referring_expr_str.translate(translator)
550
+ referring_expr_str = f'{ocd}: {referring_expr_str}'
551
+ # print(image_name, referring_expr_str)
552
+ all_res.append(referring_expr_str)
553
+
554
+ if ovod == 'ape_d':
555
+ ape_threshold = 0.1
556
+ elif ovod == 'ape_d_abl':
557
+ ape_threshold = 0.1
558
+
559
+ ape_res = []
560
+ try:
561
+ os.makedirs(f'./realfse_{vlm}_{ovod}_gpu0123', exist_ok=True)
562
+ ape_res = run_ape_model_inference(
563
+ config_file='configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k.py',
564
+ input_path=ovod_image_path,
565
+ # GPU 0
566
+ output_path=f'./realfse_{vlm}_{ovod}_gpu0123',
567
+ confidence_threshold=ape_threshold,
568
+ text_prompt=', '.join(all_res),
569
+ with_box=True,
570
+ with_mask=False,
571
+ with_sseg=False,
572
+ opts=[
573
+ f"train.init_checkpoint='{active_ape_checkpoint}'",
574
+ "model.model_language.cache_dir=''",
575
+ "model.model_vision.select_box_nums_for_evaluation=500",
576
+ "model.model_vision.text_feature_bank_reset=True",
577
+ "model.model_vision.backbone.net.xattn=False",
578
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
579
+ "model.model_vision.transformer.decoder.pytorch_attn=True"
580
+ ]
581
+ )
582
+ except Exception as e:
583
+ print(f"Error for image {image_name}. Error: {e}")
584
+
585
+ def reflection_detector(candidates, previous):
586
+ if not candidates:
587
+ return previous
588
+ try:
589
+ refined = run_ape_model_inference(
590
+ config_file='configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k.py',
591
+ input_path=ovod_image_path,
592
+ output_path=f'./realfse_{vlm}_{ovod}_gpu0123',
593
+ confidence_threshold=ape_threshold,
594
+ text_prompt=', '.join(candidates),
595
+ with_box=True,
596
+ with_mask=False,
597
+ with_sseg=False,
598
+ opts=[
599
+ f"train.init_checkpoint='{active_ape_checkpoint}'",
600
+ "model.model_language.cache_dir=''",
601
+ "model.model_vision.select_box_nums_for_evaluation=500",
602
+ "model.model_vision.text_feature_bank_reset=True",
603
+ "model.model_vision.backbone.net.xattn=False",
604
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
605
+ "model.model_vision.transformer.decoder.pytorch_attn=True"
606
+ ]
607
+ )
608
+ return previous + refined
609
+ except Exception as e:
610
+ print(f"Error during reflection redetection for {image_name}. Error: {e}")
611
+ return previous
612
+
613
+ reflection_result = run_optional_reflection(
614
+ ovod_image_path,
615
+ ape_res,
616
+ detector=reflection_detector,
617
+ enabled=enable_reflection,
618
+ model_profile=reflection_profile,
619
+ max_iterations=max_reflection_iterations,
620
+ )
621
+ if reflection_result is not None:
622
+ ape_res = reflection_result["detections"]
623
+ reflection_traces.append(
624
+ {
625
+ "image": image_name,
626
+ "image_id": extract_image_id(image_name),
627
+ "trace": reflection_result["trace"],
628
+ "max_iterations_reached": reflection_result["max_iterations_reached"],
629
+ }
630
+ )
631
+
632
+ all_ape_res.extend(enrich_ape_results(ape_res, image_name, extract_image_id))
633
+ # object_oovd_item = copy.deepcopy(llm_candidate[image_index])
634
+ # object_oovd_item['ape_result'] = all_ape_res
635
+ # # print(object_oovd_item)
636
+ # all_oovd_res[image_index] = object_oovd_item
637
+
638
+ write_json_atomic(oovd_object_bbox_path, all_ape_res)
639
+ if enable_reflection:
640
+ write_json_atomic(f"{oovd_object_bbox_path}.reflection.json", reflection_traces)
641
+
642
+
643
+ os.chdir(original_path)
644
+
645
+ elif ovod.endswith('_pass'):
646
+ print(f'Passing OVOD {ovod} ...')
647
+ else:
648
+ raise Exception('Unrecognized OVOD!')
649
+
650
+ logging.info(f'STEP #2 OVOD {ovod} analysis completed at %s', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
651
+ logging.info(f'STEP #2 OVOD {ovod} analysis total time taken: {time.time() - ovod_start_time} seconds')
652
+ # icse & fse
653
+ def extract_image_id(image_name):
654
+ # Split the image name into parts and form the image_id accordingly
655
+ parts = image_name.split('_')
656
+ print(image_name)
657
+ base, extension = parts[1].split('.')
658
+ return int(parts[0] + base.zfill(3))
659
+ # icse_rebuttal
660
+ # def extract_image_id(image_name):
661
+ # # Split the image name into parts by underscore
662
+ # parts = image_name.split('_')
663
+ # # Extracting the first part as the base and the numeric portion of the third part before the file extension
664
+ # base = parts[0] # This will give '625470'
665
+ # numeric_part = parts[2].split('.')[0] # This will give 'b3'
666
+ # # Removing non-numeric characters from 'b3'
667
+ # numeric_part = ''.join(filter(str.isdigit, numeric_part))
668
+ # # Zfill is used to ensure the numeric part has at least 3 digits, then combining with base
669
+ # print(int(base + numeric_part.zfill(3)))
670
+ # return int(base + numeric_part.zfill(3))
671
+
672
+
673
+ def main():
674
+ vlms = ['llava7b', 'bing', 'gpt4v']
675
+ llms = ['llama2', 'gemini-3-flash-preview-nothinking']
676
+ ovods = ['grounding_dino', 'glip', 'ape_d']
677
+
678
+
679
+ # python method.py -v gpt4v -l gemini-3-flash-preview-nothinking -o ape_d
680
+ # python method.py -v gpt4v -l gemini-3-flash-preview-nothinking -o ape_d_abl
681
+ # python method.py -v claude35sonnet -l gemini-3-flash-preview-nothinking -o ape_d
682
+ # python method.py -v gemini -l gemini-3-flash-preview-nothinking -o ape_d
683
+ if __name__=='__main__':
684
+ # main()
685
+
686
+ parser = argparse.ArgumentParser("Method", add_help=True)
687
+ parser.add_argument("--vlm", "-v", type=str, required=True, help="vlm")
688
+ parser.add_argument("--llm", "-l", type=str, required=True, help="llm")
689
+ parser.add_argument("--ovod", "-o", type=str, required=True, help="ovod")
690
+ parser.add_argument("--start-index", type=int, default=None, help="first JSONL row to process")
691
+ parser.add_argument("--end-index", type=int, default=None, help="exclusive JSONL row end")
692
+ parser.add_argument("--shard-index", type=int, default=None, help="zero-based shard index")
693
+ parser.add_argument("--num-shards", type=int, default=None, help="total number of shards")
694
+ parser.add_argument("--enable-reflection", action="store_true", help="run PII.5/PII.6 advisor reflection loop")
695
+ parser.add_argument("--reflection-profile", default="default", help="model profile for the reflection advisor")
696
+ parser.add_argument("--max-reflection-iterations", type=int, default=10, help="max advisor reflection rounds")
697
+ parser.add_argument("--questions", dest="questions_path", help="question manifest JSONL")
698
+ parser.add_argument("--candidates", dest="candidates_path", help="candidate JSON/JSONL for the selected detector")
699
+ parser.add_argument("--images-dir", dest="images_path", help="directory containing XR screenshots")
700
+ parser.add_argument("--output", dest="output_path", help="prediction JSON path; selection suffixes are added automatically")
701
+ parser.add_argument("--ape-root", help="APE repository directory")
702
+ parser.add_argument("--ape-checkpoint", help="APE checkpoint path")
703
+ parser.add_argument("--log-file", help="optional log file; defaults to stderr")
704
+ args = parser.parse_args()
705
+
706
+ gpu = '1-3'
707
+ stage = '1'
708
+ idx = '0001'
709
+ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
710
+ datefmt='%m/%d/%Y %H:%M:%S',
711
+ level=logging.INFO,
712
+ filename=args.log_file,
713
+ )
714
+
715
+ method(
716
+ args.vlm,
717
+ args.llm,
718
+ args.ovod,
719
+ start_index=args.start_index,
720
+ end_index=args.end_index,
721
+ shard_index=args.shard_index,
722
+ num_shards=args.num_shards,
723
+ enable_reflection=args.enable_reflection,
724
+ reflection_profile=args.reflection_profile,
725
+ max_reflection_iterations=args.max_reflection_iterations,
726
+ questions_path=args.questions_path,
727
+ candidates_path=args.candidates_path,
728
+ images_path=args.images_path,
729
+ output_path=args.output_path,
730
+ ape_root=args.ape_root,
731
+ ape_checkpoint=args.ape_checkpoint,
732
+ )
733
+
734
+ # CUDA_VISIBLE_DEVICES=0 python method.py -v gpt4v -l gemini-3-flash-preview-nothinking -o ape_d > ../log/realfse/240910_gpt4v_2_g0_0001.txt
735
+ # CUDA_VISIBLE_DEVICES=3 python method.py -v gpt4v -l gemini-3-flash-preview-nothinking -o ape_d_abl > ../log/realfse/240910_gpt4v_ape_d_abl_2_g3_0001.txt
736
+ # CUDA_VISIBLE_DEVICES=3 python method.py -v gpt4v_abl -l gemini-3-flash-preview-nothinking -o ape_d > ../log/realfse/240912_gpt4v_abl_1_g1-3_0001.txt
approach/ovod/APE/demo/__init__.py ADDED
File without changes
approach/ovod/APE/demo/pre-requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ --index-url https://download.pytorch.org/whl/cu118
2
+ torch==2.0.1
3
+ torchvision==0.15.2
4
+ torchaudio==2.0.2
approach/ovod/APE/demo/predictor_lazy.py ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates.
2
+ import atexit
3
+ import bisect
4
+ import gc
5
+ import json
6
+ import multiprocessing as mp
7
+ import time
8
+ from collections import deque
9
+
10
+ import cv2
11
+ import numpy as np
12
+ import torch
13
+
14
+ from ape.engine.defaults import DefaultPredictor
15
+ from detectron2.data import MetadataCatalog
16
+ from detectron2.utils.video_visualizer import VideoVisualizer
17
+ from detectron2.utils.visualizer import ColorMode, Visualizer
18
+
19
+
20
+ def filter_instances(instances, metadata):
21
+ # return instances
22
+
23
+ keep = []
24
+ keep_classes = []
25
+
26
+ sorted_idxs = np.argsort(-instances.scores)
27
+ instances = instances[sorted_idxs]
28
+
29
+ for i in range(len(instances)):
30
+ instance = instances[i]
31
+ pred_class = instance.pred_classes
32
+ if pred_class >= len(metadata.thing_classes):
33
+ continue
34
+
35
+ keep.append(i)
36
+ keep_classes.append(pred_class)
37
+ return instances[keep]
38
+
39
+
40
+ def cuda_grabcut(img, masks, iter=5, gamma=50, iou_threshold=0.75):
41
+ gc.collect()
42
+ torch.cuda.empty_cache()
43
+
44
+ try:
45
+ import grabcut
46
+ except Exception as e:
47
+ print("*" * 60)
48
+ print("fail to import grabCut: ", e)
49
+ print("*" * 60)
50
+ return masks
51
+ GC = grabcut.GrabCut(iter)
52
+
53
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
54
+
55
+ tic_0 = time.time()
56
+ for i in range(len(masks)):
57
+ mask = masks[i]
58
+ if mask.sum() > 10 * 10:
59
+ pass
60
+ else:
61
+ continue
62
+
63
+ # ----------------------------------------------------------------
64
+ fourmap = np.empty_like(mask, dtype=np.uint8)
65
+ fourmap[:, :] = 64
66
+ fourmap[mask == 0] = 64
67
+ fourmap[mask == 1] = 128
68
+
69
+ # Compute segmentation
70
+ tic = time.time()
71
+ seg = GC.estimateSegmentationFromFourmap(img, fourmap, gamma)
72
+ toc = time.time()
73
+ print("Time elapsed in GrabCut segmentation: " + str(toc - tic))
74
+ # ----------------------------------------------------------------
75
+
76
+ seg = torch.tensor(seg, dtype=torch.bool)
77
+ iou = (mask & seg).sum() / (mask | seg).sum()
78
+ if iou > iou_threshold:
79
+ masks[i] = seg
80
+
81
+ if toc - tic_0 > 10:
82
+ break
83
+
84
+ return masks
85
+
86
+
87
+ def opencv_grabcut(img, masks, iter=5):
88
+
89
+ for i in range(len(masks)):
90
+ mask = masks[i]
91
+
92
+ # ----------------------------------------------------------------
93
+ fourmap = np.empty_like(mask, dtype=np.uint8)
94
+ fourmap[:, :] = cv2.GC_PR_BGD
95
+ # fourmap[mask == 0] = cv2.GC_BGD
96
+ fourmap[mask == 0] = cv2.GC_PR_BGD
97
+ fourmap[mask == 1] = cv2.GC_PR_FGD
98
+ # fourmap[mask == 1] = cv2.GC_FGD
99
+
100
+ # Create GrabCut algo
101
+ bgd_model = np.zeros((1, 65), np.float64)
102
+ fgd_model = np.zeros((1, 65), np.float64)
103
+ seg = np.zeros_like(fourmap, dtype=np.uint8)
104
+
105
+ # Compute segmentation
106
+ tic = time.time()
107
+ seg, bgd_model, fgd_model = cv2.grabCut(
108
+ img, fourmap, None, bgd_model, fgd_model, iter, cv2.GC_INIT_WITH_MASK
109
+ )
110
+ toc = time.time()
111
+ print("Time elapsed in GrabCut segmentation: " + str(toc - tic))
112
+
113
+ seg = np.where((seg == 2) | (seg == 0), 0, 1).astype("bool")
114
+
115
+ # ----------------------------------------------------------------
116
+
117
+ seg = torch.tensor(seg, dtype=torch.bool)
118
+ iou = (mask & seg).sum() / (mask | seg).sum()
119
+ if iou > 0.75:
120
+ masks[i] = seg
121
+
122
+ if i > 10:
123
+ break
124
+
125
+ return masks
126
+
127
+
128
+ class VisualizationDemo(object):
129
+ def __init__(self, cfg, instance_mode=ColorMode.IMAGE, parallel=False, args=None):
130
+ """
131
+ Args:
132
+ cfg (CfgNode):
133
+ instance_mode (ColorMode):
134
+ parallel (bool): whether to run the model in different processes from visualization.
135
+ Useful since the visualization logic can be slow.
136
+ """
137
+ self.metadata = MetadataCatalog.get(
138
+ "__unused_" + "_".join([d for d in cfg.dataloader.train.dataset.names])
139
+ )
140
+ self.metadata.thing_classes = [
141
+ c
142
+ for d in cfg.dataloader.train.dataset.names
143
+ for c in MetadataCatalog.get(d).get("thing_classes", default=[])
144
+ + MetadataCatalog.get(d).get("stuff_classes", default=["thing"])[1:]
145
+ ]
146
+ self.metadata.stuff_classes = [
147
+ c
148
+ for d in cfg.dataloader.train.dataset.names
149
+ for c in MetadataCatalog.get(d).get("thing_classes", default=[])
150
+ + MetadataCatalog.get(d).get("stuff_classes", default=["thing"])[1:]
151
+ ]
152
+
153
+ # self.metadata = MetadataCatalog.get(
154
+ # "__unused_ape_" + "_".join([d for d in cfg.dataloader.train.dataset.names])
155
+ # )
156
+ # self.metadata.thing_classes = [
157
+ # c
158
+ # for d in ["coco_2017_train_panoptic_separated"]
159
+ # for c in MetadataCatalog.get(d).get("thing_classes", default=[])
160
+ # + MetadataCatalog.get(d).get("stuff_classes", default=["thing"])[1:]
161
+ # ]
162
+ # self.metadata.stuff_classes = [
163
+ # c
164
+ # for d in ["coco_2017_train_panoptic_separated"]
165
+ # for c in MetadataCatalog.get(d).get("thing_classes", default=[])
166
+ # + MetadataCatalog.get(d).get("stuff_classes", default=["thing"])[1:]
167
+ # ]
168
+
169
+ self.cpu_device = torch.device("cpu")
170
+ self.instance_mode = instance_mode
171
+
172
+ self.parallel = parallel
173
+ if parallel:
174
+ num_gpu = torch.cuda.device_count()
175
+ self.predictor = AsyncPredictor(cfg, num_gpus=num_gpu)
176
+ else:
177
+ self.predictor = DefaultPredictor(cfg)
178
+
179
+ print(args)
180
+
181
+ def run_on_image(
182
+ self,
183
+ image,
184
+ text_prompt=None,
185
+ mask_prompt=None,
186
+ with_box=True,
187
+ with_mask=True,
188
+ with_sseg=True,
189
+ ):
190
+ """
191
+ Args:
192
+ image (np.ndarray): an image of shape (H, W, C) (in BGR order).
193
+ This is the format used by OpenCV.
194
+
195
+ Returns:
196
+ predictions (dict): the output of the model.
197
+ vis_output (VisImage): the visualized image output.
198
+ """
199
+ if text_prompt:
200
+ text_list = [x.strip() for x in text_prompt.split(",")]
201
+ text_list = [x for x in text_list if len(x) > 0]
202
+ metadata = MetadataCatalog.get("__unused_ape_" + text_prompt)
203
+ metadata.thing_classes = text_list
204
+ metadata.stuff_classes = text_list
205
+ else:
206
+ metadata = self.metadata
207
+
208
+ vis_output = None
209
+ predictions = self.predictor(image, text_prompt, mask_prompt)
210
+
211
+ if "instances" in predictions:
212
+ predictions["instances"] = filter_instances(
213
+ predictions["instances"].to(self.cpu_device), metadata
214
+ )
215
+
216
+ # Convert image from OpenCV BGR format to Matplotlib RGB format.
217
+ image = image[:, :, ::-1]
218
+ visualizer = Visualizer(image, metadata, instance_mode=self.instance_mode)
219
+ vis_outputs = []
220
+ if "panoptic_seg" in predictions and with_mask and with_sseg:
221
+ panoptic_seg, segments_info = predictions["panoptic_seg"]
222
+ vis_output = visualizer.draw_panoptic_seg_predictions(
223
+ panoptic_seg.to(self.cpu_device), segments_info
224
+ )
225
+ else:
226
+ if "sem_seg" in predictions and with_sseg:
227
+ # vis_output = visualizer.draw_sem_seg(
228
+ # predictions["sem_seg"].argmax(dim=0).to(self.cpu_device)
229
+ # )
230
+
231
+ sem_seg = predictions["sem_seg"].to(self.cpu_device)
232
+ # sem_seg = opencv_grabcut(image, sem_seg, iter=10)
233
+ # sem_seg = cuda_grabcut(image, sem_seg > 0.5, iter=5, gamma=10, iou_threshold=0.1)
234
+ sem_seg = torch.cat((sem_seg, torch.ones_like(sem_seg[0:1, ...]) * 0.1), dim=0)
235
+ sem_seg = sem_seg.argmax(dim=0)
236
+ vis_output = visualizer.draw_sem_seg(sem_seg)
237
+ if "instances" in predictions and (with_box or with_mask):
238
+ instances = predictions["instances"].to(self.cpu_device)
239
+
240
+ if not with_box:
241
+ instances.remove("pred_boxes")
242
+ if not with_mask:
243
+ instances.remove("pred_masks")
244
+
245
+ if with_mask and False:
246
+ # instances.pred_masks = opencv_grabcut(image, instances.pred_masks, iter=10)
247
+ instances.pred_masks = cuda_grabcut(
248
+ image, instances.pred_masks, iter=5, gamma=10, iou_threshold=0.75
249
+ )
250
+
251
+ vis_output = visualizer.draw_instance_predictions(predictions=instances)
252
+
253
+ # for i in range(len(instances)):
254
+ # visualizer = Visualizer(image, metadata, instance_mode=self.instance_mode)
255
+ # vis_outputs.append(visualizer.draw_instance_predictions(predictions=instances[i]))
256
+
257
+ elif "proposals" in predictions:
258
+ visualizer = Visualizer(image, None, instance_mode=self.instance_mode)
259
+ instances = predictions["proposals"].to(self.cpu_device)
260
+ instances.pred_boxes = instances.proposal_boxes
261
+ instances.scores = instances.objectness_logits
262
+ vis_output = visualizer.draw_instance_predictions(predictions=instances)
263
+
264
+ return predictions, vis_output, vis_outputs, metadata
265
+
266
+ def _frame_from_video(self, video):
267
+ while video.isOpened():
268
+ success, frame = video.read()
269
+ if success:
270
+ yield frame
271
+ else:
272
+ break
273
+
274
+ def run_on_video(self, video):
275
+ """
276
+ Visualizes predictions on frames of the input video.
277
+
278
+ Args:
279
+ video (cv2.VideoCapture): a :class:`VideoCapture` object, whose source can be
280
+ either a webcam or a video file.
281
+
282
+ Yields:
283
+ ndarray: BGR visualizations of each video frame.
284
+ """
285
+ video_visualizer = VideoVisualizer(self.metadata, self.instance_mode)
286
+
287
+ def process_predictions(frame, predictions):
288
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
289
+ if "panoptic_seg" in predictions and False:
290
+ panoptic_seg, segments_info = predictions["panoptic_seg"]
291
+ vis_frame = video_visualizer.draw_panoptic_seg_predictions(
292
+ frame, panoptic_seg.to(self.cpu_device), segments_info
293
+ )
294
+ elif "instances" in predictions and False:
295
+ predictions = predictions["instances"].to(self.cpu_device)
296
+ vis_frame = video_visualizer.draw_instance_predictions(frame, predictions)
297
+ elif "sem_seg" in predictions and False:
298
+ vis_frame = video_visualizer.draw_sem_seg(
299
+ frame, predictions["sem_seg"].argmax(dim=0).to(self.cpu_device)
300
+ )
301
+
302
+ if "sem_seg" in predictions:
303
+ vis_frame = video_visualizer.draw_sem_seg(
304
+ frame, predictions["sem_seg"].argmax(dim=0).to(self.cpu_device)
305
+ )
306
+ frame = vis_frame.get_image()
307
+
308
+ if "instances" in predictions:
309
+ predictions = predictions["instances"].to(self.cpu_device)
310
+ predictions = filter_instances(predictions, self.metadata)
311
+ vis_frame = video_visualizer.draw_instance_predictions(frame, predictions)
312
+
313
+ # Converts Matplotlib RGB format to OpenCV BGR format
314
+ vis_frame = cv2.cvtColor(vis_frame.get_image(), cv2.COLOR_RGB2BGR)
315
+ return vis_frame, predictions
316
+
317
+ frame_gen = self._frame_from_video(video)
318
+ if self.parallel:
319
+ buffer_size = self.predictor.default_buffer_size
320
+
321
+ frame_data = deque()
322
+
323
+ for cnt, frame in enumerate(frame_gen):
324
+ frame_data.append(frame)
325
+ self.predictor.put(frame)
326
+
327
+ if cnt >= buffer_size:
328
+ frame = frame_data.popleft()
329
+ predictions = self.predictor.get()
330
+ yield process_predictions(frame, predictions)
331
+
332
+ while len(frame_data):
333
+ frame = frame_data.popleft()
334
+ predictions = self.predictor.get()
335
+ yield process_predictions(frame, predictions)
336
+ else:
337
+ for frame in frame_gen:
338
+ yield process_predictions(frame, self.predictor(frame))
339
+
340
+
341
+ class AsyncPredictor:
342
+ """
343
+ A predictor that runs the model asynchronously, possibly on >1 GPUs.
344
+ Because rendering the visualization takes considerably amount of time,
345
+ this helps improve throughput a little bit when rendering videos.
346
+ """
347
+
348
+ class _StopToken:
349
+ pass
350
+
351
+ class _PredictWorker(mp.Process):
352
+ def __init__(self, cfg, task_queue, result_queue):
353
+ self.cfg = cfg
354
+ self.task_queue = task_queue
355
+ self.result_queue = result_queue
356
+ super().__init__()
357
+
358
+ def run(self):
359
+ predictor = DefaultPredictor(self.cfg)
360
+
361
+ while True:
362
+ task = self.task_queue.get()
363
+ if isinstance(task, AsyncPredictor._StopToken):
364
+ break
365
+ idx, data = task
366
+ result = predictor(data)
367
+ self.result_queue.put((idx, result))
368
+
369
+ def __init__(self, cfg, num_gpus: int = 1):
370
+ """
371
+ Args:
372
+ cfg (CfgNode):
373
+ num_gpus (int): if 0, will run on CPU
374
+ """
375
+ num_workers = max(num_gpus, 1)
376
+ self.task_queue = mp.Queue(maxsize=num_workers * 3)
377
+ self.result_queue = mp.Queue(maxsize=num_workers * 3)
378
+ self.procs = []
379
+ for gpuid in range(max(num_gpus, 1)):
380
+ cfg = cfg.clone()
381
+ cfg.defrost()
382
+ cfg.MODEL.DEVICE = "cuda:{}".format(gpuid) if num_gpus > 0 else "cpu"
383
+ self.procs.append(
384
+ AsyncPredictor._PredictWorker(cfg, self.task_queue, self.result_queue)
385
+ )
386
+
387
+ self.put_idx = 0
388
+ self.get_idx = 0
389
+ self.result_rank = []
390
+ self.result_data = []
391
+
392
+ for p in self.procs:
393
+ p.start()
394
+ atexit.register(self.shutdown)
395
+
396
+ def put(self, image):
397
+ self.put_idx += 1
398
+ self.task_queue.put((self.put_idx, image))
399
+
400
+ def get(self):
401
+ self.get_idx += 1 # the index needed for this request
402
+ if len(self.result_rank) and self.result_rank[0] == self.get_idx:
403
+ res = self.result_data[0]
404
+ del self.result_data[0], self.result_rank[0]
405
+ return res
406
+
407
+ while True:
408
+ # make sure the results are returned in the correct order
409
+ idx, res = self.result_queue.get()
410
+ if idx == self.get_idx:
411
+ return res
412
+ insert = bisect.bisect(self.result_rank, idx)
413
+ self.result_rank.insert(insert, idx)
414
+ self.result_data.insert(insert, res)
415
+
416
+ def __len__(self):
417
+ return self.put_idx - self.get_idx
418
+
419
+ def __call__(self, image):
420
+ self.put(image)
421
+ return self.get()
422
+
423
+ def shutdown(self):
424
+ for _ in self.procs:
425
+ self.task_queue.put(AsyncPredictor._StopToken())
426
+
427
+ @property
428
+ def default_buffer_size(self):
429
+ return len(self.procs) * 5
approach/ovod/APE/demo/requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ transformers
2
+ cython
3
+ opencv-python
4
+ scipy
5
+ einops
6
+ lvis
7
+ fairscale
8
+ git+https://github.com/facebookresearch/detectron2@017abbf
9
+ git+https://github.com/IDEA-Research/detrex@776058e
10
+ git+https://github.com/openai/CLIP.git@d50d76d
11
+ git+https://github.com/shenyunhang/ape
approach/ovod/GroundingDINO/.gitignore ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IDE
2
+ .idea/
3
+ .vscode/
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ pip-wheel-metadata/
28
+ share/python-wheels/
29
+ *.egg-info/
30
+ .installed.cfg
31
+ *.egg
32
+ MANIFEST
33
+
34
+ # PyInstaller
35
+ # Usually these files are written by a python script from a template
36
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
37
+ *.manifest
38
+ *.spec
39
+
40
+ # Installer logs
41
+ pip-log.txt
42
+ pip-delete-this-directory.txt
43
+
44
+ # Unit test / coverage reports
45
+ htmlcov/
46
+ .tox/
47
+ .nox/
48
+ .coverage
49
+ .coverage.*
50
+ .cache
51
+ nosetests.xml
52
+ coverage.xml
53
+ *.cover
54
+ *.py,cover
55
+ .hypothesis/
56
+ .pytest_cache/
57
+
58
+ # Translations
59
+ *.mo
60
+ *.pot
61
+
62
+ # Django stuff:
63
+ *.log
64
+ local_settings.py
65
+ db.sqlite3
66
+ db.sqlite3-journal
67
+
68
+ # Flask stuff:
69
+ instance/
70
+ .webassets-cache
71
+
72
+ # Scrapy stuff:
73
+ .scrapy
74
+
75
+ # Sphinx documentation
76
+ docs/_build/
77
+
78
+ # PyBuilder
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
99
+ __pypackages__/
100
+
101
+ # Celery stuff
102
+ celerybeat-schedule
103
+ celerybeat.pid
104
+
105
+ # SageMath parsed files
106
+ *.sage.py
107
+
108
+ # Environments
109
+ .env
110
+ .venv
111
+ env/
112
+ venv/
113
+ ENV/
114
+ env.bak/
115
+ venv.bak/
116
+
117
+ # Spyder project settings
118
+ .spyderproject
119
+ .spyproject
120
+
121
+ # Rope project settings
122
+ .ropeproject
123
+
124
+ # mkdocs documentation
125
+ /site
126
+
127
+ # mypy
128
+ .mypy_cache/
129
+ .dmypy.json
130
+ dmypy.json
131
+
132
+ # Pyre type checker
133
+ .pyre/
134
+
135
+ # vscode
136
+ .vscode/
137
+ output/
138
+ outputs/
139
+ subs/
140
+ logs/
141
+
142
+ grounding/config/configs
143
+ grounding/version.py
144
+
145
+ vis/
146
+ tmp/
approach/ovod/GroundingDINO/LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2023 - present, IDEA Research.
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
approach/ovod/GroundingDINO/README.md ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+ <img src="./.asset/grounding_dino_logo.png" width="30%">
3
+ </div>
4
+
5
+ # :sauropod: Grounding DINO
6
+
7
+ [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/grounding-dino-marrying-dino-with-grounded/zero-shot-object-detection-on-mscoco)](https://paperswithcode.com/sota/zero-shot-object-detection-on-mscoco?p=grounding-dino-marrying-dino-with-grounded) [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/grounding-dino-marrying-dino-with-grounded/zero-shot-object-detection-on-odinw)](https://paperswithcode.com/sota/zero-shot-object-detection-on-odinw?p=grounding-dino-marrying-dino-with-grounded) \
8
+ [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/grounding-dino-marrying-dino-with-grounded/object-detection-on-coco-minival)](https://paperswithcode.com/sota/object-detection-on-coco-minival?p=grounding-dino-marrying-dino-with-grounded) [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/grounding-dino-marrying-dino-with-grounded/object-detection-on-coco)](https://paperswithcode.com/sota/object-detection-on-coco?p=grounding-dino-marrying-dino-with-grounded)
9
+
10
+
11
+ **[IDEA-CVR, IDEA-Research](https://github.com/IDEA-Research)**
12
+
13
+ [Shilong Liu](http://www.lsl.zone/), [Zhaoyang Zeng](https://scholar.google.com/citations?user=U_cvvUwAAAAJ&hl=zh-CN&oi=ao), [Tianhe Ren](https://rentainhe.github.io/), [Feng Li](https://scholar.google.com/citations?user=ybRe9GcAAAAJ&hl=zh-CN), [Hao Zhang](https://scholar.google.com/citations?user=B8hPxMQAAAAJ&hl=zh-CN), [Jie Yang](https://github.com/yangjie-cv), [Chunyuan Li](https://scholar.google.com/citations?user=Zd7WmXUAAAAJ&hl=zh-CN&oi=ao), [Jianwei Yang](https://jwyang.github.io/), [Hang Su](https://scholar.google.com/citations?hl=en&user=dxN1_X0AAAAJ&view_op=list_works&sortby=pubdate), [Jun Zhu](https://scholar.google.com/citations?hl=en&user=axsP38wAAAAJ), [Lei Zhang](https://www.leizhang.org/)<sup>:email:</sup>.
14
+
15
+
16
+ [[`Paper`](https://arxiv.org/abs/2303.05499)] [[`Demo`](https://huggingface.co/spaces/ShilongLiu/Grounding_DINO_demo)] [[`BibTex`](#black_nib-citation)]
17
+
18
+
19
+ PyTorch implementation and pretrained models for Grounding DINO. For details, see the paper **[Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection](https://arxiv.org/abs/2303.05499)**.
20
+
21
+ ## :sun_with_face: Helpful Tutorial
22
+
23
+ - :grapes: [[Read our arXiv Paper](https://arxiv.org/abs/2303.05499)]
24
+ - :apple: [[Watch our simple introduction video on YouTube](https://youtu.be/wxWDt5UiwY8)]
25
+ - :blossom: &nbsp;[[Try the Colab Demo](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/zero-shot-object-detection-with-grounding-dino.ipynb)]
26
+ - :sunflower: [[Try our Official Huggingface Demo](https://huggingface.co/spaces/ShilongLiu/Grounding_DINO_demo)]
27
+ - :maple_leaf: [[Watch the Step by Step Tutorial about GroundingDINO by Roboflow AI](https://youtu.be/cMa77r3YrDk)]
28
+ - :mushroom: [[GroundingDINO: Automated Dataset Annotation and Evaluation by Roboflow AI](https://youtu.be/C4NqaRBz_Kw)]
29
+ - :hibiscus: [[Accelerate Image Annotation with SAM and GroundingDINO by Roboflow AI](https://youtu.be/oEQYStnF2l8)]
30
+ - :white_flower: [[Autodistill: Train YOLOv8 with ZERO Annotations based on Grounding-DINO and Grounded-SAM by Roboflow AI](https://github.com/autodistill/autodistill)]
31
+
32
+ <!-- Grounding DINO Methods |
33
+ [![arXiv](https://img.shields.io/badge/arXiv-2303.05499-b31b1b.svg)](https://arxiv.org/abs/2303.05499)
34
+ [![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/wxWDt5UiwY8) -->
35
+
36
+ <!-- Grounding DINO Demos |
37
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/zero-shot-object-detection-with-grounding-dino.ipynb) -->
38
+ <!-- [![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/cMa77r3YrDk)
39
+ [![HuggingFace space](https://img.shields.io/badge/🤗-HuggingFace%20Space-cyan.svg)](https://huggingface.co/spaces/ShilongLiu/Grounding_DINO_demo)
40
+ [![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/oEQYStnF2l8)
41
+ [![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/C4NqaRBz_Kw) -->
42
+
43
+ ## :sparkles: Highlight Projects
44
+
45
+ - [Semantic-SAM: a universal image segmentation model to enable segment and recognize anything at any desired granularity.](https://github.com/UX-Decoder/Semantic-SAM),
46
+ - [DetGPT: Detect What You Need via Reasoning](https://github.com/OptimalScale/DetGPT)
47
+ - [Grounded-SAM: Marrying Grounding DINO with Segment Anything](https://github.com/IDEA-Research/Grounded-Segment-Anything)
48
+ - [Grounding DINO with Stable Diffusion](demo/image_editing_with_groundingdino_stablediffusion.ipynb)
49
+ - [Grounding DINO with GLIGEN for Controllable Image Editing](demo/image_editing_with_groundingdino_gligen.ipynb)
50
+ - [OpenSeeD: A Simple and Strong Openset Segmentation Model](https://github.com/IDEA-Research/OpenSeeD)
51
+ - [SEEM: Segment Everything Everywhere All at Once](https://github.com/UX-Decoder/Segment-Everything-Everywhere-All-At-Once)
52
+ - [X-GPT: Conversational Visual Agent supported by X-Decoder](https://github.com/microsoft/X-Decoder/tree/xgpt)
53
+ - [GLIGEN: Open-Set Grounded Text-to-Image Generation](https://github.com/gligen/GLIGEN)
54
+ - [LLaVA: Large Language and Vision Assistant](https://github.com/haotian-liu/LLaVA)
55
+
56
+ <!-- Extensions | [Grounding DINO with Segment Anything](https://github.com/IDEA-Research/Grounded-Segment-Anything); [Grounding DINO with Stable Diffusion](demo/image_editing_with_groundingdino_stablediffusion.ipynb); [Grounding DINO with GLIGEN](demo/image_editing_with_groundingdino_gligen.ipynb) -->
57
+
58
+
59
+
60
+ <!-- Official PyTorch implementation of [Grounding DINO](https://arxiv.org/abs/2303.05499), a stronger open-set object detector. Code is available now! -->
61
+
62
+
63
+ ## :bulb: Highlight
64
+
65
+ - **Open-Set Detection.** Detect **everything** with language!
66
+ - **High Performancce.** COCO zero-shot **52.5 AP** (training without COCO data!). COCO fine-tune **63.0 AP**.
67
+ - **Flexible.** Collaboration with Stable Diffusion for Image Editting.
68
+
69
+
70
+
71
+
72
+ ## :fire: News
73
+ - **`2023/07/18`**: We release [Semantic-SAM](https://github.com/UX-Decoder/Semantic-SAM), a universal image segmentation model to enable segment and recognize anything at any desired granularity. **Code** and **checkpoint** are available!
74
+ - **`2023/06/17`**: We provide an example to evaluate Grounding DINO on COCO zero-shot performance.
75
+ - **`2023/04/15`**: Refer to [CV in the Wild Readings](https://github.com/Computer-Vision-in-the-Wild/CVinW_Readings) for those who are interested in open-set recognition!
76
+ - **`2023/04/08`**: We release [demos](demo/image_editing_with_groundingdino_gligen.ipynb) to combine [Grounding DINO](https://arxiv.org/abs/2303.05499) with [GLIGEN](https://github.com/gligen/GLIGEN) for more controllable image editings.
77
+ - **`2023/04/08`**: We release [demos](demo/image_editing_with_groundingdino_stablediffusion.ipynb) to combine [Grounding DINO](https://arxiv.org/abs/2303.05499) with [Stable Diffusion](https://github.com/Stability-AI/StableDiffusion) for image editings.
78
+ - **`2023/04/06`**: We build a new demo by marrying GroundingDINO with [Segment-Anything](https://github.com/facebookresearch/segment-anything) named **[Grounded-Segment-Anything](https://github.com/IDEA-Research/Grounded-Segment-Anything)** aims to support segmentation in GroundingDINO.
79
+ - **`2023/03/28`**: A YouTube [video](https://youtu.be/cMa77r3YrDk) about Grounding DINO and basic object detection prompt engineering. [[SkalskiP](https://github.com/SkalskiP)]
80
+ - **`2023/03/28`**: Add a [demo](https://huggingface.co/spaces/ShilongLiu/Grounding_DINO_demo) on Hugging Face Space!
81
+ - **`2023/03/27`**: Support CPU-only mode. Now the model can run on machines without GPUs.
82
+ - **`2023/03/25`**: A [demo](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/zero-shot-object-detection-with-grounding-dino.ipynb) for Grounding DINO is available at Colab. [[SkalskiP](https://github.com/SkalskiP)]
83
+ - **`2023/03/22`**: Code is available Now!
84
+
85
+ <details open>
86
+ <summary><font size="4">
87
+ Description
88
+ </font></summary>
89
+ <a href="https://arxiv.org/abs/2303.05499">Paper</a> introduction.
90
+ <img src=".asset/hero_figure.png" alt="ODinW" width="100%">
91
+ Marrying <a href="https://github.com/IDEA-Research/GroundingDINO">Grounding DINO</a> and <a href="https://github.com/gligen/GLIGEN">GLIGEN</a>
92
+ <img src="https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/GD_GLIGEN.png" alt="gd_gligen" width="100%">
93
+ </details>
94
+
95
+ ## :star: Explanations/Tips for Grounding DINO Inputs and Outputs
96
+ - Grounding DINO accepts an `(image, text)` pair as inputs.
97
+ - It outputs `900` (by default) object boxes. Each box has similarity scores across all input words. (as shown in Figures below.)
98
+ - We defaultly choose the boxes whose highest similarities are higher than a `box_threshold`.
99
+ - We extract the words whose similarities are higher than the `text_threshold` as predicted labels.
100
+ - If you want to obtain objects of specific phrases, like the `dogs` in the sentence `two dogs with a stick.`, you can select the boxes with highest text similarities with `dogs` as final outputs.
101
+ - Note that each word can be split to **more than one** tokens with different tokenlizers. The number of words in a sentence may not equal to the number of text tokens.
102
+ - We suggest separating different category names with `.` for Grounding DINO.
103
+ ![model_explain1](.asset/model_explan1.PNG)
104
+ ![model_explain2](.asset/model_explan2.PNG)
105
+
106
+ ## :label: TODO
107
+
108
+ - [x] Release inference code and demo.
109
+ - [x] Release checkpoints.
110
+ - [x] Grounding DINO with Stable Diffusion and GLIGEN demos.
111
+ - [ ] Release training codes.
112
+
113
+ ## :hammer_and_wrench: Install
114
+
115
+ **Note:**
116
+
117
+ 0. If you have a CUDA environment, please make sure the environment variable `CUDA_HOME` is set. It will be compiled under CPU-only mode if no CUDA available.
118
+
119
+ Please make sure following the installation steps strictly, otherwise the program may produce:
120
+ ```bash
121
+ NameError: name '_C' is not defined
122
+ ```
123
+
124
+ If this happened, please reinstalled the groundingDINO by reclone the git and do all the installation steps again.
125
+
126
+ #### how to check cuda:
127
+ ```bash
128
+ echo $CUDA_HOME
129
+ ```
130
+ If it print nothing, then it means you haven't set up the path/
131
+
132
+ Run this so the environment variable will be set under current shell.
133
+ ```bash
134
+ export CUDA_HOME=/path/to/cuda-11.3
135
+ ```
136
+
137
+ Notice the version of cuda should be aligned with your CUDA runtime, for there might exists multiple cuda at the same time.
138
+
139
+ If you want to set the CUDA_HOME permanently, store it using:
140
+
141
+ ```bash
142
+ echo 'export CUDA_HOME=/path/to/cuda' >> ~/.bashrc
143
+ ```
144
+ after that, source the bashrc file and check CUDA_HOME:
145
+ ```bash
146
+ source ~/.bashrc
147
+ echo $CUDA_HOME
148
+ ```
149
+
150
+ In this example, /path/to/cuda-11.3 should be replaced with the path where your CUDA toolkit is installed. You can find this by typing **which nvcc** in your terminal:
151
+
152
+ For instance,
153
+ if the output is /usr/local/cuda/bin/nvcc, then:
154
+ ```bash
155
+ export CUDA_HOME=/usr/local/cuda
156
+ ```
157
+ **Installation:**
158
+
159
+ 1.Clone the GroundingDINO repository from GitHub.
160
+
161
+ ```bash
162
+ git clone https://github.com/IDEA-Research/GroundingDINO.git
163
+ ```
164
+
165
+ 2. Change the current directory to the GroundingDINO folder.
166
+
167
+ ```bash
168
+ cd GroundingDINO/
169
+ ```
170
+
171
+ 3. Install the required dependencies in the current directory.
172
+
173
+ ```bash
174
+ pip install -e .
175
+ ```
176
+
177
+ 4. Download pre-trained model weights.
178
+
179
+ ```bash
180
+ mkdir weights
181
+ cd weights
182
+ wget -q https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth
183
+ cd ..
184
+ ```
185
+
186
+ ## :arrow_forward: Demo
187
+ Check your GPU ID (only if you're using a GPU)
188
+
189
+ ```bash
190
+ nvidia-smi
191
+ ```
192
+ Replace `{GPU ID}`, `image_you_want_to_detect.jpg`, and `"dir you want to save the output"` with appropriate values in the following command
193
+ ```bash
194
+ CUDA_VISIBLE_DEVICES={GPU ID} python demo/inference_on_a_image.py \
195
+ -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
196
+ -p weights/groundingdino_swint_ogc.pth \
197
+ -i image_you_want_to_detect.jpg \
198
+ -o "dir you want to save the output" \
199
+ -t "chair"
200
+ [--cpu-only] # open it for cpu mode
201
+ ```
202
+
203
+ If you would like to specify the phrases to detect, here is a demo:
204
+ ```bash
205
+ CUDA_VISIBLE_DEVICES={GPU ID} python demo/inference_on_a_image.py \
206
+ -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
207
+ -p ./groundingdino_swint_ogc.pth \
208
+ -i .asset/cat_dog.jpeg \
209
+ -o logs/1111 \
210
+ -t "There is a cat and a dog in the image ." \
211
+ --token_spans "[[[9, 10], [11, 14]], [[19, 20], [21, 24]]]"
212
+ [--cpu-only] # open it for cpu mode
213
+ ```
214
+ The token_spans specify the start and end positions of a phrases. For example, the first phrase is `[[9, 10], [11, 14]]`. `"There is a cat and a dog in the image ."[9:10] = 'a'`, `"There is a cat and a dog in the image ."[11:14] = 'cat'`. Hence it refers to the phrase `a cat` . Similarly, the `[[19, 20], [21, 24]]` refers to the phrase `a dog`.
215
+
216
+ See the `demo/inference_on_a_image.py` for more details.
217
+
218
+ **Running with Python:**
219
+
220
+ ```python
221
+ from groundingdino.util.inference import load_model, load_image, predict, annotate
222
+ import cv2
223
+
224
+ model = load_model("groundingdino/config/GroundingDINO_SwinT_OGC.py", "weights/groundingdino_swint_ogc.pth")
225
+ IMAGE_PATH = "weights/dog-3.jpeg"
226
+ TEXT_PROMPT = "chair . person . dog ."
227
+ BOX_TRESHOLD = 0.35
228
+ TEXT_TRESHOLD = 0.25
229
+
230
+ image_source, image = load_image(IMAGE_PATH)
231
+
232
+ boxes, logits, phrases = predict(
233
+ model=model,
234
+ image=image,
235
+ caption=TEXT_PROMPT,
236
+ box_threshold=BOX_TRESHOLD,
237
+ text_threshold=TEXT_TRESHOLD
238
+ )
239
+
240
+ annotated_frame = annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)
241
+ cv2.imwrite("annotated_image.jpg", annotated_frame)
242
+ ```
243
+ **Web UI**
244
+
245
+ We also provide a demo code to integrate Grounding DINO with Gradio Web UI. See the file `demo/gradio_app.py` for more details.
246
+
247
+ **Notebooks**
248
+
249
+ - We release [demos](demo/image_editing_with_groundingdino_gligen.ipynb) to combine [Grounding DINO](https://arxiv.org/abs/2303.05499) with [GLIGEN](https://github.com/gligen/GLIGEN) for more controllable image editings.
250
+ - We release [demos](demo/image_editing_with_groundingdino_stablediffusion.ipynb) to combine [Grounding DINO](https://arxiv.org/abs/2303.05499) with [Stable Diffusion](https://github.com/Stability-AI/StableDiffusion) for image editings.
251
+
252
+ ## COCO Zero-shot Evaluations
253
+
254
+ We provide an example to evaluate Grounding DINO zero-shot performance on COCO. The results should be **48.5**.
255
+
256
+ ```bash
257
+ CUDA_VISIBLE_DEVICES=0 \
258
+ python demo/test_ap_on_coco.py \
259
+ -c groundingdino/config/GroundingDINO_SwinT_OGC.py \
260
+ -p weights/groundingdino_swint_ogc.pth \
261
+ --anno_path /path/to/annoataions/ie/instances_val2017.json \
262
+ --image_dir /path/to/imagedir/ie/val2017
263
+ ```
264
+
265
+
266
+ ## :luggage: Checkpoints
267
+
268
+ <!-- insert a table -->
269
+ <table>
270
+ <thead>
271
+ <tr style="text-align: right;">
272
+ <th></th>
273
+ <th>name</th>
274
+ <th>backbone</th>
275
+ <th>Data</th>
276
+ <th>box AP on COCO</th>
277
+ <th>Checkpoint</th>
278
+ <th>Config</th>
279
+ </tr>
280
+ </thead>
281
+ <tbody>
282
+ <tr>
283
+ <th>1</th>
284
+ <td>GroundingDINO-T</td>
285
+ <td>Swin-T</td>
286
+ <td>O365,GoldG,Cap4M</td>
287
+ <td>48.4 (zero-shot) / 57.2 (fine-tune)</td>
288
+ <td><a href="https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth">GitHub link</a> | <a href="https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swint_ogc.pth">HF link</a></td>
289
+ <td><a href="https://github.com/IDEA-Research/GroundingDINO/blob/main/groundingdino/config/GroundingDINO_SwinT_OGC.py">link</a></td>
290
+ </tr>
291
+ <tr>
292
+ <th>2</th>
293
+ <td>GroundingDINO-B</td>
294
+ <td>Swin-B</td>
295
+ <td>COCO,O365,GoldG,Cap4M,OpenImage,ODinW-35,RefCOCO</td>
296
+ <td>56.7 </td>
297
+ <td><a href="https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha2/groundingdino_swinb_cogcoor.pth">GitHub link</a> | <a href="https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swinb_cogcoor.pth">HF link</a>
298
+ <td><a href="https://github.com/IDEA-Research/GroundingDINO/blob/main/groundingdino/config/GroundingDINO_SwinB.cfg.py">link</a></td>
299
+ </tr>
300
+ </tbody>
301
+ </table>
302
+
303
+ ## :medal_military: Results
304
+
305
+ <details open>
306
+ <summary><font size="4">
307
+ COCO Object Detection Results
308
+ </font></summary>
309
+ <img src=".asset/COCO.png" alt="COCO" width="100%">
310
+ </details>
311
+
312
+ <details open>
313
+ <summary><font size="4">
314
+ ODinW Object Detection Results
315
+ </font></summary>
316
+ <img src=".asset/ODinW.png" alt="ODinW" width="100%">
317
+ </details>
318
+
319
+ <details open>
320
+ <summary><font size="4">
321
+ Marrying Grounding DINO with <a href="https://github.com/Stability-AI/StableDiffusion">Stable Diffusion</a> for Image Editing
322
+ </font></summary>
323
+ See our example <a href="https://github.com/IDEA-Research/GroundingDINO/blob/main/demo/image_editing_with_groundingdino_stablediffusion.ipynb">notebook</a> for more details.
324
+ <img src=".asset/GD_SD.png" alt="GD_SD" width="100%">
325
+ </details>
326
+
327
+
328
+ <details open>
329
+ <summary><font size="4">
330
+ Marrying Grounding DINO with <a href="https://github.com/gligen/GLIGEN">GLIGEN</a> for more Detailed Image Editing.
331
+ </font></summary>
332
+ See our example <a href="https://github.com/IDEA-Research/GroundingDINO/blob/main/demo/image_editing_with_groundingdino_gligen.ipynb">notebook</a> for more details.
333
+ <img src=".asset/GD_GLIGEN.png" alt="GD_GLIGEN" width="100%">
334
+ </details>
335
+
336
+ ## :sauropod: Model: Grounding DINO
337
+
338
+ Includes: a text backbone, an image backbone, a feature enhancer, a language-guided query selection, and a cross-modality decoder.
339
+
340
+ ![arch](.asset/arch.png)
341
+
342
+
343
+ ## :hearts: Acknowledgement
344
+
345
+ Our model is related to [DINO](https://github.com/IDEA-Research/DINO) and [GLIP](https://github.com/microsoft/GLIP). Thanks for their great work!
346
+
347
+ We also thank great previous work including DETR, Deformable DETR, SMCA, Conditional DETR, Anchor DETR, Dynamic DETR, DAB-DETR, DN-DETR, etc. More related work are available at [Awesome Detection Transformer](https://github.com/IDEACVR/awesome-detection-transformer). A new toolbox [detrex](https://github.com/IDEA-Research/detrex) is available as well.
348
+
349
+ Thanks [Stable Diffusion](https://github.com/Stability-AI/StableDiffusion) and [GLIGEN](https://github.com/gligen/GLIGEN) for their awesome models.
350
+
351
+
352
+ ## :black_nib: Citation
353
+
354
+ If you find our work helpful for your research, please consider citing the following BibTeX entry.
355
+
356
+ ```bibtex
357
+ @article{liu2023grounding,
358
+ title={Grounding dino: Marrying dino with grounded pre-training for open-set object detection},
359
+ author={Liu, Shilong and Zeng, Zhaoyang and Ren, Tianhe and Li, Feng and Zhang, Hao and Yang, Jie and Li, Chunyuan and Yang, Jianwei and Su, Hang and Zhu, Jun and others},
360
+ journal={arXiv preprint arXiv:2303.05499},
361
+ year={2023}
362
+ }
363
+ ```
364
+
365
+
366
+
367
+
approach/ovod/GroundingDINO/gdino.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from groundingdino.util.inference import load_model, load_image, predict, annotate
2
+ import cv2
3
+
4
+ model = load_model("./groundingdino/config/GroundingDINO_SwinT_OGC.py", "weights/groundingdino_swint_ogc.pth")
5
+
6
+ def peform_ovod(image_path, text_prompt, box_threshold, text_threshold):
7
+ image_path = "weights/dog.jpg"
8
+ text_prompt = "chair . person . dog ."
9
+ box_threshold = 0.35
10
+ text_threshold = 0.25
11
+
12
+ image_source, image = load_image(image_path)
13
+
14
+ boxes, logits, phrases = predict(
15
+ model=model,
16
+ image=image,
17
+ caption=text_prompt,
18
+ box_threshold=box_threshold,
19
+ text_threshold=text_threshold
20
+ )
21
+
22
+ annotated_frame = annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)
23
+ cv2.imwrite("annotated_image.jpg", annotated_frame)
approach/ovod/GroundingDINO/requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ transformers
4
+ addict
5
+ yapf
6
+ timm
7
+ numpy
8
+ opencv-python
9
+ supervision==0.6.0
10
+ pycocotools
approach/ovod/GroundingDINO/setup.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2022 The IDEA Authors. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ------------------------------------------------------------------------------------------------
16
+ # Modified from
17
+ # https://github.com/fundamentalvision/Deformable-DETR/blob/main/models/ops/setup.py
18
+ # https://github.com/facebookresearch/detectron2/blob/main/setup.py
19
+ # https://github.com/open-mmlab/mmdetection/blob/master/setup.py
20
+ # https://github.com/Oneflow-Inc/libai/blob/main/setup.py
21
+ # ------------------------------------------------------------------------------------------------
22
+
23
+ import glob
24
+ import os
25
+ import subprocess
26
+
27
+ import torch
28
+ from setuptools import find_packages, setup
29
+ from torch.utils.cpp_extension import CUDA_HOME, CppExtension, CUDAExtension
30
+
31
+ # groundingdino version info
32
+ version = "0.1.0"
33
+ package_name = "groundingdino"
34
+ cwd = os.path.dirname(os.path.abspath(__file__))
35
+
36
+
37
+ sha = "Unknown"
38
+ try:
39
+ sha = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd).decode("ascii").strip()
40
+ except Exception:
41
+ pass
42
+
43
+
44
+ def write_version_file():
45
+ version_path = os.path.join(cwd, "groundingdino", "version.py")
46
+ with open(version_path, "w") as f:
47
+ f.write(f"__version__ = '{version}'\n")
48
+ # f.write(f"git_version = {repr(sha)}\n")
49
+
50
+
51
+ requirements = ["torch", "torchvision"]
52
+
53
+ torch_ver = [int(x) for x in torch.__version__.split(".")[:2]]
54
+
55
+
56
+ def get_extensions():
57
+ this_dir = os.path.dirname(os.path.abspath(__file__))
58
+ extensions_dir = os.path.join(this_dir, "groundingdino", "models", "GroundingDINO", "csrc")
59
+
60
+ main_source = os.path.join(extensions_dir, "vision.cpp")
61
+ sources = glob.glob(os.path.join(extensions_dir, "**", "*.cpp"))
62
+ source_cuda = glob.glob(os.path.join(extensions_dir, "**", "*.cu")) + glob.glob(
63
+ os.path.join(extensions_dir, "*.cu")
64
+ )
65
+
66
+ sources = [main_source] + sources
67
+
68
+ extension = CppExtension
69
+
70
+ extra_compile_args = {"cxx": []}
71
+ define_macros = []
72
+
73
+ if CUDA_HOME is not None and (torch.cuda.is_available() or "TORCH_CUDA_ARCH_LIST" in os.environ):
74
+ print("Compiling with CUDA")
75
+ extension = CUDAExtension
76
+ sources += source_cuda
77
+ define_macros += [("WITH_CUDA", None)]
78
+ extra_compile_args["nvcc"] = [
79
+ "-DCUDA_HAS_FP16=1",
80
+ "-D__CUDA_NO_HALF_OPERATORS__",
81
+ "-D__CUDA_NO_HALF_CONVERSIONS__",
82
+ "-D__CUDA_NO_HALF2_OPERATORS__",
83
+ ]
84
+ else:
85
+ print("Compiling without CUDA")
86
+ define_macros += [("WITH_HIP", None)]
87
+ extra_compile_args["nvcc"] = []
88
+ return None
89
+
90
+ sources = [os.path.join(extensions_dir, s) for s in sources]
91
+ include_dirs = [extensions_dir]
92
+
93
+ ext_modules = [
94
+ extension(
95
+ "groundingdino._C",
96
+ sources,
97
+ include_dirs=include_dirs,
98
+ define_macros=define_macros,
99
+ extra_compile_args=extra_compile_args,
100
+ )
101
+ ]
102
+
103
+ return ext_modules
104
+
105
+
106
+ def parse_requirements(fname="requirements.txt", with_version=True):
107
+ """Parse the package dependencies listed in a requirements file but strips
108
+ specific versioning information.
109
+
110
+ Args:
111
+ fname (str): path to requirements file
112
+ with_version (bool, default=False): if True include version specs
113
+
114
+ Returns:
115
+ List[str]: list of requirements items
116
+
117
+ CommandLine:
118
+ python -c "import setup; print(setup.parse_requirements())"
119
+ """
120
+ import re
121
+ import sys
122
+ from os.path import exists
123
+
124
+ require_fpath = fname
125
+
126
+ def parse_line(line):
127
+ """Parse information from a line in a requirements text file."""
128
+ if line.startswith("-r "):
129
+ # Allow specifying requirements in other files
130
+ target = line.split(" ")[1]
131
+ for info in parse_require_file(target):
132
+ yield info
133
+ else:
134
+ info = {"line": line}
135
+ if line.startswith("-e "):
136
+ info["package"] = line.split("#egg=")[1]
137
+ elif "@git+" in line:
138
+ info["package"] = line
139
+ else:
140
+ # Remove versioning from the package
141
+ pat = "(" + "|".join([">=", "==", ">"]) + ")"
142
+ parts = re.split(pat, line, maxsplit=1)
143
+ parts = [p.strip() for p in parts]
144
+
145
+ info["package"] = parts[0]
146
+ if len(parts) > 1:
147
+ op, rest = parts[1:]
148
+ if ";" in rest:
149
+ # Handle platform specific dependencies
150
+ # http://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-platform-specific-dependencies
151
+ version, platform_deps = map(str.strip, rest.split(";"))
152
+ info["platform_deps"] = platform_deps
153
+ else:
154
+ version = rest # NOQA
155
+ info["version"] = (op, version)
156
+ yield info
157
+
158
+ def parse_require_file(fpath):
159
+ with open(fpath, "r") as f:
160
+ for line in f.readlines():
161
+ line = line.strip()
162
+ if line and not line.startswith("#"):
163
+ for info in parse_line(line):
164
+ yield info
165
+
166
+ def gen_packages_items():
167
+ if exists(require_fpath):
168
+ for info in parse_require_file(require_fpath):
169
+ parts = [info["package"]]
170
+ if with_version and "version" in info:
171
+ parts.extend(info["version"])
172
+ if not sys.version.startswith("3.4"):
173
+ # apparently package_deps are broken in 3.4
174
+ platform_deps = info.get("platform_deps")
175
+ if platform_deps is not None:
176
+ parts.append(";" + platform_deps)
177
+ item = "".join(parts)
178
+ yield item
179
+
180
+ packages = list(gen_packages_items())
181
+ return packages
182
+
183
+
184
+ if __name__ == "__main__":
185
+ print(f"Building wheel {package_name}-{version}")
186
+
187
+ with open("LICENSE", "r", encoding="utf-8") as f:
188
+ license = f.read()
189
+
190
+ write_version_file()
191
+
192
+ setup(
193
+ name="groundingdino",
194
+ version="0.1.0",
195
+ author="International Digital Economy Academy, Shilong Liu",
196
+ url="https://github.com/IDEA-Research/GroundingDINO",
197
+ description="open-set object detector",
198
+ license=license,
199
+ install_requires=parse_requirements("requirements.txt"),
200
+ packages=find_packages(
201
+ exclude=(
202
+ "configs",
203
+ "tests",
204
+ )
205
+ ),
206
+ ext_modules=get_extensions(),
207
+ cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension},
208
+ )
approach/ovod/GroundingDINO/test.ipynb ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "from groundingdino.util.inference import load_model, load_image, predict, annotate\n",
10
+ "import cv2\n",
11
+ "\n",
12
+ "model = load_model(\"groundingdino/config/GroundingDINO_SwinT_OGC.py\", \"../04-06-segment-anything/weights/groundingdino_swint_ogc.pth\")\n",
13
+ "IMAGE_PATH = \".asset/cat_dog.jpeg\"\n",
14
+ "TEXT_PROMPT = \"chair . person . dog .\"\n",
15
+ "BOX_TRESHOLD = 0.35\n",
16
+ "TEXT_TRESHOLD = 0.25\n",
17
+ "\n",
18
+ "image_source, image = load_image(IMAGE_PATH)\n",
19
+ "\n",
20
+ "boxes, logits, phrases = predict(\n",
21
+ " model=model,\n",
22
+ " image=image,\n",
23
+ " caption=TEXT_PROMPT,\n",
24
+ " box_threshold=BOX_TRESHOLD,\n",
25
+ " text_threshold=TEXT_TRESHOLD\n",
26
+ ")\n",
27
+ "\n",
28
+ "annotated_frame = annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)\n",
29
+ "cv2.imwrite(\"annotated_image.jpg\", annotated_frame)"
30
+ ]
31
+ }
32
+ ],
33
+ "metadata": {
34
+ "kernelspec": {
35
+ "display_name": "base",
36
+ "language": "python",
37
+ "name": "python3"
38
+ },
39
+ "language_info": {
40
+ "codemirror_mode": {
41
+ "name": "ipython",
42
+ "version": 3
43
+ },
44
+ "file_extension": ".py",
45
+ "mimetype": "text/x-python",
46
+ "name": "python",
47
+ "nbconvert_exporter": "python",
48
+ "pygments_lexer": "ipython3",
49
+ "version": "3.8.10"
50
+ },
51
+ "orig_nbformat": 4
52
+ },
53
+ "nbformat": 4,
54
+ "nbformat_minor": 2
55
+ }
approach/ovod/d-cube/.gitignore ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .vscode/*
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # poetry
99
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
103
+ #poetry.lock
104
+
105
+ # pdm
106
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
107
+ #pdm.lock
108
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
109
+ # in version control.
110
+ # https://pdm.fming.dev/#use-with-ide
111
+ .pdm.toml
112
+
113
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
114
+ __pypackages__/
115
+
116
+ # Celery stuff
117
+ celerybeat-schedule
118
+ celerybeat.pid
119
+
120
+ # SageMath parsed files
121
+ *.sage.py
122
+
123
+ # Environments
124
+ .env
125
+ .venv
126
+ env/
127
+ venv/
128
+ ENV/
129
+ env.bak/
130
+ venv.bak/
131
+
132
+ # Spyder project settings
133
+ .spyderproject
134
+ .spyproject
135
+
136
+ # Rope project settings
137
+ .ropeproject
138
+
139
+ # mkdocs documentation
140
+ /site
141
+
142
+ # mypy
143
+ .mypy_cache/
144
+ .dmypy.json
145
+ dmypy.json
146
+
147
+ # Pyre type checker
148
+ .pyre/
149
+
150
+ # pytype static type analyzer
151
+ .pytype/
152
+
153
+ # Cython debug symbols
154
+ cython_debug/
155
+
156
+ # PyCharm
157
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
158
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
159
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
160
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
161
+ #.idea/
162
+
163
+ # mac system
164
+ *.DS_Store
approach/ovod/d-cube/README.md ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- PROJECT LOGO -->
2
+ <br />
3
+ <p align="center">
4
+ <a href="#">
5
+ <img src=".assets/d-cube_logo.png" alt="Logo" width="310"></a>
6
+ <h4 align="center">A detection/segmentation dataset with class names characterized by intricate and flexible expressions</h4>
7
+ <p align="center">
8
+ The repo is the toolbox for <b>D<sup>3</sup></b>
9
+ <br />
10
+ <a href="doc.md"><strong> [Doc 📚]</strong></a>
11
+ <!-- <a href="https://huggingface.co/datasets/zbrl/d-cube"><strong> [HuggingFace 🤗]</strong></a> -->
12
+ <a href="https://arxiv.org/abs/2307.12813"><strong> [Paper (DOD) 📄] </strong></a>
13
+ <a href="https://arxiv.org/abs/2305.12452"><strong> [Paper (GRES) 📄] </strong></a>
14
+ <a href="https://github.com/Charles-Xie/awesome-described-object-detection"><strong> [Awesome-DOD 🕶️] </strong></a>
15
+ <br />
16
+ </p>
17
+ </p>
18
+
19
+ ***
20
+ Description Detection Dataset ($D^3$, /dikju:b/) is an attempt at creating a next-generation object detection dataset. Unlike traditional detection datasets, the class names of the objects are no longer simple nouns or noun phrases, but rather complex and descriptive, such as `a dog not being held by a leash`. For each image in the dataset, any object that matches the description is annotated. The dataset provides annotations such as bounding boxes and finely crafted instance masks. We believe it will contribute to computer vision and vision-language communities.
21
+
22
+
23
+
24
+ # News
25
+ - [02/14/2024] Evaluation on several SOTA methods (SPHNX (the first MLLM evaluated!), G-DINO, UNINEXT, etc.) are released, together with a [leaderboard](https://github.com/shikras/d-cube/tree/main/eval_sota) for $D^3$. :fire::fire:
26
+
27
+ - [10/12/2023] We released an [awesome-described-object-detection](https://github.com/Charles-Xie/awesome-described-object-detection) list to collect and track related works.
28
+
29
+ - [09/22/2023] Our DOD [paper](https://arxiv.org/abs/2307.12813) just got accepted by NeurIPS 2023! :fire:
30
+
31
+ - [07/25/2023] This toolkit is available on PyPI now. You can install this repo with `pip install ddd-dataset`.
32
+
33
+ - [07/25/2023] The [paper preprint](https://arxiv.org/abs/2307.12813) introducing the DOD task and the $D^3$ dataset, is available on arxiv. Check it out!
34
+
35
+ - [07/18/2023] We have released our Description Detection Dataset ($D^3$) and the first version of $D^3$ toolbox. You can download it now for your project.
36
+
37
+ - [07/14/2023] Our GRES [paper](https://arxiv.org/abs/2305.12452) has been accepted by ICCV 2023.
38
+
39
+
40
+
41
+ # Contents
42
+ - [Dataset Highlight](#task-and-dataset-highlight)
43
+ - [Download](#download)
44
+ - [Installation](#installation)
45
+ - [Usage](#usage)
46
+
47
+
48
+
49
+ # Task and Dataset Highlight
50
+
51
+ The $D^3$ dataset is meant for the Described Object Detection (DOD) task. In the image below we show the difference between Referring Expression Comprehension (REC), Object Detection/Open-Vocabulary Detection (OVD) and Described Object Detection (DOD). OVD detect object based on category name, and each category can have zero to multiple instances; REC grounds one region based on a language description, whether the object truly exits or not; DOD detect all instances on each image in the dataset, based on a flexible reference. Related works are tracked in the [awesome-DOD](https://github.com/Charles-Xie/awesome-described-object-detection) list.
52
+
53
+ ![Dataset Highlight](.assets/teaser.png "Highlight of the task & dataset")
54
+
55
+ For more information on the characteristics of this dataset, please refer to our paper.
56
+
57
+
58
+
59
+ # Download
60
+ Currently we host the $D^3$ dataset on cloud drives. You can download the dataset from [Google Drive](https://drive.google.com/drive/folders/11kfY12NzKPwsliLEcIYki1yUqt7PbMEi?usp=sharing) or [Baidu Pan]().
61
+
62
+ After downloading the `d3_images.zip` (images in the dataset), `d3_pkl.zip` (dataset information for this toolkit) and `d3_json.zip` (annotation for evaluation), please extract these 3 zip files to your custom `IMG_ROOT`, `PKL_PATH` and `JSON_ANNO_PATH` directory. These paths will be used when you perform inference or evaluation on this dataset.
63
+
64
+
65
+
66
+ # Installation
67
+
68
+ ## Prerequisites
69
+ This toolkit requires a few python packages like `numpy` and `pycocotools`. Other packages like `matplotlib` and `opencv-python` may also be required if you want to utilize the visualization scripts.
70
+
71
+ <!-- There are three ways to install $D^3$ toolbox, and the third one (with huggingface) is currently in the works and will be available soon. -->
72
+
73
+ There are multiple ways to install $D^3$ toolbox, as listed below:
74
+
75
+
76
+ ## Install with pip
77
+ ```bash
78
+ pip install ddd-dataset
79
+ ```
80
+
81
+ ## Install from source
82
+ ```bash
83
+ git clone https://github.com/shikra/d-cube.git
84
+ # option 1: install it as a python package
85
+ cd d-cube
86
+ python -m pip install .
87
+ # done
88
+
89
+ # option 2: just put the d-cube/d_cube directory in the root directory of your local repository
90
+ ```
91
+
92
+ <!-- ## Via HuggingFace Datasets 🤗
93
+ ```bash
94
+ coming soon
95
+ ``` -->
96
+
97
+
98
+
99
+ # Usage
100
+ Please refer to the [documentation 📚](doc.md) for more details.
101
+ Our toolbox is similar to [cocoapi](https://github.com/cocodataset/cocoapi) in style.
102
+
103
+ Here is a quick example of how to use $D^3$.
104
+ ```python
105
+ from d_cube import D3
106
+ d3 = D3(IMG_ROOT, PKL_ANNO_PATH)
107
+ all_img_ids = d3.get_img_ids() # get the image ids in the dataset
108
+ all_img_info = d3.load_imgs(all_img_ids) # load images by passing a list of some image ids
109
+ img_path = all_img_info[0]["file_name"] # obtain one image path so you can load it and inference
110
+ ```
111
+
112
+ Some frequently asked questions are answered in [this Q&A file](./qa.md).
113
+
114
+ # Citation
115
+
116
+ If you use our $D^3$ dataset, this toolbox, or otherwise find our work valuable, please cite [our paper](https://arxiv.org/abs/2307.12813):
117
+
118
+ ```bibtex
119
+ @inproceedings{xie2023DOD,
120
+ title={Described Object Detection: Liberating Object Detection with Flexible Expressions},
121
+ author={Xie, Chi and Zhang, Zhao and Wu, Yixuan and Zhu, Feng and Zhao, Rui and Liang, Shuang},
122
+ booktitle={Thirty-seventh Conference on Neural Information Processing Systems (NeurIPS)},
123
+ year={2023}
124
+ }
125
+
126
+ @inproceedings{wu2023gres,
127
+ title={Advancing Referring Expression Segmentation Beyond Single Image},
128
+ author={Wu, Yixuan and Zhang, Zhao and Xie, Chi and Zhu, Feng and Zhao, Rui},
129
+ booktitle={International Conference on Computer Vision (ICCV)},
130
+ year={2023}
131
+ }
132
+ ```
133
+
134
+ More works related to Described Object Detection are tracked in this list: [awesome-described-object-detection](https://github.com/Charles-Xie/awesome-described-object-detection).
approach/ovod/d-cube/qa.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Frequently Asked Questions
2
+
3
+ Q:
4
+ What's the difference between Intra-Group and Inter-Group setting in [the DOD paper](https://arxiv.org/abs/2307.12813), and how to set them?
5
+
6
+ A:
7
+ Please see [this explanation in the document](./doc.md#intra--or-inter-group-settings).
8
+
9
+
10
+
11
+ Q:
12
+ What's the meaning of and difference between FULL, PRES, and ABS?
13
+
14
+ A:
15
+ Please see [this explanation in the document](./doc.md#full-pres-and-abs).
16
+
17
+
18
+
19
+ Q:
20
+ How do I perform a visualization of ground truth or prediction on a image?
21
+
22
+ A:
23
+ You can use `d3.get_anno_ids` function and pass the `img_id` you choose as parameter to get the annotation ids for a image.
24
+ After this, you can obtain the annotation details (class ids, bboxes) with `d3.load_annos`.
approach/ovod/d-cube/requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ numpy
2
+ pycocotools
3
+ opencv-python
4
+ matplotlib
approach/ovod/d-cube/setup.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import setuptools
2
+
3
+ setuptools.setup(
4
+ name='ddd-dataset',
5
+ version='0.1.1',
6
+ author='Chi Xie',
7
+ author_email='chixie.personal@gmail.com',
8
+ description='Toolkit for Description Detection Dataset ($D^3$)',
9
+ long_description='Toolkit for Description Detection Dataset ($D^3$): A detection dataset with class names characterized by intricate and flexible expressions, for the Described Object Detection (DOD) task.',
10
+ long_description_content_type='text/markdown',
11
+ license='CC BY-NC 4.0',
12
+ packages=['d_cube'],
13
+ package_dir={"d_cube": "d_cube"},
14
+ url='https://github.com/shikras/d-cube',
15
+ project_urls={
16
+ "Bug Tracker": "https://github.com/shikras/d-cube/issues",
17
+ },
18
+ install_requires=['numpy', 'pycocotools', 'opencv-python', 'matplotlib'],
19
+
20
+ classifiers=[
21
+ 'Development Status :: 4 - Beta',
22
+ 'Intended Audience :: Science/Research',
23
+ 'Intended Audience :: Developers',
24
+ 'Intended Audience :: Education',
25
+ 'Operating System :: MacOS',
26
+ 'Operating System :: Microsoft :: Windows',
27
+ 'Operating System :: POSIX :: Linux',
28
+ 'Programming Language :: Python :: 3',
29
+ ],
30
+ )
approach/ovod/detectron2/.clang-format ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ AccessModifierOffset: -1
2
+ AlignAfterOpenBracket: AlwaysBreak
3
+ AlignConsecutiveAssignments: false
4
+ AlignConsecutiveDeclarations: false
5
+ AlignEscapedNewlinesLeft: true
6
+ AlignOperands: false
7
+ AlignTrailingComments: false
8
+ AllowAllParametersOfDeclarationOnNextLine: false
9
+ AllowShortBlocksOnASingleLine: false
10
+ AllowShortCaseLabelsOnASingleLine: false
11
+ AllowShortFunctionsOnASingleLine: Empty
12
+ AllowShortIfStatementsOnASingleLine: false
13
+ AllowShortLoopsOnASingleLine: false
14
+ AlwaysBreakAfterReturnType: None
15
+ AlwaysBreakBeforeMultilineStrings: true
16
+ AlwaysBreakTemplateDeclarations: true
17
+ BinPackArguments: false
18
+ BinPackParameters: false
19
+ BraceWrapping:
20
+ AfterClass: false
21
+ AfterControlStatement: false
22
+ AfterEnum: false
23
+ AfterFunction: false
24
+ AfterNamespace: false
25
+ AfterObjCDeclaration: false
26
+ AfterStruct: false
27
+ AfterUnion: false
28
+ BeforeCatch: false
29
+ BeforeElse: false
30
+ IndentBraces: false
31
+ BreakBeforeBinaryOperators: None
32
+ BreakBeforeBraces: Attach
33
+ BreakBeforeTernaryOperators: true
34
+ BreakConstructorInitializersBeforeComma: false
35
+ BreakAfterJavaFieldAnnotations: false
36
+ BreakStringLiterals: false
37
+ ColumnLimit: 80
38
+ CommentPragmas: '^ IWYU pragma:'
39
+ ConstructorInitializerAllOnOneLineOrOnePerLine: true
40
+ ConstructorInitializerIndentWidth: 4
41
+ ContinuationIndentWidth: 4
42
+ Cpp11BracedListStyle: true
43
+ DerivePointerAlignment: false
44
+ DisableFormat: false
45
+ ForEachMacros: [ FOR_EACH, FOR_EACH_R, FOR_EACH_RANGE, ]
46
+ IncludeCategories:
47
+ - Regex: '^<.*\.h(pp)?>'
48
+ Priority: 1
49
+ - Regex: '^<.*'
50
+ Priority: 2
51
+ - Regex: '.*'
52
+ Priority: 3
53
+ IndentCaseLabels: true
54
+ IndentWidth: 2
55
+ IndentWrappedFunctionNames: false
56
+ KeepEmptyLinesAtTheStartOfBlocks: false
57
+ MacroBlockBegin: ''
58
+ MacroBlockEnd: ''
59
+ MaxEmptyLinesToKeep: 1
60
+ NamespaceIndentation: None
61
+ ObjCBlockIndentWidth: 2
62
+ ObjCSpaceAfterProperty: false
63
+ ObjCSpaceBeforeProtocolList: false
64
+ PenaltyBreakBeforeFirstCallParameter: 1
65
+ PenaltyBreakComment: 300
66
+ PenaltyBreakFirstLessLess: 120
67
+ PenaltyBreakString: 1000
68
+ PenaltyExcessCharacter: 1000000
69
+ PenaltyReturnTypeOnItsOwnLine: 200
70
+ PointerAlignment: Left
71
+ ReflowComments: true
72
+ SortIncludes: true
73
+ SpaceAfterCStyleCast: false
74
+ SpaceBeforeAssignmentOperators: true
75
+ SpaceBeforeParens: ControlStatements
76
+ SpaceInEmptyParentheses: false
77
+ SpacesBeforeTrailingComments: 1
78
+ SpacesInAngles: false
79
+ SpacesInContainerLiterals: true
80
+ SpacesInCStyleCastParentheses: false
81
+ SpacesInParentheses: false
82
+ SpacesInSquareBrackets: false
83
+ Standard: Cpp11
84
+ TabWidth: 8
85
+ UseTab: Never
approach/ovod/detectron2/.flake8 ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is an example .flake8 config, used when developing *Black* itself.
2
+ # Keep in sync with setup.cfg which is used for source packages.
3
+
4
+ [flake8]
5
+ ignore = W503, E203, E221, C901, C408, E741, C407, B017, F811, C101, EXE001, EXE002
6
+ max-line-length = 100
7
+ max-complexity = 18
8
+ select = B,C,E,F,W,T4,B9
9
+ exclude = build
10
+ per-file-ignores =
11
+ **/__init__.py:F401,F403,E402
12
+ **/configs/**.py:F401,E402
13
+ configs/**.py:F401,E402
14
+ **/tests/config/**.py:F401,E402
15
+ tests/config/**.py:F401,E402
approach/ovod/detectron2/.gitignore ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # output dir
2
+ output
3
+ instant_test_output
4
+ inference_test_output
5
+
6
+
7
+ *.png
8
+ *.json
9
+ *.diff
10
+ *.jpg
11
+ !/projects/DensePose/doc/images/*.jpg
12
+
13
+ # compilation and distribution
14
+ __pycache__
15
+ _ext
16
+ *.pyc
17
+ *.pyd
18
+ *.so
19
+ *.dll
20
+ *.egg-info/
21
+ build/
22
+ dist/
23
+ wheels/
24
+
25
+ # pytorch/python/numpy formats
26
+ *.pth
27
+ *.pkl
28
+ *.npy
29
+ *.ts
30
+ model_ts*.txt
31
+
32
+ # ipython/jupyter notebooks
33
+ *.ipynb
34
+ **/.ipynb_checkpoints/
35
+
36
+ # Editor temporaries
37
+ *.swn
38
+ *.swo
39
+ *.swp
40
+ *~
41
+
42
+ # editor settings
43
+ .idea
44
+ .vscode
45
+ _darcs
46
+
47
+ # project dirs
48
+ /detectron2/model_zoo/configs
49
+ /datasets/*
50
+ !/datasets/*.*
51
+ /projects/*/datasets
52
+ /models
53
+ /snippet
approach/ovod/detectron2/GETTING_STARTED.md ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Getting Started with Detectron2
2
+
3
+ This document provides a brief intro of the usage of builtin command-line tools in detectron2.
4
+
5
+ For a tutorial that involves actual coding with the API,
6
+ see our [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5)
7
+ which covers how to run inference with an
8
+ existing model, and how to train a builtin model on a custom dataset.
9
+
10
+
11
+ ### Inference Demo with Pre-trained Models
12
+
13
+ 1. Pick a model and its config file from
14
+ [model zoo](MODEL_ZOO.md),
15
+ for example, `mask_rcnn_R_50_FPN_3x.yaml`.
16
+ 2. We provide `demo.py` that is able to demo builtin configs. Run it with:
17
+ ```
18
+ cd demo/
19
+ python demo.py --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \
20
+ --input input1.jpg input2.jpg \
21
+ [--other-options]
22
+ --opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl
23
+ ```
24
+ The configs are made for training, therefore we need to specify `MODEL.WEIGHTS` to a model from model zoo for evaluation.
25
+ This command will run the inference and show visualizations in an OpenCV window.
26
+
27
+ For details of the command line arguments, see `demo.py -h` or look at its source code
28
+ to understand its behavior. Some common arguments are:
29
+ * To run __on your webcam__, replace `--input files` with `--webcam`.
30
+ * To run __on a video__, replace `--input files` with `--video-input video.mp4`.
31
+ * To run __on cpu__, add `MODEL.DEVICE cpu` after `--opts`.
32
+ * To save outputs to a directory (for images) or a file (for webcam or video), use `--output`.
33
+
34
+
35
+ ### Training & Evaluation in Command Line
36
+
37
+ We provide two scripts in "tools/plain_train_net.py" and "tools/train_net.py",
38
+ that are made to train all the configs provided in detectron2. You may want to
39
+ use it as a reference to write your own training script.
40
+
41
+ Compared to "train_net.py", "plain_train_net.py" supports fewer default
42
+ features. It also includes fewer abstraction, therefore is easier to add custom
43
+ logic.
44
+
45
+ To train a model with "train_net.py", first
46
+ setup the corresponding datasets following
47
+ [datasets/README.md](./datasets/README.md),
48
+ then run:
49
+ ```
50
+ cd tools/
51
+ ./train_net.py --num-gpus 8 \
52
+ --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml
53
+ ```
54
+
55
+ The configs are made for 8-GPU training.
56
+ To train on 1 GPU, you may need to [change some parameters](https://arxiv.org/abs/1706.02677), e.g.:
57
+ ```
58
+ ./train_net.py \
59
+ --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
60
+ --num-gpus 1 SOLVER.IMS_PER_BATCH 2 SOLVER.BASE_LR 0.0025
61
+ ```
62
+
63
+ To evaluate a model's performance, use
64
+ ```
65
+ ./train_net.py \
66
+ --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
67
+ --eval-only MODEL.WEIGHTS /path/to/checkpoint_file
68
+ ```
69
+ For more options, see `./train_net.py -h`.
70
+
71
+ ### Use Detectron2 APIs in Your Code
72
+
73
+ See our [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5)
74
+ to learn how to use detectron2 APIs to:
75
+ 1. run inference with an existing model
76
+ 2. train a builtin model on a custom dataset
77
+
78
+ See [detectron2/projects](https://github.com/facebookresearch/detectron2/tree/main/projects)
79
+ for more ways to build your project on detectron2.
approach/ovod/detectron2/INSTALL.md ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Installation
2
+
3
+ ### Requirements
4
+ - Linux or macOS with Python ≥ 3.7
5
+ - PyTorch ≥ 1.8 and [torchvision](https://github.com/pytorch/vision/) that matches the PyTorch installation.
6
+ Install them together at [pytorch.org](https://pytorch.org) to make sure of this
7
+ - OpenCV is optional but needed by demo and visualization
8
+
9
+
10
+ ### Build Detectron2 from Source
11
+
12
+ gcc & g++ ≥ 5.4 are required. [ninja](https://ninja-build.org/) is optional but recommended for faster build.
13
+ After having them, run:
14
+ ```
15
+ python -m pip install 'git+https://github.com/facebookresearch/detectron2.git'
16
+ # (add --user if you don't have permission)
17
+
18
+ # Or, to install it from a local clone:
19
+ git clone https://github.com/facebookresearch/detectron2.git
20
+ python -m pip install -e detectron2
21
+
22
+ # On macOS, you may need to prepend the above commands with a few environment variables:
23
+ CC=clang CXX=clang++ ARCHFLAGS="-arch x86_64" python -m pip install ...
24
+ ```
25
+
26
+ To __rebuild__ detectron2 that's built from a local clone, use `rm -rf build/ **/*.so` to clean the
27
+ old build first. You often need to rebuild detectron2 after reinstalling PyTorch.
28
+
29
+ ### Install Pre-Built Detectron2 (Linux only)
30
+
31
+ Choose from this table to install [v0.6 (Oct 2021)](https://github.com/facebookresearch/detectron2/releases):
32
+
33
+ <table class="docutils"><tbody><th width="80"> CUDA </th><th valign="bottom" align="left" width="100">torch 1.10</th><th valign="bottom" align="left" width="100">torch 1.9</th><th valign="bottom" align="left" width="100">torch 1.8</th> <tr><td align="left">11.3</td><td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
34
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html
35
+ </code></pre> </details> </td> <td align="left"> </td> <td align="left"> </td> </tr> <tr><td align="left">11.1</td><td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
36
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.10/index.html
37
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
38
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.9/index.html
39
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
40
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.8/index.html
41
+ </code></pre> </details> </td> </tr> <tr><td align="left">10.2</td><td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
42
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.10/index.html
43
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
44
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.9/index.html
45
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
46
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.8/index.html
47
+ </code></pre> </details> </td> </tr> <tr><td align="left">10.1</td><td align="left"> </td> <td align="left"> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
48
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.8/index.html
49
+ </code></pre> </details> </td> </tr> <tr><td align="left">cpu</td><td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
50
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.10/index.html
51
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
52
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.9/index.html
53
+ </code></pre> </details> </td> <td align="left"><details><summary> install </summary><pre><code>python -m pip install detectron2 -f \
54
+ https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.8/index.html
55
+ </code></pre> </details> </td> </tr></tbody></table>
56
+
57
+ Note that:
58
+ 1. The pre-built packages have to be used with corresponding version of CUDA and the official package of PyTorch.
59
+ Otherwise, please build detectron2 from source.
60
+ 2. New packages are released every few months. Therefore, packages may not contain latest features in the main
61
+ branch and may not be compatible with the main branch of a research project that uses detectron2
62
+ (e.g. those in [projects](projects)).
63
+
64
+ ### Common Installation Issues
65
+
66
+ Click each issue for its solutions:
67
+
68
+ <details>
69
+ <summary>
70
+ Undefined symbols that looks like "TH..","at::Tensor...","torch..."
71
+ </summary>
72
+ <br/>
73
+
74
+ This usually happens when detectron2 or torchvision is not
75
+ compiled with the version of PyTorch you're running.
76
+
77
+ If the error comes from a pre-built torchvision, uninstall torchvision and pytorch and reinstall them
78
+ following [pytorch.org](http://pytorch.org). So the versions will match.
79
+
80
+ If the error comes from a pre-built detectron2, check [release notes](https://github.com/facebookresearch/detectron2/releases),
81
+ uninstall and reinstall the correct pre-built detectron2 that matches pytorch version.
82
+
83
+ If the error comes from detectron2 or torchvision that you built manually from source,
84
+ remove files you built (`build/`, `**/*.so`) and rebuild it so it can pick up the version of pytorch currently in your environment.
85
+
86
+ If the above instructions do not resolve this problem, please provide an environment (e.g. a dockerfile) that can reproduce the issue.
87
+ </details>
88
+
89
+ <details>
90
+ <summary>
91
+ Missing torch dynamic libraries, OR segmentation fault immediately when using detectron2.
92
+ </summary>
93
+ This usually happens when detectron2 or torchvision is not
94
+ compiled with the version of PyTorch you're running. See the previous common issue for the solution.
95
+ </details>
96
+
97
+ <details>
98
+ <summary>
99
+ Undefined C++ symbols (e.g. "GLIBCXX..") or C++ symbols not found.
100
+ </summary>
101
+ <br/>
102
+ Usually it's because the library is compiled with a newer C++ compiler but run with an old C++ runtime.
103
+
104
+ This often happens with old anaconda.
105
+ It may help to run `conda update libgcc` to upgrade its runtime.
106
+
107
+ The fundamental solution is to avoid the mismatch, either by compiling using older version of C++
108
+ compiler, or run the code with proper C++ runtime.
109
+ To run the code with a specific C++ runtime, you can use environment variable `LD_PRELOAD=/path/to/libstdc++.so`.
110
+
111
+ </details>
112
+
113
+ <details>
114
+ <summary>
115
+ "nvcc not found" or "Not compiled with GPU support" or "Detectron2 CUDA Compiler: not available".
116
+ </summary>
117
+ <br/>
118
+ CUDA is not found when building detectron2.
119
+ You should make sure
120
+
121
+ ```
122
+ python -c 'import torch; from torch.utils.cpp_extension import CUDA_HOME; print(torch.cuda.is_available(), CUDA_HOME)'
123
+ ```
124
+
125
+ print `(True, a directory with cuda)` at the time you build detectron2.
126
+
127
+ Most models can run inference (but not training) without GPU support. To use CPUs, set `MODEL.DEVICE='cpu'` in the config.
128
+ </details>
129
+
130
+ <details>
131
+ <summary>
132
+ "invalid device function" or "no kernel image is available for execution".
133
+ </summary>
134
+ <br/>
135
+ Two possibilities:
136
+
137
+ * You build detectron2 with one version of CUDA but run it with a different version.
138
+
139
+ To check whether it is the case,
140
+ use `python -m detectron2.utils.collect_env` to find out inconsistent CUDA versions.
141
+ In the output of this command, you should expect "Detectron2 CUDA Compiler", "CUDA_HOME", "PyTorch built with - CUDA"
142
+ to contain cuda libraries of the same version.
143
+
144
+ When they are inconsistent,
145
+ you need to either install a different build of PyTorch (or build by yourself)
146
+ to match your local CUDA installation, or install a different version of CUDA to match PyTorch.
147
+
148
+ * PyTorch/torchvision/Detectron2 is not built for the correct GPU SM architecture (aka. compute capability).
149
+
150
+ The architecture included by PyTorch/detectron2/torchvision is available in the "architecture flags" in
151
+ `python -m detectron2.utils.collect_env`. It must include
152
+ the architecture of your GPU, which can be found at [developer.nvidia.com/cuda-gpus](https://developer.nvidia.com/cuda-gpus).
153
+
154
+ If you're using pre-built PyTorch/detectron2/torchvision, they have included support for most popular GPUs already.
155
+ If not supported, you need to build them from source.
156
+
157
+ When building detectron2/torchvision from source, they detect the GPU device and build for only the device.
158
+ This means the compiled code may not work on a different GPU device.
159
+ To recompile them for the correct architecture, remove all installed/compiled files,
160
+ and rebuild them with the `TORCH_CUDA_ARCH_LIST` environment variable set properly.
161
+ For example, `export TORCH_CUDA_ARCH_LIST="6.0;7.0"` makes it compile for both P100s and V100s.
162
+ </details>
163
+
164
+ <details>
165
+ <summary>
166
+ Undefined CUDA symbols; Cannot open libcudart.so
167
+ </summary>
168
+ <br/>
169
+ The version of NVCC you use to build detectron2 or torchvision does
170
+ not match the version of CUDA you are running with.
171
+ This often happens when using anaconda's CUDA runtime.
172
+
173
+ Use `python -m detectron2.utils.collect_env` to find out inconsistent CUDA versions.
174
+ In the output of this command, you should expect "Detectron2 CUDA Compiler", "CUDA_HOME", "PyTorch built with - CUDA"
175
+ to contain cuda libraries of the same version.
176
+
177
+ When they are inconsistent,
178
+ you need to either install a different build of PyTorch (or build by yourself)
179
+ to match your local CUDA installation, or install a different version of CUDA to match PyTorch.
180
+ </details>
181
+
182
+
183
+ <details>
184
+ <summary>
185
+ C++ compilation errors from NVCC / NVRTC, or "Unsupported gpu architecture"
186
+ </summary>
187
+ <br/>
188
+ A few possibilities:
189
+
190
+ 1. Local CUDA/NVCC version has to match the CUDA version of your PyTorch. Both can be found in `python collect_env.py`
191
+ (download from [here](./detectron2/utils/collect_env.py)).
192
+ When they are inconsistent, you need to either install a different build of PyTorch (or build by yourself)
193
+ to match your local CUDA installation, or install a different version of CUDA to match PyTorch.
194
+
195
+ 2. Local CUDA/NVCC version shall support the SM architecture (a.k.a. compute capability) of your GPU.
196
+ The capability of your GPU can be found at [developer.nvidia.com/cuda-gpus](https://developer.nvidia.com/cuda-gpus).
197
+ The capability supported by NVCC is listed at [here](https://gist.github.com/ax3l/9489132).
198
+ If your NVCC version is too old, this can be workaround by setting environment variable
199
+ `TORCH_CUDA_ARCH_LIST` to a lower, supported capability.
200
+
201
+ 3. The combination of NVCC and GCC you use is incompatible. You need to change one of their versions.
202
+ See [here](https://gist.github.com/ax3l/9489132) for some valid combinations.
203
+ Notably, CUDA<=10.1.105 doesn't support GCC>7.3.
204
+
205
+ The CUDA/GCC version used by PyTorch can be found by `print(torch.__config__.show())`.
206
+
207
+ </details>
208
+
209
+
210
+ <details>
211
+ <summary>
212
+ "ImportError: cannot import name '_C'".
213
+ </summary>
214
+ <br/>
215
+ Please build and install detectron2 following the instructions above.
216
+
217
+ Or, if you are running code from detectron2's root directory, `cd` to a different one.
218
+ Otherwise you may not import the code that you installed.
219
+ </details>
220
+
221
+
222
+ <details>
223
+ <summary>
224
+ Any issue on windows.
225
+ </summary>
226
+ <br/>
227
+
228
+ Detectron2 is continuously built on windows with [CircleCI](https://app.circleci.com/pipelines/github/facebookresearch/detectron2?branch=main).
229
+ However we do not provide official support for it.
230
+ PRs that improves code compatibility on windows are welcome.
231
+ </details>
232
+
233
+ <details>
234
+ <summary>
235
+ ONNX conversion segfault after some "TraceWarning".
236
+ </summary>
237
+ <br/>
238
+ The ONNX package is compiled with a too old compiler.
239
+
240
+ Please build and install ONNX from its source code using a compiler
241
+ whose version is closer to what's used by PyTorch (available in `torch.__config__.show()`).
242
+ </details>
243
+
244
+
245
+ <details>
246
+ <summary>
247
+ "library not found for -lstdc++" on older version of MacOS
248
+ </summary>
249
+ <br/>
250
+
251
+ See [this stackoverflow answer](https://stackoverflow.com/questions/56083725/macos-build-issues-lstdc-not-found-while-building-python-package).
252
+
253
+ </details>
254
+
255
+
256
+ ### Installation inside specific environments:
257
+
258
+ * __Colab__: see our [Colab Tutorial](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5)
259
+ which has step-by-step instructions.
260
+
261
+ * __Docker__: The official [Dockerfile](docker) installs detectron2 with a few simple commands.
approach/ovod/detectron2/LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
approach/ovod/detectron2/MODEL_ZOO.md ADDED
@@ -0,0 +1,1052 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Detectron2 Model Zoo and Baselines
2
+
3
+ ## Introduction
4
+
5
+ This file documents a large collection of baselines trained
6
+ with detectron2 in Sep-Oct, 2019.
7
+ All numbers were obtained on [Big Basin](https://engineering.fb.com/data-center-engineering/introducing-big-basin-our-next-generation-ai-hardware/)
8
+ servers with 8 NVIDIA V100 GPUs & NVLink. The speed numbers are periodically updated with latest PyTorch/CUDA/cuDNN versions.
9
+ You can access these models from code using [detectron2.model_zoo](https://detectron2.readthedocs.io/modules/model_zoo.html) APIs.
10
+
11
+ In addition to these official baseline models, you can find more models in [projects/](projects/).
12
+
13
+ #### How to Read the Tables
14
+ * The "Name" column contains a link to the config file. Models can be reproduced using `tools/train_net.py` with the corresponding yaml config file,
15
+ or `tools/lazyconfig_train_net.py` for python config files.
16
+ * Training speed is averaged across the entire training.
17
+ We keep updating the speed with latest version of detectron2/pytorch/etc.,
18
+ so they might be different from the `metrics` file.
19
+ Training speed for multi-machine jobs is not provided.
20
+ * Inference speed is measured by `tools/train_net.py --eval-only`, or [inference_on_dataset()](https://detectron2.readthedocs.io/modules/evaluation.html#detectron2.evaluation.inference_on_dataset),
21
+ with batch size 1 in detectron2 directly.
22
+ Measuring it with custom code may introduce other overhead.
23
+ Actual deployment in production should in general be faster than the given inference
24
+ speed due to more optimizations.
25
+ * The *model id* column is provided for ease of reference.
26
+ To check downloaded file integrity, any model on this page contains its md5 prefix in its file name.
27
+ * Training curves and other statistics can be found in `metrics` for each model.
28
+
29
+ #### Common Settings for COCO Models
30
+ * All COCO models were trained on `train2017` and evaluated on `val2017`.
31
+ * The default settings are __not directly comparable__ with Detectron's standard settings.
32
+ For example, our default training data augmentation uses scale jittering in addition to horizontal flipping.
33
+
34
+ To make fair comparisons with Detectron's settings, see
35
+ [Detectron1-Comparisons](configs/Detectron1-Comparisons/) for accuracy comparison,
36
+ and [benchmarks](https://detectron2.readthedocs.io/notes/benchmarks.html)
37
+ for speed comparison.
38
+ * For Faster/Mask R-CNN, we provide baselines based on __3 different backbone combinations__:
39
+ * __FPN__: Use a ResNet+FPN backbone with standard conv and FC heads for mask and box prediction,
40
+ respectively. It obtains the best
41
+ speed/accuracy tradeoff, but the other two are still useful for research.
42
+ * __C4__: Use a ResNet conv4 backbone with conv5 head. The original baseline in the Faster R-CNN paper.
43
+ * __DC5__ (Dilated-C5): Use a ResNet conv5 backbone with dilations in conv5, and standard conv and FC heads
44
+ for mask and box prediction, respectively.
45
+ This is used by the Deformable ConvNet paper.
46
+ * Most models are trained with the 3x schedule (~37 COCO epochs).
47
+ Although 1x models are heavily under-trained, we provide some ResNet-50 models with the 1x (~12 COCO epochs)
48
+ training schedule for comparison when doing quick research iteration.
49
+
50
+ #### ImageNet Pretrained Models
51
+
52
+ It's common to initialize from backbone models pre-trained on ImageNet classification tasks. The following backbone models are available:
53
+
54
+ * [R-50.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/MSRA/R-50.pkl): converted copy of [MSRA's original ResNet-50](https://github.com/KaimingHe/deep-residual-networks) model.
55
+ * [R-101.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/MSRA/R-101.pkl): converted copy of [MSRA's original ResNet-101](https://github.com/KaimingHe/deep-residual-networks) model.
56
+ * [X-101-32x8d.pkl](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/FAIR/X-101-32x8d.pkl): ResNeXt-101-32x8d model trained with Caffe2 at FB.
57
+ * [R-50.pkl (torchvision)](https://dl.fbaipublicfiles.com/detectron2/ImageNetPretrained/torchvision/R-50.pkl): converted copy of [torchvision's ResNet-50](https://pytorch.org/docs/stable/torchvision/models.html#torchvision.models.resnet50) model.
58
+ More details can be found in [the conversion script](tools/convert-torchvision-to-d2.py).
59
+
60
+ Note that the above models have __different__ format from those provided in Detectron: we do not fuse BatchNorm into an affine layer.
61
+ Pretrained models in Detectron's format can still be used. For example:
62
+ * [X-152-32x8d-IN5k.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/25093814/X-152-32x8d-IN5k.pkl):
63
+ ResNeXt-152-32x8d model trained on ImageNet-5k with Caffe2 at FB (see ResNeXt paper for details on ImageNet-5k).
64
+ * [R-50-GN.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/47261647/R-50-GN.pkl):
65
+ ResNet-50 with Group Normalization.
66
+ * [R-101-GN.pkl](https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/47592356/R-101-GN.pkl):
67
+ ResNet-101 with Group Normalization.
68
+
69
+ These models require slightly different settings regarding normalization and architecture. See the model zoo configs for reference.
70
+
71
+ #### License
72
+
73
+ All models available for download through this document are licensed under the
74
+ [Creative Commons Attribution-ShareAlike 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/).
75
+
76
+ ### COCO Object Detection Baselines
77
+
78
+ #### Faster R-CNN:
79
+ <!--
80
+ (fb only) To update the table in vim:
81
+ 1. Remove the old table: d}
82
+ 2. Copy the below command to the place of the table
83
+ 3. :.!bash
84
+
85
+ ./gen_html_table.py --config 'COCO-Detection/faster*50*'{1x,3x}'*' 'COCO-Detection/faster*101*' --name R50-C4 R50-DC5 R50-FPN R50-C4 R50-DC5 R50-FPN R101-C4 R101-DC5 R101-FPN X101-FPN --fields lr_sched train_speed inference_speed mem box_AP
86
+ -->
87
+
88
+
89
+ <table><tbody>
90
+ <!-- START TABLE -->
91
+ <!-- TABLE HEADER -->
92
+ <th valign="bottom">Name</th>
93
+ <th valign="bottom">lr<br/>sched</th>
94
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
95
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
96
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
97
+ <th valign="bottom">box<br/>AP</th>
98
+ <th valign="bottom">model id</th>
99
+ <th valign="bottom">download</th>
100
+ <!-- TABLE BODY -->
101
+ <!-- ROW: faster_rcnn_R_50_C4_1x -->
102
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml">R50-C4</a></td>
103
+ <td align="center">1x</td>
104
+ <td align="center">0.551</td>
105
+ <td align="center">0.102</td>
106
+ <td align="center">4.8</td>
107
+ <td align="center">35.7</td>
108
+ <td align="center">137257644</td>
109
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_C4_1x/137257644/model_final_721ade.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_C4_1x/137257644/metrics.json">metrics</a></td>
110
+ </tr>
111
+ <!-- ROW: faster_rcnn_R_50_DC5_1x -->
112
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_DC5_1x.yaml">R50-DC5</a></td>
113
+ <td align="center">1x</td>
114
+ <td align="center">0.380</td>
115
+ <td align="center">0.068</td>
116
+ <td align="center">5.0</td>
117
+ <td align="center">37.3</td>
118
+ <td align="center">137847829</td>
119
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_DC5_1x/137847829/model_final_51d356.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_DC5_1x/137847829/metrics.json">metrics</a></td>
120
+ </tr>
121
+ <!-- ROW: faster_rcnn_R_50_FPN_1x -->
122
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml">R50-FPN</a></td>
123
+ <td align="center">1x</td>
124
+ <td align="center">0.210</td>
125
+ <td align="center">0.038</td>
126
+ <td align="center">3.0</td>
127
+ <td align="center">37.9</td>
128
+ <td align="center">137257794</td>
129
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_FPN_1x/137257794/model_final_b275ba.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_FPN_1x/137257794/metrics.json">metrics</a></td>
130
+ </tr>
131
+ <!-- ROW: faster_rcnn_R_50_C4_3x -->
132
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_C4_3x.yaml">R50-C4</a></td>
133
+ <td align="center">3x</td>
134
+ <td align="center">0.543</td>
135
+ <td align="center">0.104</td>
136
+ <td align="center">4.8</td>
137
+ <td align="center">38.4</td>
138
+ <td align="center">137849393</td>
139
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_C4_3x/137849393/model_final_f97cb7.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_C4_3x/137849393/metrics.json">metrics</a></td>
140
+ </tr>
141
+ <!-- ROW: faster_rcnn_R_50_DC5_3x -->
142
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_DC5_3x.yaml">R50-DC5</a></td>
143
+ <td align="center">3x</td>
144
+ <td align="center">0.378</td>
145
+ <td align="center">0.070</td>
146
+ <td align="center">5.0</td>
147
+ <td align="center">39.0</td>
148
+ <td align="center">137849425</td>
149
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_DC5_3x/137849425/model_final_68d202.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_DC5_3x/137849425/metrics.json">metrics</a></td>
150
+ </tr>
151
+ <!-- ROW: faster_rcnn_R_50_FPN_3x -->
152
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml">R50-FPN</a></td>
153
+ <td align="center">3x</td>
154
+ <td align="center">0.209</td>
155
+ <td align="center">0.038</td>
156
+ <td align="center">3.0</td>
157
+ <td align="center">40.2</td>
158
+ <td align="center">137849458</td>
159
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_FPN_3x/137849458/model_final_280758.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_50_FPN_3x/137849458/metrics.json">metrics</a></td>
160
+ </tr>
161
+ <!-- ROW: faster_rcnn_R_101_C4_3x -->
162
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_101_C4_3x.yaml">R101-C4</a></td>
163
+ <td align="center">3x</td>
164
+ <td align="center">0.619</td>
165
+ <td align="center">0.139</td>
166
+ <td align="center">5.9</td>
167
+ <td align="center">41.1</td>
168
+ <td align="center">138204752</td>
169
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_C4_3x/138204752/model_final_298dad.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_C4_3x/138204752/metrics.json">metrics</a></td>
170
+ </tr>
171
+ <!-- ROW: faster_rcnn_R_101_DC5_3x -->
172
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_101_DC5_3x.yaml">R101-DC5</a></td>
173
+ <td align="center">3x</td>
174
+ <td align="center">0.452</td>
175
+ <td align="center">0.086</td>
176
+ <td align="center">6.1</td>
177
+ <td align="center">40.6</td>
178
+ <td align="center">138204841</td>
179
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_DC5_3x/138204841/model_final_3e0943.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_DC5_3x/138204841/metrics.json">metrics</a></td>
180
+ </tr>
181
+ <!-- ROW: faster_rcnn_R_101_FPN_3x -->
182
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml">R101-FPN</a></td>
183
+ <td align="center">3x</td>
184
+ <td align="center">0.286</td>
185
+ <td align="center">0.051</td>
186
+ <td align="center">4.1</td>
187
+ <td align="center">42.0</td>
188
+ <td align="center">137851257</td>
189
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_FPN_3x/137851257/model_final_f6e8b1.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_R_101_FPN_3x/137851257/metrics.json">metrics</a></td>
190
+ </tr>
191
+ <!-- ROW: faster_rcnn_X_101_32x8d_FPN_3x -->
192
+ <tr><td align="left"><a href="configs/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml">X101-FPN</a></td>
193
+ <td align="center">3x</td>
194
+ <td align="center">0.638</td>
195
+ <td align="center">0.098</td>
196
+ <td align="center">6.7</td>
197
+ <td align="center">43.0</td>
198
+ <td align="center">139173657</td>
199
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x/139173657/model_final_68b088.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x/139173657/metrics.json">metrics</a></td>
200
+ </tr>
201
+ </tbody></table>
202
+
203
+ #### RetinaNet:
204
+ <!--
205
+ ./gen_html_table.py --config 'COCO-Detection/retina*50*' 'COCO-Detection/retina*101*' --name R50 R50 R101 --fields lr_sched train_speed inference_speed mem box_AP
206
+ -->
207
+
208
+ <table><tbody>
209
+ <!-- START TABLE -->
210
+ <!-- TABLE HEADER -->
211
+ <th valign="bottom">Name</th>
212
+ <th valign="bottom">lr<br/>sched</th>
213
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
214
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
215
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
216
+ <th valign="bottom">box<br/>AP</th>
217
+ <th valign="bottom">model id</th>
218
+ <th valign="bottom">download</th>
219
+ <!-- TABLE BODY -->
220
+ <!-- ROW: retinanet_R_50_FPN_1x -->
221
+ <tr><td align="left"><a href="configs/COCO-Detection/retinanet_R_50_FPN_1x.yaml">R50</a></td>
222
+ <td align="center">1x</td>
223
+ <td align="center">0.205</td>
224
+ <td align="center">0.041</td>
225
+ <td align="center">4.1</td>
226
+ <td align="center">37.4</td>
227
+ <td align="center">190397773</td>
228
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_50_FPN_1x/190397773/model_final_bfca0b.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_50_FPN_1x/190397773/metrics.json">metrics</a></td>
229
+ </tr>
230
+ <!-- ROW: retinanet_R_50_FPN_3x -->
231
+ <tr><td align="left"><a href="configs/COCO-Detection/retinanet_R_50_FPN_3x.yaml">R50</a></td>
232
+ <td align="center">3x</td>
233
+ <td align="center">0.205</td>
234
+ <td align="center">0.041</td>
235
+ <td align="center">4.1</td>
236
+ <td align="center">38.7</td>
237
+ <td align="center">190397829</td>
238
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_50_FPN_3x/190397829/model_final_5bd44e.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_50_FPN_3x/190397829/metrics.json">metrics</a></td>
239
+ </tr>
240
+ <!-- ROW: retinanet_R_101_FPN_3x -->
241
+ <tr><td align="left"><a href="configs/COCO-Detection/retinanet_R_101_FPN_3x.yaml">R101</a></td>
242
+ <td align="center">3x</td>
243
+ <td align="center">0.291</td>
244
+ <td align="center">0.054</td>
245
+ <td align="center">5.2</td>
246
+ <td align="center">40.4</td>
247
+ <td align="center">190397697</td>
248
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_101_FPN_3x/190397697/model_final_971ab9.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/retinanet_R_101_FPN_3x/190397697/metrics.json">metrics</a></td>
249
+ </tr>
250
+ </tbody></table>
251
+
252
+
253
+ #### RPN & Fast R-CNN:
254
+ <!--
255
+ ./gen_html_table.py --config 'COCO-Detection/rpn*' 'COCO-Detection/fast_rcnn*' --name "RPN R50-C4" "RPN R50-FPN" "Fast R-CNN R50-FPN" --fields lr_sched train_speed inference_speed mem box_AP prop_AR
256
+ -->
257
+
258
+ <table><tbody>
259
+ <!-- START TABLE -->
260
+ <!-- TABLE HEADER -->
261
+ <th valign="bottom">Name</th>
262
+ <th valign="bottom">lr<br/>sched</th>
263
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
264
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
265
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
266
+ <th valign="bottom">box<br/>AP</th>
267
+ <th valign="bottom">prop.<br/>AR</th>
268
+ <th valign="bottom">model id</th>
269
+ <th valign="bottom">download</th>
270
+ <!-- TABLE BODY -->
271
+ <!-- ROW: rpn_R_50_C4_1x -->
272
+ <tr><td align="left"><a href="configs/COCO-Detection/rpn_R_50_C4_1x.yaml">RPN R50-C4</a></td>
273
+ <td align="center">1x</td>
274
+ <td align="center">0.130</td>
275
+ <td align="center">0.034</td>
276
+ <td align="center">1.5</td>
277
+ <td align="center"></td>
278
+ <td align="center">51.6</td>
279
+ <td align="center">137258005</td>
280
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/rpn_R_50_C4_1x/137258005/model_final_450694.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/rpn_R_50_C4_1x/137258005/metrics.json">metrics</a></td>
281
+ </tr>
282
+ <!-- ROW: rpn_R_50_FPN_1x -->
283
+ <tr><td align="left"><a href="configs/COCO-Detection/rpn_R_50_FPN_1x.yaml">RPN R50-FPN</a></td>
284
+ <td align="center">1x</td>
285
+ <td align="center">0.186</td>
286
+ <td align="center">0.032</td>
287
+ <td align="center">2.7</td>
288
+ <td align="center"></td>
289
+ <td align="center">58.0</td>
290
+ <td align="center">137258492</td>
291
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/rpn_R_50_FPN_1x/137258492/model_final_02ce48.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/rpn_R_50_FPN_1x/137258492/metrics.json">metrics</a></td>
292
+ </tr>
293
+ <!-- ROW: fast_rcnn_R_50_FPN_1x -->
294
+ <tr><td align="left"><a href="configs/COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml">Fast R-CNN R50-FPN</a></td>
295
+ <td align="center">1x</td>
296
+ <td align="center">0.140</td>
297
+ <td align="center">0.029</td>
298
+ <td align="center">2.6</td>
299
+ <td align="center">37.8</td>
300
+ <td align="center"></td>
301
+ <td align="center">137635226</td>
302
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/fast_rcnn_R_50_FPN_1x/137635226/model_final_e5f7ce.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Detection/fast_rcnn_R_50_FPN_1x/137635226/metrics.json">metrics</a></td>
303
+ </tr>
304
+ </tbody></table>
305
+
306
+ ### COCO Instance Segmentation Baselines with Mask R-CNN
307
+ <!--
308
+ ./gen_html_table.py --config 'COCO-InstanceSegmentation/mask*50*'{1x,3x}'*' 'COCO-InstanceSegmentation/mask*101*' --name R50-C4 R50-DC5 R50-FPN R50-C4 R50-DC5 R50-FPN R101-C4 R101-DC5 R101-FPN X101-FPN --fields lr_sched train_speed inference_speed mem box_AP mask_AP
309
+ -->
310
+
311
+
312
+
313
+ <table><tbody>
314
+ <!-- START TABLE -->
315
+ <!-- TABLE HEADER -->
316
+ <th valign="bottom">Name</th>
317
+ <th valign="bottom">lr<br/>sched</th>
318
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
319
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
320
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
321
+ <th valign="bottom">box<br/>AP</th>
322
+ <th valign="bottom">mask<br/>AP</th>
323
+ <th valign="bottom">model id</th>
324
+ <th valign="bottom">download</th>
325
+ <!-- TABLE BODY -->
326
+ <!-- ROW: mask_rcnn_R_50_C4_1x -->
327
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x.yaml">R50-C4</a></td>
328
+ <td align="center">1x</td>
329
+ <td align="center">0.584</td>
330
+ <td align="center">0.110</td>
331
+ <td align="center">5.2</td>
332
+ <td align="center">36.8</td>
333
+ <td align="center">32.2</td>
334
+ <td align="center">137259246</td>
335
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x/137259246/model_final_9243eb.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_1x/137259246/metrics.json">metrics</a></td>
336
+ </tr>
337
+ <!-- ROW: mask_rcnn_R_50_DC5_1x -->
338
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x.yaml">R50-DC5</a></td>
339
+ <td align="center">1x</td>
340
+ <td align="center">0.471</td>
341
+ <td align="center">0.076</td>
342
+ <td align="center">6.5</td>
343
+ <td align="center">38.3</td>
344
+ <td align="center">34.2</td>
345
+ <td align="center">137260150</td>
346
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x/137260150/model_final_4f86c3.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_1x/137260150/metrics.json">metrics</a></td>
347
+ </tr>
348
+ <!-- ROW: mask_rcnn_R_50_FPN_1x -->
349
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml">R50-FPN</a></td>
350
+ <td align="center">1x</td>
351
+ <td align="center">0.261</td>
352
+ <td align="center">0.043</td>
353
+ <td align="center">3.4</td>
354
+ <td align="center">38.6</td>
355
+ <td align="center">35.2</td>
356
+ <td align="center">137260431</td>
357
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/model_final_a54504.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/metrics.json">metrics</a></td>
358
+ </tr>
359
+ <!-- ROW: mask_rcnn_R_50_C4_3x -->
360
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x.yaml">R50-C4</a></td>
361
+ <td align="center">3x</td>
362
+ <td align="center">0.575</td>
363
+ <td align="center">0.111</td>
364
+ <td align="center">5.2</td>
365
+ <td align="center">39.8</td>
366
+ <td align="center">34.4</td>
367
+ <td align="center">137849525</td>
368
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x/137849525/model_final_4ce675.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_C4_3x/137849525/metrics.json">metrics</a></td>
369
+ </tr>
370
+ <!-- ROW: mask_rcnn_R_50_DC5_3x -->
371
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x.yaml">R50-DC5</a></td>
372
+ <td align="center">3x</td>
373
+ <td align="center">0.470</td>
374
+ <td align="center">0.076</td>
375
+ <td align="center">6.5</td>
376
+ <td align="center">40.0</td>
377
+ <td align="center">35.9</td>
378
+ <td align="center">137849551</td>
379
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x/137849551/model_final_84107b.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_DC5_3x/137849551/metrics.json">metrics</a></td>
380
+ </tr>
381
+ <!-- ROW: mask_rcnn_R_50_FPN_3x -->
382
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml">R50-FPN</a></td>
383
+ <td align="center">3x</td>
384
+ <td align="center">0.261</td>
385
+ <td align="center">0.043</td>
386
+ <td align="center">3.4</td>
387
+ <td align="center">41.0</td>
388
+ <td align="center">37.2</td>
389
+ <td align="center">137849600</td>
390
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/metrics.json">metrics</a></td>
391
+ </tr>
392
+ <!-- ROW: mask_rcnn_R_101_C4_3x -->
393
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x.yaml">R101-C4</a></td>
394
+ <td align="center">3x</td>
395
+ <td align="center">0.652</td>
396
+ <td align="center">0.145</td>
397
+ <td align="center">6.3</td>
398
+ <td align="center">42.6</td>
399
+ <td align="center">36.7</td>
400
+ <td align="center">138363239</td>
401
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x/138363239/model_final_a2914c.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_C4_3x/138363239/metrics.json">metrics</a></td>
402
+ </tr>
403
+ <!-- ROW: mask_rcnn_R_101_DC5_3x -->
404
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x.yaml">R101-DC5</a></td>
405
+ <td align="center">3x</td>
406
+ <td align="center">0.545</td>
407
+ <td align="center">0.092</td>
408
+ <td align="center">7.6</td>
409
+ <td align="center">41.9</td>
410
+ <td align="center">37.3</td>
411
+ <td align="center">138363294</td>
412
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x/138363294/model_final_0464b7.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_DC5_3x/138363294/metrics.json">metrics</a></td>
413
+ </tr>
414
+ <!-- ROW: mask_rcnn_R_101_FPN_3x -->
415
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml">R101-FPN</a></td>
416
+ <td align="center">3x</td>
417
+ <td align="center">0.340</td>
418
+ <td align="center">0.056</td>
419
+ <td align="center">4.6</td>
420
+ <td align="center">42.9</td>
421
+ <td align="center">38.6</td>
422
+ <td align="center">138205316</td>
423
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x/138205316/model_final_a3ec72.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x/138205316/metrics.json">metrics</a></td>
424
+ </tr>
425
+ <!-- ROW: mask_rcnn_X_101_32x8d_FPN_3x -->
426
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml">X101-FPN</a></td>
427
+ <td align="center">3x</td>
428
+ <td align="center">0.690</td>
429
+ <td align="center">0.103</td>
430
+ <td align="center">7.2</td>
431
+ <td align="center">44.3</td>
432
+ <td align="center">39.5</td>
433
+ <td align="center">139653917</td>
434
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x/139653917/model_final_2d9806.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x/139653917/metrics.json">metrics</a></td>
435
+ </tr>
436
+ </tbody></table>
437
+
438
+
439
+
440
+ #### New baselines using Large-Scale Jitter and Longer Training Schedule
441
+
442
+ The following baselines of COCO Instance Segmentation with Mask R-CNN are generated
443
+ using a longer training schedule and large-scale jitter as described in Google's
444
+ [Simple Copy-Paste Data Augmentation](https://arxiv.org/pdf/2012.07177.pdf) paper. These
445
+ models are trained from scratch using random initialization. These baselines exceed the
446
+ previous Mask R-CNN baselines.
447
+
448
+ In the following table, one epoch consists of training on 118000 COCO images.
449
+
450
+ <table><tbody>
451
+ <!-- START TABLE -->
452
+ <!-- TABLE HEADER -->
453
+ <th valign="bottom">Name</th>
454
+ <th valign="bottom">epochs</th>
455
+ <th valign="bottom">train<br/>time<br/>(s/im)</th>
456
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
457
+ <th valign="bottom">box<br/>AP</th>
458
+ <th valign="bottom">mask<br/>AP</th>
459
+ <th valign="bottom">model id</th>
460
+ <th valign="bottom">download</th>
461
+ <!-- TABLE BODY -->
462
+ <!-- ROW: mask_rcnn_R_50_FPN_100ep_LSJ -->
463
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ.py">R50-FPN</a></td>
464
+ <td align="center">100</td>
465
+ <td align="center">0.376</td>
466
+ <td align="center">0.069</td>
467
+ <td align="center">44.6</td>
468
+ <td align="center">40.3</td>
469
+ <td align="center">42047764</td>
470
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ/42047764/model_final_bb69de.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_100ep_LSJ/42047764/metrics.json">metrics</a></td>
471
+ </tr>
472
+ <!-- ROW: mask_rcnn_R_50_FPN_200ep_LSJ -->
473
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ.py">R50-FPN</a></td>
474
+ <td align="center">200</td>
475
+ <td align="center">0.376</td>
476
+ <td align="center">0.069</td>
477
+ <td align="center">46.3</td>
478
+ <td align="center">41.7</td>
479
+ <td align="center">42047638</td>
480
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ/42047638/model_final_89a8d3.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_200ep_LSJ/42047638/metrics.json">metrics</a></td>
481
+ </tr>
482
+ <!-- ROW: mask_rcnn_R_50_FPN_400ep_LSJ -->
483
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ.py">R50-FPN</a></td>
484
+ <td align="center">400</td>
485
+ <td align="center">0.376</td>
486
+ <td align="center">0.069</td>
487
+ <td align="center">47.4</td>
488
+ <td align="center">42.5</td>
489
+ <td align="center">42019571</td>
490
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ/42019571/model_final_14d201.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_50_FPN_400ep_LSJ/42019571/metrics.json">metrics</a></td>
491
+ </tr>
492
+ <!-- ROW: mask_rcnn_R_101_FPN_100ep_LSJ -->
493
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ.py">R101-FPN</a></td>
494
+ <td align="center">100</td>
495
+ <td align="center">0.518</td>
496
+ <td align="center">0.073</td>
497
+ <td align="center">46.4</td>
498
+ <td align="center">41.6</td>
499
+ <td align="center">42025812</td>
500
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ/42025812/model_final_4f7b58.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_100ep_LSJ/42025812/metrics.json">metrics</a></td>
501
+ </tr>
502
+ <!-- ROW: mask_rcnn_R_101_FPN_200ep_LSJ -->
503
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ.py">R101-FPN</a></td>
504
+ <td align="center">200</td>
505
+ <td align="center">0.518</td>
506
+ <td align="center">0.073</td>
507
+ <td align="center">48.0</td>
508
+ <td align="center">43.1</td>
509
+ <td align="center">42131867</td>
510
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ/42131867/model_final_0bb7ae.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_200ep_LSJ/42131867/metrics.json">metrics</a></td>
511
+ </tr>
512
+ <!-- ROW: mask_rcnn_R_101_FPN_400ep_LSJ -->
513
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ.py">R101-FPN</a></td>
514
+ <td align="center">400</td>
515
+ <td align="center">0.518</td>
516
+ <td align="center">0.073</td>
517
+ <td align="center">48.9</td>
518
+ <td align="center">43.7</td>
519
+ <td align="center">42073830</td>
520
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ/42073830/model_final_f96b26.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_R_101_FPN_400ep_LSJ/42073830/metrics.json">metrics</a></td>
521
+ </tr>
522
+ <!-- ROW: mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ -->
523
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ.py">regnetx_4gf_dds_FPN</a></td>
524
+ <td align="center">100</td>
525
+ <td align="center">0.474</td>
526
+ <td align="center">0.071</td>
527
+ <td align="center">46.0</td>
528
+ <td align="center">41.3</td>
529
+ <td align="center">42047771</td>
530
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ/42047771/model_final_b7fbab.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_100ep_LSJ/42047771/metrics.json">metrics</a></td>
531
+ </tr>
532
+ <!-- ROW: mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ -->
533
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ.py">regnetx_4gf_dds_FPN</a></td>
534
+ <td align="center">200</td>
535
+ <td align="center">0.474</td>
536
+ <td align="center">0.071</td>
537
+ <td align="center">48.1</td>
538
+ <td align="center">43.1</td>
539
+ <td align="center">42132721</td>
540
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ/42132721/model_final_5d87c1.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_200ep_LSJ/42132721/metrics.json">metrics</a></td>
541
+ </tr>
542
+ <!-- ROW: mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ -->
543
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ.py">regnetx_4gf_dds_FPN</a></td>
544
+ <td align="center">400</td>
545
+ <td align="center">0.474</td>
546
+ <td align="center">0.071</td>
547
+ <td align="center">48.6</td>
548
+ <td align="center">43.5</td>
549
+ <td align="center">42025447</td>
550
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ/42025447/model_final_f1362d.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnetx_4gf_dds_FPN_400ep_LSJ/42025447/metrics.json">metrics</a></td>
551
+ </tr>
552
+ <!-- ROW: mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ -->
553
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ.py">regnety_4gf_dds_FPN</a></td>
554
+ <td align="center">100</td>
555
+ <td align="center">0.487</td>
556
+ <td align="center">0.073</td>
557
+ <td align="center">46.1</td>
558
+ <td align="center">41.6</td>
559
+ <td align="center">42047784</td>
560
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ/42047784/model_final_6ba57e.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_100ep_LSJ/42047784/metrics.json">metrics</a></td>
561
+ </tr>
562
+ <!-- ROW: mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ -->
563
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ.py">regnety_4gf_dds_FPN</a></td>
564
+ <td align="center">200</td>
565
+ <td align="center">0.487</td>
566
+ <td align="center">0.072</td>
567
+ <td align="center">47.8</td>
568
+ <td align="center">43.0</td>
569
+ <td align="center">42047642</td>
570
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ/42047642/model_final_27b9c1.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_200ep_LSJ/42047642/metrics.json">metrics</a></td>
571
+ </tr>
572
+ <!-- ROW: mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ -->
573
+ <tr><td align="left"><a href="configs/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ.py">regnety_4gf_dds_FPN</a></td>
574
+ <td align="center">400</td>
575
+ <td align="center">0.487</td>
576
+ <td align="center">0.072</td>
577
+ <td align="center">48.2</td>
578
+ <td align="center">43.3</td>
579
+ <td align="center">42045954</td>
580
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ/42045954/model_final_ef3a80.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ/42045954/metrics.json">metrics</a></td>
581
+ </tr>
582
+ </tbody></table>
583
+
584
+ ### COCO Person Keypoint Detection Baselines with Keypoint R-CNN
585
+ <!--
586
+ ./gen_html_table.py --config 'COCO-Keypoints/*50*' 'COCO-Keypoints/*101*' --name R50-FPN R50-FPN R101-FPN X101-FPN --fields lr_sched train_speed inference_speed mem box_AP keypoint_AP
587
+ -->
588
+
589
+
590
+ <table><tbody>
591
+ <!-- START TABLE -->
592
+ <!-- TABLE HEADER -->
593
+ <th valign="bottom">Name</th>
594
+ <th valign="bottom">lr<br/>sched</th>
595
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
596
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
597
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
598
+ <th valign="bottom">box<br/>AP</th>
599
+ <th valign="bottom">kp.<br/>AP</th>
600
+ <th valign="bottom">model id</th>
601
+ <th valign="bottom">download</th>
602
+ <!-- TABLE BODY -->
603
+ <!-- ROW: keypoint_rcnn_R_50_FPN_1x -->
604
+ <tr><td align="left"><a href="configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x.yaml">R50-FPN</a></td>
605
+ <td align="center">1x</td>
606
+ <td align="center">0.315</td>
607
+ <td align="center">0.072</td>
608
+ <td align="center">5.0</td>
609
+ <td align="center">53.6</td>
610
+ <td align="center">64.0</td>
611
+ <td align="center">137261548</td>
612
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x/137261548/model_final_04e291.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_50_FPN_1x/137261548/metrics.json">metrics</a></td>
613
+ </tr>
614
+ <!-- ROW: keypoint_rcnn_R_50_FPN_3x -->
615
+ <tr><td align="left"><a href="configs/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x.yaml">R50-FPN</a></td>
616
+ <td align="center">3x</td>
617
+ <td align="center">0.316</td>
618
+ <td align="center">0.066</td>
619
+ <td align="center">5.0</td>
620
+ <td align="center">55.4</td>
621
+ <td align="center">65.5</td>
622
+ <td align="center">137849621</td>
623
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x/137849621/model_final_a6e10b.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_50_FPN_3x/137849621/metrics.json">metrics</a></td>
624
+ </tr>
625
+ <!-- ROW: keypoint_rcnn_R_101_FPN_3x -->
626
+ <tr><td align="left"><a href="configs/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x.yaml">R101-FPN</a></td>
627
+ <td align="center">3x</td>
628
+ <td align="center">0.390</td>
629
+ <td align="center">0.076</td>
630
+ <td align="center">6.1</td>
631
+ <td align="center">56.4</td>
632
+ <td align="center">66.1</td>
633
+ <td align="center">138363331</td>
634
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x/138363331/model_final_997cc7.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_R_101_FPN_3x/138363331/metrics.json">metrics</a></td>
635
+ </tr>
636
+ <!-- ROW: keypoint_rcnn_X_101_32x8d_FPN_3x -->
637
+ <tr><td align="left"><a href="configs/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x.yaml">X101-FPN</a></td>
638
+ <td align="center">3x</td>
639
+ <td align="center">0.738</td>
640
+ <td align="center">0.121</td>
641
+ <td align="center">8.7</td>
642
+ <td align="center">57.3</td>
643
+ <td align="center">66.0</td>
644
+ <td align="center">139686956</td>
645
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x/139686956/model_final_5ad38f.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-Keypoints/keypoint_rcnn_X_101_32x8d_FPN_3x/139686956/metrics.json">metrics</a></td>
646
+ </tr>
647
+ </tbody></table>
648
+
649
+ ### COCO Panoptic Segmentation Baselines with Panoptic FPN
650
+ <!--
651
+ ./gen_html_table.py --config 'COCO-PanopticSegmentation/*50*' 'COCO-PanopticSegmentation/*101*' --name R50-FPN R50-FPN R101-FPN --fields lr_sched train_speed inference_speed mem box_AP mask_AP PQ
652
+ -->
653
+
654
+
655
+ <table><tbody>
656
+ <!-- START TABLE -->
657
+ <!-- TABLE HEADER -->
658
+ <th valign="bottom">Name</th>
659
+ <th valign="bottom">lr<br/>sched</th>
660
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
661
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
662
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
663
+ <th valign="bottom">box<br/>AP</th>
664
+ <th valign="bottom">mask<br/>AP</th>
665
+ <th valign="bottom">PQ</th>
666
+ <th valign="bottom">model id</th>
667
+ <th valign="bottom">download</th>
668
+ <!-- TABLE BODY -->
669
+ <!-- ROW: panoptic_fpn_R_50_1x -->
670
+ <tr><td align="left"><a href="configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x.yaml">R50-FPN</a></td>
671
+ <td align="center">1x</td>
672
+ <td align="center">0.304</td>
673
+ <td align="center">0.053</td>
674
+ <td align="center">4.8</td>
675
+ <td align="center">37.6</td>
676
+ <td align="center">34.7</td>
677
+ <td align="center">39.4</td>
678
+ <td align="center">139514544</td>
679
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x/139514544/model_final_dbfeb4.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_50_1x/139514544/metrics.json">metrics</a></td>
680
+ </tr>
681
+ <!-- ROW: panoptic_fpn_R_50_3x -->
682
+ <tr><td align="left"><a href="configs/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x.yaml">R50-FPN</a></td>
683
+ <td align="center">3x</td>
684
+ <td align="center">0.302</td>
685
+ <td align="center">0.053</td>
686
+ <td align="center">4.8</td>
687
+ <td align="center">40.0</td>
688
+ <td align="center">36.5</td>
689
+ <td align="center">41.5</td>
690
+ <td align="center">139514569</td>
691
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x/139514569/model_final_c10459.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_50_3x/139514569/metrics.json">metrics</a></td>
692
+ </tr>
693
+ <!-- ROW: panoptic_fpn_R_101_3x -->
694
+ <tr><td align="left"><a href="configs/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x.yaml">R101-FPN</a></td>
695
+ <td align="center">3x</td>
696
+ <td align="center">0.392</td>
697
+ <td align="center">0.066</td>
698
+ <td align="center">6.0</td>
699
+ <td align="center">42.4</td>
700
+ <td align="center">38.5</td>
701
+ <td align="center">43.0</td>
702
+ <td align="center">139514519</td>
703
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x/139514519/model_final_cafdb1.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-PanopticSegmentation/panoptic_fpn_R_101_3x/139514519/metrics.json">metrics</a></td>
704
+ </tr>
705
+ </tbody></table>
706
+
707
+
708
+ ### LVIS Instance Segmentation Baselines with Mask R-CNN
709
+
710
+ Mask R-CNN baselines on the [LVIS dataset](https://lvisdataset.org), v0.5.
711
+ These baselines are described in Table 3(c) of the [LVIS paper](https://arxiv.org/abs/1908.03195).
712
+
713
+ NOTE: the 1x schedule here has the same amount of __iterations__ as the COCO 1x baselines.
714
+ They are roughly 24 epochs of LVISv0.5 data.
715
+ The final results of these configs have large variance across different runs.
716
+
717
+ <!--
718
+ ./gen_html_table.py --config 'LVISv0.5-InstanceSegmentation/mask*50*' 'LVISv0.5-InstanceSegmentation/mask*101*' --name R50-FPN R101-FPN X101-FPN --fields lr_sched train_speed inference_speed mem box_AP mask_AP
719
+ -->
720
+
721
+
722
+ <table><tbody>
723
+ <!-- START TABLE -->
724
+ <!-- TABLE HEADER -->
725
+ <th valign="bottom">Name</th>
726
+ <th valign="bottom">lr<br/>sched</th>
727
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
728
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
729
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
730
+ <th valign="bottom">box<br/>AP</th>
731
+ <th valign="bottom">mask<br/>AP</th>
732
+ <th valign="bottom">model id</th>
733
+ <th valign="bottom">download</th>
734
+ <!-- TABLE BODY -->
735
+ <!-- ROW: mask_rcnn_R_50_FPN_1x -->
736
+ <tr><td align="left"><a href="configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml">R50-FPN</a></td>
737
+ <td align="center">1x</td>
738
+ <td align="center">0.292</td>
739
+ <td align="center">0.107</td>
740
+ <td align="center">7.1</td>
741
+ <td align="center">23.6</td>
742
+ <td align="center">24.4</td>
743
+ <td align="center">144219072</td>
744
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/144219072/model_final_571f7c.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/144219072/metrics.json">metrics</a></td>
745
+ </tr>
746
+ <!-- ROW: mask_rcnn_R_101_FPN_1x -->
747
+ <tr><td align="left"><a href="configs/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x.yaml">R101-FPN</a></td>
748
+ <td align="center">1x</td>
749
+ <td align="center">0.371</td>
750
+ <td align="center">0.114</td>
751
+ <td align="center">7.8</td>
752
+ <td align="center">25.6</td>
753
+ <td align="center">25.9</td>
754
+ <td align="center">144219035</td>
755
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x/144219035/model_final_824ab5.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_R_101_FPN_1x/144219035/metrics.json">metrics</a></td>
756
+ </tr>
757
+ <!-- ROW: mask_rcnn_X_101_32x8d_FPN_1x -->
758
+ <tr><td align="left"><a href="configs/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x.yaml">X101-FPN</a></td>
759
+ <td align="center">1x</td>
760
+ <td align="center">0.712</td>
761
+ <td align="center">0.151</td>
762
+ <td align="center">10.2</td>
763
+ <td align="center">26.7</td>
764
+ <td align="center">27.1</td>
765
+ <td align="center">144219108</td>
766
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x/144219108/model_final_5e3439.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/LVISv0.5-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_1x/144219108/metrics.json">metrics</a></td>
767
+ </tr>
768
+ </tbody></table>
769
+
770
+
771
+
772
+ ### Cityscapes & Pascal VOC Baselines
773
+
774
+ Simple baselines for
775
+ * Mask R-CNN on Cityscapes instance segmentation (initialized from COCO pre-training, then trained on Cityscapes fine annotations only)
776
+ * Faster R-CNN on PASCAL VOC object detection (trained on VOC 2007 train+val + VOC 2012 train+val, tested on VOC 2007 using 11-point interpolated AP)
777
+
778
+ <!--
779
+ ./gen_html_table.py --config 'Cityscapes/*' 'PascalVOC-Detection/*' --name "R50-FPN, Cityscapes" "R50-C4, VOC" --fields train_speed inference_speed mem box_AP box_AP50 mask_AP
780
+ -->
781
+
782
+
783
+ <table><tbody>
784
+ <!-- START TABLE -->
785
+ <!-- TABLE HEADER -->
786
+ <th valign="bottom">Name</th>
787
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
788
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
789
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
790
+ <th valign="bottom">box<br/>AP</th>
791
+ <th valign="bottom">box<br/>AP50</th>
792
+ <th valign="bottom">mask<br/>AP</th>
793
+ <th valign="bottom">model id</th>
794
+ <th valign="bottom">download</th>
795
+ <!-- TABLE BODY -->
796
+ <!-- ROW: mask_rcnn_R_50_FPN -->
797
+ <tr><td align="left"><a href="configs/Cityscapes/mask_rcnn_R_50_FPN.yaml">R50-FPN, Cityscapes</a></td>
798
+ <td align="center">0.240</td>
799
+ <td align="center">0.078</td>
800
+ <td align="center">4.4</td>
801
+ <td align="center"></td>
802
+ <td align="center"></td>
803
+ <td align="center">36.5</td>
804
+ <td align="center">142423278</td>
805
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Cityscapes/mask_rcnn_R_50_FPN/142423278/model_final_af9cf5.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Cityscapes/mask_rcnn_R_50_FPN/142423278/metrics.json">metrics</a></td>
806
+ </tr>
807
+ <!-- ROW: faster_rcnn_R_50_C4 -->
808
+ <tr><td align="left"><a href="configs/PascalVOC-Detection/faster_rcnn_R_50_C4.yaml">R50-C4, VOC</a></td>
809
+ <td align="center">0.537</td>
810
+ <td align="center">0.081</td>
811
+ <td align="center">4.8</td>
812
+ <td align="center">51.9</td>
813
+ <td align="center">80.3</td>
814
+ <td align="center"></td>
815
+ <td align="center">142202221</td>
816
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/PascalVOC-Detection/faster_rcnn_R_50_C4/142202221/model_final_b1acc2.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/PascalVOC-Detection/faster_rcnn_R_50_C4/142202221/metrics.json">metrics</a></td>
817
+ </tr>
818
+ </tbody></table>
819
+
820
+
821
+
822
+ ### Other Settings
823
+
824
+ Ablations for Deformable Conv and Cascade R-CNN:
825
+
826
+ <!--
827
+ ./gen_html_table.py --config 'COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml' 'Misc/*R_50_FPN_1x_dconv*' 'Misc/cascade*1x.yaml' 'COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml' 'Misc/*R_50_FPN_3x_dconv*' 'Misc/cascade*3x.yaml' --name "Baseline R50-FPN" "Deformable Conv" "Cascade R-CNN" "Baseline R50-FPN" "Deformable Conv" "Cascade R-CNN" --fields lr_sched train_speed inference_speed mem box_AP mask_AP
828
+ -->
829
+
830
+
831
+ <table><tbody>
832
+ <!-- START TABLE -->
833
+ <!-- TABLE HEADER -->
834
+ <th valign="bottom">Name</th>
835
+ <th valign="bottom">lr<br/>sched</th>
836
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
837
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
838
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
839
+ <th valign="bottom">box<br/>AP</th>
840
+ <th valign="bottom">mask<br/>AP</th>
841
+ <th valign="bottom">model id</th>
842
+ <th valign="bottom">download</th>
843
+ <!-- TABLE BODY -->
844
+ <!-- ROW: mask_rcnn_R_50_FPN_1x -->
845
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml">Baseline R50-FPN</a></td>
846
+ <td align="center">1x</td>
847
+ <td align="center">0.261</td>
848
+ <td align="center">0.043</td>
849
+ <td align="center">3.4</td>
850
+ <td align="center">38.6</td>
851
+ <td align="center">35.2</td>
852
+ <td align="center">137260431</td>
853
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/model_final_a54504.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/metrics.json">metrics</a></td>
854
+ </tr>
855
+ <!-- ROW: mask_rcnn_R_50_FPN_1x_dconv_c3-c5 -->
856
+ <tr><td align="left"><a href="configs/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5.yaml">Deformable Conv</a></td>
857
+ <td align="center">1x</td>
858
+ <td align="center">0.342</td>
859
+ <td align="center">0.048</td>
860
+ <td align="center">3.5</td>
861
+ <td align="center">41.5</td>
862
+ <td align="center">37.5</td>
863
+ <td align="center">138602867</td>
864
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5/138602867/model_final_65c703.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_1x_dconv_c3-c5/138602867/metrics.json">metrics</a></td>
865
+ </tr>
866
+ <!-- ROW: cascade_mask_rcnn_R_50_FPN_1x -->
867
+ <tr><td align="left"><a href="configs/Misc/cascade_mask_rcnn_R_50_FPN_1x.yaml">Cascade R-CNN</a></td>
868
+ <td align="center">1x</td>
869
+ <td align="center">0.317</td>
870
+ <td align="center">0.052</td>
871
+ <td align="center">4.0</td>
872
+ <td align="center">42.1</td>
873
+ <td align="center">36.4</td>
874
+ <td align="center">138602847</td>
875
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_R_50_FPN_1x/138602847/model_final_e9d89b.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_R_50_FPN_1x/138602847/metrics.json">metrics</a></td>
876
+ </tr>
877
+ <!-- ROW: mask_rcnn_R_50_FPN_3x -->
878
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml">Baseline R50-FPN</a></td>
879
+ <td align="center">3x</td>
880
+ <td align="center">0.261</td>
881
+ <td align="center">0.043</td>
882
+ <td align="center">3.4</td>
883
+ <td align="center">41.0</td>
884
+ <td align="center">37.2</td>
885
+ <td align="center">137849600</td>
886
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/metrics.json">metrics</a></td>
887
+ </tr>
888
+ <!-- ROW: mask_rcnn_R_50_FPN_3x_dconv_c3-c5 -->
889
+ <tr><td align="left"><a href="configs/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5.yaml">Deformable Conv</a></td>
890
+ <td align="center">3x</td>
891
+ <td align="center">0.349</td>
892
+ <td align="center">0.047</td>
893
+ <td align="center">3.5</td>
894
+ <td align="center">42.7</td>
895
+ <td align="center">38.5</td>
896
+ <td align="center">144998336</td>
897
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5/144998336/model_final_821d0b.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_dconv_c3-c5/144998336/metrics.json">metrics</a></td>
898
+ </tr>
899
+ <!-- ROW: cascade_mask_rcnn_R_50_FPN_3x -->
900
+ <tr><td align="left"><a href="configs/Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml">Cascade R-CNN</a></td>
901
+ <td align="center">3x</td>
902
+ <td align="center">0.328</td>
903
+ <td align="center">0.053</td>
904
+ <td align="center">4.0</td>
905
+ <td align="center">44.3</td>
906
+ <td align="center">38.5</td>
907
+ <td align="center">144998488</td>
908
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_R_50_FPN_3x/144998488/model_final_480dd8.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_R_50_FPN_3x/144998488/metrics.json">metrics</a></td>
909
+ </tr>
910
+ </tbody></table>
911
+
912
+
913
+ Ablations for normalization methods, and a few models trained from scratch following [Rethinking ImageNet Pre-training](https://arxiv.org/abs/1811.08883).
914
+ (Note: The baseline uses `2fc` head while the others use [`4conv1fc` head](https://arxiv.org/abs/1803.08494))
915
+ <!--
916
+ ./gen_html_table.py --config 'COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml' 'Misc/mask*50_FPN_3x_gn.yaml' 'Misc/mask*50_FPN_3x_syncbn.yaml' 'Misc/scratch*' --name "Baseline R50-FPN" "GN" "SyncBN" "GN (from scratch)" "GN (from scratch)" "SyncBN (from scratch)" --fields lr_sched train_speed inference_speed mem box_AP mask_AP
917
+ -->
918
+
919
+
920
+ <table><tbody>
921
+ <!-- START TABLE -->
922
+ <!-- TABLE HEADER -->
923
+ <th valign="bottom">Name</th>
924
+ <th valign="bottom">lr<br/>sched</th>
925
+ <th valign="bottom">train<br/>time<br/>(s/iter)</th>
926
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
927
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
928
+ <th valign="bottom">box<br/>AP</th>
929
+ <th valign="bottom">mask<br/>AP</th>
930
+ <th valign="bottom">model id</th>
931
+ <th valign="bottom">download</th>
932
+ <!-- TABLE BODY -->
933
+ <!-- ROW: mask_rcnn_R_50_FPN_3x -->
934
+ <tr><td align="left"><a href="configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml">Baseline R50-FPN</a></td>
935
+ <td align="center">3x</td>
936
+ <td align="center">0.261</td>
937
+ <td align="center">0.043</td>
938
+ <td align="center">3.4</td>
939
+ <td align="center">41.0</td>
940
+ <td align="center">37.2</td>
941
+ <td align="center">137849600</td>
942
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/metrics.json">metrics</a></td>
943
+ </tr>
944
+ <!-- ROW: mask_rcnn_R_50_FPN_3x_gn -->
945
+ <tr><td align="left"><a href="configs/Misc/mask_rcnn_R_50_FPN_3x_gn.yaml">GN</a></td>
946
+ <td align="center">3x</td>
947
+ <td align="center">0.309</td>
948
+ <td align="center">0.060</td>
949
+ <td align="center">5.6</td>
950
+ <td align="center">42.6</td>
951
+ <td align="center">38.6</td>
952
+ <td align="center">138602888</td>
953
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_gn/138602888/model_final_dc5d9e.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_gn/138602888/metrics.json">metrics</a></td>
954
+ </tr>
955
+ <!-- ROW: mask_rcnn_R_50_FPN_3x_syncbn -->
956
+ <tr><td align="left"><a href="configs/Misc/mask_rcnn_R_50_FPN_3x_syncbn.yaml">SyncBN</a></td>
957
+ <td align="center">3x</td>
958
+ <td align="center">0.345</td>
959
+ <td align="center">0.053</td>
960
+ <td align="center">5.5</td>
961
+ <td align="center">41.9</td>
962
+ <td align="center">37.8</td>
963
+ <td align="center">169527823</td>
964
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_syncbn/169527823/model_final_3b3c51.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/mask_rcnn_R_50_FPN_3x_syncbn/169527823/metrics.json">metrics</a></td>
965
+ </tr>
966
+ <!-- ROW: scratch_mask_rcnn_R_50_FPN_3x_gn -->
967
+ <tr><td align="left"><a href="configs/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn.yaml">GN (from scratch)</a></td>
968
+ <td align="center">3x</td>
969
+ <td align="center">0.338</td>
970
+ <td align="center">0.061</td>
971
+ <td align="center">7.2</td>
972
+ <td align="center">39.9</td>
973
+ <td align="center">36.6</td>
974
+ <td align="center">138602908</td>
975
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn/138602908/model_final_01ca85.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_3x_gn/138602908/metrics.json">metrics</a></td>
976
+ </tr>
977
+ <!-- ROW: scratch_mask_rcnn_R_50_FPN_9x_gn -->
978
+ <tr><td align="left"><a href="configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn.yaml">GN (from scratch)</a></td>
979
+ <td align="center">9x</td>
980
+ <td align="center">N/A</td>
981
+ <td align="center">0.061</td>
982
+ <td align="center">7.2</td>
983
+ <td align="center">43.7</td>
984
+ <td align="center">39.6</td>
985
+ <td align="center">183808979</td>
986
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn/183808979/model_final_da7b4c.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_9x_gn/183808979/metrics.json">metrics</a></td>
987
+ </tr>
988
+ <!-- ROW: scratch_mask_rcnn_R_50_FPN_9x_syncbn -->
989
+ <tr><td align="left"><a href="configs/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn.yaml">SyncBN (from scratch)</a></td>
990
+ <td align="center">9x</td>
991
+ <td align="center">N/A</td>
992
+ <td align="center">0.055</td>
993
+ <td align="center">7.2</td>
994
+ <td align="center">43.6</td>
995
+ <td align="center">39.3</td>
996
+ <td align="center">184226666</td>
997
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn/184226666/model_final_5ce33e.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/scratch_mask_rcnn_R_50_FPN_9x_syncbn/184226666/metrics.json">metrics</a></td>
998
+ </tr>
999
+ </tbody></table>
1000
+
1001
+
1002
+ A few very large models trained for a long time, for demo purposes. They are trained using multiple machines:
1003
+
1004
+ <!--
1005
+ ./gen_html_table.py --config 'Misc/panoptic_*dconv*' 'Misc/cascade_*152*' --name "Panoptic FPN R101" "Mask R-CNN X152" --fields inference_speed mem box_AP mask_AP PQ
1006
+ # manually add TTA results
1007
+ -->
1008
+
1009
+
1010
+ <table><tbody>
1011
+ <!-- START TABLE -->
1012
+ <!-- TABLE HEADER -->
1013
+ <th valign="bottom">Name</th>
1014
+ <th valign="bottom">inference<br/>time<br/>(s/im)</th>
1015
+ <th valign="bottom">train<br/>mem<br/>(GB)</th>
1016
+ <th valign="bottom">box<br/>AP</th>
1017
+ <th valign="bottom">mask<br/>AP</th>
1018
+ <th valign="bottom">PQ</th>
1019
+ <th valign="bottom">model id</th>
1020
+ <th valign="bottom">download</th>
1021
+ <!-- TABLE BODY -->
1022
+ <!-- ROW: panoptic_fpn_R_101_dconv_cascade_gn_3x -->
1023
+ <tr><td align="left"><a href="configs/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x.yaml">Panoptic FPN R101</a></td>
1024
+ <td align="center">0.098</td>
1025
+ <td align="center">11.4</td>
1026
+ <td align="center">47.4</td>
1027
+ <td align="center">41.3</td>
1028
+ <td align="center">46.1</td>
1029
+ <td align="center">139797668</td>
1030
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x/139797668/model_final_be35db.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/panoptic_fpn_R_101_dconv_cascade_gn_3x/139797668/metrics.json">metrics</a></td>
1031
+ </tr>
1032
+ <!-- ROW: cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv -->
1033
+ <tr><td align="left"><a href="configs/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv.yaml">Mask R-CNN X152</a></td>
1034
+ <td align="center">0.234</td>
1035
+ <td align="center">15.1</td>
1036
+ <td align="center">50.2</td>
1037
+ <td align="center">44.0</td>
1038
+ <td align="center"></td>
1039
+ <td align="center">18131413</td>
1040
+ <td align="center"><a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv/18131413/model_0039999_e76410.pkl">model</a>&nbsp;|&nbsp;<a href="https://dl.fbaipublicfiles.com/detectron2/Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv/18131413/metrics.json">metrics</a></td>
1041
+ </tr>
1042
+ <!-- ROW: TTA cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv -->
1043
+ <tr><td align="left">above + test-time aug.</td>
1044
+ <td align="center"></td>
1045
+ <td align="center"></td>
1046
+ <td align="center">51.9</td>
1047
+ <td align="center">45.9</td>
1048
+ <td align="center"></td>
1049
+ <td align="center"></td>
1050
+ <td align="center"></td>
1051
+ </tr>
1052
+ </tbody></table>
approach/ovod/detectron2/README.md ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <img src=".github/Detectron2-Logo-Horz.svg" width="300" >
2
+
3
+ <a href="https://opensource.facebook.com/support-ukraine">
4
+ <img src="https://img.shields.io/badge/Support-Ukraine-FFD500?style=flat&labelColor=005BBB" alt="Support Ukraine - Help Provide Humanitarian Aid to Ukraine." />
5
+ </a>
6
+
7
+ Detectron2 is Facebook AI Research's next generation library
8
+ that provides state-of-the-art detection and segmentation algorithms.
9
+ It is the successor of
10
+ [Detectron](https://github.com/facebookresearch/Detectron/)
11
+ and [maskrcnn-benchmark](https://github.com/facebookresearch/maskrcnn-benchmark/).
12
+ It supports a number of computer vision research projects and production applications in Facebook.
13
+
14
+ <div align="center">
15
+ <img src="https://user-images.githubusercontent.com/1381301/66535560-d3422200-eace-11e9-9123-5535d469db19.png"/>
16
+ </div>
17
+ <br>
18
+
19
+ ## Learn More about Detectron2
20
+
21
+ Explain Like I’m 5: Detectron2 | Using Machine Learning with Detectron2
22
+ :-------------------------:|:-------------------------:
23
+ [![Explain Like I’m 5: Detectron2](https://img.youtube.com/vi/1oq1Ye7dFqc/0.jpg)](https://www.youtube.com/watch?v=1oq1Ye7dFqc) | [![Using Machine Learning with Detectron2](https://img.youtube.com/vi/eUSgtfK4ivk/0.jpg)](https://www.youtube.com/watch?v=eUSgtfK4ivk)
24
+
25
+ ## What's New
26
+ * Includes new capabilities such as panoptic segmentation, Densepose, Cascade R-CNN, rotated bounding boxes, PointRend,
27
+ DeepLab, ViTDet, MViTv2 etc.
28
+ * Used as a library to support building [research projects](projects/) on top of it.
29
+ * Models can be exported to TorchScript format or Caffe2 format for deployment.
30
+ * It [trains much faster](https://detectron2.readthedocs.io/notes/benchmarks.html).
31
+
32
+ See our [blog post](https://ai.facebook.com/blog/-detectron2-a-pytorch-based-modular-object-detection-library-/)
33
+ to see more demos and learn about detectron2.
34
+
35
+ ## Installation
36
+
37
+ See [installation instructions](https://detectron2.readthedocs.io/tutorials/install.html).
38
+
39
+ ## Getting Started
40
+
41
+ See [Getting Started with Detectron2](https://detectron2.readthedocs.io/tutorials/getting_started.html),
42
+ and the [Colab Notebook](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5)
43
+ to learn about basic usage.
44
+
45
+ Learn more at our [documentation](https://detectron2.readthedocs.org).
46
+ And see [projects/](projects/) for some projects that are built on top of detectron2.
47
+
48
+ ## Model Zoo and Baselines
49
+
50
+ We provide a large set of baseline results and trained models available for download in the [Detectron2 Model Zoo](MODEL_ZOO.md).
51
+
52
+ ## License
53
+
54
+ Detectron2 is released under the [Apache 2.0 license](LICENSE).
55
+
56
+ ## Citing Detectron2
57
+
58
+ If you use Detectron2 in your research or wish to refer to the baseline results published in the [Model Zoo](MODEL_ZOO.md), please use the following BibTeX entry.
59
+
60
+ ```BibTeX
61
+ @misc{wu2019detectron2,
62
+ author = {Yuxin Wu and Alexander Kirillov and Francisco Massa and
63
+ Wan-Yen Lo and Ross Girshick},
64
+ title = {Detectron2},
65
+ howpublished = {\url{https://github.com/facebookresearch/detectron2}},
66
+ year = {2019}
67
+ }
68
+ ```
approach/ovod/detectron2/setup.cfg ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [isort]
2
+ line_length=100
3
+ multi_line_output=3
4
+ include_trailing_comma=True
5
+ known_standard_library=numpy,setuptools,mock
6
+ skip=./datasets,docs
7
+ skip_glob=*/__init__.py,**/configs/**,**/tests/config/**
8
+ known_myself=detectron2
9
+ known_third_party=fvcore,matplotlib,cv2,torch,torchvision,PIL,pycocotools,yacs,termcolor,cityscapesscripts,tabulate,tqdm,scipy,lvis,psutil,pkg_resources,caffe2,onnx,panopticapi,black,isort,av,iopath,omegaconf,hydra,yaml,pydoc,submitit,cloudpickle,packaging
10
+ no_lines_before=STDLIB,THIRDPARTY
11
+ sections=FUTURE,STDLIB,THIRDPARTY,myself,FIRSTPARTY,LOCALFOLDER
12
+ default_section=FIRSTPARTY
13
+
14
+ [mypy]
15
+ python_version=3.7
16
+ ignore_missing_imports = True
17
+ warn_unused_configs = True
18
+ disallow_untyped_defs = True
19
+ check_untyped_defs = True
20
+ warn_unused_ignores = True
21
+ warn_redundant_casts = True
22
+ show_column_numbers = True
23
+ follow_imports = silent
24
+ allow_redefinition = True
25
+ ; Require all functions to be annotated
26
+ disallow_incomplete_defs = True
approach/ovod/detectron2/setup.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+
4
+ import glob
5
+ import os
6
+ import shutil
7
+ from os import path
8
+ from setuptools import find_packages, setup
9
+ from typing import List
10
+ import torch
11
+ from torch.utils.cpp_extension import CUDA_HOME, CppExtension, CUDAExtension
12
+
13
+ torch_ver = [int(x) for x in torch.__version__.split(".")[:2]]
14
+ assert torch_ver >= [1, 8], "Requires PyTorch >= 1.8"
15
+
16
+
17
+ def get_version():
18
+ init_py_path = path.join(path.abspath(path.dirname(__file__)), "detectron2", "__init__.py")
19
+ init_py = open(init_py_path, "r").readlines()
20
+ version_line = [l.strip() for l in init_py if l.startswith("__version__")][0]
21
+ version = version_line.split("=")[-1].strip().strip("'\"")
22
+
23
+ # The following is used to build release packages.
24
+ # Users should never use it.
25
+ suffix = os.getenv("D2_VERSION_SUFFIX", "")
26
+ version = version + suffix
27
+ if os.getenv("BUILD_NIGHTLY", "0") == "1":
28
+ from datetime import datetime
29
+
30
+ date_str = datetime.today().strftime("%y%m%d")
31
+ version = version + ".dev" + date_str
32
+
33
+ new_init_py = [l for l in init_py if not l.startswith("__version__")]
34
+ new_init_py.append('__version__ = "{}"\n'.format(version))
35
+ with open(init_py_path, "w") as f:
36
+ f.write("".join(new_init_py))
37
+ return version
38
+
39
+
40
+ def get_extensions():
41
+ this_dir = path.dirname(path.abspath(__file__))
42
+ extensions_dir = path.join(this_dir, "detectron2", "layers", "csrc")
43
+
44
+ main_source = path.join(extensions_dir, "vision.cpp")
45
+ sources = glob.glob(path.join(extensions_dir, "**", "*.cpp"))
46
+
47
+ from torch.utils.cpp_extension import ROCM_HOME
48
+
49
+ is_rocm_pytorch = (
50
+ True if ((torch.version.hip is not None) and (ROCM_HOME is not None)) else False
51
+ )
52
+ if is_rocm_pytorch:
53
+ assert torch_ver >= [1, 8], "ROCM support requires PyTorch >= 1.8!"
54
+
55
+ # common code between cuda and rocm platforms, for hipify version [1,0,0] and later.
56
+ source_cuda = glob.glob(path.join(extensions_dir, "**", "*.cu")) + glob.glob(
57
+ path.join(extensions_dir, "*.cu")
58
+ )
59
+ sources = [main_source] + sources
60
+
61
+ extension = CppExtension
62
+
63
+ extra_compile_args = {"cxx": []}
64
+ define_macros = []
65
+
66
+ if (torch.cuda.is_available() and ((CUDA_HOME is not None) or is_rocm_pytorch)) or os.getenv(
67
+ "FORCE_CUDA", "0"
68
+ ) == "1":
69
+ extension = CUDAExtension
70
+ sources += source_cuda
71
+
72
+ if not is_rocm_pytorch:
73
+ define_macros += [("WITH_CUDA", None)]
74
+ extra_compile_args["nvcc"] = [
75
+ "-O3",
76
+ "-DCUDA_HAS_FP16=1",
77
+ "-D__CUDA_NO_HALF_OPERATORS__",
78
+ "-D__CUDA_NO_HALF_CONVERSIONS__",
79
+ "-D__CUDA_NO_HALF2_OPERATORS__",
80
+ ]
81
+ else:
82
+ define_macros += [("WITH_HIP", None)]
83
+ extra_compile_args["nvcc"] = []
84
+
85
+ if torch_ver < [1, 7]:
86
+ # supported by https://github.com/pytorch/pytorch/pull/43931
87
+ CC = os.environ.get("CC", None)
88
+ if CC is not None:
89
+ extra_compile_args["nvcc"].append("-ccbin={}".format(CC))
90
+
91
+ include_dirs = [extensions_dir]
92
+
93
+ ext_modules = [
94
+ extension(
95
+ "detectron2._C",
96
+ sources,
97
+ include_dirs=include_dirs,
98
+ define_macros=define_macros,
99
+ extra_compile_args=extra_compile_args,
100
+ )
101
+ ]
102
+
103
+ return ext_modules
104
+
105
+
106
+ def get_model_zoo_configs() -> List[str]:
107
+ """
108
+ Return a list of configs to include in package for model zoo. Copy over these configs inside
109
+ detectron2/model_zoo.
110
+ """
111
+
112
+ # Use absolute paths while symlinking.
113
+ source_configs_dir = path.join(path.dirname(path.realpath(__file__)), "configs")
114
+ destination = path.join(
115
+ path.dirname(path.realpath(__file__)), "detectron2", "model_zoo", "configs"
116
+ )
117
+ # Symlink the config directory inside package to have a cleaner pip install.
118
+
119
+ # Remove stale symlink/directory from a previous build.
120
+ if path.exists(source_configs_dir):
121
+ if path.islink(destination):
122
+ os.unlink(destination)
123
+ elif path.isdir(destination):
124
+ shutil.rmtree(destination)
125
+
126
+ if not path.exists(destination):
127
+ try:
128
+ os.symlink(source_configs_dir, destination)
129
+ except OSError:
130
+ # Fall back to copying if symlink fails: ex. on Windows.
131
+ shutil.copytree(source_configs_dir, destination)
132
+
133
+ config_paths = glob.glob("configs/**/*.yaml", recursive=True) + glob.glob(
134
+ "configs/**/*.py", recursive=True
135
+ )
136
+ return config_paths
137
+
138
+
139
+ # For projects that are relative small and provide features that are very close
140
+ # to detectron2's core functionalities, we install them under detectron2.projects
141
+ PROJECTS = {
142
+ "detectron2.projects.point_rend": "projects/PointRend/point_rend",
143
+ "detectron2.projects.deeplab": "projects/DeepLab/deeplab",
144
+ "detectron2.projects.panoptic_deeplab": "projects/Panoptic-DeepLab/panoptic_deeplab",
145
+ }
146
+
147
+ setup(
148
+ name="detectron2",
149
+ version=get_version(),
150
+ author="FAIR",
151
+ url="https://github.com/facebookresearch/detectron2",
152
+ description="Detectron2 is FAIR's next-generation research "
153
+ "platform for object detection and segmentation.",
154
+ packages=find_packages(exclude=("configs", "tests*")) + list(PROJECTS.keys()),
155
+ package_dir=PROJECTS,
156
+ package_data={"detectron2.model_zoo": get_model_zoo_configs()},
157
+ python_requires=">=3.7",
158
+ install_requires=[
159
+ # These dependencies are not pure-python.
160
+ # In general, avoid adding more dependencies like them because they are not
161
+ # guaranteed to be installable by `pip install` on all platforms.
162
+ # To tell if a package is pure-python, go to https://pypi.org/project/{name}/#files
163
+ "Pillow>=7.1", # or use pillow-simd for better performance
164
+ "matplotlib", # TODO move it to optional after we add opencv visualization
165
+ "pycocotools>=2.0.2", # corresponds to https://github.com/ppwwyyxx/cocoapi
166
+ # Do not add opencv here. Just like pytorch, user should install
167
+ # opencv themselves, preferrably by OS's package manager, or by
168
+ # choosing the proper pypi package name at https://github.com/skvark/opencv-python
169
+ # The following are pure-python dependencies that should be easily installable
170
+ "termcolor>=1.1",
171
+ "yacs>=0.1.8",
172
+ "tabulate",
173
+ "cloudpickle",
174
+ "tqdm>4.29.0",
175
+ "tensorboard",
176
+ # Lock version of fvcore/iopath because they may have breaking changes
177
+ # NOTE: when updating fvcore/iopath version, make sure fvcore depends
178
+ # on compatible version of iopath.
179
+ "fvcore>=0.1.5,<0.1.6", # required like this to make it pip installable
180
+ "iopath>=0.1.7,<0.1.10",
181
+ "future", # used by caffe2
182
+ "pydot", # used to save caffe2 SVGs
183
+ "dataclasses; python_version<'3.7'",
184
+ "omegaconf>=2.1",
185
+ "hydra-core>=1.1",
186
+ "black==22.3.0",
187
+ "timm",
188
+ "fairscale",
189
+ "packaging",
190
+ # If a new dependency is required at import time (in addition to runtime), it
191
+ # probably needs to exist in docs/requirements.txt, or as a mock in docs/conf.py
192
+ ],
193
+ extras_require={
194
+ # optional dependencies, required by some features
195
+ "all": [
196
+ "scipy>1.5.1",
197
+ "shapely",
198
+ "pygments>=2.2",
199
+ "psutil",
200
+ "panopticapi @ https://github.com/cocodataset/panopticapi/archive/master.zip",
201
+ ],
202
+ # dev dependencies. Install them by `pip install 'detectron2[dev]'`
203
+ "dev": [
204
+ "flake8==3.8.1",
205
+ "isort==4.3.21",
206
+ "flake8-bugbear",
207
+ "flake8-comprehensions",
208
+ ],
209
+ },
210
+ ext_modules=get_extensions(),
211
+ cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension},
212
+ )
approach/ovod/gdino.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from groundingdino.util.inference import load_model, load_image, predict, annotate
2
+ import cv2
3
+
4
+ model = load_model("./groundingdino/config/GroundingDINO_SwinT_OGC.py", "weights/groundingdino_swint_ogc.pth")
5
+
6
+ # def peform_ovod(image_path, text_prompt, box_threshold, text_threshold)
7
+ image_path = "weights/dog.jpg"
8
+ text_prompt = "chair . person . dog ."
9
+ box_threshold = 0.35
10
+ text_threshold = 0.25
11
+
12
+ image_source, image = load_image(image_path)
13
+
14
+ boxes, logits, phrases = predict(
15
+ model=model,
16
+ image=image,
17
+ caption=text_prompt,
18
+ box_threshold=box_threshold,
19
+ text_threshold=text_threshold
20
+ )
21
+
22
+ annotated_frame = annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)
23
+ cv2.imwrite("annotated_image.jpg", annotated_frame)
approach/pipeline_utils.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from pathlib import Path
4
+ import re
5
+ import tempfile
6
+ from typing import Iterable, List, Optional, Sequence
7
+
8
+
9
+ IMAGE_NAME_PATTERN = re.compile(r"^(?P<app_id>[0-9]+)_(?P<frame_id>[0-9]+)\.[A-Za-z0-9]+$")
10
+
11
+
12
+ def parse_orienter_image_name(image_name: str) -> tuple[str, str, int]:
13
+ path = Path(image_name)
14
+ if path.name != image_name:
15
+ raise ValueError(f"Image name must be a basename, not a path: {image_name}")
16
+ match = IMAGE_NAME_PATTERN.match(image_name)
17
+ if not match:
18
+ raise ValueError(
19
+ "Image name must match <app_id>_<frame>.<ext> with numeric app_id and frame: "
20
+ f"{image_name}"
21
+ )
22
+ app_id = match.group("app_id")
23
+ frame_id = match.group("frame_id")
24
+ frame_number = int(frame_id)
25
+ if frame_number > 999:
26
+ raise ValueError(f"Image frame must be in [0, 999] for the documented image_id: {image_name}")
27
+ return app_id, frame_id, int(f"{app_id}{frame_number:03d}")
28
+
29
+
30
+ def resolve_image_path(images_dir: Path, image_name: str) -> Path:
31
+ """Resolve a manifest image path without allowing escape from images_dir."""
32
+ if not isinstance(image_name, str) or not image_name:
33
+ raise ValueError("Manifest image must be a non-empty relative path")
34
+ relative = Path(image_name)
35
+ if relative.is_absolute() or ".." in relative.parts:
36
+ raise ValueError(f"Manifest image must stay inside images-dir: {image_name}")
37
+ root = images_dir.resolve()
38
+ resolved = (root / relative).resolve()
39
+ try:
40
+ resolved.relative_to(root)
41
+ except ValueError as exc:
42
+ raise ValueError(f"Manifest image must stay inside images-dir: {image_name}") from exc
43
+ return resolved
44
+
45
+
46
+ def select_jsonl_lines(
47
+ lines: Sequence[str],
48
+ start_index: Optional[int] = None,
49
+ end_index: Optional[int] = None,
50
+ shard_index: Optional[int] = None,
51
+ num_shards: Optional[int] = None,
52
+ ) -> List[str]:
53
+ uses_range = start_index is not None or end_index is not None
54
+ uses_shard = shard_index is not None or num_shards is not None
55
+ if uses_range and uses_shard:
56
+ raise ValueError("range selection and shard selection are mutually exclusive")
57
+ if (shard_index is None) != (num_shards is None):
58
+ raise ValueError("shard_index and num_shards must be set together")
59
+ if num_shards is not None:
60
+ if num_shards <= 0:
61
+ raise ValueError("num_shards must be positive")
62
+ if shard_index < 0 or shard_index >= num_shards:
63
+ raise ValueError("shard_index must be in [0, num_shards)")
64
+
65
+ selected = list(lines)
66
+ if uses_range:
67
+ start = 0 if start_index is None else start_index
68
+ end = len(selected) if end_index is None else end_index
69
+ if start < 0 or end < 0:
70
+ raise ValueError("start_index and end_index must be non-negative")
71
+ if start > end:
72
+ raise ValueError("start_index must be <= end_index")
73
+ if end > len(selected):
74
+ raise ValueError("end_index must be <= number of records")
75
+ selected = selected[start:end]
76
+
77
+ if num_shards is not None:
78
+ selected = [line for idx, line in enumerate(selected) if idx % num_shards == shard_index]
79
+
80
+ return selected
81
+
82
+
83
+ def output_path_for_selection(
84
+ path: str,
85
+ start_index: Optional[int] = None,
86
+ end_index: Optional[int] = None,
87
+ shard_index: Optional[int] = None,
88
+ num_shards: Optional[int] = None,
89
+ ) -> str:
90
+ uses_range = start_index is not None or end_index is not None
91
+ uses_shard = shard_index is not None or num_shards is not None
92
+ if uses_range and uses_shard:
93
+ raise ValueError("range selection and shard selection are mutually exclusive")
94
+ if (shard_index is None) != (num_shards is None):
95
+ raise ValueError("shard_index and num_shards must be set together")
96
+
97
+ suffix = ""
98
+ if uses_shard:
99
+ if num_shards <= 0 or shard_index < 0 or shard_index >= num_shards:
100
+ raise ValueError("invalid shard parameters")
101
+ width = max(2, len(str(num_shards - 1)))
102
+ suffix = f".shard{shard_index:0{width}d}-of-{num_shards:0{width}d}"
103
+ elif uses_range:
104
+ start = 0 if start_index is None else start_index
105
+ end = "end" if end_index is None else str(end_index)
106
+ if start < 0 or (end_index is not None and end_index < start):
107
+ raise ValueError("invalid range parameters")
108
+ suffix = f".rows{start}-{end}"
109
+
110
+ if not suffix:
111
+ return path
112
+ root, extension = os.path.splitext(path)
113
+ return f"{root}{suffix}{extension or '.json'}"
114
+
115
+
116
+ def enrich_ape_results(ape_results: Iterable[dict], image_name: str, extract_image_id) -> List[dict]:
117
+ image_id = extract_image_id(image_name)
118
+ enriched = []
119
+ for ape_item in ape_results:
120
+ item = dict(ape_item)
121
+ item["image_id"] = image_id
122
+ item["category_id"] = item.get("category_name")
123
+ enriched.append(item)
124
+ return enriched
125
+
126
+
127
+ def write_json_atomic(path: str, payload) -> None:
128
+ directory = os.path.dirname(os.path.abspath(path))
129
+ os.makedirs(directory, exist_ok=True)
130
+ file_descriptor, tmp_path = tempfile.mkstemp(
131
+ prefix=".orienter-",
132
+ suffix=".json.tmp",
133
+ dir=directory,
134
+ )
135
+ try:
136
+ with os.fdopen(file_descriptor, "w", encoding="utf-8") as out_file:
137
+ json.dump(payload, out_file, indent=4)
138
+ out_file.write("\n")
139
+ os.replace(tmp_path, path)
140
+ except Exception:
141
+ if os.path.exists(tmp_path):
142
+ os.unlink(tmp_path)
143
+ raise
144
+
145
+
146
+ def run_optional_reflection(
147
+ image_path: str,
148
+ detections: List[dict],
149
+ detector,
150
+ enabled: bool = False,
151
+ model_profile: str = "default",
152
+ max_iterations: int = 10,
153
+ advisor=None,
154
+ ):
155
+ if not enabled:
156
+ return None
157
+
158
+ from PIL import Image
159
+
160
+ from approach.reflection import openai_compatible_advisor, run_reflection_loop
161
+
162
+ def mine_feedback(trace):
163
+ if not trace:
164
+ return []
165
+ return trace[-1].get("feedback", [])
166
+
167
+ reflection_advisor = advisor or openai_compatible_advisor(model_profile)
168
+ with Image.open(image_path) as image:
169
+ return run_reflection_loop(
170
+ image.convert("RGB"),
171
+ list(detections),
172
+ miner=mine_feedback,
173
+ detector=detector,
174
+ advisor=reflection_advisor,
175
+ max_iterations=max_iterations,
176
+ )
approach/run_ape.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configurable APE detection entrypoint for the public Orienter pipeline."""
2
+
3
+ import argparse
4
+ import hashlib
5
+ import json
6
+ import os
7
+ import sys
8
+ from contextlib import contextmanager
9
+ from pathlib import Path
10
+
11
+ if __package__ in {None, ""}:
12
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
13
+
14
+ from approach.ape_stage import run_ape_stage
15
+ from approach.pipeline_utils import (
16
+ output_path_for_selection,
17
+ run_optional_reflection,
18
+ select_jsonl_lines,
19
+ write_json_atomic,
20
+ )
21
+
22
+
23
+ DEFAULT_APE_CONFIG = (
24
+ "configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_"
25
+ "PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_"
26
+ "cp_16x4_1080k.py"
27
+ )
28
+ APE_CHECKPOINT_SHA256 = "3548f41a3238148180e08fd4b16c71f4abc3ac3caf9c8434444462d1bdb7f965"
29
+ APE_CHECKPOINT_SIZE = 5_956_547_279
30
+
31
+
32
+ def _load_jsonl(path: Path):
33
+ with path.open(encoding="utf-8") as file:
34
+ return [json.loads(line) for line in file if line.strip()]
35
+
36
+
37
+ def _normalize_candidate(record):
38
+ normalized = dict(record)
39
+ text = normalized.get("text")
40
+ if isinstance(text, str):
41
+ stripped = text.strip()
42
+ if stripped.startswith("```"):
43
+ lines = stripped.splitlines()
44
+ stripped = "\n".join(lines[1:-1] if lines[-1].strip() == "```" else lines[1:])
45
+ normalized["text"] = json.loads(stripped)
46
+ if normalized.get("text") is not None and "objects" not in normalized["text"]:
47
+ raise ValueError(
48
+ f"candidate record {normalized.get('question_id')!r} is missing text.objects"
49
+ )
50
+ return normalized
51
+
52
+
53
+ @contextmanager
54
+ def _working_directory(path: Path):
55
+ previous = Path.cwd()
56
+ os.chdir(path)
57
+ try:
58
+ yield
59
+ finally:
60
+ os.chdir(previous)
61
+
62
+
63
+ def _resolve_ape_checkpoint(ape_root: Path, checkpoint: Path) -> Path:
64
+ if checkpoint.is_absolute():
65
+ return checkpoint
66
+ project_root = Path(__file__).resolve().parents[1]
67
+ repo_relative = (project_root / checkpoint).resolve()
68
+ if repo_relative.exists():
69
+ return repo_relative
70
+ return (ape_root.resolve() / checkpoint).resolve()
71
+
72
+
73
+ def _sha256_file(path: Path) -> str:
74
+ digest = hashlib.sha256()
75
+ with path.open("rb") as file:
76
+ for chunk in iter(lambda: file.read(1024 * 1024), b""):
77
+ digest.update(chunk)
78
+ return digest.hexdigest()
79
+
80
+
81
+ def _verify_ape_checkpoint(checkpoint: Path, trust_custom_checkpoint: bool = False) -> None:
82
+ if not checkpoint.is_file():
83
+ raise FileNotFoundError(f"APE checkpoint does not exist: {checkpoint}")
84
+
85
+ size = checkpoint.stat().st_size
86
+ if size == APE_CHECKPOINT_SIZE:
87
+ digest = _sha256_file(checkpoint)
88
+ if digest == APE_CHECKPOINT_SHA256:
89
+ return
90
+ mismatch = f"SHA-256 {digest} does not match the released APE-L_D checkpoint"
91
+ else:
92
+ mismatch = (
93
+ f"size {size} does not match the released APE-L_D checkpoint "
94
+ f"({APE_CHECKPOINT_SIZE} bytes)"
95
+ )
96
+
97
+ if trust_custom_checkpoint:
98
+ return
99
+ raise ValueError(
100
+ f"Refusing unverified checkpoint {checkpoint}: {mismatch}. "
101
+ "Use --trust-custom-checkpoint only for a checkpoint whose provenance you verified."
102
+ )
103
+
104
+
105
+ def _make_live_inference(args):
106
+ from approach.ovod.APE.demo.ape_inference import run_ape_model_inference
107
+
108
+ ape_root = args.ape_root.resolve()
109
+ checkpoint = _resolve_ape_checkpoint(ape_root, args.ape_checkpoint)
110
+ _verify_ape_checkpoint(checkpoint, args.trust_custom_checkpoint)
111
+ visualization_dir = args.visualization_dir.resolve()
112
+ visualization_dir.mkdir(parents=True, exist_ok=True)
113
+
114
+ def inference(input_path, text_prompt, confidence_threshold):
115
+ with _working_directory(ape_root):
116
+ return run_ape_model_inference(
117
+ config_file=args.ape_config,
118
+ input_path=input_path,
119
+ output_path=str(visualization_dir),
120
+ confidence_threshold=confidence_threshold,
121
+ text_prompt=text_prompt,
122
+ with_box=True,
123
+ with_mask=False,
124
+ with_sseg=False,
125
+ opts=[
126
+ f"train.init_checkpoint='{checkpoint}'",
127
+ "model.model_language.cache_dir=''",
128
+ "model.model_vision.select_box_nums_for_evaluation=500",
129
+ "model.model_vision.text_feature_bank_reset=True",
130
+ "model.model_vision.backbone.net.xattn=False",
131
+ "model.model_vision.transformer.encoder.pytorch_attn=True",
132
+ "model.model_vision.transformer.decoder.pytorch_attn=True",
133
+ ],
134
+ )
135
+
136
+ return inference
137
+
138
+
139
+ def _merge_detections(retained, new_detections):
140
+ merged = list(retained)
141
+ seen = {
142
+ (item.get("category_name"), tuple(item.get("bbox", [])))
143
+ for item in retained
144
+ }
145
+ for item in new_detections:
146
+ key = item.get("category_name"), tuple(item.get("bbox", []))
147
+ if key not in seen:
148
+ merged.append(item)
149
+ seen.add(key)
150
+ return merged
151
+
152
+
153
+ def build_parser():
154
+ project_root = Path(__file__).resolve().parent
155
+ parser = argparse.ArgumentParser(description=__doc__)
156
+ parser.add_argument("--questions", type=Path, required=True, help="question manifest JSONL")
157
+ parser.add_argument("--candidates", type=Path, required=True, help="candidate JSONL")
158
+ parser.add_argument("--images-dir", type=Path, required=True)
159
+ parser.add_argument("--output", type=Path, required=True)
160
+ parser.add_argument("--start-index", type=int)
161
+ parser.add_argument("--end-index", type=int)
162
+ parser.add_argument("--shard-index", type=int)
163
+ parser.add_argument("--num-shards", type=int)
164
+ parser.add_argument("--resume", action="store_true")
165
+ parser.add_argument("--threshold", type=float, default=0.15)
166
+ parser.add_argument(
167
+ "--ape-root",
168
+ type=Path,
169
+ default=project_root / "ovod" / "APE",
170
+ )
171
+ parser.add_argument("--ape-config", default=DEFAULT_APE_CONFIG)
172
+ parser.add_argument(
173
+ "--ape-checkpoint",
174
+ type=Path,
175
+ default=Path("ape_d_model_final.pth"),
176
+ )
177
+ parser.add_argument(
178
+ "--trust-custom-checkpoint",
179
+ action="store_true",
180
+ help="allow a checkpoint that does not match the released model hash",
181
+ )
182
+ parser.add_argument(
183
+ "--visualization-dir",
184
+ type=Path,
185
+ default=Path("outputs/ape_visualizations"),
186
+ )
187
+ parser.add_argument("--enable-reflection", action="store_true")
188
+ parser.add_argument("--reflection-profile", default="default")
189
+ parser.add_argument("--max-reflection-iterations", type=int, default=10)
190
+ return parser
191
+
192
+
193
+ def run(args, inference=None):
194
+ questions = {
195
+ item["question_id"]: item
196
+ for item in _load_jsonl(args.questions)
197
+ }
198
+ records = [_normalize_candidate(item) for item in _load_jsonl(args.candidates)]
199
+ selected = select_jsonl_lines(
200
+ records,
201
+ start_index=args.start_index,
202
+ end_index=args.end_index,
203
+ shard_index=args.shard_index,
204
+ num_shards=args.num_shards,
205
+ )
206
+ selected_output = Path(
207
+ output_path_for_selection(
208
+ str(args.output),
209
+ start_index=args.start_index,
210
+ end_index=args.end_index,
211
+ shard_index=args.shard_index,
212
+ num_shards=args.num_shards,
213
+ )
214
+ )
215
+ base_inference = inference or _make_live_inference(args)
216
+ reflection_traces = []
217
+
218
+ def configured_inference(**kwargs):
219
+ detections = base_inference(**kwargs)
220
+ if not args.enable_reflection:
221
+ return detections
222
+
223
+ def redetect(candidates, retained):
224
+ if not candidates:
225
+ return retained
226
+ new_detections = base_inference(
227
+ input_path=kwargs["input_path"],
228
+ text_prompt=", ".join(candidates),
229
+ confidence_threshold=kwargs["confidence_threshold"],
230
+ )
231
+ return _merge_detections(retained, new_detections)
232
+
233
+ try:
234
+ reflection = run_optional_reflection(
235
+ kwargs["input_path"],
236
+ detections,
237
+ detector=redetect,
238
+ enabled=True,
239
+ model_profile=args.reflection_profile,
240
+ max_iterations=args.max_reflection_iterations,
241
+ )
242
+ except Exception as exc:
243
+ reflection_traces.append(
244
+ {
245
+ "image": Path(kwargs["input_path"]).name,
246
+ "error_type": type(exc).__name__,
247
+ "message": str(exc),
248
+ }
249
+ )
250
+ return detections
251
+
252
+ reflection_traces.append(
253
+ {
254
+ "image": Path(kwargs["input_path"]).name,
255
+ "trace": reflection["trace"],
256
+ "max_iterations_reached": reflection["max_iterations_reached"],
257
+ }
258
+ )
259
+ return reflection["detections"]
260
+
261
+ error_path = selected_output.with_suffix(".errors.json")
262
+ results, errors = run_ape_stage(
263
+ records=selected,
264
+ questions=questions,
265
+ images_dir=args.images_dir,
266
+ output_path=selected_output,
267
+ inference=configured_inference,
268
+ inference_kwargs={"confidence_threshold": args.threshold},
269
+ error_path=error_path,
270
+ resume=args.resume,
271
+ )
272
+ if args.enable_reflection:
273
+ write_json_atomic(
274
+ str(selected_output.with_suffix(".reflection.json")),
275
+ reflection_traces,
276
+ )
277
+ return {
278
+ "output": str(selected_output),
279
+ "records_selected": len(selected),
280
+ "predictions": len(results),
281
+ "errors": len(errors),
282
+ }
283
+
284
+
285
+ def main(argv=None):
286
+ args = build_parser().parse_args(argv)
287
+ print(json.dumps(run(args), indent=2))
288
+
289
+
290
+ if __name__ == "__main__":
291
+ main()
approach/util/test.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import time
3
+ import os
4
+ import argparse
5
+ import shutil
6
+ import sys
7
+
8
+ def parse_args():
9
+ parser = argparse.ArgumentParser(description='Matrix multiplication')
10
+ parser.add_argument('--gpus', help='gpu amount', required=True, type=int)
11
+ parser.add_argument('--size', help='matrix size', required=True, type=int)
12
+ parser.add_argument('--interval', help='sleep interval', required=True, type=float)
13
+ args = parser.parse_args()
14
+ return args
15
+
16
+
17
+ def matrix_multiplication(args):
18
+
19
+ a_list, b_list, result = [], [], []
20
+ size = (args.size, args.size)
21
+
22
+ for i in range(args.gpus):
23
+ a_list.append(torch.rand(size, device=i))
24
+ b_list.append(torch.rand(size, device=i))
25
+ result.append(torch.rand(size, device=i))
26
+
27
+ while True:
28
+ for i in range(args.gpus):
29
+ result[i] = a_list[i] * b_list[i]
30
+ time.sleep(args.interval)
31
+
32
+ if __name__ == "__main__":
33
+ # usage: python test.py --size 32000 --gpus 4 --interval 0.01
34
+ args = parse_args()
35
+ matrix_multiplication(args)
approach/vlm/LLaVA/.gitignore ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__
3
+ *.pyc
4
+ *.egg-info
5
+ dist
6
+
7
+ # Log
8
+ *.log
9
+ *.log.*
10
+ *.json
11
+ *.jsonl
12
+
13
+ # Data
14
+ !**/alpaca-data-conversation.json
15
+
16
+ # Editor
17
+ .idea
18
+ *.swp
19
+
20
+ # Other
21
+ .DS_Store
22
+ wandb
23
+ output
24
+
25
+ checkpoints
26
+ ckpts*
27
+
28
+ .ipynb_checkpoints
29
+ *.ipynb
approach/vlm/LLaVA/LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
approach/vlm/LLaVA/README.md ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🌋 LLaVA: Large Language and Vision Assistant
2
+
3
+ *Visual instruction tuning towards large language and vision models with GPT-4 level capabilities.*
4
+
5
+ [[Project Page](https://llava-vl.github.io/)] [[Demo](https://llava.hliu.cc/)] [[Data](https://github.com/haotian-liu/LLaVA/blob/main/docs/Data.md)] [[Model Zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md)]
6
+
7
+ **Improved Baselines with Visual Instruction Tuning** [[Paper](https://arxiv.org/abs/2310.03744)] <br>
8
+ [Haotian Liu](https://hliu.cc), [Chunyuan Li](https://chunyuan.li/), [Yuheng Li](https://yuheng-li.github.io/), [Yong Jae Lee](https://pages.cs.wisc.edu/~yongjaelee/)
9
+
10
+ **Visual Instruction Tuning** (NeurIPS 2023, **Oral**) [[Paper](https://arxiv.org/abs/2304.08485)]<br>
11
+ [Haotian Liu*](https://hliu.cc), [Chunyuan Li*](https://chunyuan.li/), [Qingyang Wu](https://scholar.google.ca/citations?user=HDiw-TsAAAAJ&hl=en/), [Yong Jae Lee](https://pages.cs.wisc.edu/~yongjaelee/) (*Equal Contribution)
12
+
13
+ <p align="center">
14
+ <a href="https://llava.hliu.cc/"><img src="images/llava_logo.png" width="50%"></a> <br>
15
+ Generated by <a href="https://gligen.github.io/">GLIGEN</a> via "a cute lava llama with glasses" and box prompt
16
+ </p>
17
+
18
+
19
+ ## Release
20
+ - [10/5] 🔥 LLaVA-1.5 is out! Achieving SoTA on 11 benchmarks, with just simple modifications to the original LLaVA, utilizes all public data, completes training in ~1 day on a single 8-A100 node, and surpasses methods like Qwen-VL-Chat that use billion-scale data. Check out the [technical report](https://arxiv.org/abs/2310.03744), and explore the [demo](https://llava.hliu.cc/)! Models are available in [Model Zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md), with training and evaluation scripts coming in the next week!
21
+ - [9/26] LLaVA is improved with reinforcement learning from human feedback (RLHF) to improve fact grounding and reduce hallucination. Check out the new SFT and RLHF checkpoints at project [[LLavA-RLHF]](https://llava-rlhf.github.io/)
22
+ - [9/22] [LLaVA](https://arxiv.org/abs/2304.08485) is accpeted by NeurIPS 2023 as **oral presentation**, and [LLaVA-Med](https://arxiv.org/abs/2306.00890) is accpeted by NeurIPS 2023 Datasets and Benchmarks Track as **spotlight presentation**.
23
+ - [9/20] We summarize our emprical study of training 33B and 65B LLaVA mdoels in a [note](https://arxiv.org/abs/2309.09958). Further, if you are interested in the comprehensive review, evolution and trend of multimodal foundation models, please check out our recent survey paper [``Multimodal Foundation Models: From Specialists to General-Purpose Assistants''.](https://arxiv.org/abs/2309.10020)
24
+ <p align="center">
25
+ <img src="https://github.com/Computer-Vision-in-the-Wild/CVinW_Readings/blob/main/images/mfm_evolution.jpeg?raw=true" width=50%/>
26
+ </p>
27
+
28
+ - [7/19] 🔥 We release a major upgrade, including support for LLaMA-2, LoRA training, 4-/8-bit inference, higher resolution (336x336), and a lot more. We release [LLaVA Bench](https://github.com/haotian-liu/LLaVA/blob/main/docs/LLaVA_Bench.md) for benchmarking open-ended visual chat with results from Bard and Bing-Chat. We also support and verify training with RTX 3090 and RTX A6000. Check out [LLaVA-from-LLaMA-2](https://github.com/haotian-liu/LLaVA/blob/main/docs/LLaVA_from_LLaMA2.md), and our [model zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md)!
29
+ - [6/26] [CVPR 2023 Tutorial](https://vlp-tutorial.github.io/) on **Large Multimodal Models: Towards Building and Surpassing Multimodal GPT-4**! Please check out [[Slides](https://datarelease.blob.core.windows.net/tutorial/vision_foundation_models_2023/slides/Chunyuan_cvpr2023_tutorial_lmm.pdf)] [[Notes](https://arxiv.org/abs/2306.14895)] [[YouTube](https://youtu.be/mkI7EPD1vp8)] [[Bilibli](https://www.bilibili.com/video/BV1Ng4y1T7v3/)].
30
+ - [6/11] We released the preview for the most requested feature: DeepSpeed and LoRA support! Please see documentations [here](./docs/LoRA.md).
31
+ - [6/1] We released **LLaVA-Med: Large Language and Vision Assistant for Biomedicine**, a step towards building biomedical domain large language and vision models with GPT-4 level capabilities. Checkout the [paper](https://arxiv.org/abs/2306.00890) and [page](https://github.com/microsoft/LLaVA-Med).
32
+ - [5/6] We are releasing [LLaVA-Lighting-MPT-7B-preview](https://huggingface.co/liuhaotian/LLaVA-Lightning-MPT-7B-preview), based on MPT-7B-Chat! See [here](#LLaVA-MPT-7b) for more details.
33
+ - [5/2] 🔥 We are releasing LLaVA-Lighting! Train a lite, multimodal GPT-4 with just $40 in 3 hours! See [here](#train-llava-lightning) for more details.
34
+ - [4/27] Thanks to the community effort, LLaVA-13B with 4-bit quantization allows you to run on a GPU with as few as 12GB VRAM! Try it out [here](https://github.com/oobabooga/text-generation-webui/tree/main/extensions/llava).
35
+ - [4/17] 🔥 We released **LLaVA: Large Language and Vision Assistant**. We propose visual instruction tuning, towards building large language and vision models with GPT-4 level capabilities. Checkout the [paper](https://arxiv.org/abs/2304.08485) and [demo](https://llava.hliu.cc/).
36
+
37
+ <!-- <a href="https://llava.hliu.cc/"><img src="assets/demo.gif" width="70%"></a> -->
38
+
39
+ [![Code License](https://img.shields.io/badge/Code%20License-Apache_2.0-green.svg)](https://github.com/tatsu-lab/stanford_alpaca/blob/main/LICENSE)
40
+ [![Data License](https://img.shields.io/badge/Data%20License-CC%20By%20NC%204.0-red.svg)](https://github.com/tatsu-lab/stanford_alpaca/blob/main/DATA_LICENSE)
41
+ **Usage and License Notices**: The data and checkpoint is intended and licensed for research use only. They are also restricted to uses that follow the license agreement of LLaMA, Vicuna and GPT-4. The dataset is CC BY NC 4.0 (allowing only non-commercial use) and models trained using the dataset should not be used outside of research purposes.
42
+
43
+
44
+ ## Contents
45
+ - [Install](#install)
46
+ - [LLaVA Weights](#llava-weights)
47
+ - [Demo](#Demo)
48
+ - [Model Zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md)
49
+ - [Dataset](https://github.com/haotian-liu/LLaVA/blob/main/docs/Data.md)
50
+ - [Train](#train)
51
+ - [Evaluation](#evaluation)
52
+
53
+ ## Install
54
+
55
+ 1. Clone this repository and navigate to LLaVA folder
56
+ ```bash
57
+ git clone https://github.com/haotian-liu/LLaVA.git
58
+ cd LLaVA
59
+ ```
60
+
61
+ 2. Install Package
62
+ ```Shell
63
+ conda create -n llava python=3.10 -y
64
+ conda activate llava
65
+ pip install --upgrade pip # enable PEP 660 support
66
+ pip install -e .
67
+ ```
68
+
69
+ 3. Install additional packages for training cases
70
+ ```
71
+ pip install ninja
72
+ pip install flash-attn --no-build-isolation
73
+ ```
74
+
75
+ ### Upgrade to latest code base
76
+
77
+ ```Shell
78
+ git pull
79
+ pip uninstall transformers
80
+ pip install -e .
81
+ ```
82
+
83
+ ## LLaVA Weights
84
+ Please check out our [Model Zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md) for all public LLaVA checkpoints, and the instructions of how to use the weights.
85
+
86
+ ## Demo
87
+
88
+ To run our demo, you need to prepare LLaVA checkpoints locally. Please follow the instructions [here](#llava-weights) to download the checkpoints.
89
+
90
+ ### Gradio Web UI
91
+
92
+ To launch a Gradio demo locally, please run the following commands one by one. If you plan to launch multiple model workers to compare between different checkpoints, you only need to launch the controller and the web server *ONCE*.
93
+
94
+ #### Launch a controller
95
+ ```Shell
96
+ python -m llava.serve.controller --host 0.0.0.0 --port 10000
97
+ ```
98
+
99
+ #### Launch a gradio web server.
100
+ ```Shell
101
+ python -m llava.serve.gradio_web_server --controller http://localhost:10000 --model-list-mode reload
102
+ ```
103
+ You just launched the Gradio web interface. Now, you can open the web interface with the URL printed on the screen. You may notice that there is no model in the model list. Do not worry, as we have not launched any model worker yet. It will be automatically updated when you launch a model worker.
104
+
105
+ #### Launch a model worker
106
+
107
+ This is the actual *worker* that performs the inference on the GPU. Each worker is responsible for a single model specified in `--model-path`.
108
+
109
+ ```Shell
110
+ python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/llava-v1.5-13b
111
+ ```
112
+ Wait until the process finishes loading the model and you see "Uvicorn running on ...". Now, refresh your Gradio web UI, and you will see the model you just launched in the model list.
113
+
114
+ You can launch as many workers as you want, and compare between different model checkpoints in the same Gradio interface. Please keep the `--controller` the same, and modify the `--port` and `--worker` to a different port number for each worker.
115
+ ```Shell
116
+ python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port <different from 40000, say 40001> --worker http://localhost:<change accordingly, i.e. 40001> --model-path <ckpt2>
117
+ ```
118
+
119
+ If you are using an Apple device with an M1 or M2 chip, you can specify the mps device by using the `--device` flag: `--device mps`.
120
+
121
+ #### Launch a model worker (Multiple GPUs, when GPU VRAM <= 24GB)
122
+
123
+ If the VRAM of your GPU is less than 24GB (e.g., RTX 3090, RTX 4090, etc.), you may try running it with multiple GPUs. Our latest code base will automatically try to use multiple GPUs if you have more than one GPU. You can specify which GPUs to use with `CUDA_VISIBLE_DEVICES`. Below is an example of running with the first two GPUs.
124
+
125
+ ```Shell
126
+ CUDA_VISIBLE_DEVICES=0,1 python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/llava-v1.5-13b
127
+ ```
128
+
129
+ #### Launch a model worker (4-bit, 8-bit inference, quantized)
130
+
131
+ You can launch the model worker with quantized bits (4-bit, 8-bit), which allows you to run the inference with reduced GPU memory footprint, potentially allowing you to run on a GPU with as few as 12GB VRAM. Note that inference with quantized bits may not be as accurate as the full-precision model. Simply append `--load-4bit` or `--load-8bit` to the **model worker** command that you are executing. Below is an example of running with 4-bit quantization.
132
+
133
+ ```Shell
134
+ python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/llava-v1.5-13b --load-4bit
135
+ ```
136
+
137
+ #### Launch a model worker (LoRA weights, unmerged)
138
+
139
+ You can launch the model worker with LoRA weights, without merging them with the base checkpoint, to save disk space. There will be additional loading time, while the inference speed is the same as the merged checkpoints. Unmerged LoRA checkpoints do not have `lora-merge` in the model name, and are usually much smaller (less than 1GB) than the merged checkpoints (13G for 7B, and 25G for 13B).
140
+
141
+ To load unmerged LoRA weights, you simply need to pass an additional argument `--model-base`, which is the base LLM that is used to train the LoRA weights. You can check the base LLM of each LoRA weights in the [model zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md).
142
+
143
+ ```Shell
144
+ python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/llava-v1-0719-336px-lora-vicuna-13b-v1.3 --model-base lmsys/vicuna-13b-v1.3
145
+ ```
146
+
147
+ ### CLI Inference
148
+
149
+ Chat about images using LLaVA without the need of Gradio interface. It also supports multiple GPUs, 4-bit and 8-bit quantized inference. With 4-bit quantization, for our LLaVA-1.5-7B, it uses less than 8GB VRAM on a single GPU.
150
+
151
+ ```Shell
152
+ python -m llava.serve.cli \
153
+ --model-path liuhaotian/llava-v1.5-7b \
154
+ --image-file "https://llava-vl.github.io/static/images/view.jpg" \
155
+ --load-4bit
156
+ ```
157
+
158
+ <img src="images/demo_cli.gif" width="70%">
159
+
160
+ ## Train
161
+
162
+ LLaVA training consists of two stages: (1) feature alignment stage: use approximately 600K filtered CC3M to connect a *frozen pretrained* vision encoder to a *frozen LLM*; (2) visual instruction tuning stage: use 150K GPT-generated multimodal instruction-following to teach the model to follow multimodal instructions.
163
+
164
+ LLaVA is trained on 8 A100 GPUs with 80GB memory. To train on fewer GPUs, you can reduce the `per_device_train_batch_size` and increase the `gradient_accumulation_steps` accordingly. Always keep the global batch size the same: `per_device_train_batch_size` x `gradient_accumulation_steps` x `num_gpus`.
165
+
166
+ ### Hyperparameters
167
+ We use a similar set of hyperparameters as Vicuna in finetuning. Both hyperparameters used in pretraining and finetuning are provided below.
168
+
169
+ 1. Pretraining
170
+
171
+ | Hyperparameter | Global Batch Size | Learning rate | Epochs | Max length | Weight decay |
172
+ | --- | ---: | ---: | ---: | ---: | ---: |
173
+ | LLaVA-13B | 256 | 1e-3 | 1 | 2048 | 0 |
174
+
175
+ 2. Finetuning
176
+
177
+ | Hyperparameter | Global Batch Size | Learning rate | Epochs | Max length | Weight decay |
178
+ | --- | ---: | ---: | ---: | ---: | ---: |
179
+ | LLaVA-13B | 128 | 2e-5 | 1 | 2048 | 0 |
180
+
181
+ ### Prepare Vicuna checkpoints
182
+
183
+ Before you start, prepare our base model Vicuna, which is an instruction-tuned chatbot. Please download its weights [here](https://github.com/lm-sys/FastChat#model-weights).
184
+
185
+ Vicuna has two versions: v0 and v1, the main difference between them is the prompt of format. We support both. To ensure the best performance, you need to specify the correct prompt version corresponding to the weights you download: `v0` for `v0` weights, and `v1` for all Vicuna `v1.x` models.
186
+
187
+ ### Pretrain (feature alignment)
188
+
189
+ Please download the subset of the CC3M dataset we use in the paper [here](https://huggingface.co/datasets/liuhaotian/LLaVA-CC3M-Pretrain-595K).
190
+
191
+ Pretrain takes around 4 hours for LLaVA-13B on 8x A100 (80G). It takes around 2 hours for 7B checkpoints.
192
+
193
+ We recommend training with DeepSpeed as it can save a lot of GPU RAM. We provide training script with DeepSpeed [here](https://github.com/haotian-liu/LLaVA/blob/main/scripts/pretrain.sh).
194
+
195
+ You may run this with a single A100 GPU with the following code. Please note that the `per_device_train_batch_size` * `gradient_accumulation_steps` should be equal to 128 to keep the global batch size the same.
196
+
197
+ <details>
198
+ <summary>Pretrain: LLaVA-13B, 1x A100 (80G). Time: ~33 hours.</summary>
199
+
200
+ ```Shell
201
+ python llava/train/train_mem.py \
202
+ --model_name_or_path ./checkpoints/vicuna-13b \
203
+ --version [v0 or v1] \
204
+ --data_path /path/to/cc3m_595k.json \
205
+ --image_folder /path/to/cc3m_595k_images \
206
+ --vision_tower openai/clip-vit-large-patch14 \
207
+ --tune_mm_mlp_adapter True \
208
+ --mm_vision_select_layer -2 \
209
+ --mm_use_im_start_end False \
210
+ --mm_use_im_patch_token False \
211
+ --bf16 True \
212
+ --output_dir ./checkpoints/llava-13b-pretrain \
213
+ --num_train_epochs 1 \
214
+ --per_device_train_batch_size 16 \
215
+ --per_device_eval_batch_size 4 \
216
+ --gradient_accumulation_steps 8 \
217
+ --evaluation_strategy "no" \
218
+ --save_strategy "steps" \
219
+ --save_steps 2400 \
220
+ --save_total_limit 1 \
221
+ --learning_rate 2e-3 \
222
+ --weight_decay 0. \
223
+ --warmup_ratio 0.03 \
224
+ --lr_scheduler_type "cosine" \
225
+ --logging_steps 1 \
226
+ --tf32 True \
227
+ --model_max_length 2048 \
228
+ --gradient_checkpointing True \
229
+ --lazy_preprocess True \
230
+ --report_to wandb
231
+ ```
232
+ </details>
233
+
234
+
235
+ ### Visual Instruction Tuning
236
+
237
+ 1. Prepare data
238
+
239
+ Please download the annotation of our instruction tuning data [llava_instruct_158k.json](https://huggingface.co/datasets/liuhaotian/LLaVA-Instruct-150K/blob/main/llava_instruct_150k.json), and download the COCO train2017 images [here](https://cocodataset.org/#download).
240
+
241
+ 2. Start training!
242
+
243
+ You may download our pretrained projectors in [Model Zoo](https://github.com/haotian-liu/LLaVA/blob/main/docs/MODEL_ZOO.md). It is not recommended to use legacy projectors, as they may be trained with a different version of the codebase, and if any option is off, the model will not function/train as we expected.
244
+
245
+ When we initially released our paper, we used a full 3-epoch schedule on the LLaVA-Instruct-158K dataset. The scripts are provided [here](https://github.com/haotian-liu/LLaVA/blob/main/scripts/finetune_full_schedule.sh).
246
+
247
+ In our later exploration, we introduced LLaVA-Lightning, as we find that a much faster 1-epoch schedule on LLaVA-Instruct-80K can achieve fast convergence and good performance. With LLaVA Lightning, we are able to train, validate, and release LLaVA-LLaMA-2 checkpoints preview on the same day as LLaMA-2 release. If you are interested to learn more about LLaVA Lightning, please continue to the following section.
248
+
249
+ ### Lightning
250
+
251
+ LLaVA-Lightning can be trained on 8x A100 GPUs in just 3 hours, including both pretraining and finetuning. When using spot instances, it costs just ~$40.
252
+
253
+ For LLaVA Lightning, we create two distilled subset to ensure both a broad concept coverage, and the efficiency in training. Furthermore, we only perform instruction tuning for 1 epoch, in contrast to 3 epochs in the paper. We find such schedule is effective and can achieve fast convergence and good performance.
254
+
255
+ For pretraining, we create a concept-balanced subset of LAION-CC-SBU. It consists of 558K images. Download data [here](https://huggingface.co/datasets/liuhaotian/LLaVA-Pretrain/tree/main).
256
+
257
+ For instruction tuning, we create a subset of LLaVA-Instruct-150K. It consists of 80K image-instruction pairs, consisting of 40K conversation and 40K complex reasoning data, with non-overlapping images. Download `llava_instruct_80k.json` [here](https://huggingface.co/datasets/liuhaotian/LLaVA-Instruct-150K/blob/main/llava_instruct_80k.json).
258
+
259
+ #### Hyperparameters
260
+
261
+ 1. Pretraining ([script](https://github.com/haotian-liu/LLaVA/blob/main/scripts/pretrain.sh))
262
+
263
+ | Hyperparameter | Global Batch Size | Learning rate | Epochs | Max length | Weight decay |
264
+ | --- | ---: | ---: | ---: | ---: | ---: |
265
+ | LLaVA-Lightning | 128 | 2e-3 | 1 | 2048 | 0 |
266
+
267
+ 2. Visual Instruction Tuning ([script](https://github.com/haotian-liu/LLaVA/blob/main/scripts/finetune.sh))
268
+
269
+ | Hyperparameter | Global Batch Size | Learning rate | Epochs | Max length | Weight decay |
270
+ | --- | ---: | ---: | ---: | ---: | ---: |
271
+ | LLaVA-Lightning | 128 | 2e-5 | 1 | 2048 | 0 |
272
+
273
+ #### LLaVA-MPT-7b
274
+ Thanks to LLaVA-Lightning, we are able to train a checkpoint based on MPT-7B-Chat on 8x A100 GPUs in just 3 hours, including both pretraining and finetuning.
275
+
276
+ **NOTE**: This is a research preview of the LLaVA-Lightning based on MPT-7B-chat checkpoint. The usage of the model should comply with MPT-7B-chat license and agreements.
277
+
278
+ 1. Usage
279
+
280
+ You do not need to download our checkpoint, it will directly load from our Hugging Face model: [`liuhaotian/LLaVA-Lightning-MPT-7B-preview`](https://huggingface.co/liuhaotian/LLaVA-Lightning-MPT-7B-preview).
281
+
282
+ ```Shell
283
+ python -m llava.serve.controller --host 0.0.0.0 --port 10000
284
+ python -m llava.serve.model_worker --host 0.0.0.0 --controller http://localhost:10000 --port 40000 --worker http://localhost:40000 --model-path liuhaotian/LLaVA-Lightning-MPT-7B-preview
285
+ python -m llava.serve.gradio_web_server --controller http://localhost:10000
286
+ ```
287
+
288
+ 2. Training
289
+
290
+ We use the same set of training dataset, and the hyperparameters as other *Lightning* checkpoints.
291
+
292
+ ## Evaluation
293
+
294
+ ### GPT-assisted Evaluation
295
+
296
+ Our GPT-assisted evaluation pipeline for multimodal modeling is provided for a comprehensive understanding of the capabilities of vision-language models. Please see our paper for more details.
297
+
298
+ 1. Generate LLaVA responses
299
+
300
+ ```Shell
301
+ python model_vqa.py \
302
+ --model-path ./checkpoints/LLaVA-13B-v0 \
303
+ --question-file \
304
+ playground/data/coco2014_val_qa_eval/qa90_questions.jsonl \
305
+ --image-folder \
306
+ /path/to/coco2014_val \
307
+ --answers-file \
308
+ /path/to/answer-file-our.jsonl
309
+ ```
310
+
311
+ 2. Evaluate the generated responses. In our case, [`answer-file-ref.jsonl`](./playground/data/coco2014_val_qa_eval/qa90_gpt4_answer.jsonl) is the response generated by text-only GPT-4 (0314), with the context captions/boxes provided.
312
+
313
+ ```Shell
314
+ OPENAI_API_KEY="sk-***********************************" python llava/eval/eval_gpt_review_visual.py \
315
+ --question playground/data/coco2014_val_qa_eval/qa90_questions.jsonl \
316
+ --context llava/eval/table/caps_boxes_coco2014_val_80.jsonl \
317
+ --answer-list \
318
+ /path/to/answer-file-ref.jsonl \
319
+ /path/to/answer-file-our.jsonl \
320
+ --rule llava/eval/table/rule.json \
321
+ --output /path/to/review.json
322
+ ```
323
+
324
+ 3. Summarize the evaluation results
325
+
326
+ ```Shell
327
+ python summarize_gpt_review.py
328
+ ```
329
+
330
+ ## ScienceQA
331
+
332
+ Please check out the documentation [here](https://github.com/haotian-liu/LLaVA/blob/main/docs/ScienceQA.md).
333
+
334
+ ## Citation
335
+
336
+ If you find LLaVA useful for your research and applications, please cite using this BibTeX:
337
+ ```bibtex
338
+
339
+ @misc{liu2023improvedllava,
340
+ title={Improved Baselines with Visual Instruction Tuning},
341
+ author={Liu, Haotian and Li, Chunyuan and Li, Yuheng and Lee, Yong Jae},
342
+ publisher={arXiv:2310.03744},
343
+ year={2023},
344
+ }
345
+
346
+ @misc{liu2023llava,
347
+ title={Visual Instruction Tuning},
348
+ author={Liu, Haotian and Li, Chunyuan and Wu, Qingyang and Lee, Yong Jae},
349
+ publisher={arXiv:2304.08485},
350
+ year={2023},
351
+ }
352
+ ```
353
+
354
+ ## Acknowledgement
355
+
356
+ - [Vicuna](https://github.com/lm-sys/FastChat): the codebase we built upon, and our base model Vicuna-13B that has the amazing language capabilities!
357
+
358
+ ## Related Projects
359
+
360
+ - [Instruction Tuning with GPT-4](https://github.com/Instruction-Tuning-with-GPT-4/GPT-4-LLM)
361
+ - [LLaVA-Med: Training a Large Language-and-Vision Assistant for Biomedicine in One Day](https://github.com/microsoft/LLaVA-Med)
362
+ - [Otter: In-Context Multi-Modal Instruction Tuning](https://github.com/Luodian/Otter)
363
+
364
+ For future project ideas, please check out:
365
+ - [SEEM: Segment Everything Everywhere All at Once](https://github.com/UX-Decoder/Segment-Everything-Everywhere-All-At-Once)
366
+ - [Grounded-Segment-Anything](https://github.com/IDEA-Research/Grounded-Segment-Anything) to detect, segment, and generate anything by marrying [Grounding DINO](https://github.com/IDEA-Research/GroundingDINO) and [Segment-Anything](https://github.com/facebookresearch/segment-anything).
approach/vlm/LLaVA/pyproject.toml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "llava"
7
+ version = "1.1.0"
8
+ description = "Towards GPT-4 like large language and visual assistant."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: Apache Software License",
14
+ ]
15
+ dependencies = [
16
+ "einops", "fastapi", "gradio==3.35.2", "markdown2[all]", "numpy",
17
+ "requests", "sentencepiece", "tokenizers>=0.12.1",
18
+ "torch==2.0.1", "torchvision==0.15.2", "uvicorn", "wandb",
19
+ "shortuuid", "httpx==0.24.0",
20
+ "deepspeed==0.9.5",
21
+ "peft==0.4.0",
22
+ "transformers==4.31.0",
23
+ "accelerate==0.21.0",
24
+ "bitsandbytes==0.41.0",
25
+ "scikit-learn==1.2.2",
26
+ "sentencepiece==0.1.99",
27
+ "einops==0.6.1", "einops-exts==0.0.4", "timm==0.6.13",
28
+ "gradio_client==0.2.9"
29
+ ]
30
+
31
+ [project.urls]
32
+ "Homepage" = "https://llava-vl.github.io"
33
+ "Bug Tracker" = "https://github.com/haotian-liu/LLaVA/issues"
34
+
35
+ [tool.setuptools.packages.find]
36
+ exclude = ["assets*", "benchmark*", "docs", "dist*", "playground*", "scripts*", "tests*"]
37
+
38
+ [tool.wheel]
39
+ exclude = ["assets*", "benchmark*", "docs", "dist*", "playground*", "scripts*", "tests*"]
approach/vlm/gpt4v/cu_gpt4v.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compatibility wrapper for the former CUHK-specific GPT-4V adapter."""
2
+
3
+ import os
4
+
5
+ from approach.vlm.gpt4v.gpt4v import (
6
+ encode_image,
7
+ generate_gpt4v_prompt,
8
+ get_steam_app_data,
9
+ process_image as _process_image,
10
+ process_image_q,
11
+ )
12
+
13
+
14
+ def process_image(image_question, image_path, ablation, key_idx=0):
15
+ profile = os.environ.get("ORIENT_MODEL_PROFILE", "default")
16
+ return _process_image(profile, image_question, image_path, ablation, key_idx)
17
+
18
+
19
+ __all__ = [
20
+ "encode_image",
21
+ "generate_gpt4v_prompt",
22
+ "get_steam_app_data",
23
+ "process_image",
24
+ "process_image_q",
25
+ ]
approach/vlm/gpt4v/gpt4v.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import mimetypes
4
+ import requests
5
+ import logging
6
+ from bs4 import BeautifulSoup
7
+ from approach.app_metadata import get_app_metadata, load_app_metadata_cache
8
+ from approach.config import get_model_profile
9
+ from approach.providers import EncodedImage, OpenAICompatibleChatClient
10
+
11
+ DEFAULT_PROFILE = os.environ.get("ORIENT_MODEL_PROFILE", "default")
12
+
13
+
14
+ def _app_metadata_from_cache(app_id, metadata_cache):
15
+ return get_app_metadata(app_id, metadata_cache)
16
+
17
+
18
+ def get_steam_app_data(app_id, image_name, metadata_cache=None):
19
+ if metadata_cache is not None:
20
+ return _app_metadata_from_cache(app_id, metadata_cache)
21
+
22
+ if app_id == '1718650':
23
+ app_name = 'Nuremberg: VRdict of Nations'
24
+ app_description = 'A VR investigation of the crimes against humanity committed by the Nazi leaders. This is a detective story in VR, a documentary investigation, brought to you by Rossiya Segodnya. Your goal is to find and collect evidence to prove that the key Nazi criminals and the leaders of the Third Reich are guilty. Today, less than 50% of young people are familiar with the historic Nuremberg trial, its process and results (according to a survey conducted by the “Nuremberg: Casus Pacis” project). The charges and verdicts brought forward by the Nuremberg tribunal, its fairness or even necessity are often questioned. This happens out of ignorance or under pressure from those who benefit from distorting the historical facts. Your virtual journey begins in the Spandau Prison dining area recreated from one of the legendary post-war photos. Here, you are met by serenely dining Nuremberg defendants – Göring, Dönitz, Rosenberg, von Ribbentrop and von Schirach. By touching each of them, you can travel back to these Nazi criminals’ past. Your task is to find evidence of their terrible crimes against humanity in – seemingly – an ordinary and peaceful environment. As you gather more pieces of evidence, you put together a convincing dossier, akin to those ones that the 1946 Nuremberg verdict was based on. Thus you will restore the historical truth.'
25
+ return app_name, app_description
26
+
27
+ url = f"https://store.steampowered.com/app/{app_id}"
28
+
29
+ # proxies = {
30
+ # "http": f"http://{proxy}",
31
+ # "https": f"http://{proxy}"
32
+ # }
33
+
34
+ headers = {
35
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
36
+ }
37
+
38
+ try:
39
+ response = requests.get(url, headers=headers, timeout=30)
40
+ response.raise_for_status()
41
+
42
+ soup = BeautifulSoup(response.content, "html.parser")
43
+
44
+ app_name = soup.find("div", {"id": "appHubAppName"}).get_text(strip=True)
45
+ short_desc = soup.find("div", class_="game_description_snippet").get_text(strip=True)
46
+ long_desc = soup.find("div", {"id": "game_area_description"}).get_text(strip=True)
47
+
48
+ return app_name, short_desc + " " + long_desc
49
+ except Exception as e:
50
+ # print(f"Error fetching app data for app_id {app_id} of image {image_name}. Error: {e}")
51
+ logging.error(f"Error fetching app data for app_id {app_id} of image {image_name}. Error: {e}")
52
+ return "", ""
53
+
54
+ # Function to encode the image
55
+ def encode_image(image_path):
56
+ with open(image_path, "rb") as image_file:
57
+ return base64.b64encode(image_file.read()).decode('utf-8')
58
+
59
+
60
+ def generate_gpt4v_prompt(app_name, app_description, image_question, ablation):
61
+ if ablation:
62
+ # ISSTA version
63
+ # return 'Describe the image.'
64
+
65
+ # ICSE 2025 version
66
+ return f'''
67
+ --- Context and Task ---
68
+ You are a virtual reality game player.
69
+ Currently, you are playing a game named {app_name} with the following description. Now in your field of view from the VR headset, you can see the VR scenario as the uploaded screenshot figure.
70
+ Please write referring expressions for all objects in the scenario.
71
+ For referring expressions, describe all characteristics from different perspectives that make the object distinguishable from other objects such as <size, color, shape and type>.
72
+ DO NOT MENTION LOCATION INFORMATION OR MENTION OTHER OBJECTS IN REFERRING EXPRESSIONS!\n
73
+
74
+ --- Instructions and Demonstrations ---
75
+ Ignore user-controlled VR device objects, e.g., controllers, hands and gloves, which are near the users in screenshot.\n
76
+
77
+ --- Output Format ---
78
+ Output in JSON format: {{"objects": {{"here_is_object_name": referring_expression_1, "here_is_object_name": referring_expression_2}}}}. NO DOT OUTPUT any other content besides JSON.\n
79
+
80
+ --- App Description Information ---
81
+ The description of the app:
82
+ {app_description}.
83
+ '''
84
+ elif not ablation:
85
+ # ISSTA 2024 version
86
+ # return f'''
87
+ # You are a virtual reality game player. Currently, you are playing a game named {app_name} with the following description and get the screenshot I uploaded. Please describe all objects in the screenshot.
88
+
89
+ # The description of the app:
90
+ # {app_description}.
91
+ # '''
92
+
93
+ # ICSE 2025 version
94
+ return f'''
95
+ --- Context and Task ---
96
+ You are a virtual reality game player.
97
+ Currently, you are playing a game named {app_name} with the following description. Now in your field of view from the VR headset, you can see the VR scenario as the uploaded screenshot figure.
98
+ Please: (1) identify all user-interactable objects in this screenshot, with which you can use VR devices like handheld controllers to interact; and (2) write referring expressions for user-interactable objects.
99
+ For referring expressions, describe all characteristics from different perspectives that make the object distinguishable from other objects such as <size, color, shape and type>.
100
+ DO NOT MENTION LOCATION INFORMATION OR MENTION OTHER OBJECTS IN REFERRING EXPRESSIONS!\n
101
+
102
+ --- Instructions and Demonstrations ---
103
+ (1) For a tree object in a tree-planting game, the users need to pick up and plant the tree, thus the object is interactable.
104
+ (2) But for a tree object appeard in the background scenery of a fishing-only game, the object is highly likely non-interactable.
105
+ (3) Ignore user-controlled VR device objects, e.g., controllers, hands and gloves, which are near the users in screenshot.\n
106
+
107
+ --- Output Format ---
108
+ Output in JSON format: {{"objects": {{"here_is_object_name": referring_expression_1, "here_is_object_name": referring_expression_2}}}}. NO DOT OUTPUT any other content besides JSON.\n
109
+
110
+ --- App Description Information ---
111
+ The description of the app:
112
+ {app_description}.
113
+ '''
114
+
115
+ def process_image_q(image_question, image_path, key_idx, metadata_cache=None):
116
+ # time.sleep(2)
117
+ app_id = image_path.split('/')[-1].split("_")[0]
118
+ # print(app_id)
119
+ app_name, app_description = get_steam_app_data(app_id, image_path, metadata_cache)
120
+
121
+ gpt4v_prompt = generate_gpt4v_prompt(app_name, app_description, image_question, True)
122
+
123
+ return gpt4v_prompt
124
+
125
+
126
+
127
+ def process_image(vlm, image_question, image_path, ablation, key_idx, metadata_cache=None):
128
+ app_id = image_path.split('/')[-1].split("_")[0]
129
+ # print(app_id)
130
+ app_name, app_description = get_steam_app_data(app_id, image_path, metadata_cache)
131
+
132
+ # Getting the base64 string
133
+ base64_image = encode_image(image_path)
134
+
135
+ gpt4v_prompt = generate_gpt4v_prompt(app_name, app_description, image_question, ablation)
136
+ # gpt4v_prompt = image_question
137
+
138
+ try:
139
+ profile = get_model_profile(vlm or DEFAULT_PROFILE)
140
+ media_type = mimetypes.guess_type(image_path)[0] or "image/jpeg"
141
+ client = OpenAICompatibleChatClient(profile)
142
+ return client.complete_json(
143
+ gpt4v_prompt,
144
+ [EncodedImage(base64_image, media_type)],
145
+ )
146
+ except Exception as e:
147
+ logging.error(f"Error generating completion for image {image_path}. Error: {e}")
148
+ return ''
configs/model_profiles.yaml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ profiles:
2
+ default:
3
+ provider: openrouter
4
+ model: openai/gpt-5.6-sol
5
+ base_url: https://openrouter.ai/api/v1
6
+ api_key_env: OPENROUTER_API_KEY
7
+ best_value:
8
+ provider: openrouter
9
+ model: openai/gpt-5.6-terra
10
+ base_url: https://openrouter.ai/api/v1
11
+ api_key_env: OPENROUTER_API_KEY
12
+ paper_openai:
13
+ provider: openrouter
14
+ model: openai/gpt-4o-2024-08-06
15
+ base_url: https://openrouter.ai/api/v1
16
+ api_key_env: OPENROUTER_API_KEY
17
+ paper_claude:
18
+ provider: openrouter
19
+ model: anthropic/claude-3.5-sonnet
20
+ base_url: https://openrouter.ai/api/v1
21
+ api_key_env: OPENROUTER_API_KEY
22
+ paper_gemini:
23
+ provider: openrouter
24
+ model: google/gemini-pro-1.5
25
+ base_url: https://openrouter.ai/api/v1
26
+ api_key_env: OPENROUTER_API_KEY
27
+ fastuse_experimental:
28
+ provider: openrouter
29
+ model: google/gemini-3.1-pro-preview
30
+ base_url: https://openrouter.ai/api/v1
31
+ api_key_env: OPENROUTER_API_KEY
dataset/statistics/app_genre.csv ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ id,genre
2
+ 1026760,Casual
3
+ 1033960,Casual
4
+ 1063530,Adventure
5
+ 1113370,Action
6
+ 1150310,Sports
7
+ 1157070,Casual
8
+ 1172280,Casual
9
+ 1178780,Strategy
10
+ 1210650,Adventure
11
+ 1217930,Indie
12
+ 1245640,Adventure
13
+ 1248270,Adventure
14
+ 1250210,Action
15
+ 1264160,Simulation
16
+ 1269890,Action
17
+ 1270910,Simulation
18
+ 1295570,Indie
19
+ 1298890,Adventure
20
+ 1334900,Indie
21
+ 1337060,Education
22
+ 1337530,Adventure
23
+ 1382350,Adventure
24
+ 1388030,Sports
25
+ 1394210,Action
26
+ 1394410,Action
27
+ 1404360,Adventure
28
+ 1453730,Casual
29
+ 1456280,Action
30
+ 1480650,Adventure
31
+ 1481400,Adventure
32
+ 1485260,Casual
33
+ 1486660,Adventure
34
+ 1488730,Sports
35
+ 1512840,Simulation
36
+ 1550280,Action
37
+ 1561560,Casual
38
+ 1595490,Action
39
+ 1601810,Adventure
40
+ 1612820,Casual
41
+ 1652800,Indie
42
+ 1676620,Adventure
43
+ 1695870,Indie
44
+ 1705030,Action
45
+ 1707840,Casual
46
+ 1730290,Simulation
47
+ 1801560,Action
48
+ 1805510,Simulation
49
+ 1825460,Simulation
50
+ 1862180,Simulation
51
+ 1906880,Action
52
+ 1931980,Indie
53
+ 1960620,Strategy
54
+ 2020950,Indie
55
+ 2025000,Simulation
56
+ 2057000,Simulation
57
+ 2077870,Action
58
+ 2089520,RPG
59
+ 2163140,Adventure
60
+ 2193270,Adventure
61
+ 2224020,Simulation
62
+ 2293180,Action
63
+ 2308940,Strategy
64
+ 269170,Sports
65
+ 343740,Indie
66
+ 438100,Massively Multiplayer
67
+ 451980,Simulation
68
+ 457380,Indie
69
+ 457550,Simulation
70
+ 463290,Casual
71
+ 490250,Simulation
72
+ 497820,Simulation
73
+ 513490,Indie
74
+ 518580,Indie
75
+ 528580,Adventure
76
+ 529150,Strategy
77
+ 533970,Design & Illustration
78
+ 591680,Simulation
79
+ 600140,Strategy
80
+ 605850,Casual
81
+ 622310,Casual
82
+ 631660,Strategy
83
+ 660520,Action
84
+ 667010,Action
85
+ 714100,Animation & Modeling
86
+ 716260,Action
87
+ 720300,Adventure
88
+ 726910,Casual
89
+ 731790,Simulation
90
+ 758210,Simulation
91
+ 790750,Action
92
+ 812460,Indie
93
+ 815280,Action
94
+ 866540,Adventure
95
+ 891960,Simulation
96
+ 898080,Indie
97
+ 910190,Action
98
+ 954160,Indie
99
+ 982710,Indie
100
+ 997760,Sports
101
+ 998660,Simulation
dataset/statistics/app_tag.csv ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ id,tag
2
+ 1026760,Casual;VR;Immersive;Nature;Cinematic;Free to Play;Early Access;Colorful;3D;360 Video;Experimental;Singleplayer
3
+ 1033960,Casual;VR;Time Management;Funny;Family Friendly;Dog
4
+ 1063530,Adventure;Action;Indie;Casual;RPG;VR;Free to Play
5
+ 1113370,Action;Free to Play;Indie;Casual;Sports;VR;Sci-fi;Real-Time;Stylized;Futuristic;Competitive
6
+ 1150310,VR;3D Platformer;Skiing;Sports;Racing;Runner;Immersive Sim;Arcade;Walking Simulator;First-Person;3D;Cute;Time Manipulation;Casual;Cartoony;Colorful;Family Friendly;6DOF;Atmospheric;Nature
7
+ 1157070,Casual;Indie;VR;Puzzle;First-Person;Family Friendly;Relaxing;Singleplayer;Atmospheric;Solitaire;Physics;Tabletop
8
+ 1172280,Automobile Sim;VR;Experience;Cinematic;Psychedelic;Minimalist;6DOF;Transportation;Psychological Horror;Abstract;Comedy;Experimental;Atmospheric;Surreal;Horror;Casual;Singleplayer;Immersive Sim;Simulation;Indie
9
+ 1178780,Space Sim;Space;VR;Multiplayer;Co-op;Sci-fi;First-Person;RTS;Strategy;Singleplayer;Simulation;Real Time Tactics;PvP;Tactical;Action;War;Real-Time;Local Co-Op;Bullet Time;Real-Time with Pause
10
+ 1210650,Adventure;Free to Play;Indie;VR;Singleplayer;Escape Room
11
+ 1217930,VR;Flight;Multiplayer;Shooter;Simulation;Space Sim;FPS;Battle Royale;Action;Adventure;Massively Multiplayer;Indie;Early Access;Fantasy;Twin Stick Shooter;Futuristic;Robots;Sci-fi;Space;Surreal
12
+ 1245640,Interactive Fiction;VR;Story Rich;Narrative;6DOF;Historical;Education;Emotional;Documentary;First-Person;3D;Cinematic;Linear;Narration;Singleplayer;Feature Film;Adventure;Colorful;Casual;Exploration
13
+ 1248270,VR;Free to Play;Exploration;Interactive Fiction;Experience;Singleplayer;Casual;Surreal;Magic;Medieval;Adventure
14
+ 1250210,Indie;Action;Massively Multiplayer;Gore;Violent;Early Access;VR;Looter Shooter
15
+ 1264160,Immersive Sim;Simulation;Anime;Experience;VR;Comic Book;Cute;Dating Sim;Crowdfunded;FMV;Singleplayer;Realistic;Casual;Atmospheric;Drama;Conversation;Story Rich;Romance;Sexual Content;Funny
16
+ 1269890,Education;Arcade;Casual;Free to Play;On-Rails Shooter;Hack and Slash;VR;Action;Singleplayer;Indie;Strategy;RPG;Great Soundtrack
17
+ 1270910,Free to Play;Indie;Casual;Simulation;Villain Protagonist;Singleplayer
18
+ 1295570,Indie;VR;Story Rich;Atmospheric;Emotional
19
+ 1298890,Casual;Exploration;Walking Simulator;VR;Story Rich;Surreal;Atmospheric;Psychological;Adventure;Singleplayer;Narrative;Indie;Mystery
20
+ 1334900,Casual;Action;Arcade;VR;Parody;Hack and Slash;Level Editor;Singleplayer;6DOF;Gore;Violent;Indie
21
+ 1337060,Education;Science
22
+ 1337530,VR;Adventure;Puzzle;Stylized;Open World;Silent Protagonist;Nonlinear;Interactive Fiction;Story Rich;Fantasy;Indie;Narration;Physics;Atmospheric;Singleplayer;Cinematic;Exploration;6DOF;3D;First-Person
23
+ 1382350,Adventure;VR;Detective;Puzzle;Strategy;Singleplayer;Mystery;Investigation;Time Travel;Atmospheric;Interactive Fiction;First-Person;Indie;Dark;Supernatural;6DOF;Story Rich
24
+ 1388030,Sports;VR;PvP;Realistic;Competitive;Simulation;Physics;Turn-Based Tactics;Casual;Real Time Tactics;3D;Real-Time;Arcade;Funny;Action-Adventure;Multiplayer;Singleplayer;First-Person;Arena Shooter;Grand Strategy
25
+ 1394210,Action;VR;Arcade;Shooter;Shoot 'Em Up;Bullet Hell;3D;Aliens;Fantasy;Futuristic;Jet;Mechs;Robots;Sci-fi;Space;Bullet Time;Combat;Flight;PvE;Score Attack
26
+ 1394410,Action;VR;Magic;Swordplay;Fighting;PvP;Futuristic;Combat;PvE;Singleplayer;Multiplayer;Spectacle fighter;Sci-fi
27
+ 1404360,Casual;VR;Hidden Object;Investigation;Exploration;Collectathon;Cute;Relaxing;Atmospheric;Puzzle;Fantasy;Conversation;Narration;Family Friendly;Nature;Singleplayer;6DOF;Indie;Adventure;Free to Play
28
+ 1453730,Casual;Relaxing;Atmospheric;Experimental;Colorful;Psychedelic;Abstract;VR;Space;Free to Play;Family Friendly;Ambient;Early Access;3D;6DOF;Exploration;Education;Singleplayer
29
+ 1456280,Action;Fighting;Shooter;3D Fighter;Arena Shooter;VR;Flight;First-Person;Aliens;Cyberpunk;Post-apocalyptic;Sci-fi;PvP;Artificial Intelligence;Multiplayer;Singleplayer
30
+ 1480650,Adventure;Action-Adventure;Puzzle;VR;First-Person;Tactical;Snow;Choices Matter;Quick-Time Events;Action;Real Time Tactics;Magic;Fantasy;Survival;Lore-Rich;Arcade;Crafting;Physics;Superhero;Time Manipulation
31
+ 1481400,Horror;Lovecraftian;Atmospheric;Visual Novel;First-Person;Story Rich;Psychological Horror;Dark;Narration;Choose Your Own Adventure;VR;Adventure;Interactive Fiction;Point & Click;Mystery;Indie;Walking Simulator;Text-Based;Realistic;Emotional
32
+ 1485260,Relaxing;Casual;Abstract;Psychedelic;Experimental;Cinematic;3D Vision;Exploration;3D;Stylized;6DOF;Procedural Generation;Singleplayer;VR
33
+ 1486660,Casual;VR;Action;Dragons;Puzzle;Adventure;Exploration;Arcade;Walking Simulator;Education;3D;First-Person;Realistic;Dinosaurs;Logic;3D Vision;Narration;Action-Adventure;Singleplayer;Flight
34
+ 1488730,Casual;Simulation;Sports;eSports;Arcade;Immersive Sim;Grand Strategy;3D;VR;Real Time Tactics;Family Friendly;Nature;Physics;Singleplayer
35
+ 1512840,Casual;Simulation;Photo Editing;Design & Illustration;Utilities;VR;Experience;Walking Simulator
36
+ 1550280,VR;Atmospheric;Casual;Building;LEGO;Simulation;Interactive Fiction;Abstract;Family Friendly;Life Sim;Immersive Sim;Magic;Colorful;Physics;Cute;Sandbox;First-Person;Utilities;Moddable;Space
37
+ 1561560,Free to Play;VR;Singleplayer;Time Management;Puzzle;Sandbox;Physics;Casual;Management;Artificial Intelligence;Early Access;Simulation;Life Sim;Arcade;First-Person;Medieval;3D;Cute;Lovecraftian;Cartoony
38
+ 1595490,Action Roguelike;VR;Roguelite;Sailing;Perma Death;Arcade;Roguelike;First-Person;3D;Action;Post-apocalyptic;Casual;Cartoony;Dystopian;Management;6DOF;Artificial Intelligence;Resource Management;Singleplayer;Free to Play
39
+ 1601810,Adventure;Nature;VR
40
+ 1612820,Casual;VR;Funny;Cartoony;Hand-drawn;Arcade;Stylized;Free to Play;Singleplayer
41
+ 1652800,Puzzle;Casual;Female Protagonist;3D;First-Person;VR;Linear;Sci-fi;Indie;Science;Singleplayer
42
+ 1676620,Adventure;Education;Action-Adventure;Medical Sim;3D;VR;6DOF;Free to Play;Singleplayer
43
+ 1695870,Free to Play;VR;Walking Simulator;Singleplayer;Atmospheric;Surreal;Short;Colorful;Immersive;Linear;Stylized;Magic;6DOF;First-Person;Mystery;Relaxing;Exploration;Funny;Adventure;Indie
44
+ 1705030,Shooter;Sandbox;Platformer;VR;Multiplayer;Action;Parkour;eSports;Physics;PvP;Arena Shooter;Bullet Hell;FPS;3D;First-Person;Sports;Character Customization;Adventure;3D Platformer;Cartoony
45
+ 1707840,Casual;Strategy;Puzzle;Shooter;Match 3;VR;Cartoony;Colorful;Atmospheric;Nature;Relaxing;6DOF;Choices Matter;Singleplayer
46
+ 1730290,Casual;Simulation;Arcade;Tabletop;Visual Novel;VR;3D;Abstract;Artificial Intelligence;Free to Play;Sci-fi;Singleplayer
47
+ 1801560,Action;Shooter;Rhythm;Shoot 'Em Up;FPS;Bullet Hell;3D;Realistic;Destruction;Singleplayer;VR
48
+ 1805510,Action;Simulation;Action-Adventure;Life Sim;Exploration;Immersive Sim;3D;VR;America;Building;Capitalism;Comedy;Story Rich;Trading;Controller;Resource Management;Singleplayer;Indie;Arcade;Dark Humor
49
+ 1825460,Simulation;Education;VR;Immersive Sim;3D;Crafting;Realistic;Singleplayer;Hardware
50
+ 1862180,Simulation;VR;Space;Immersive Sim;Exploration;Education;Science;Realistic;Sci-fi;Physics;3D;Artificial Intelligence;Atmospheric;Space Sim;Open World;Singleplayer;Difficult;Early Access;Immersive;Golf
51
+ 1906880,Casual;Action;VR;Combat;Action-Adventure;First-Person;3D Platformer;FPS;Singleplayer;Hack and Slash;Free to Play;RPG;Indie;3D;War;Martial Arts;Atmospheric;PvE
52
+ 1931980,Escape Room;Local Co-Op;VR;Hand-drawn;Investigation;Co-op;Puzzle;Indie;Strategy
53
+ 1960620,Strategy;VR;Psychological Horror;Chess;Board Game;Tabletop;Singleplayer;Hentai
54
+ 2020950,VR;Emotional;6DOF;Immersive;Colorful;Cinematic;Atmospheric;Story Rich;Electronic Music;Visual Novel;Design & Illustration;Stylized;3D;Audio Production;Singleplayer;Drama;Abstract;First-Person;Casual;Linear
55
+ 2025000,VR;Arcade;Simulation;Roguelite;Funny;Management;Job Simulator;Perma Death;Psychedelic;Time Management;Immersive Sim;3D;Cooking;Casual;Physics;Action;Colorful;Indie;Nature;Singleplayer
56
+ 2057000,Casual;Simulation;Software;Puzzle;Utilities;Word Game;Immersive Sim;3D;3D Vision;Colorful;VR;First-Person;Education;Foreign;6DOF;Conversation;Open World;PvE;Singleplayer;Early Access
57
+ 2077870,Action;Adventure;Simulation;Strategy;Arcade;VR;First-Person;Atmospheric;PvE;Singleplayer;Choices Matter;Dark Humor;Free to Play;FPS;Funny;Futuristic;Memes;Sequel;Shoot 'Em Up;Multiple Endings
58
+ 2089520,VR;Massively Multiplayer;Anime;Multiplayer;Funny;3D Platformer;MMORPG;First-Person;Open World;6DOF;Nature;3D;Stylized;Atmospheric;Drama;Story Rich;Cartoon;Co-op;PvP;RPG
59
+ 2163140,VR;Puzzle;Singleplayer;Escape Room;Detective;Adventure;Investigation;Historical;Trains;Mystery;Walking Simulator;Exploration;Surreal;Stylized;Interactive Fiction;Hidden Object;Immersive Sim;Colorful;6DOF;Indie
60
+ 2193270,Adventure;VR;Historical;Sailing;Casual;Education;Visual Novel;Action-Adventure;Exploration;Immersive Sim;Colorful;First-Person;Stylized;Atmospheric;Diplomacy;Drama;Family Friendly;Political;Choices Matter;Linear
61
+ 2224020,Simulation;VR;Life Sim;Immersive Sim;Realistic;Singleplayer;Historical;Atmospheric;Free to Play;3D;Nudity;Walking Simulator;Nonlinear
62
+ 2293180,VR;Experimental;Shoot 'Em Up;Singleplayer;Action;Arcade;RPG;Shooter;Zombies;FPS;Combat;Physics;Free to Play;PvE
63
+ 2308940,VR;Building;Education;Strategy;LEGO;First-Person;Controller;Simulation;Arcade;Turn-Based Strategy;FPS;Real Time Tactics;Time Management;Colorful;Family Friendly;Logic;Modern;Tactical;6DOF;Base Building
64
+ 269170,VR;Snooker;Sports;Simulation;Casual;Pool;Indie;Local Multiplayer;Strategy;Physics;Multiplayer;Addictive
65
+ 343740,VR;Free to Play;Indie;Action;Education;Casual;Sci-fi;Singleplayer;Science;Exploration;3D Vision;Dynamic Narration;Funny;Comedy;Racing;Physics;Simulation;Space
66
+ 438100,VR;Free to Play;Multiplayer;Memes;Anime;Funny;Massively Multiplayer;First-Person;Early Access;Open World;Simulation;Casual;Adventure;MMORPG;Comedy;Sandbox;Action;Dating Sim;Survival Horror;Atmospheric
67
+ 451980,Simulation;Casual;VR;Education;Great Soundtrack;Exploration;First-Person;Physics;Free to Play;Indie;Atmospheric
68
+ 457380,Adventure;Simulation;Indie;Casual;VR;Episodic;Survival
69
+ 457550,VR;Free to Play;Software;Open World;Utilities;Split Screen;Multiplayer;3D;Movie;First-Person;Choose Your Own Adventure;Casual;Cinematic;Exploration;Simulation;Futuristic;Nature;Relaxing;Sci-fi;Conversation
70
+ 463290,VR;Indie;Casual;Immersive;Atmospheric
71
+ 490250,Simulation;Indie;Casual;Free to Play;VR;Trains;Relaxing;On-Rails Shooter
72
+ 497820,Free to Play;VR;Cyberpunk
73
+ 513490,Indie;VR;Historical;Free to Play;Education;World War II
74
+ 518580,Indie;VR;Adventure;Comedy;Free to Play;Dark Humor;Horror;Funny;Singleplayer
75
+ 528580,Adventure;Free to Play;VR;Early Access;Indie;Casual;Fantasy;Cinematic;First-Person;Dragons;Interactive Fiction;Experimental
76
+ 529150,Strategy;Indie;VR;Arcade;RTS;Free to Play
77
+ 533970,Design & Illustration;Free to Play;VR;Animation & Modeling
78
+ 591680,Simulation;Indie;VR;Physics;Casual;Funny;Addictive;Free to Play;Arcade;Management;FPS;Cartoony;3D;Colorful;Comedy;Dark Humor;Education;Relaxing;Score Attack;Singleplayer
79
+ 600140,Free to Play;VR;Strategy;Casual;Indie;Action;Puzzle;Gore;Violent;Escape Room;Sexual Content
80
+ 605850,Indie;Casual;VR;Pinball
81
+ 622310,Strategy;Free to Play;Massively Multiplayer;Casual;Simulation;VR
82
+ 631660,Free to Play;Strategy;Casual;Sports;Tabletop;VR;Chess
83
+ 660520,Simulation;Free to Play;Action;Indie;VR;Mechs;Robots
84
+ 667010,Action;Indie;Casual;Violent;VR;Cartoony;Dark Comedy;Zombies;Post-apocalyptic;Survival Horror;Vampire;Funny;First-Person;Comedy;Shooter;Blood;Dark Humor;Horror;Sports;1980s
85
+ 714100,Animation & Modeling;VR;Anime;Sexual Content;Nudity
86
+ 716260,Free to Play;Adventure;Action;Indie;VR;Shooter;Western
87
+ 720300,Indie;Adventure;Free to Play;VR;Short;Singleplayer;Sci-fi;Atmospheric;Futuristic;Puzzle;Space;Great Soundtrack;Relaxing;Beautiful;Experimental
88
+ 726910,Free to Play;VR;Robots;Adventure;Sci-fi;Casual;Short;First-Person;Multiplayer;Singleplayer;Survival;Strategy;Action;Atmospheric;Open World;Indie;Interactive Fiction;Immersive Sim;Local Multiplayer;Nudity
89
+ 731790,Casual;Simulation;VR;Indie;Competitive;Atmospheric;Singleplayer;Violent;Difficult;Horror;Fast-Paced;First-Person;Funny;War;Action;Tactical;Comedy;Replay Value;Colorful;Arcade
90
+ 758210,Adventure;Early Access;Simulation;VR;Escape Room
91
+ 790750,Arena Shooter;Hero Shooter;FPS;Archery;PvP;Competitive;Shooter;Arcade;Character Customization;Silent Protagonist;First-Person;VR;Action;Casual;Dystopian;Robots;Co-op;Multiplayer;Online Co-Op;Singleplayer
92
+ 812460,Indie;Casual;Simulation;World War II;Historical;VR
93
+ 815280,Strategy;Action;Indie;Early Access;VR;Pirates
94
+ 866540,Free to Play;Adventure;Indie;RPG;VR;Short;Funny;Sci-fi;Physics;Space;Singleplayer;Story Rich;Atmospheric;Comedy;First-Person;Robots
95
+ 891960,Free to Play;Casual;Simulation;VR;Space Sim;Space;Exploration;Physics
96
+ 898080,Indie;Sexual Content;VR;Free to Play;Psychological Horror
97
+ 910190,Free to Play;Indie;Action;VR;Sci-fi;FPS;Aliens;Space;Arcade
98
+ 954160,Free to Play;Indie;VR
99
+ 982710,Free to Play;Indie;VR;Local Multiplayer;Local Co-Op;Minigames;Villain Protagonist
100
+ 997760,Sports;VR;Arcade;Baseball
101
+ 998660,Free to Play;Early Access;VR;Action;Simulation;Casual;Flight;Multiplayer
dataset/statistics/plot.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import pandas as pd
3
+ from collections import defaultdict
4
+ from matplotlib import pyplot as plt
5
+ import numpy as np
6
+
7
+ SPLIT_GENRE = {
8
+ "TRAIN": [
9
+ "Casual",
10
+ "Adventure",
11
+ "Action",
12
+ "Indie"
13
+ ],
14
+ "VAL": [
15
+ "Strategy",
16
+ "Education",
17
+ "RPG",
18
+ "Massively Multiplayer",
19
+ "Design & Illustration",
20
+ "Animation & Modeling"
21
+ ],
22
+ "TEST": [
23
+ "Simulation",
24
+ "Sports"
25
+ ]
26
+ }
27
+
28
+
29
+ def parse_img_id(img_id):
30
+ img_id = str(img_id)
31
+ return int(img_id[:-3]), int(img_id[-3:])
32
+
33
+
34
+ def plot(data, img_name, is_genre=False):
35
+ plt.rcParams.update({'font.size': 18})
36
+ colors = []
37
+ for cat in data.keys():
38
+ if cat in SPLIT_GENRE['TRAIN']:
39
+ colors.append('tab:blue')
40
+ elif cat in SPLIT_GENRE['VAL']:
41
+ colors.append('tab:orange')
42
+ elif cat in SPLIT_GENRE['TEST']:
43
+ colors.append('tab:green')
44
+ else:
45
+ colors.append('gray')
46
+
47
+
48
+ if is_genre:
49
+ plt.figure(figsize=(10, 6))
50
+ plt.grid(True, axis='y', zorder=0)
51
+ plt.bar(data.keys(), data.values(), color=colors, zorder=3)
52
+ plt.xticks(rotation=30, ha='right')
53
+ plt.legend(handles=[
54
+ plt.Line2D([0], [0], color='tab:blue', lw=10, label='Train'),
55
+ plt.Line2D([0], [0], color='tab:orange', lw=10, label='Val'),
56
+ plt.Line2D([0], [0], color='tab:green', lw=10, label='Test'),
57
+ ])
58
+ else:
59
+ plt.figure(figsize=(15, 6))
60
+ plt.grid(True, axis='y', zorder=0)
61
+ plt.bar(data.keys(), data.values(), zorder=3)
62
+ plt.xticks(rotation=45, ha='right')
63
+ plt.gca().yaxis.set_major_locator(plt.MaxNLocator(integer=True))
64
+ for i, v in enumerate(data.values()):
65
+ plt.text(i, v, str(v), ha='center', va='bottom')
66
+ y_max = max(data.values())
67
+ plt.ylim(0, 1.1 * y_max)
68
+
69
+ plt.tight_layout()
70
+ plt.savefig(img_name + '.png')
71
+ plt.savefig(img_name + '.pdf')
72
+
73
+
74
+ def plot_genre():
75
+
76
+ df = pd.read_csv('app_genre.csv')
77
+ with open('../data/coco_merged/annotations/semantics.json', 'r') as f:
78
+ dataset = json.load(f)
79
+
80
+ app_img_map = {}
81
+
82
+ for img in dataset['images']:
83
+ img_id = img['id']
84
+ app_id, _ = parse_img_id(img['id'])
85
+ if app_id not in app_img_map:
86
+ app_img_map[app_id] = []
87
+ app_img_map[app_id].append(img_id)
88
+
89
+ gnr_app_map = defaultdict(list)
90
+
91
+ for i in range(len(df)):
92
+ app_id = df['id'][i]
93
+ tags = df['genre'][i].split(';')
94
+ for tag in tags:
95
+ gnr_app_map[tag].append(int(app_id))
96
+
97
+
98
+ gnr_app_count = {cat: len(apps) for cat, apps in gnr_app_map.items()}
99
+ gnr_img_count = {cat: sum([len(app_img_map[app]) for app in apps]) for cat, apps in gnr_app_map.items()}
100
+ gnr_anno_count = {cat: sum([len([anno for anno in dataset['annotations'] if anno['image_id'] in app_img_map[app]]) for app in apps]) for cat, apps in gnr_app_map.items()}
101
+
102
+ split_genre_order = {genre: i for i, genre in enumerate(SPLIT_GENRE['TRAIN'] + SPLIT_GENRE['VAL'] + SPLIT_GENRE['TEST'])}
103
+ gnr_app_count = {cat: gnr_app_count[cat] for cat in sorted(gnr_app_count, key=lambda x: split_genre_order.get(x, float('inf')))}
104
+ gnr_img_count = {cat: gnr_img_count[cat] for cat in sorted(gnr_img_count, key=lambda x: split_genre_order.get(x, float('inf')))}
105
+ gnr_anno_count = {cat: gnr_anno_count[cat] for cat in sorted(gnr_anno_count, key=lambda x: split_genre_order.get(x, float('inf')))}
106
+
107
+
108
+ plot(gnr_app_count, 'genre_app_count', is_genre=True)
109
+ plot(gnr_img_count, 'genre_img_count', is_genre=True)
110
+ plot(gnr_anno_count, 'genre_anno_count', is_genre=True)
111
+
112
+
113
+ def plot_cat():
114
+
115
+ df = pd.read_csv('app_tag.csv')
116
+ with open('../data/coco_merged/annotations/semantics.json', 'r') as f:
117
+ dataset = json.load(f)
118
+
119
+ app_img_map = {}
120
+
121
+ for img in dataset['images']:
122
+ img_id = img['id']
123
+ app_id, _ = parse_img_id(img['id'])
124
+ if app_id not in app_img_map:
125
+ app_img_map[app_id] = []
126
+ app_img_map[app_id].append(img_id)
127
+
128
+ cat_app_map = defaultdict(list)
129
+
130
+ for i in range(len(df)):
131
+ app_id = df['id'][i]
132
+ tags = df['tag'][i].split(';')
133
+ for tag in tags:
134
+ cat_app_map[tag].append(int(app_id))
135
+
136
+ cat_app_map.pop('VR')
137
+
138
+ cat_app_count = {cat: len(apps) for cat, apps in cat_app_map.items()}
139
+ cat_img_count = {cat: sum([len(app_img_map[app]) for app in apps]) for cat, apps in cat_app_map.items()}
140
+ cat_anno_count = {cat: sum([len([anno for anno in dataset['annotations'] if anno['image_id'] in app_img_map[app]]) for app in apps]) for cat, apps in cat_app_map.items()}
141
+
142
+ cat_app_count = {cat: count for cat, count in list(cat_app_count.items())[:30]}
143
+ cat_img_count = {cat: count for cat, count in list(cat_img_count.items())[:30]}
144
+ cat_anno_count = {cat: count for cat, count in list(cat_anno_count.items())[:30]}
145
+
146
+ cat_app_count = {cat: count for cat, count in sorted(cat_app_count.items(), key=lambda item: item[1], reverse=True)}
147
+ cat_img_count = {cat: count for cat, count in sorted(cat_img_count.items(), key=lambda item: item[1], reverse=True)}
148
+ cat_anno_count = {cat: count for cat, count in sorted(cat_anno_count.items(), key=lambda item: item[1], reverse=True)}
149
+
150
+ plot(cat_app_count, 'tag_app_count')
151
+ plot(cat_img_count, 'tag_img_count')
152
+ plot(cat_anno_count, 'tag_anno_count')
153
+
154
+
155
+ def plot_cat_anno():
156
+ with open('../data/coco_merged/annotations/semantics.json', 'r') as f:
157
+ dataset = json.load(f)
158
+
159
+ cat_catname_map = {}
160
+ for cat in dataset['categories']:
161
+ cat_catname_map[cat['id']] = cat['name']
162
+
163
+ cat_anno_map = defaultdict(list)
164
+ for anno in dataset['annotations']:
165
+ cat_anno_map[cat_catname_map[anno['category_id']]].append(anno)
166
+
167
+ print(len(cat_anno_map['button']))
168
+ cat_anno_map.pop('button')
169
+
170
+ cat_anno_count = {cat: len(annos) for cat, annos in cat_anno_map.items()}
171
+ cat_anno_count = {cat: count for cat, count in sorted(cat_anno_count.items(), key=lambda item: item[1], reverse=True)}
172
+ cat_anno_count = {cat: count for cat, count in list(cat_anno_count.items())[:30]}
173
+ plot(cat_anno_count, 'ige_cat_anno_count')
174
+
175
+
176
+
177
+ plot_genre()
178
+ plot_cat()
179
+ plot_cat_anno()
docs/ASSETS.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Required external assets
2
+
3
+ This public copy includes the APE-L\(_D\) checkpoint required by the main detector. It intentionally excludes generated artifacts, credential-bearing files, private data, historical experiment outputs, and full dataset image payloads.
4
+
5
+ ## Minimum smoke test
6
+
7
+ To validate one Orienter inference example, provide:
8
+
9
+ | Asset | Expected location or interface | Required metadata |
10
+ | --- | --- | --- |
11
+ | One representative XR screenshot | a test-only folder matching the question manifest | image license/permission and expected image ID |
12
+ | Matching question/context fixture | JSONL consumed by `approach/run_vlm.py`, generated by `scripts/generate_questions.py` when screenshots are available | selected prompt, provider, model ID, filename convention, and expected schema |
13
+ | App metadata cache | an external path supplied through `--app-metadata-cache` | `app_id`, app name, app description, source URL, version/date, license/permission |
14
+ | APE-L\(_D\) checkpoint | bundled at `approach/ovod/APE/ape_d_model_final.pth` | official source, Apache-2.0 license, SHA-256, and size recorded in `docs/MODEL_MANIFEST.md` |
15
+ | Built APE extension | local build/install under the target CUDA environment | generated from source after cloning; compiled artifacts are intentionally not redistributed |
16
+ | One supported provider credential | `openrouter-run` or an equivalent process-scoped secret manager | access to the selected OpenRouter model and an explicit spending limit |
17
+ | Expected prediction | private comparison fixture | expected candidate labels and approximate boxes |
18
+
19
+ Run `python -B scripts/verify_assets.py --repo-root .` to validate the bundled checkpoint size. Add `--hash-checkpoint` for SHA-256 verification. When screenshots and metadata are mounted, pass `--questions`, `--images-dir`, and `--app-metadata-cache` to check image naming, image ID consistency, and metadata coverage. Pass `--embedding-cache /path/to/embedding_dict.json` to hash the external semantic cache against `evaluation/cache_manifest.json` before an offline evaluation.
20
+
21
+ The default Stage 2 runner also verifies the released checkpoint hash before loading it. Loading any different PyTorch checkpoint requires the explicit `--trust-custom-checkpoint` flag and should be done only after independent provenance and checksum verification.
22
+
23
+ ## Full paper reproduction
24
+
25
+ Provide or publish all of the following as versioned assets:
26
+
27
+ 1. The 1,552-image XR UI screenshot payload and a canonical versioned annotation release. Selected COCO-format evaluation ground-truth splits are included in this repository, but must be tied to the public dataset version and license.
28
+ 2. App, genre, and context-sensitive split manifests, including the extra non-interactable context annotations.
29
+ 3. Steam/application metadata used for global context, preferably as a pinned JSON/JSONL cache that avoids live-page drift. The public runner fails closed on missing cache entries when `--app-metadata-cache` is supplied.
30
+ 4. The complete prompt templates, demonstration examples, and the random-selection/seed policy.
31
+ 5. Exact model identifiers and access paths for every Orienter variant evaluated in the paper. The code defaults to OpenRouter `openai/gpt-5.6-sol`; exact paper profiles are included for GPT-4o-2024-08-06, Claude 3.5 Sonnet, and Gemini 1.5 Pro. If a provider retires a historical route, supply equivalent access through a custom profile or direct vendor credentials and document the substitution.
32
+ 6. The bundled APE-L\(_D\) checkpoint identity, official source, revision, license, and checksum in `docs/MODEL_MANIFEST.md`.
33
+ 7. A working CUDA/PyTorch/Detectron2 APE environment with the APE native extension built locally from the released source tree.
34
+ 8. The reviewed `embedding-3` semantic cache identified by `evaluation/cache_manifest.json`. Mount it read-only and use offline mode for historical reproduction. Zhipu access is optional and should be enabled only to extend a separate cache copy when a new model produces an uncached category.
35
+ 9. Expected per-split metrics or prediction checksums for a deterministic regression check.
36
+ 10. Hardware, CUDA, PyTorch, Python, and package versions from the successful experiment environment. See `docs/ENVIRONMENT.md` for the current public build boundary.
37
+
38
+ ## Credential names found in code
39
+
40
+ The following names are referenced by the main or optional baseline paths:
41
+
42
+ - `OPENAI_API_KEY`
43
+ - `OPENROUTER_API_KEY`
44
+ - `GOOGLE_API_KEY`
45
+ - `ANTHROPIC_API_KEY`
46
+ - `ZHIPU_API_KEY`
47
+ - `ARK_API_KEY`
48
+ - `DASHSCOPE_API_KEY`
49
+ - `DEEPSEEK_API_KEY`
50
+ - `THEB_API_KEY`
51
+ - `INTERNVL_API_KEY`
52
+
53
+ Only `OPENROUTER_API_KEY` is needed for the recommended Orienter inference path; the other variables belong to optional evaluation or baseline code. Never send credentials through Git, issue trackers, logs, or README examples. Rotate any credential that has previously appeared in a file or experiment log.
54
+
55
+ Stage 1 sends full screenshots to the configured remote provider; reflection additionally sends crops and annotated scenes. Do not submit private or unauthorized screenshots. Review the provider's data-handling terms and keep generated candidates, predictions, traces, metadata caches, and error files outside the public repository because they can reveal source-image content or filenames.
56
+
57
+ ## Publication format
58
+
59
+ For each data/model asset, publish: human-readable name, stable URL, version/revision, SHA-256, license, expected local path, compressed/uncompressed size, and a minimal schema example. The bundled APE checkpoint should be published through Hugging Face/LFS-style large-file storage; keep private raw data and generated experiment outputs outside the public repository.
docs/ENVIRONMENT.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Environment and APE build
2
+
3
+ Orienter has two runtime layers. The lightweight manifest, provider, and evaluation utilities use the root `requirements.txt`. Stage 2 additionally needs PyTorch, CUDA, Detectron2, detrex, and the compiled `ape._C` extension.
4
+
5
+ ## Public starting point
6
+
7
+ Use Python 3.10 or later for the public environment. This is required by the current Pillow security release; the historical Python 3.9 environment is recorded below for provenance, not recommended for processing untrusted images.
8
+
9
+ For lightweight utilities:
10
+
11
+ ```bash
12
+ python -B -m venv .venv
13
+ source .venv/bin/activate
14
+ python -B -m pip install --upgrade pip
15
+ python -B -m pip install -r requirements.txt
16
+ ```
17
+
18
+ For the CUDA detector, `environment.reference.yml` is a compatibility starting point based on the verified experiment host, with Python and Pillow moved to currently supported public versions:
19
+
20
+ ```bash
21
+ conda env create -f environment.reference.yml
22
+ conda activate orienter-ape-reference
23
+ bash scripts/build_ape_extension.sh
24
+ ```
25
+
26
+ The environment file pins PyTorch 2.2.0 with CUDA 12.1 and the exact Detectron2 and detrex commits observed in the working server environment. It deliberately builds the vendored APE source after environment creation instead of redistributing a machine-specific binary. It is not a cross-platform lockfile or a security attestation for the older research stack. Audit the resolved environment on the publication host. The target machine needs a CUDA toolkit compatible with its PyTorch build, a supported C++ compiler, and enough memory/disk to compile the extension.
27
+
28
+ `scripts/build_ape_extension.sh` does not install or upgrade dependencies. It performs an editable build of the vendored APE source in the active environment, then runs the environment checker. Review the active environment before executing it.
29
+
30
+ ## Verify the runtime
31
+
32
+ From the repository root:
33
+
34
+ ```bash
35
+ python -B scripts/check_environment.py
36
+ python -B scripts/verify_assets.py --repo-root . --hash-checkpoint
37
+ python -B scripts/smoke_control_path.py
38
+ python scripts/run_tests.py
39
+ ```
40
+
41
+ The environment check fails if the detector dependency stack is unavailable. `--allow-no-cuda` relaxes only the CUDA-availability check, and `--skip-ape-extension` relaxes only the compiled `ape._C` check; both remain diagnostic flags and still require PyTorch, torchvision, Detectron2, and detrex. They do not turn this command into a checker for the lightweight root requirements, and they are not valid evidence for Stage 2 inference readiness.
42
+
43
+ After mounting screenshots and application metadata, validate their contracts before a live run:
44
+
45
+ ```bash
46
+ python -B scripts/verify_assets.py \
47
+ --repo-root . \
48
+ --questions /absolute/path/to/questions.jsonl \
49
+ --images-dir /absolute/path/to/images \
50
+ --app-metadata-cache /absolute/path/to/app_metadata.json
51
+ ```
52
+
53
+ To reproduce semantic evaluation offline, separately mount the frozen cache and verify its full SHA-256:
54
+
55
+ ```bash
56
+ python -B scripts/verify_assets.py \
57
+ --repo-root . \
58
+ --skip-checkpoint \
59
+ --embedding-cache /absolute/path/to/embedding_dict.json
60
+ ```
61
+
62
+ ## Verified historical server environment
63
+
64
+ The release checkpoint, one-image APE smoke test, and test suite were exercised in the historical server `conda` environment named `ape` with:
65
+
66
+ | Component | Observed version |
67
+ | --- | --- |
68
+ | Python | 3.9.18 |
69
+ | PyTorch | 2.2.0+cu121 |
70
+ | torchvision | 0.17.0+cu121 |
71
+ | CUDA runtime reported by PyTorch | 12.1 |
72
+ | CUDA toolkit (`nvcc`) | 12.2 |
73
+ | NVIDIA driver | 535.261.03 |
74
+ | GPU | NVIDIA A100-PCIE-40GB |
75
+ | GCC | 11.4.0 |
76
+ | Detectron2 | 0.6, commit `017abbfa5f2c2a2afa045200c2af9ccf2fc6227f` |
77
+ | detrex | 0.3.0, commit `776058ec229be37a5ff2a2b0bb54133bdd5da663` |
78
+ | transformers | 4.37.2 |
79
+ | NumPy | 1.22.4 |
80
+ | SciPy | 1.7.3 |
81
+ | Pillow | 10.2.0 |
82
+ | OpenCV Python | 4.9.0.80 |
83
+ | xformers | 0.0.24 |
84
+ | fairscale | 0.4.13 |
85
+ | lvis | 0.5.3 |
86
+
87
+ `torch.cuda.is_available()` returned `True`, and `ape._C` imported successfully when invoked from the Orienter repository root. Running Python from inside `approach/ovod/APE` before building the local extension can shadow the installed APE package with the unbuilt source tree; build first and run the public entrypoints from the Orienter root.
88
+
89
+ The historical environment includes an old Pillow version and is retained only as execution provenance. Do not use it for arbitrary or untrusted images. A fresh build of `environment.reference.yml` on the final Hugging Face target remains part of the release gate because compiled CUDA extensions are host-sensitive.
90
+
91
+ ## Files that must stay local
92
+
93
+ Do not commit compiled extensions, `build/`, `*.egg-info`, model caches, virtual/conda environments, logs, generated candidates or predictions, or configuration files containing credentials or private absolute paths. Re-run the release hygiene tests after every live validation.
docs/MODEL_MANIFEST.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model manifest
2
+
3
+ This public release bundles only the model file required by the main Orienter detector. Baseline training checkpoints, fold-specific weights, duplicate backups, and prior experiment outputs are excluded.
4
+
5
+ | File | Size | SHA-256 | Purpose | License |
6
+ | --- | ---: | --- | --- | --- |
7
+ | `approach/ovod/APE/ape_d_model_final.pth` | 5,956,547,279 bytes | `3548f41a3238148180e08fd4b16c71f4abc3ac3caf9c8434444462d1bdb7f965` | APE-L\(_D\) detector checkpoint used by Stage 2 grounding | Apache-2.0 |
8
+
9
+ Upstream source: [official `shenyunhang/APE` checkpoint](https://huggingface.co/shenyunhang/APE/blob/6ee15cf54c3930528ac49be165b45d5bcb1f4fd9/configs/LVISCOCOCOCOSTUFF_O365_OID_VGR_SA1B_REFCOCO_GQA_PhraseCut_Flickr30k/ape_deta/ape_deta_vitl_eva02_clip_vlf_lsj1024_cp_16x4_1080k_mdl_20230829_162438/model_final.pth), pinned at repository revision `6ee15cf54c3930528ac49be165b45d5bcb1f4fd9`. The official file reports the same SHA-256 and the upstream model repository declares Apache-2.0. The corresponding license text is retained at `approach/ovod/APE/LICENSE`.
10
+
11
+ The checkpoint uses PyTorch pickle serialization. Load it only through the pinned APE environment and treat replacement checkpoint files as executable untrusted input until independently verified.