Skip to content

Commit 9b6dcc3

Browse files
committed
reading metadata, populating comboboxes and auto completion
1 parent 0b12d43 commit 9b6dcc3

File tree

1 file changed

+122
-16
lines changed

1 file changed

+122
-16
lines changed

src/dataset_image_annotator/__main__.py

+122-16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import argparse
2+
import json
23
import sys
34
from pathlib import Path
4-
from typing import Sequence, Union
5+
from typing import Sequence, Union, Optional
56

67
import rawpy
7-
from PySide6.QtCore import QFile, QIODevice, QDir, QFileInfo, QModelIndex
8+
from PySide6.QtCore import QFile, QIODevice, QDir, QFileInfo, QModelIndex, Qt, QStringListModel
89
from PySide6.QtGui import QPixmap, QIcon
910
from PySide6.QtUiTools import QUiLoader
1011
from PySide6.QtWidgets import (
11-
QApplication, QGraphicsScene, QFileDialog, QFileSystemModel, QListView, QFileIconProvider
12+
QApplication, QGraphicsScene, QFileDialog, QFileSystemModel, QListView, QFileIconProvider, QCompleter
1213
)
1314

1415

@@ -22,15 +23,45 @@ def get_parsed_args():
2223
return args
2324

2425

25-
def list_dir_images(path: Path) -> Sequence[Path]:
26+
def list_dir(path: Path, mask: str) -> Sequence[Path]:
2627
if path.is_dir():
27-
files = sorted(path.glob('*.ARW'))
28+
files = sorted(path.glob(mask))
2829
else:
2930
raise FileNotFoundError('Path must be directory')
3031

3132
return files
3233

3334

35+
def list_dir_images(path: Path) -> Sequence[Path]:
36+
return list_dir(path, '*.ARW')
37+
38+
39+
def list_dir_metadata(path: Path) -> Optional[Sequence[Path]]:
40+
metadata_dir_path = Path(path, '.metadata')
41+
42+
if metadata_dir_path.exists():
43+
return list_dir(metadata_dir_path, '*.json')
44+
45+
return None
46+
47+
48+
def load_metadata(data_root_path: Path):
49+
metadata_files = list_dir_metadata(data_root_path)
50+
51+
if not metadata_files:
52+
return
53+
54+
metadata = {}
55+
56+
for metadata_file in metadata_files:
57+
try:
58+
with open(metadata_file, 'r') as f:
59+
metadata[metadata_file.name.lower()] = json.load(f)
60+
except FileNotFoundError:
61+
pass
62+
63+
return metadata
64+
3465
def get_raw_thumbnail(path: Union[str, Path]):
3566
with rawpy.imread(str(path)) as raw:
3667
try:
@@ -74,7 +105,14 @@ def icon(self, file_info: QFileInfo) -> QIcon:
74105

75106
class MainWindow:
76107
def __init__(self, data_root_path: Path):
77-
self.data_root_path = data_root_path
108+
self.data_root_path = None
109+
self.metadata = {}
110+
self.types = set()
111+
self.makes = set()
112+
self.models = set()
113+
self.bodies = set()
114+
self.colors = set()
115+
78116
ui_file_name = 'main_window.ui'
79117
ui_file = QFile(Path(__file__).resolve().parent / ui_file_name)
80118

@@ -86,12 +124,32 @@ def __init__(self, data_root_path: Path):
86124
self.window = loader.load(ui_file)
87125
ui_file.close()
88126

89-
self.set_data_root_path(str(data_root_path))
127+
self.type_completer = QCompleter()
128+
self.type_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
129+
self.type_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
130+
self.type_completer.setWidget(self.window.type_combo_box)
131+
self.make_completer = QCompleter()
132+
self.make_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
133+
self.make_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
134+
self.make_completer.setWidget(self.window.make_combo_box)
135+
self.model_completer = QCompleter()
136+
self.model_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
137+
self.model_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
138+
self.model_completer.setWidget(self.window.model_combo_box)
139+
self.body_completer = QCompleter()
140+
self.body_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
141+
self.body_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
142+
self.body_completer.setWidget(self.window.body_combo_box)
143+
self.color_completer = QCompleter()
144+
self.color_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
145+
self.color_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
146+
self.color_completer.setWidget(self.window.color_combo_box)
147+
90148
self.window.path_browser_button.clicked.connect(self.browse_directory)
91-
self.window.path_edit.textChanged.connect(self.load_images)
149+
self.window.path_edit.textChanged.connect(self.on_data_root_path_changed)
92150

93-
if self.data_root_path:
94-
self.load_images()
151+
if data_root_path:
152+
self.window.path_edit.setText(str(data_root_path))
95153

96154
if not self.window:
97155
print(loader.errorString())
@@ -103,7 +161,7 @@ def __init__(self, data_root_path: Path):
103161
def browse_directory(self):
104162
path = QFileDialog.getExistingDirectory(self.window, 'Select dataset directory', str(self.data_root_path),
105163
options=QFileDialog.Option.ShowDirsOnly)
106-
self.set_data_root_path(path)
164+
self.window.path_edit.setText(path)
107165

108166
def on_file_selected(self, index: QModelIndex):
109167
file_name = index.data()
@@ -118,17 +176,65 @@ def on_file_selected(self, index: QModelIndex):
118176
self.window.photo_view.setScene(scene)
119177

120178
self.window.type_combo_box.setEnabled(True)
179+
self.window.type_combo_box.setCompleter(self.type_completer)
121180
self.window.make_combo_box.setEnabled(True)
181+
self.window.make_combo_box.setCompleter(self.make_completer)
122182
self.window.model_combo_box.setEnabled(True)
183+
self.window.model_combo_box.setCompleter(self.model_completer)
123184
self.window.body_combo_box.setEnabled(True)
185+
self.window.body_combo_box.setCompleter(self.body_completer)
124186
self.window.color_combo_box.setEnabled(True)
187+
self.window.color_combo_box.setCompleter(self.color_completer)
125188

126-
def set_data_root_path(self, path: str):
127-
self.window.path_edit.setText(path)
128-
self.data_root_path = Path(path)
129189

130-
def load_images(self):
131-
data_root_path = Path(self.window.path_edit.text())
190+
def on_data_root_path_changed(self):
191+
self.data_root_path = Path(self.window.path_edit.text())
192+
self.load_images(self.data_root_path)
193+
self.metadata = load_metadata(self.data_root_path)
194+
195+
self.types = set()
196+
self.makes = set()
197+
self.models = set()
198+
self.bodies = set()
199+
self.colors = set()
200+
201+
for item in self.metadata.values():
202+
if _type := item.get('type'):
203+
self.types.add(_type)
204+
205+
if make := item.get('make'):
206+
self.makes.add(make)
207+
208+
if model := item.get('model'):
209+
self.models.add(model)
210+
211+
if body := item.get('body'):
212+
self.bodies.add(body)
213+
214+
if color := item.get('color'):
215+
self.colors.add(color)
216+
217+
self.window.type_combo_box.clear()
218+
self.window.type_combo_box.addItems(sorted(self.types))
219+
self.type_completer.setModel(QStringListModel(sorted(self.types)))
220+
221+
self.window.make_combo_box.clear()
222+
self.window.make_combo_box.addItems(sorted(self.makes))
223+
self.make_completer.setModel(QStringListModel(sorted(self.makes)))
224+
225+
self.window.model_combo_box.clear()
226+
self.window.model_combo_box.addItems(sorted(self.models))
227+
self.model_completer.setModel(QStringListModel(sorted(self.models)))
228+
229+
self.window.body_combo_box.clear()
230+
self.window.body_combo_box.addItems(sorted(self.bodies))
231+
self.body_completer.setModel(QStringListModel(sorted(self.bodies)))
232+
233+
self.window.color_combo_box.clear()
234+
self.window.color_combo_box.addItems(sorted(self.colors))
235+
self.color_completer.setModel(QStringListModel(sorted(self.colors)))
236+
237+
def load_images(self, data_root_path: Path):
132238
image_file_paths = list_dir_images(data_root_path)
133239

134240
if image_file_paths:

0 commit comments

Comments
 (0)