Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_41840029
PaddleOCR
提交
b103b755
P
PaddleOCR
项目概览
weixin_41840029
/
PaddleOCR
与 Fork 源项目一致
Fork自
PaddlePaddle / PaddleOCR
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleOCR
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
b103b755
编写于
12月 31, 2021
作者:
E
Evezerest
提交者:
GitHub
12月 31, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #5040 from redearly123/dygraph
add feature lockshapes
上级
ebc6ce21
107f07c2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
147 addition
and
38 deletion
+147
-38
PPOCRLabel/PPOCRLabel.py
PPOCRLabel/PPOCRLabel.py
+135
-35
PPOCRLabel/libs/canvas.py
PPOCRLabel/libs/canvas.py
+4
-0
PPOCRLabel/libs/shape.py
PPOCRLabel/libs/shape.py
+2
-1
PPOCRLabel/resources/icons/lock.png
PPOCRLabel/resources/icons/lock.png
+0
-0
PPOCRLabel/resources/strings/strings-en.properties
PPOCRLabel/resources/strings/strings-en.properties
+3
-1
PPOCRLabel/resources/strings/strings-zh-CN.properties
PPOCRLabel/resources/strings/strings-zh-CN.properties
+3
-1
未找到文件。
PPOCRLabel/PPOCRLabel.py
浏览文件 @
b103b755
...
...
@@ -61,7 +61,7 @@ from combobox import ComboBox
from
libs.constants
import
*
from
libs.utils
import
*
from
libs.settings
import
Settings
from
libs.shape
import
Shape
,
DEFAULT_LINE_COLOR
,
DEFAULT_FILL_COLOR
from
libs.shape
import
Shape
,
DEFAULT_LINE_COLOR
,
DEFAULT_FILL_COLOR
,
DEFAULT_LOCK_COLOR
from
libs.stringBundle
import
StringBundle
from
libs.canvas
import
Canvas
from
libs.zoomWidget
import
ZoomWidget
...
...
@@ -126,7 +126,7 @@ class MainWindow(QMainWindow, WindowMixin):
self
.
labelHist
=
[]
self
.
lastOpenDir
=
None
self
.
result_dic
=
[]
self
.
result_dic_locked
=
[]
self
.
changeFileFolder
=
False
self
.
haveAutoReced
=
False
self
.
labelFile
=
None
...
...
@@ -395,6 +395,7 @@ class MainWindow(QMainWindow, WindowMixin):
delete
=
action
(
getStr
(
'delBox'
),
self
.
deleteSelectedShape
,
'backspace'
,
'delete'
,
getStr
(
'delBoxDetail'
),
enabled
=
False
)
copy
=
action
(
getStr
(
'dupBox'
),
self
.
copySelectedShape
,
'Ctrl+C'
,
'copy'
,
getStr
(
'dupBoxDetail'
),
enabled
=
False
)
...
...
@@ -405,6 +406,7 @@ class MainWindow(QMainWindow, WindowMixin):
showAll
=
action
(
getStr
(
'showBox'
),
partial
(
self
.
togglePolygons
,
True
),
'Ctrl+A'
,
'hide'
,
getStr
(
'showAllBoxDetail'
),
enabled
=
False
)
help
=
action
(
getStr
(
'tutorial'
),
self
.
showTutorialDialog
,
None
,
'help'
,
getStr
(
'tutorialDetail'
))
showInfo
=
action
(
getStr
(
'info'
),
self
.
showInfoDialog
,
None
,
'help'
,
getStr
(
'info'
))
...
...
@@ -476,6 +478,10 @@ class MainWindow(QMainWindow, WindowMixin):
undo
=
action
(
getStr
(
"undo"
),
self
.
undoShapeEdit
,
'Ctrl+Z'
,
"undo"
,
getStr
(
"undo"
),
enabled
=
False
)
lock
=
action
(
getStr
(
"lockBox"
),
self
.
lockSelectedShape
,
None
,
"lock"
,
getStr
(
"lockBoxDetail"
),
enabled
=
False
)
self
.
editButton
.
setDefaultAction
(
edit
)
self
.
newButton
.
setDefaultAction
(
create
)
...
...
@@ -538,13 +544,13 @@ class MainWindow(QMainWindow, WindowMixin):
fitWindow
=
fitWindow
,
fitWidth
=
fitWidth
,
zoomActions
=
zoomActions
,
saveLabel
=
saveLabel
,
undo
=
undo
,
undoLastPoint
=
undoLastPoint
,
open_dataset_dir
=
open_dataset_dir
,
rotateLeft
=
rotateLeft
,
rotateRight
=
rotateRight
,
rotateLeft
=
rotateLeft
,
rotateRight
=
rotateRight
,
lock
=
lock
,
fileMenuActions
=
(
opendir
,
open_dataset_dir
,
saveLabel
,
resetAll
,
quit
),
beginner
=
(),
advanced
=
(),
editMenu
=
(
createpoly
,
edit
,
copy
,
delete
,
singleRere
,
None
,
undo
,
undoLastPoint
,
None
,
rotateLeft
,
rotateRight
,
None
,
color1
,
self
.
drawSquaresOption
),
beginnerContext
=
(
create
,
edit
,
copy
,
delete
,
singleRere
,
rotateLeft
,
rotateRight
,),
None
,
rotateLeft
,
rotateRight
,
None
,
color1
,
self
.
drawSquaresOption
,
lock
),
beginnerContext
=
(
create
,
edit
,
copy
,
delete
,
singleRere
,
rotateLeft
,
rotateRight
,
lock
),
advancedContext
=
(
createMode
,
editMode
,
edit
,
copy
,
delete
,
shapeLineColor
,
shapeFillColor
),
onLoadActive
=
(
...
...
@@ -998,6 +1004,7 @@ class MainWindow(QMainWindow, WindowMixin):
self
.
actions
.
delete
.
setEnabled
(
n_selected
)
self
.
actions
.
copy
.
setEnabled
(
n_selected
)
self
.
actions
.
edit
.
setEnabled
(
n_selected
==
1
)
self
.
actions
.
lock
.
setEnabled
(
n_selected
)
def
addLabel
(
self
,
shape
):
shape
.
paintLabel
=
self
.
displayLabelOption
.
isChecked
()
...
...
@@ -1041,7 +1048,7 @@ class MainWindow(QMainWindow, WindowMixin):
def
loadLabels
(
self
,
shapes
):
s
=
[]
for
label
,
points
,
line_color
,
fill_color
,
difficult
in
shapes
:
shape
=
Shape
(
label
=
label
)
shape
=
Shape
(
label
=
label
,
line_color
=
line_color
)
for
x
,
y
in
points
:
# Ensure the labels are within the bounds of the image. If not, fix them.
...
...
@@ -1051,6 +1058,7 @@ class MainWindow(QMainWindow, WindowMixin):
shape
.
addPoint
(
QPointF
(
x
,
y
))
shape
.
difficult
=
difficult
#shape.locked = False
shape
.
close
()
s
.
append
(
shape
)
...
...
@@ -1063,10 +1071,12 @@ class MainWindow(QMainWindow, WindowMixin):
# shape.fill_color = QColor(*fill_color)
# else:
# shape.fill_color = generateColorByText(label)
self
.
addLabel
(
shape
)
self
.
updateComboBox
()
self
.
canvas
.
loadShapes
(
s
)
def
singleLabel
(
self
,
shape
):
if
shape
is
None
:
...
...
@@ -1106,10 +1116,9 @@ class MainWindow(QMainWindow, WindowMixin):
difficult
=
s
.
difficult
)
# bool
shapes
=
[]
if
mode
==
'Auto'
else
\
[
format_shape
(
shape
)
for
shape
in
self
.
canvas
.
shapes
]
[
format_shape
(
shape
)
for
shape
in
self
.
canvas
.
shapes
if
shape
.
line_color
!=
DEFAULT_LOCK_COLOR
]
# Can add differrent annotation formats here
for
box
in
self
.
result_dic
:
for
box
in
self
.
result_dic
:
trans_dic
=
{
"label"
:
box
[
1
][
0
],
"points"
:
box
[
0
],
'difficult'
:
False
}
if
trans_dic
[
"label"
]
==
""
and
mode
==
'Auto'
:
continue
...
...
@@ -1120,7 +1129,6 @@ class MainWindow(QMainWindow, WindowMixin):
for
box
in
shapes
:
trans_dic
.
append
({
"transcription"
:
box
[
'label'
],
"points"
:
box
[
'points'
],
'difficult'
:
box
[
'difficult'
]})
self
.
PPlabel
[
annotationFilePath
]
=
trans_dic
if
mode
==
'Auto'
:
self
.
Cachelabel
[
annotationFilePath
]
=
trans_dic
...
...
@@ -1313,6 +1321,7 @@ class MainWindow(QMainWindow, WindowMixin):
# unicodeFilePath = os.path.abspath(unicodeFilePath)
# Tzutalin 20160906 : Add file list and dock to move faster
# Highlight the file item
if
unicodeFilePath
and
self
.
fileListWidget
.
count
()
>
0
:
if
unicodeFilePath
in
self
.
mImgList
:
index
=
self
.
mImgList
.
index
(
unicodeFilePath
)
...
...
@@ -1322,6 +1331,7 @@ class MainWindow(QMainWindow, WindowMixin):
###
self
.
iconlist
.
clear
()
self
.
additems5
(
None
)
for
i
in
range
(
5
):
item_tooltip
=
self
.
iconlist
.
item
(
i
).
toolTip
()
# print(i,"---",item_tooltip)
...
...
@@ -1340,7 +1350,6 @@ class MainWindow(QMainWindow, WindowMixin):
if
unicodeFilePath
and
os
.
path
.
exists
(
unicodeFilePath
):
self
.
canvas
.
verified
=
False
cvimg
=
cv2
.
imdecode
(
np
.
fromfile
(
unicodeFilePath
,
dtype
=
np
.
uint8
),
1
)
height
,
width
,
depth
=
cvimg
.
shape
cvimg
=
cv2
.
cvtColor
(
cvimg
,
cv2
.
COLOR_BGR2RGB
)
...
...
@@ -1361,16 +1370,19 @@ class MainWindow(QMainWindow, WindowMixin):
else
:
self
.
dirty
=
False
self
.
actions
.
save
.
setEnabled
(
True
)
if
len
(
self
.
canvas
.
lockedShapes
)
!=
0
:
self
.
actions
.
save
.
setEnabled
(
True
)
self
.
setDirty
()
self
.
canvas
.
setEnabled
(
True
)
self
.
adjustScale
(
initial
=
True
)
self
.
paintCanvas
()
self
.
addRecentFile
(
self
.
filePath
)
self
.
toggleActions
(
True
)
self
.
showBoundingBoxFromPPlabel
(
filePath
)
self
.
setWindowTitle
(
__appname__
+
' '
+
filePath
)
# Default : select last item if there is at least one item
if
self
.
labelList
.
count
():
self
.
labelList
.
setCurrentItem
(
self
.
labelList
.
item
(
self
.
labelList
.
count
()
-
1
))
...
...
@@ -1380,15 +1392,23 @@ class MainWindow(QMainWindow, WindowMixin):
return
True
return
False
def
showBoundingBoxFromPPlabel
(
self
,
filePath
):
width
,
height
=
self
.
image
.
width
(),
self
.
image
.
height
()
imgidx
=
self
.
getImglabelidx
(
filePath
)
if
imgidx
not
in
self
.
PPlabel
.
keys
():
return
shapes
=
[]
for
box
in
self
.
PPlabel
[
imgidx
]:
shapes
.
append
((
box
[
'transcription'
],
box
[
'points'
],
None
,
None
,
box
[
'difficult'
]))
shapes
=
[]
#box['ratio'] of the shapes saved in lockedShapes contains the ratio of the
# four corner coordinates of the shapes to the height and width of the image
for
box
in
self
.
canvas
.
lockedShapes
:
if
self
.
canvas
.
isInTheSameImage
:
shapes
.
append
((
box
[
'transcription'
],
[[
s
[
0
]
*
width
,
s
[
1
]
*
height
]
for
s
in
box
[
'ratio'
]],
DEFAULT_LOCK_COLOR
,
None
,
box
[
'difficult'
]))
else
:
shapes
.
append
((
'锁定框:待检测'
,
[[
s
[
0
]
*
width
,
s
[
1
]
*
height
]
for
s
in
box
[
'ratio'
]],
DEFAULT_LOCK_COLOR
,
None
,
box
[
'difficult'
]))
if
imgidx
in
self
.
PPlabel
.
keys
():
for
box
in
self
.
PPlabel
[
imgidx
]:
shapes
.
append
((
box
[
'transcription'
],
box
[
'points'
],
None
,
None
,
box
[
'difficult'
]))
self
.
loadLabels
(
shapes
)
self
.
canvas
.
verified
=
False
...
...
@@ -1646,9 +1666,37 @@ class MainWindow(QMainWindow, WindowMixin):
else
:
return
fullFilePath
return
''
def
saveLockedShapes
(
self
):
self
.
canvas
.
lockedShapes
=
[]
self
.
canvas
.
selectedShapes
=
[]
for
s
in
self
.
canvas
.
shapes
:
if
s
.
line_color
==
DEFAULT_LOCK_COLOR
:
self
.
canvas
.
selectedShapes
.
append
(
s
)
self
.
lockSelectedShape
()
for
s
in
self
.
canvas
.
shapes
:
if
s
.
line_color
==
DEFAULT_LOCK_COLOR
:
self
.
canvas
.
selectedShapes
.
remove
(
s
)
self
.
canvas
.
shapes
.
remove
(
s
)
def
_saveFile
(
self
,
annotationFilePath
,
mode
=
'Manual'
):
if
len
(
self
.
canvas
.
lockedShapes
)
!=
0
:
self
.
saveLockedShapes
()
if
mode
==
'Manual'
:
self
.
result_dic_locked
=
[]
img
=
cv2
.
imread
(
self
.
filePath
)
width
,
height
=
self
.
image
.
width
(),
self
.
image
.
height
()
for
shape
in
self
.
canvas
.
lockedShapes
:
box
=
[[
int
(
p
[
0
]
*
width
),
int
(
p
[
1
]
*
height
)]
for
p
in
shape
[
'ratio'
]]
assert
len
(
box
)
==
4
result
=
[(
shape
[
'transcription'
],
1
)]
result
.
insert
(
0
,
box
)
self
.
result_dic_locked
.
append
(
result
)
self
.
result_dic
+=
self
.
result_dic_locked
self
.
result_dic_locked
=
[]
if
annotationFilePath
and
self
.
saveLabels
(
annotationFilePath
,
mode
=
mode
):
self
.
setClean
()
self
.
statusBar
().
showMessage
(
'Saved to %s'
%
annotationFilePath
)
...
...
@@ -1663,13 +1711,13 @@ class MainWindow(QMainWindow, WindowMixin):
self
.
savePPlabel
(
mode
=
'Auto'
)
self
.
fileListWidget
.
insertItem
(
int
(
currIndex
),
item
)
self
.
openNextImg
()
if
not
self
.
canvas
.
isInTheSameImage
:
self
.
openNextImg
()
self
.
actions
.
saveRec
.
setEnabled
(
True
)
self
.
actions
.
saveLabel
.
setEnabled
(
True
)
elif
mode
==
'Auto'
:
if
annotationFilePath
and
self
.
saveLabels
(
annotationFilePath
,
mode
=
mode
):
self
.
setClean
()
self
.
statusBar
().
showMessage
(
'Saved to %s'
%
annotationFilePath
)
self
.
statusBar
().
show
()
...
...
@@ -1733,7 +1781,9 @@ class MainWindow(QMainWindow, WindowMixin):
if
discardChanges
==
QMessageBox
.
No
:
return
True
elif
discardChanges
==
QMessageBox
.
Yes
:
self
.
canvas
.
isInTheSameImage
=
True
self
.
saveFile
()
self
.
canvas
.
isInTheSameImage
=
False
return
True
else
:
return
False
...
...
@@ -1872,6 +1922,7 @@ class MainWindow(QMainWindow, WindowMixin):
# org_box = [dic['points'] for dic in self.PPlabel[self.getImglabelidx(self.filePath)]]
if
self
.
canvas
.
shapes
:
self
.
result_dic
=
[]
self
.
result_dic_locked
=
[]
# result_dic_locked stores the ocr result of self.canvas.lockedShapes
rec_flag
=
0
for
shape
in
self
.
canvas
.
shapes
:
box
=
[[
int
(
p
.
x
()),
int
(
p
.
y
())]
for
p
in
shape
.
points
]
...
...
@@ -1883,21 +1934,32 @@ class MainWindow(QMainWindow, WindowMixin):
return
result
=
self
.
ocr
.
ocr
(
img_crop
,
cls
=
True
,
det
=
False
)
if
result
[
0
][
0
]
!=
''
:
result
.
insert
(
0
,
box
)
print
(
'result in reRec is '
,
result
)
self
.
result_dic
.
append
(
result
)
if
shape
.
line_color
==
DEFAULT_LOCK_COLOR
:
shape
.
label
=
result
[
0
][
0
]
result
.
insert
(
0
,
box
)
self
.
result_dic_locked
.
append
(
result
)
else
:
result
.
insert
(
0
,
box
)
self
.
result_dic
.
append
(
result
)
else
:
print
(
'Can not recognise the box'
)
self
.
result_dic
.
append
([
box
,(
self
.
noLabelText
,
0
)])
if
self
.
noLabelText
==
shape
.
label
or
result
[
1
][
0
]
==
shape
.
label
:
print
(
'label no change'
)
else
:
rec_flag
+=
1
if
len
(
self
.
result_dic
)
>
0
and
rec_flag
>
0
:
if
shape
.
line_color
==
DEFAULT_LOCK_COLOR
:
shape
.
label
=
result
[
0
][
0
]
self
.
result_dic_locked
.
append
([
box
,(
self
.
noLabelText
,
0
)])
else
:
self
.
result_dic
.
append
([
box
,(
self
.
noLabelText
,
0
)])
try
:
if
self
.
noLabelText
==
shape
.
label
or
result
[
1
][
0
]
==
shape
.
label
:
print
(
'label no change'
)
else
:
rec_flag
+=
1
except
IndexError
as
e
:
print
(
'Can not recognise the box'
)
if
(
len
(
self
.
result_dic
)
>
0
and
rec_flag
>
0
)
or
self
.
canvas
.
lockedShapes
:
self
.
canvas
.
isInTheSameImage
=
True
self
.
saveFile
(
mode
=
'Auto'
)
self
.
loadFile
(
self
.
filePath
)
self
.
canvas
.
isInTheSameImage
=
False
self
.
setDirty
()
elif
len
(
self
.
result_dic
)
==
len
(
self
.
canvas
.
shapes
)
and
rec_flag
==
0
:
QMessageBox
.
information
(
self
,
"Information"
,
"The recognition result remains unchanged!"
)
...
...
@@ -2107,6 +2169,44 @@ class MainWindow(QMainWindow, WindowMixin):
self
.
labelList
.
clearSelection
()
self
.
_noSelectionSlot
=
False
self
.
canvas
.
loadShapes
(
shapes
,
replace
=
replace
)
print
(
"loadShapes"
)
#1
def
lockSelectedShape
(
self
):
"""lock the selsected shapes.
Add self.selectedShapes to lock self.canvas.lockedShapes,
which holds the ratio of the four coordinates of the locked shapes
to the width and height of the image
"""
width
,
height
=
self
.
image
.
width
(),
self
.
image
.
height
()
def
format_shape
(
s
):
return
dict
(
label
=
s
.
label
,
# str
line_color
=
s
.
line_color
.
getRgb
(),
fill_color
=
s
.
fill_color
.
getRgb
(),
ratio
=
[[
int
(
p
.
x
())
/
width
,
int
(
p
.
y
())
/
height
]
for
p
in
s
.
points
],
# QPonitF
# add chris
difficult
=
s
.
difficult
)
# bool
#lock
if
len
(
self
.
canvas
.
lockedShapes
)
==
0
:
for
s
in
self
.
canvas
.
selectedShapes
:
s
.
line_color
=
DEFAULT_LOCK_COLOR
s
.
locked
=
True
shapes
=
[
format_shape
(
shape
)
for
shape
in
self
.
canvas
.
selectedShapes
]
trans_dic
=
[]
for
box
in
shapes
:
trans_dic
.
append
({
"transcription"
:
box
[
'label'
],
"ratio"
:
box
[
'ratio'
],
'difficult'
:
box
[
'difficult'
]})
self
.
canvas
.
lockedShapes
=
trans_dic
self
.
actions
.
save
.
setEnabled
(
True
)
#unlock
else
:
for
s
in
self
.
canvas
.
shapes
:
s
.
line_color
=
DEFAULT_LINE_COLOR
self
.
canvas
.
lockedShapes
=
[]
self
.
result_dic_locked
=
[]
self
.
setDirty
()
self
.
actions
.
save
.
setEnabled
(
True
)
def
inverted
(
color
):
...
...
PPOCRLabel/libs/canvas.py
浏览文件 @
b103b755
...
...
@@ -87,6 +87,10 @@ class Canvas(QWidget):
#initialisation for panning
self
.
pan_initial_pos
=
QPoint
()
#lockedshapes related
self
.
lockedShapes
=
[]
self
.
isInTheSameImage
=
False
def
setDrawingColor
(
self
,
qColor
):
self
.
drawingLineColor
=
qColor
self
.
drawingRectColor
=
qColor
...
...
PPOCRLabel/libs/shape.py
浏览文件 @
b103b755
...
...
@@ -30,6 +30,7 @@ DEFAULT_SELECT_LINE_COLOR = QColor(255, 255, 255)
DEFAULT_SELECT_FILL_COLOR
=
QColor
(
0
,
128
,
255
,
155
)
DEFAULT_VERTEX_FILL_COLOR
=
QColor
(
0
,
255
,
0
,
255
)
DEFAULT_HVERTEX_FILL_COLOR
=
QColor
(
255
,
0
,
0
)
DEFAULT_LOCK_COLOR
=
QColor
(
255
,
0
,
255
)
MIN_Y_LABEL
=
10
...
...
@@ -57,7 +58,7 @@ class Shape(object):
self
.
selected
=
False
self
.
difficult
=
difficult
self
.
paintLabel
=
paintLabel
self
.
locked
=
False
self
.
_highlightIndex
=
None
self
.
_highlightMode
=
self
.
NEAR_VERTEX
self
.
_highlightSettings
=
{
...
...
PPOCRLabel/resources/icons/lock.png
0 → 100644
浏览文件 @
b103b755
2.9 KB
PPOCRLabel/resources/strings/strings-en.properties
浏览文件 @
b103b755
...
...
@@ -104,4 +104,6 @@ singleRe=Re-recognition RectBox
labelDialogOption
=
Pop-up Label Input Dialog
undo
=
Undo
undoLastPoint
=
Undo Last Point
autoSaveMode
=
Auto Export Label Mode
\ No newline at end of file
autoSaveMode
=
Auto Export Label Mode
lockBox
=
Lock selected box/Unlock all box
lockBoxDetail
=
Lock selected box/Unlock all box
\ No newline at end of file
PPOCRLabel/resources/strings/strings-zh-CN.properties
浏览文件 @
b103b755
...
...
@@ -104,4 +104,6 @@ singleRe=重识别此区块
labelDialogOption
=
弹出标记输入框
undo
=
撤销
undoLastPoint
=
撤销上个点
autoSaveMode
=
自动导出标记结果
\ No newline at end of file
autoSaveMode
=
自动导出标记结果
lockBox
=
锁定框/解除锁定框
lockBoxDetail
=
若当前没有框处于锁定状态则锁定选中的框,若存在锁定框则解除所有锁定框的锁定状态
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录