Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
不会修仙的道士
labelme
提交
ba7830a0
L
labelme
项目概览
不会修仙的道士
/
labelme
与 Fork 源项目一致
从无法访问的项目Fork
通知
4
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
labelme
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ba7830a0
编写于
4月 26, 2018
作者:
K
Kentaro Wada
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Enable user configure GUI with args and a yaml file
上级
70e4bb1f
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
84 addition
and
56 deletion
+84
-56
labelme/app.py
labelme/app.py
+42
-40
labelme/config/__init__.py
labelme/config/__init__.py
+31
-14
labelme/config/default_config.yaml
labelme/config/default_config.yaml
+8
-0
labelme/labelDialog.py
labelme/labelDialog.py
+3
-2
未找到文件。
labelme/app.py
浏览文件 @
ba7830a0
...
...
@@ -121,14 +121,14 @@ class LabelQListWidget(QtWidgets.QListWidget):
class
MainWindow
(
QtWidgets
.
QMainWindow
,
WindowMixin
):
FIT_WINDOW
,
FIT_WIDTH
,
MANUAL_ZOOM
=
0
,
1
,
2
def
__init__
(
self
,
filename
=
None
,
output
=
None
,
store_data
=
True
,
labels
=
None
,
sort_labels
=
True
,
auto_save
=
False
,
validate_label
=
None
,
config
=
None
):
super
(
MainWindow
,
self
).
__init__
()
self
.
setWindowTitle
(
__appname__
)
def
__init__
(
self
,
config
=
None
,
filename
=
None
,
output
=
None
):
# see labelme/config/default_config.yaml for valid configuration
if
config
is
None
:
config
=
get_config
()
self
.
_config
=
config
super
(
MainWindow
,
self
).
__init__
()
self
.
setWindowTitle
(
__appname__
)
# Whether we need to save or not.
self
.
dirty
=
False
...
...
@@ -136,8 +136,12 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
self
.
_noSelectionSlot
=
False
# Main widgets and related state.
self
.
labelDialog
=
LabelDialog
(
parent
=
self
,
labels
=
labels
,
sort_labels
=
sort_labels
)
self
.
labelDialog
=
LabelDialog
(
parent
=
self
,
labels
=
self
.
_config
[
'labels'
],
sort_labels
=
self
.
_config
[
'sort_labels'
],
show_text_field
=
self
.
_config
[
'show_label_text_field'
],
)
self
.
labelList
=
LabelQListWidget
()
self
.
lastOpenDir
=
None
...
...
@@ -164,8 +168,8 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
self
.
uniqLabelList
.
setToolTip
(
"Select label to start annotating for it. "
"Press 'Esc' to deselect."
)
if
labels
:
self
.
uniqLabelList
.
addItems
(
labels
)
if
self
.
_config
[
'labels'
]
:
self
.
uniqLabelList
.
addItems
(
self
.
_config
[
'labels'
]
)
self
.
uniqLabelList
.
sortItems
()
self
.
labelsdock
=
QtWidgets
.
QDockWidget
(
u
'Label List'
,
self
)
self
.
labelsdock
.
setObjectName
(
u
'Label List'
)
...
...
@@ -220,7 +224,7 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
# Actions
action
=
functools
.
partial
(
newAction
,
self
)
shortcuts
=
config
[
'shortcuts'
]
shortcuts
=
self
.
_
config
[
'shortcuts'
]
quit
=
action
(
'&Quit'
,
self
.
close
,
shortcuts
[
'quit'
],
'quit'
,
'Quit application'
)
open_
=
action
(
'&Open'
,
self
.
openFile
,
shortcuts
[
'open'
],
'open'
,
...
...
@@ -400,18 +404,12 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
# Application state.
self
.
image
=
QtGui
.
QImage
()
self
.
imagePath
=
None
if
auto_save
and
output
is
not
None
:
if
self
.
_config
[
'auto_save'
]
and
output
is
not
None
:
warnings
.
warn
(
'If `auto_save` argument is True, `output` argument '
'is ignored and output filename is automatically '
'set as IMAGE_BASENAME.json.'
)
self
.
labeling_once
=
output
is
not
None
self
.
output
=
output
self
.
_auto_save
=
auto_save
self
.
_store_data
=
store_data
if
validate_label
not
in
[
None
,
'exact'
,
'instance'
]:
raise
ValueError
(
'Unexpected `validate_label`: {}'
.
format
(
validate_label
))
self
.
_validate_label
=
validate_label
self
.
recentFiles
=
[]
self
.
maxRecent
=
7
self
.
lineColor
=
None
...
...
@@ -477,7 +475,7 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
addActions
(
self
.
menus
.
edit
,
actions
+
self
.
actions
.
editMenu
)
def
setDirty
(
self
):
if
self
.
_
auto_save
:
if
self
.
_
config
[
'auto_save'
]
:
label_file
=
os
.
path
.
splitext
(
self
.
imagePath
)[
0
]
+
'.json'
self
.
saveLabels
(
label_file
)
return
...
...
@@ -587,15 +585,15 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
def
validateLabel
(
self
,
label
):
# no validation
if
self
.
_
validate_label
is
None
:
if
self
.
_
config
[
'validate_label'
]
is
None
:
return
True
for
i
in
range
(
self
.
uniqLabelList
.
count
()):
l
=
self
.
uniqLabelList
.
item
(
i
).
text
()
if
self
.
_
validate_label
in
[
'exact'
,
'instance'
]:
if
self
.
_
config
[
'validate_label'
]
in
[
'exact'
,
'instance'
]:
if
l
==
label
:
return
True
if
self
.
_
validate_label
==
'instance'
:
if
self
.
_
config
[
'validate_label'
]
==
'instance'
:
m
=
re
.
match
(
r
'^{}-[0-9]*$'
.
format
(
l
),
label
)
if
m
:
return
True
...
...
@@ -611,7 +609,7 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
if
not
self
.
validateLabel
(
text
):
self
.
errorMessage
(
'Invalid label'
,
"Invalid label '{}' with validation type '{}'"
.
format
(
text
,
self
.
_
validate_label
))
.
format
(
text
,
self
.
_
config
[
'validate_label'
]
))
return
item
.
setText
(
text
)
self
.
setDirty
()
...
...
@@ -702,7 +700,7 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
try
:
imagePath
=
os
.
path
.
relpath
(
self
.
imagePath
,
os
.
path
.
dirname
(
filename
))
imageData
=
self
.
imageData
if
self
.
_
store_data
else
None
imageData
=
self
.
imageData
if
self
.
_
config
[
'store_data'
]
else
None
lf
.
save
(
filename
,
shapes
,
imagePath
,
imageData
,
self
.
lineColor
.
getRgb
(),
self
.
fillColor
.
getRgb
(),
self
.
otherData
)
...
...
@@ -750,7 +748,7 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
if
text
is
not
None
and
not
self
.
validateLabel
(
text
):
self
.
errorMessage
(
'Invalid label'
,
"Invalid label '{}' with validation type '{}'"
.
format
(
text
,
self
.
_
validate_label
))
.
format
(
text
,
self
.
_
config
[
'validate_label'
]
))
text
=
None
if
text
is
None
:
self
.
canvas
.
undoLastLine
()
...
...
@@ -1200,21 +1198,24 @@ def read(filename, default=None):
def
main
():
"""Standard boilerplate Qt application code."""
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'--version'
,
'-V'
,
action
=
'store_true'
,
help
=
'show version'
)
parser
.
add_argument
(
'filename'
,
nargs
=
'?'
,
help
=
'image or label filename'
)
parser
.
add_argument
(
'--output'
,
'-O'
,
'-o'
,
help
=
'output label name'
)
parser
.
add_argument
(
'--config'
,
dest
=
'config_file'
,
help
=
'config file'
)
# config
parser
.
add_argument
(
'--nodata'
,
dest
=
'store_data'
,
action
=
'store_false'
,
help
=
'stop storing image data to JSON file'
)
parser
.
add_argument
(
'--autosave'
,
action
=
'store_true'
,
help
=
'auto save'
)
parser
.
add_argument
(
'--autosave'
,
dest
=
'auto_save'
,
action
=
'store_true'
,
help
=
'auto save'
)
parser
.
add_argument
(
'--labels'
,
help
=
'comma separated list of labels OR file '
'containing one label per line'
)
parser
.
add_argument
(
'--nosortlabels'
,
dest
=
'sort_labels'
,
action
=
'store_false'
,
help
=
'stop sorting labels'
)
parser
.
add_argument
(
'--validatelabel'
,
choices
=
[
'exact'
,
'instance'
],
parser
.
add_argument
(
'--validatelabel'
,
dest
=
'validate_label'
,
choices
=
[
'exact'
,
'instance'
],
help
=
'label validation types'
)
args
=
parser
.
parse_args
()
...
...
@@ -1223,8 +1224,10 @@ def main():
sys
.
exit
(
0
)
if
args
.
labels
is
None
:
if
args
.
validatelabel
is
not
None
:
logger
.
error
(
'--labels must be specified with --validatelabel'
)
if
args
.
validate_label
is
not
None
:
logger
.
error
(
'--labels must be specified with --validatelabel or '
'validate_label: true in the config file '
'(ex. ~/.labelmerc).'
)
sys
.
exit
(
1
)
else
:
if
os
.
path
.
isfile
(
args
.
labels
):
...
...
@@ -1233,18 +1236,17 @@ def main():
else
:
args
.
labels
=
[
l
for
l
in
args
.
labels
.
split
(
','
)
if
l
]
config_from_args
=
args
.
__dict__
config_from_args
.
pop
(
'version'
)
filename
=
config_from_args
.
pop
(
'filename'
)
output
=
config_from_args
.
pop
(
'output'
)
config_file
=
config_from_args
.
pop
(
'config_file'
)
config
=
get_config
(
config_from_args
,
config_file
)
app
=
QtWidgets
.
QApplication
(
sys
.
argv
)
app
.
setApplicationName
(
__appname__
)
app
.
setWindowIcon
(
newIcon
(
"icon"
))
win
=
MainWindow
(
filename
=
args
.
filename
,
output
=
args
.
output
,
store_data
=
args
.
store_data
,
labels
=
args
.
labels
,
sort_labels
=
args
.
sort_labels
,
auto_save
=
args
.
autosave
,
validate_label
=
args
.
validatelabel
,
)
app
.
setWindowIcon
(
newIcon
(
'icon'
))
win
=
MainWindow
(
config
=
config
,
filename
=
filename
,
output
=
output
)
win
.
show
()
win
.
raise_
()
sys
.
exit
(
app
.
exec_
())
...
...
labelme/config/__init__.py
浏览文件 @
ba7830a0
...
...
@@ -9,38 +9,55 @@ from labelme import logger
here
=
osp
.
dirname
(
osp
.
abspath
(
__file__
))
def
update_dict
(
target_dict
,
new_dict
):
def
update_dict
(
target_dict
,
new_dict
,
validate_item
=
None
):
for
key
,
value
in
new_dict
.
items
():
if
validate_item
:
validate_item
(
key
,
value
)
if
key
not
in
target_dict
:
logger
.
warn
(
'Skipping unexpected key in config: {}'
.
format
(
key
))
continue
if
isinstance
(
target_dict
[
key
],
dict
)
and
\
isinstance
(
value
,
dict
):
update_dict
(
target_dict
[
key
],
value
)
update_dict
(
target_dict
[
key
],
value
,
validate_item
=
validate_item
)
else
:
target_dict
[
key
]
=
value
# -----------------------------------------------------------------------------
def
get_default_config
():
config_file
=
osp
.
join
(
here
,
'default_config.yaml'
)
config
=
yaml
.
load
(
open
(
config_file
))
return
config
def
get_config
():
def
validate_config_item
(
key
,
value
):
if
key
==
'validate_label'
and
value
not
in
[
None
,
'exact'
,
'instance'
]:
raise
ValueError
(
'Unexpected value `{}` for key `{}`'
.
format
(
value
,
key
))
def
get_config
(
config_from_args
=
None
,
config_file
=
None
):
# default config
config
=
get_default_config
()
# shortcuts for actions
if
config_from_args
is
not
None
:
update_dict
(
config
,
config_from_args
,
validate_item
=
validate_config_item
)
save_config_file
=
False
if
config_file
is
None
:
home
=
os
.
path
.
expanduser
(
'~'
)
config_file
=
os
.
path
.
join
(
home
,
'.labelmerc'
)
save_config_file
=
True
if
os
.
path
.
exists
(
config_file
):
user_config
=
yaml
.
load
(
open
(
config_file
))
or
{}
update_dict
(
config
,
user_config
)
update_dict
(
config
,
user_config
,
validate_item
=
validate_config_item
)
# save config
if
save_config_file
:
try
:
yaml
.
safe_dump
(
config
,
open
(
config_file
,
'w'
),
default_flow_style
=
False
)
...
...
labelme/config/default_config.yaml
浏览文件 @
ba7830a0
auto_save
:
false
store_data
:
true
labels
:
null
sort_labels
:
true
validate_label
:
null
show_label_text_field
:
true
shortcuts
:
close
:
Ctrl+W
open
:
Ctrl+O
...
...
labelme/labelDialog.py
浏览文件 @
ba7830a0
...
...
@@ -28,13 +28,14 @@ class LabelQLineEdit(QtWidgets.QLineEdit):
class
LabelDialog
(
QtWidgets
.
QDialog
):
def
__init__
(
self
,
text
=
"Enter object label"
,
parent
=
None
,
labels
=
None
,
sort_labels
=
True
):
sort_labels
=
True
,
show_text_field
=
True
):
super
(
LabelDialog
,
self
).
__init__
(
parent
)
self
.
edit
=
LabelQLineEdit
()
self
.
edit
.
setPlaceholderText
(
text
)
self
.
edit
.
setValidator
(
labelValidator
())
self
.
edit
.
editingFinished
.
connect
(
self
.
postProcess
)
layout
=
QtWidgets
.
QVBoxLayout
()
if
show_text_field
:
layout
.
addWidget
(
self
.
edit
)
# buttons
self
.
buttonBox
=
bb
=
QtWidgets
.
QDialogButtonBox
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录