Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
疯人忠
Cvat
提交
821c456e
C
Cvat
项目概览
疯人忠
/
Cvat
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Cvat
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
821c456e
编写于
6月 22, 2023
作者:
K
klakhov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fixed more comments
上级
27a18618
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
121 addition
and
148 deletion
+121
-148
cvat-ui/src/components/annotation-page/canvas/views/canvas2d/canvas-wrapper.tsx
.../annotation-page/canvas/views/canvas2d/canvas-wrapper.tsx
+1
-1
cvat-ui/src/components/annotation-page/review-workspace/review-workspace.tsx
...nts/annotation-page/review-workspace/review-workspace.tsx
+0
-2
cvat-ui/src/components/annotation-page/review/conflicts-aggregator.tsx
...omponents/annotation-page/review/conflicts-aggregator.tsx
+0
-125
cvat-ui/src/components/annotation-page/review/issues-aggregator.tsx
...c/components/annotation-page/review/issues-aggregator.tsx
+94
-8
cvat-ui/src/components/annotation-page/tag-annotation-workspace/frame-tags.tsx
...s/annotation-page/tag-annotation-workspace/frame-tags.tsx
+11
-7
cvat-ui/src/utils/filter-annotations.ts
cvat-ui/src/utils/filter-annotations.ts
+15
-5
未找到文件。
cvat-ui/src/components/annotation-page/canvas/views/canvas2d/canvas-wrapper.tsx
浏览文件 @
821c456e
...
...
@@ -906,7 +906,7 @@ class CanvasWrapperComponent extends React.PureComponent<Props> {
frame
,
groundTruthJobFramesMeta
,
workspace
,
filterTags
:
true
,
exclude
:
[
ObjectType
.
TAG
]
,
});
canvasInstance
.
setup
(
...
...
cvat-ui/src/components/annotation-page/review-workspace/review-workspace.tsx
浏览文件 @
821c456e
...
...
@@ -13,7 +13,6 @@ import ObjectSideBarComponent from 'components/annotation-page/standard-workspac
import
ObjectsListContainer
from
'
containers/annotation-page/standard-workspace/objects-side-bar/objects-list
'
;
import
CanvasContextMenuContainer
from
'
containers/annotation-page/canvas/canvas-context-menu
'
;
import
IssueAggregatorComponent
from
'
components/annotation-page/review/issues-aggregator
'
;
import
ConflictAggregatorComponent
from
'
components/annotation-page/review/conflicts-aggregator
'
;
export
default
function
ReviewWorkspaceComponent
():
JSX
.
Element
{
return
(
...
...
@@ -23,7 +22,6 @@ export default function ReviewWorkspaceComponent(): JSX.Element {
<
ObjectSideBarComponent
objectsList
=
{
<
ObjectsListContainer
readonly
/>
}
/>
<
CanvasContextMenuContainer
readonly
/>
<
IssueAggregatorComponent
/>
<
ConflictAggregatorComponent
/>
</
Layout
>
);
}
cvat-ui/src/components/annotation-page/review/conflicts-aggregator.tsx
已删除
100644 → 0
浏览文件 @
27a18618
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
import
'
./styles.scss
'
;
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
'
react
'
;
import
{
useDispatch
,
useSelector
}
from
'
react-redux
'
;
import
{
ActiveControl
,
CombinedState
}
from
'
reducers
'
;
import
{
Canvas
}
from
'
cvat-canvas/src/typescript/canvas
'
;
import
{
AnnotationConflict
,
ObjectState
,
QualityConflict
}
from
'
cvat-core-wrapper
'
;
import
{
highlightConflict
}
from
'
actions/annotation-actions
'
;
import
ConflictLabel
from
'
./conflict-label
'
;
export
default
function
ConflictAggregatorComponent
():
JSX
.
Element
|
null
{
const
dispatch
=
useDispatch
();
const
qualityConflicts
=
useSelector
((
state
:
CombinedState
)
=>
state
.
review
.
frameConflicts
);
const
objectStates
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
annotations
.
states
);
const
currentFrame
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
player
.
frame
.
number
);
const
showConflicts
=
useSelector
((
state
:
CombinedState
)
=>
state
.
settings
.
shapes
.
showGroundTruth
);
const
highlightedConflict
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
annotations
.
highlightedConflict
);
const
highlightedObjectsIDs
=
highlightedConflict
?.
annotationConflicts
?.
map
((
c
:
AnnotationConflict
)
=>
c
.
clientID
);
const
canvasInstance
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
canvas
.
instance
);
const
canvasIsReady
=
useSelector
((
state
:
CombinedState
):
boolean
=>
state
.
annotation
.
canvas
.
ready
);
const
[
geometry
,
setGeometry
]
=
useState
<
Canvas
[
'
geometry
'
]
|
null
>
(
null
);
const
ready
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
canvas
.
ready
);
const
activeControl
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
canvas
.
activeControl
);
const
onEnter
=
useCallback
((
conflict
:
QualityConflict
)
=>
{
if
(
ready
&&
activeControl
===
ActiveControl
.
CURSOR
)
{
dispatch
(
highlightConflict
(
conflict
));
}
},
[
ready
,
activeControl
]);
const
onLeave
=
useCallback
(()
=>
{
if
(
ready
&&
activeControl
===
ActiveControl
.
CURSOR
)
{
dispatch
(
highlightConflict
(
null
));
}
},
[
ready
,
activeControl
]);
const
conflictLabels
:
JSX
.
Element
[]
=
[];
useEffect
(()
=>
{
if
(
canvasInstance
instanceof
Canvas
)
{
const
{
geometry
:
updatedGeometry
}
=
canvasInstance
;
setGeometry
(
updatedGeometry
);
const
geometryListener
=
():
void
=>
{
dispatch
(
highlightConflict
(
null
));
setGeometry
(
canvasInstance
.
geometry
);
};
canvasInstance
.
html
().
addEventListener
(
'
canvas.zoom
'
,
geometryListener
);
canvasInstance
.
html
().
addEventListener
(
'
canvas.fit
'
,
geometryListener
);
canvasInstance
.
html
().
addEventListener
(
'
canvas.reshape
'
,
geometryListener
);
return
()
=>
{
canvasInstance
.
html
().
removeEventListener
(
'
canvas.zoom
'
,
geometryListener
);
canvasInstance
.
html
().
removeEventListener
(
'
canvas.fit
'
,
geometryListener
);
canvasInstance
.
html
().
addEventListener
(
'
canvas.reshape
'
,
geometryListener
);
};
}
return
()
=>
{};
},
[
canvasInstance
,
ready
]);
const
[
mapping
,
setMapping
]
=
useState
<
any
>
([]);
useEffect
(()
=>
{
if
(
canvasInstance
instanceof
Canvas
&&
geometry
&&
showConflicts
)
{
const
newMapping
=
qualityConflicts
.
map
((
conflict
:
QualityConflict
)
=>
{
const
c
=
conflict
.
annotationConflicts
[
0
];
const
state
=
objectStates
.
find
((
s
:
ObjectState
)
=>
s
.
jobID
===
c
.
jobID
&&
s
.
serverID
===
c
.
serverID
);
if
(
state
&&
canvasInstance
)
{
const
points
=
canvasInstance
.
setupConflictsRegions
(
state
);
if
(
points
)
{
return
{
description
:
conflict
.
description
,
severity
:
conflict
.
severity
,
x
:
points
[
0
],
y
:
points
[
1
],
clientID
:
c
.
clientID
,
conflict
,
};
}
}
return
[];
}).
filter
((
el
)
=>
!
Array
.
isArray
(
el
));
setMapping
(
newMapping
);
}
else
{
setMapping
([]);
}
},
[
geometry
,
objectStates
,
showConflicts
,
currentFrame
,
canvasInstance
,
ready
]);
if
(
!
(
canvasInstance
instanceof
Canvas
)
||
!
canvasIsReady
||
!
geometry
)
{
return
null
;
}
for
(
const
conflict
of
mapping
)
{
conflictLabels
.
push
(
<
ConflictLabel
key
=
{
(
Math
.
random
()
+
1
).
toString
(
36
).
substring
(
7
)
}
text
=
{
conflict
.
description
}
top
=
{
conflict
.
y
}
left
=
{
conflict
.
x
}
angle
=
{
-
geometry
.
angle
}
scale
=
{
1
/
geometry
.
scale
}
severity
=
{
conflict
.
severity
}
darken
=
{
!!
highlightedConflict
&&
!!
highlightedObjectsIDs
&&
(
!
highlightedObjectsIDs
.
includes
(
conflict
.
clientID
))
}
conflict
=
{
conflict
.
conflict
}
onEnter
=
{
onEnter
}
onLeave
=
{
onLeave
}
tooltipVisible
=
{
!!
highlightedConflict
&&
!!
highlightedObjectsIDs
&&
highlightedObjectsIDs
.
includes
(
conflict
.
clientID
)
}
/>,
);
}
return
(
<>
{
conflictLabels
}
</>
);
}
cvat-ui/src/components/annotation-page/review/issues-aggregator.tsx
浏览文件 @
821c456e
...
...
@@ -4,17 +4,31 @@
// SPDX-License-Identifier: MIT
import
'
./styles.scss
'
;
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
React
,
{
useState
,
useEffect
,
useCallback
}
from
'
react
'
;
import
{
useSelector
,
useDispatch
}
from
'
react-redux
'
;
import
{
CombinedState
}
from
'
reducers
'
;
import
{
ActiveControl
,
CombinedState
}
from
'
reducers
'
;
import
{
Canvas
}
from
'
cvat-canvas/src/typescript/canvas
'
;
import
{
commentIssueAsync
,
resolveIssueAsync
,
reopenIssueAsync
}
from
'
actions/review-actions
'
;
import
{
AnnotationConflict
,
ConflictSeverity
,
ObjectState
,
QualityConflict
,
}
from
'
cvat-core-wrapper
'
;
import
{
highlightConflict
}
from
'
actions/annotation-actions
'
;
import
CreateIssueDialog
from
'
./create-issue-dialog
'
;
import
HiddenIssueLabel
from
'
./hidden-issue-label
'
;
import
IssueDialog
from
'
./issue-dialog
'
;
import
ConflictLabel
from
'
./conflict-label
'
;
interface
ConflictMappingElement
{
description
:
string
;
severity
:
ConflictSeverity
;
x
:
number
;
y
:
number
;
clientID
:
number
;
conflict
:
QualityConflict
;
}
export
default
function
IssueAggregatorComponent
():
JSX
.
Element
|
null
{
const
dispatch
=
useDispatch
();
...
...
@@ -26,14 +40,38 @@ export default function IssueAggregatorComponent(): JSX.Element | null {
const
canvasIsReady
=
useSelector
((
state
:
CombinedState
):
boolean
=>
state
.
annotation
.
canvas
.
ready
);
const
newIssuePosition
=
useSelector
((
state
:
CombinedState
):
number
[]
|
null
=>
state
.
review
.
newIssuePosition
);
const
issueFetching
=
useSelector
((
state
:
CombinedState
):
number
|
null
=>
state
.
review
.
fetching
.
issueId
);
const
ready
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
canvas
.
ready
);
const
[
geometry
,
setGeometry
]
=
useState
<
Canvas
[
'
geometry
'
]
|
null
>
(
null
);
const
qualityConflicts
=
useSelector
((
state
:
CombinedState
)
=>
state
.
review
.
frameConflicts
);
const
objectStates
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
annotations
.
states
);
const
showConflicts
=
useSelector
((
state
:
CombinedState
)
=>
state
.
settings
.
shapes
.
showGroundTruth
);
const
highlightedConflict
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
annotations
.
highlightedConflict
);
const
highlightedObjectsIDs
=
highlightedConflict
?.
annotationConflicts
?.
map
((
c
:
AnnotationConflict
)
=>
c
.
clientID
);
const
activeControl
=
useSelector
((
state
:
CombinedState
)
=>
state
.
annotation
.
canvas
.
activeControl
);
const
readyToRender
=
canvasInstance
instanceof
Canvas
&&
canvasIsReady
;
const
onEnter
=
useCallback
((
conflict
:
QualityConflict
)
=>
{
if
(
readyToRender
&&
activeControl
===
ActiveControl
.
CURSOR
)
{
dispatch
(
highlightConflict
(
conflict
));
}
},
[
readyToRender
,
activeControl
]);
const
onLeave
=
useCallback
(()
=>
{
if
(
readyToRender
&&
activeControl
===
ActiveControl
.
CURSOR
)
{
dispatch
(
highlightConflict
(
null
));
}
},
[
readyToRender
,
activeControl
]);
const
[
conflictMapping
,
setConflictMapping
]
=
useState
<
ConflictMappingElement
[]
>
([]);
const
issueLabels
:
JSX
.
Element
[]
=
[];
const
issueDialogs
:
JSX
.
Element
[]
=
[];
const
conflictLabels
:
JSX
.
Element
[]
=
[];
useEffect
(()
=>
{
if
(
canvasInstance
instanceof
Canvas
)
{
if
(
readyToRender
)
{
const
{
geometry
:
updatedGeometry
}
=
canvasInstance
;
setGeometry
(
updatedGeometry
);
...
...
@@ -53,10 +91,10 @@ export default function IssueAggregatorComponent(): JSX.Element | null {
}
return
()
=>
{};
},
[
canvasInstance
,
ready
]);
},
[
readyToRender
]);
useEffect
(()
=>
{
if
(
canvasInstance
instanceof
Canvas
)
{
if
(
readyToRender
)
{
type
IssueRegionSet
=
Record
<
number
,
{
hidden
:
boolean
;
points
:
number
[]
}
>
;
const
regions
=
!
issuesHidden
?
frameIssues
.
filter
((
_issue
:
any
)
=>
!
issuesResolvedHidden
||
!
_issue
.
resolved
)
...
...
@@ -86,9 +124,35 @@ export default function IssueAggregatorComponent(): JSX.Element | null {
}
}
}
},
[
newIssuePosition
,
frameIssues
,
issuesResolvedHidden
,
issuesHidden
,
canvasInstance
]);
},
[
newIssuePosition
,
frameIssues
,
issuesResolvedHidden
,
issuesHidden
,
readyToRender
,
showConflicts
]);
useEffect
(()
=>
{
if
(
readyToRender
&&
showConflicts
)
{
const
newconflictMapping
=
qualityConflicts
.
map
((
conflict
:
QualityConflict
)
=>
{
const
c
=
conflict
.
annotationConflicts
[
0
];
const
state
=
objectStates
.
find
((
s
:
ObjectState
)
=>
s
.
jobID
===
c
.
jobID
&&
s
.
serverID
===
c
.
serverID
);
if
(
state
)
{
const
points
=
canvasInstance
.
setupConflictsRegions
(
state
);
if
(
points
)
{
return
{
description
:
conflict
.
description
,
severity
:
conflict
.
severity
,
x
:
points
[
0
],
y
:
points
[
1
],
clientID
:
c
.
clientID
,
conflict
,
};
}
}
return
null
;
}).
filter
((
element
)
=>
element
);
setConflictMapping
(
newconflictMapping
as
ConflictMappingElement
[]);
}
else
{
setConflictMapping
([]);
}
},
[
geometry
,
objectStates
,
showConflicts
,
readyToRender
]);
if
(
!
(
canvasInstance
instanceof
Canvas
)
||
!
canvasIsReady
||
!
geometry
)
{
if
(
!
readyToRender
||
!
geometry
)
{
return
null
;
}
...
...
@@ -173,6 +237,27 @@ export default function IssueAggregatorComponent(): JSX.Element | null {
Math
.
min
(...
translated
.
filter
((
_
:
number
,
idx
:
number
):
boolean
=>
idx
%
2
!==
0
))
:
null
;
for
(
const
conflict
of
conflictMapping
)
{
conflictLabels
.
push
(
<
ConflictLabel
key
=
{
(
Math
.
random
()
+
1
).
toString
(
36
).
substring
(
7
)
}
text
=
{
conflict
.
description
}
top
=
{
conflict
.
y
}
left
=
{
conflict
.
x
}
angle
=
{
-
geometry
.
angle
}
scale
=
{
1
/
geometry
.
scale
}
severity
=
{
conflict
.
severity
}
darken
=
{
!!
highlightedConflict
&&
!!
highlightedObjectsIDs
&&
(
!
highlightedObjectsIDs
.
includes
(
conflict
.
clientID
))
}
conflict
=
{
conflict
.
conflict
}
onEnter
=
{
onEnter
}
onLeave
=
{
onLeave
}
tooltipVisible
=
{
!!
highlightedConflict
&&
!!
highlightedObjectsIDs
&&
highlightedObjectsIDs
.
includes
(
conflict
.
clientID
)
}
/>,
);
}
return
(
<>
{
createLeft
!==
null
&&
createTop
!==
null
?
(
...
...
@@ -185,6 +270,7 @@ export default function IssueAggregatorComponent(): JSX.Element | null {
)
:
null
}
{
issueDialogs
}
{
issueLabels
}
{
conflictLabels
}
</>
);
}
cvat-ui/src/components/annotation-page/tag-annotation-workspace/frame-tags.tsx
浏览文件 @
821c456e
...
...
@@ -11,12 +11,14 @@ import { ThunkDispatch } from 'redux-thunk';
import
{
removeObject
as
removeObjectAction
,
}
from
'
actions/annotation-actions
'
;
import
{
CombinedState
,
ObjectType
}
from
'
reducers
'
;
import
{
CombinedState
,
ObjectType
,
Workspace
}
from
'
reducers
'
;
import
{
ObjectState
}
from
'
cvat-core-wrapper
'
;
import
{
filterAnnotations
}
from
'
utils/filter-annotations
'
;
interface
StateToProps
{
states
:
ObjectState
[];
statesSources
:
number
[];
workspace
:
Workspace
;
}
interface
DispatchToProps
{
...
...
@@ -27,12 +29,14 @@ function mapStateToProps(state: CombinedState): StateToProps {
const
{
annotation
:
{
annotations
:
{
states
,
statesSources
},
workspace
,
},
}
=
state
;
return
{
states
,
statesSources
,
workspace
,
};
}
...
...
@@ -48,6 +52,7 @@ function FrameTags(props: StateToProps & DispatchToProps): JSX.Element {
const
{
states
,
statesSources
,
workspace
,
removeObject
,
}
=
props
;
...
...
@@ -59,12 +64,11 @@ function FrameTags(props: StateToProps & DispatchToProps): JSX.Element {
useEffect
(()
=>
{
setFrameTags
(
states
.
filter
(
(
objectState
:
ObjectState
):
boolean
=>
(
objectState
.
objectType
===
ObjectType
.
TAG
&&
(
!
objectState
.
jobID
||
statesSources
.
includes
(
objectState
.
jobID
))
),
),
filterAnnotations
(
states
,
{
statesSources
,
workspace
,
include
:
[
ObjectType
.
TAG
],
}),
);
},
[
states
,
statesSources
]);
...
...
cvat-ui/src/utils/filter-annotations.ts
浏览文件 @
821c456e
...
...
@@ -9,16 +9,26 @@ export interface FilterAnnotationsParams {
workspace
:
Workspace
;
statesSources
:
number
[];
groundTruthJobFramesMeta
?:
FramesMetaData
|
null
;
filterTags
?:
boolean
;
frame
:
number
;
exclude
?:
ObjectType
[];
include
?:
ObjectType
[];
frame
?:
number
;
}
export
function
filterAnnotations
(
annotations
:
ObjectState
[],
params
:
FilterAnnotationsParams
):
ObjectState
[]
{
const
{
workspace
,
statesSources
,
groundTruthJobFramesMeta
,
filterTags
,
frame
,
workspace
,
statesSources
,
groundTruthJobFramesMeta
,
exclude
,
include
,
frame
,
}
=
params
;
if
(
Array
.
isArray
(
exclude
)
&&
Array
.
isArray
(
include
))
{
throw
Error
(
'
Can not filter annotations with exclude and include filters simultaneously
'
);
}
const
filteredAnnotations
=
annotations
.
filter
((
state
)
=>
{
if
(
filterTags
&&
state
.
objectType
===
ObjectType
.
TAG
)
{
if
(
Array
.
isArray
(
exclude
)
&&
exclude
.
includes
(
state
.
objectType
))
{
return
false
;
}
if
(
Array
.
isArray
(
include
)
&&
!
include
.
includes
(
state
.
objectType
))
{
return
false
;
}
...
...
@@ -27,7 +37,7 @@ export function filterAnnotations(annotations: ObjectState[], params: FilterAnno
}
// GT tracks are shown only on GT frames
if
(
workspace
===
Workspace
.
REVIEW_WORKSPACE
&&
groundTruthJobFramesMeta
)
{
if
(
workspace
===
Workspace
.
REVIEW_WORKSPACE
&&
groundTruthJobFramesMeta
&&
frame
)
{
if
(
state
.
objectType
===
ObjectType
.
TRACK
&&
state
.
isGroundTruth
)
{
return
groundTruthJobFramesMeta
.
includedFrames
.
includes
(
frame
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录