Pull request #1: Setup
Merge in RR/fb_detr_prediction_container from setup to master
Squashed commit of the following:
commit 7fae4878d4250676367b7201fa163a4b67f79f84
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Thu Feb 3 11:22:12 2022 +0100
readded annotation to client
commit ff788030f6b3b342919a7fd31dfa66940033d7e1
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Thu Feb 3 11:15:16 2022 +0100
applied black
commit 3521444f678950a2772b725c6964751e0e655736
Merge: 4080aff 51d6597
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Thu Feb 3 10:39:11 2022 +0100
Merge branch 'setup' of ssh://git.iqser.com:2222/rr/fb_detr_prediction_container into setup
commit 4080affd21a02ad32c61fbd2027511f51a202d63
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Thu Feb 3 10:39:02 2022 +0100
added poppler-utils download to Dockerfile, since pdf2image only is a wrapper for it
commit 51d6597b056ae9ac693280f65a3f37d46b1276cf
Author: Julius Unverfehrt <Julius.Unverfehrt@iqser.com>
Date: Thu Feb 3 09:43:35 2022 +0100
Structure change for local backbone lookup (working now)
commit ac314d5148d6e026c67f00df45a8bbc70c15b52d
Author: Julius Unverfehrt <Julius.Unverfehrt@iqser.com>
Date: Thu Feb 3 09:35:41 2022 +0100
env bug fixed
commit 1c3221fe4956911b29fd8fede8d07dcdefad06d8
Author: Julius Unverfehrt <Julius.Unverfehrt@iqser.com>
Date: Thu Feb 3 09:23:55 2022 +0100
ENV correctly set now
commit 58069440583f1f78cfb2fb796fa4dc4a63e2916a
Author: Julius Unverfehrt <Julius.Unverfehrt@iqser.com>
Date: Thu Feb 3 08:41:29 2022 +0100
ENV for local torch model lookup set
commit f0501cf0bf904793e8e04afbd3d80ee84af9d981
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 18:28:44 2022 +0100
changed host and port for flask
commit 986fda22f6656b10930628d0d284995b33ea2df5
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 17:33:07 2022 +0100
added debug webserver method
commit 64b857ce53757ec2b7e7c327962fa65b551603a0
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 16:59:11 2022 +0100
moved utils into module; fixed open-cv (maybe)
commit c62ada183135e12b41a29c6822472e33698f947f
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 15:55:10 2022 +0100
made bash scripts executable
commit 982bdd7503c14fcf1776ae10c38589475199545e
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 15:35:16 2022 +0100
service building logic added (WIP)
commit 46e5e3b8e67e54ecedaeee4765a3437f08fa4b17
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 14:37:28 2022 +0100
applied black
commit ad93130e66d2e87bc86b2bf1de6234f3c037df48
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 14:36:09 2022 +0100
fixed formatting (w, h -> x2, y2); added drawing logic to caller mock
commit df76f033599e66aaa52143f5e2b156530f643df9
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 13:54:34 2022 +0100
page indices in predictions
commit 5e87c57dff752419486d1a44de9a734e3f840816
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 13:17:34 2022 +0100
service main loop WIP (working in basic version)
commit ba5ec3d57621d090201413309126955940602be9
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 13:03:52 2022 +0100
service main loop WIP
commit 77266f6982ec826eadcdd8a18c5ccf0fc380611b
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 11:24:27 2022 +0100
fixed bug for self.classes == None
commit 858ef7589d6914ad503660a3ddc5e75bf72a6bb7
Author: Matthias Bisping <matthias.bisping@iqser.com>
Date: Wed Feb 2 11:09:11 2022 +0100
removed 'postprocessors' argument and attribute
... and 32 more commits
This commit is contained in:
parent
42075bf2a0
commit
e4dc6631b5
3
.dvc/.gitignore
vendored
Normal file
3
.dvc/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/config.local
|
||||||
|
/tmp
|
||||||
|
/cache
|
||||||
6
.dvc/config
Normal file
6
.dvc/config
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[core]
|
||||||
|
remote = vector
|
||||||
|
autostage = true
|
||||||
|
['remote "vector"']
|
||||||
|
url = ssh://vector.iqser.com/research/detr_server/
|
||||||
|
port = 22
|
||||||
107
.dvc/plots/confusion.json
Normal file
107
.dvc/plots/confusion.json
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"facet": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"transform": [
|
||||||
|
{
|
||||||
|
"aggregate": [
|
||||||
|
{
|
||||||
|
"op": "count",
|
||||||
|
"as": "xy_count"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupby": [
|
||||||
|
"<DVC_METRIC_Y>",
|
||||||
|
"<DVC_METRIC_X>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"impute": "xy_count",
|
||||||
|
"groupby": [
|
||||||
|
"rev",
|
||||||
|
"<DVC_METRIC_Y>"
|
||||||
|
],
|
||||||
|
"key": "<DVC_METRIC_X>",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"impute": "xy_count",
|
||||||
|
"groupby": [
|
||||||
|
"rev",
|
||||||
|
"<DVC_METRIC_X>"
|
||||||
|
],
|
||||||
|
"key": "<DVC_METRIC_Y>",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joinaggregate": [
|
||||||
|
{
|
||||||
|
"op": "max",
|
||||||
|
"field": "xy_count",
|
||||||
|
"as": "max_count"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupby": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"calculate": "datum.xy_count / datum.max_count",
|
||||||
|
"as": "percent_of_max"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "nominal",
|
||||||
|
"sort": "ascending",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "nominal",
|
||||||
|
"sort": "ascending",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": "rect",
|
||||||
|
"width": 300,
|
||||||
|
"height": 300,
|
||||||
|
"encoding": {
|
||||||
|
"color": {
|
||||||
|
"field": "xy_count",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "",
|
||||||
|
"scale": {
|
||||||
|
"domainMin": 0,
|
||||||
|
"nice": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mark": "text",
|
||||||
|
"encoding": {
|
||||||
|
"text": {
|
||||||
|
"field": "xy_count",
|
||||||
|
"type": "quantitative"
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"condition": {
|
||||||
|
"test": "datum.percent_of_max > 0.5",
|
||||||
|
"value": "white"
|
||||||
|
},
|
||||||
|
"value": "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
112
.dvc/plots/confusion_normalized.json
Normal file
112
.dvc/plots/confusion_normalized.json
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"facet": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"transform": [
|
||||||
|
{
|
||||||
|
"aggregate": [
|
||||||
|
{
|
||||||
|
"op": "count",
|
||||||
|
"as": "xy_count"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupby": [
|
||||||
|
"<DVC_METRIC_Y>",
|
||||||
|
"<DVC_METRIC_X>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"impute": "xy_count",
|
||||||
|
"groupby": [
|
||||||
|
"rev",
|
||||||
|
"<DVC_METRIC_Y>"
|
||||||
|
],
|
||||||
|
"key": "<DVC_METRIC_X>",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"impute": "xy_count",
|
||||||
|
"groupby": [
|
||||||
|
"rev",
|
||||||
|
"<DVC_METRIC_X>"
|
||||||
|
],
|
||||||
|
"key": "<DVC_METRIC_Y>",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joinaggregate": [
|
||||||
|
{
|
||||||
|
"op": "sum",
|
||||||
|
"field": "xy_count",
|
||||||
|
"as": "sum_y"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupby": [
|
||||||
|
"<DVC_METRIC_Y>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"calculate": "datum.xy_count / datum.sum_y",
|
||||||
|
"as": "percent_of_y"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "nominal",
|
||||||
|
"sort": "ascending",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "nominal",
|
||||||
|
"sort": "ascending",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": "rect",
|
||||||
|
"width": 300,
|
||||||
|
"height": 300,
|
||||||
|
"encoding": {
|
||||||
|
"color": {
|
||||||
|
"field": "percent_of_y",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "",
|
||||||
|
"scale": {
|
||||||
|
"domain": [
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mark": "text",
|
||||||
|
"encoding": {
|
||||||
|
"text": {
|
||||||
|
"field": "percent_of_y",
|
||||||
|
"type": "quantitative",
|
||||||
|
"format": ".2f"
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"condition": {
|
||||||
|
"test": "datum.percent_of_y > 0.5",
|
||||||
|
"value": "white"
|
||||||
|
},
|
||||||
|
"value": "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
116
.dvc/plots/linear.json
Normal file
116
.dvc/plots/linear.json
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"width": 300,
|
||||||
|
"height": 300,
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>",
|
||||||
|
"scale": {
|
||||||
|
"zero": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": "line"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selection": {
|
||||||
|
"label": {
|
||||||
|
"type": "single",
|
||||||
|
"nearest": true,
|
||||||
|
"on": "mouseover",
|
||||||
|
"encodings": [
|
||||||
|
"x"
|
||||||
|
],
|
||||||
|
"empty": "none",
|
||||||
|
"clear": "mouseout"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mark": "point",
|
||||||
|
"encoding": {
|
||||||
|
"opacity": {
|
||||||
|
"condition": {
|
||||||
|
"selection": "label",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transform": [
|
||||||
|
{
|
||||||
|
"filter": {
|
||||||
|
"selection": "label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": {
|
||||||
|
"type": "rule",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"encoding": {
|
||||||
|
"text": {
|
||||||
|
"type": "quantitative",
|
||||||
|
"field": "<DVC_METRIC_Y>"
|
||||||
|
},
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": {
|
||||||
|
"type": "text",
|
||||||
|
"align": "left",
|
||||||
|
"dx": 5,
|
||||||
|
"dy": -5
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"color": {
|
||||||
|
"type": "nominal",
|
||||||
|
"field": "rev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
104
.dvc/plots/scatter.json
Normal file
104
.dvc/plots/scatter.json
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"width": 300,
|
||||||
|
"height": 300,
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>",
|
||||||
|
"scale": {
|
||||||
|
"zero": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": "point"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selection": {
|
||||||
|
"label": {
|
||||||
|
"type": "single",
|
||||||
|
"nearest": true,
|
||||||
|
"on": "mouseover",
|
||||||
|
"encodings": [
|
||||||
|
"x"
|
||||||
|
],
|
||||||
|
"empty": "none",
|
||||||
|
"clear": "mouseout"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mark": "point",
|
||||||
|
"encoding": {
|
||||||
|
"opacity": {
|
||||||
|
"condition": {
|
||||||
|
"selection": "label",
|
||||||
|
"value": 1
|
||||||
|
},
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transform": [
|
||||||
|
{
|
||||||
|
"filter": {
|
||||||
|
"selection": "label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"encoding": {
|
||||||
|
"text": {
|
||||||
|
"type": "quantitative",
|
||||||
|
"field": "<DVC_METRIC_Y>"
|
||||||
|
},
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer": [
|
||||||
|
{
|
||||||
|
"mark": {
|
||||||
|
"type": "text",
|
||||||
|
"align": "left",
|
||||||
|
"dx": 5,
|
||||||
|
"dy": -5
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"color": {
|
||||||
|
"type": "nominal",
|
||||||
|
"field": "rev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
31
.dvc/plots/simple.json
Normal file
31
.dvc/plots/simple.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"width": 300,
|
||||||
|
"height": 300,
|
||||||
|
"mark": {
|
||||||
|
"type": "line"
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>",
|
||||||
|
"scale": {
|
||||||
|
"zero": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
.dvc/plots/smooth.json
Normal file
39
.dvc/plots/smooth.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
|
||||||
|
"data": {
|
||||||
|
"values": "<DVC_METRIC_DATA>"
|
||||||
|
},
|
||||||
|
"title": "<DVC_METRIC_TITLE>",
|
||||||
|
"mark": {
|
||||||
|
"type": "line"
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"x": {
|
||||||
|
"field": "<DVC_METRIC_X>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_X_LABEL>"
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"field": "<DVC_METRIC_Y>",
|
||||||
|
"type": "quantitative",
|
||||||
|
"title": "<DVC_METRIC_Y_LABEL>",
|
||||||
|
"scale": {
|
||||||
|
"zero": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"field": "rev",
|
||||||
|
"type": "nominal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transform": [
|
||||||
|
{
|
||||||
|
"loess": "<DVC_METRIC_Y>",
|
||||||
|
"on": "<DVC_METRIC_X>",
|
||||||
|
"groupby": [
|
||||||
|
"rev"
|
||||||
|
],
|
||||||
|
"bandwidth": 0.3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
3
.dvcignore
Normal file
3
.dvcignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Add patterns of files dvc should ignore, which could improve
|
||||||
|
# the performance. Learn more at
|
||||||
|
# https://dvc.org/doc/user-guide/dvcignore
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "incl/detr"]
|
||||||
|
path = incl/detr
|
||||||
|
url = ssh://git@git.iqser.com:2222/rr/detr.git
|
||||||
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
FROM python:3.8 as builder1
|
||||||
|
|
||||||
|
# Use a virtual environment.
|
||||||
|
RUN python -m venv /app/venv
|
||||||
|
ENV PATH="/app/venv/bin:$PATH"
|
||||||
|
|
||||||
|
# Upgrade pip.
|
||||||
|
RUN python -m pip install --upgrade pip
|
||||||
|
|
||||||
|
# Make a directory for the service files and copy the service repo into the container.
|
||||||
|
WORKDIR /app/service
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
# Set up service as a module and install all its dependencies.
|
||||||
|
RUN bash setup/docker_local.sh
|
||||||
|
|
||||||
|
# Make a new container and copy all relevant files over to filter out temporary files
|
||||||
|
# produced during setup to reduce the final container's size.
|
||||||
|
FROM python:3.8
|
||||||
|
|
||||||
|
WORKDIR /app/
|
||||||
|
COPY --from=builder1 /app .
|
||||||
|
ENV PATH="/app/venv/bin:$PATH"
|
||||||
|
|
||||||
|
WORKDIR /app/service
|
||||||
|
|
||||||
|
RUN apt update --yes
|
||||||
|
RUN apt install vim --yes
|
||||||
|
RUN apt install poppler-utils --yes
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Run the service loop.
|
||||||
|
CMD ["python3", "src/run_service.py"]
|
||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
7
config.yaml
Normal file
7
config.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
device: cpu
|
||||||
|
threshold: .5
|
||||||
|
|
||||||
|
classes: ["logo", "other", "formula", "signature", "handwriting_other"]
|
||||||
|
rejection_class: "other"
|
||||||
|
|
||||||
|
checkpoint: checkpoint.pth
|
||||||
1
data/.gitignore
vendored
Normal file
1
data/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/checkpoint.pth
|
||||||
4
data/checkpoint.pth.dvc
Normal file
4
data/checkpoint.pth.dvc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
outs:
|
||||||
|
- md5: 9face65530febd41a0722e0513da2264
|
||||||
|
size: 496696129
|
||||||
|
path: checkpoint.pth
|
||||||
1
data/hub/checkpoints/.gitignore
vendored
Normal file
1
data/hub/checkpoints/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/resnet50-0676ba61.pth
|
||||||
4
data/hub/checkpoints/resnet50-0676ba61.pth.dvc
Normal file
4
data/hub/checkpoints/resnet50-0676ba61.pth.dvc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
outs:
|
||||||
|
- md5: b94941323912291bb67db6fdb1d80c11
|
||||||
|
size: 102530333
|
||||||
|
path: resnet50-0676ba61.pth
|
||||||
0
fb_detr/__init__.py
Normal file
0
fb_detr/__init__.py
Normal file
7
fb_detr/locations.py
Normal file
7
fb_detr/locations.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
CONFIG_FILE = MODULE_ROOT / "config.yaml"
|
||||||
|
DATA_DIR = MODULE_ROOT / "data"
|
||||||
|
TORCH_HOME = DATA_DIR
|
||||||
121
fb_detr/predictor.py
Normal file
121
fb_detr/predictor.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import argparse
|
||||||
|
from itertools import compress, starmap
|
||||||
|
from operator import itemgetter
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Iterable
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from detr.models import build_model
|
||||||
|
from detr.test import get_args_parser, infer
|
||||||
|
from iteration_utilities import starfilter
|
||||||
|
|
||||||
|
from fb_detr.utils.config import read_config
|
||||||
|
|
||||||
|
|
||||||
|
def load_model(checkpoint_path):
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(parents=[get_args_parser()])
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.output_dir:
|
||||||
|
Path(args.output_dir).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
device = torch.device(read_config("device"))
|
||||||
|
|
||||||
|
model, _, _ = build_model(args)
|
||||||
|
|
||||||
|
checkpoint = torch.load(checkpoint_path, map_location="cpu")
|
||||||
|
model.load_state_dict(checkpoint["model"])
|
||||||
|
|
||||||
|
model.to(device)
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
class Predictor:
|
||||||
|
def __init__(self, checkpoint_path, classes=None, rejection_class=None):
|
||||||
|
self.model = load_model(checkpoint_path)
|
||||||
|
self.classes = classes
|
||||||
|
self.rejection_class = rejection_class
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __format_boxes(boxes):
|
||||||
|
|
||||||
|
keys = "x1", "y1", "x2", "y2"
|
||||||
|
|
||||||
|
x1s = boxes[:, 0].tolist()
|
||||||
|
y1s = boxes[:, 1].tolist()
|
||||||
|
x2s = boxes[:, 2].tolist()
|
||||||
|
y2s = boxes[:, 3].tolist()
|
||||||
|
|
||||||
|
boxes = [dict(zip(keys, vs)) for vs in zip(x1s, y1s, x2s, y2s)]
|
||||||
|
|
||||||
|
return boxes
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __normalize_to_list(maybe_multiple):
|
||||||
|
return maybe_multiple if isinstance(maybe_multiple, tuple) else tuple([maybe_multiple])
|
||||||
|
|
||||||
|
def __format_classes(self, classes):
|
||||||
|
if self.classes:
|
||||||
|
return self.__normalize_to_list(itemgetter(*classes.tolist())(self.classes))
|
||||||
|
else:
|
||||||
|
return classes.tolist()
|
||||||
|
|
||||||
|
def __format_prediction(self, output: dict):
|
||||||
|
|
||||||
|
boxes, classes = itemgetter("bboxes", "classes")(output)
|
||||||
|
|
||||||
|
if len(boxes):
|
||||||
|
boxes = self.__format_boxes(boxes)
|
||||||
|
classes = self.__format_classes(classes)
|
||||||
|
else:
|
||||||
|
boxes, classes = [], []
|
||||||
|
|
||||||
|
output["bboxes"] = boxes
|
||||||
|
output["classes"] = classes
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def __filter_predictions_for_image(self, predictions):
|
||||||
|
|
||||||
|
boxes, classes = itemgetter("bboxes", "classes")(predictions)
|
||||||
|
|
||||||
|
if boxes:
|
||||||
|
keep = map(lambda c: c != self.rejection_class, classes)
|
||||||
|
compressed = list(compress(zip(boxes, classes), keep))
|
||||||
|
boxes, classes = map(list, zip(*compressed)) if compressed else ([], [])
|
||||||
|
predictions["bboxes"] = boxes
|
||||||
|
predictions["classes"] = classes
|
||||||
|
|
||||||
|
return predictions
|
||||||
|
|
||||||
|
def filter_predictions(self, predictions):
|
||||||
|
def detections_present(_, prediction):
|
||||||
|
return bool(prediction["classes"])
|
||||||
|
|
||||||
|
def build_return_dict(page_idx, predictions):
|
||||||
|
return {"page_idx": page_idx, **predictions}
|
||||||
|
|
||||||
|
filtered_rejections = map(self.__filter_predictions_for_image, predictions)
|
||||||
|
filtered_no_detections = starfilter(detections_present, enumerate(filtered_rejections))
|
||||||
|
filtered_no_detections = starmap(build_return_dict, filtered_no_detections)
|
||||||
|
|
||||||
|
return filtered_no_detections
|
||||||
|
|
||||||
|
def format_predictions(self, outputs: Iterable):
|
||||||
|
return map(self.__format_prediction, outputs)
|
||||||
|
|
||||||
|
def predict(self, images, threshold=None, format_output=False):
|
||||||
|
|
||||||
|
if not threshold:
|
||||||
|
threshold = read_config("threshold")
|
||||||
|
|
||||||
|
predictions = infer(images, self.model, read_config("device"), threshold)
|
||||||
|
|
||||||
|
if format_output:
|
||||||
|
predictions = self.format_predictions(predictions)
|
||||||
|
if self.rejection_class:
|
||||||
|
predictions = self.filter_predictions(predictions)
|
||||||
|
|
||||||
|
return predictions
|
||||||
0
fb_detr/utils/__init__.py
Normal file
0
fb_detr/utils/__init__.py
Normal file
18
fb_detr/utils/config.py
Normal file
18
fb_detr/utils/config.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import yaml
|
||||||
|
|
||||||
|
from fb_detr.locations import CONFIG_FILE
|
||||||
|
|
||||||
|
|
||||||
|
def read_config(key, config_path: str = CONFIG_FILE):
|
||||||
|
"""Reads the values associated with a key from a config.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: Key to look up the value to.
|
||||||
|
config_path: Path to config.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value associated with `key`.
|
||||||
|
"""
|
||||||
|
with open(config_path) as f:
|
||||||
|
config = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
|
return config[key]
|
||||||
0
incl/__init__.py
Normal file
0
incl/__init__.py
Normal file
1
incl/detr
Submodule
1
incl/detr
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 7e3258ccc1fa2be7a9d8ab333873b79de7005809
|
||||||
14
requirements.txt
Normal file
14
requirements.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
torch==1.10.2
|
||||||
|
numpy==1.22.1
|
||||||
|
#opencv-python==4.5.5.62
|
||||||
|
opencv-python-headless==4.5.5.62
|
||||||
|
torchvision==0.11.3
|
||||||
|
pycocotools==2.0.4
|
||||||
|
scipy==1.7.3
|
||||||
|
pdf2image==1.16.0
|
||||||
|
PyYAML==6.0
|
||||||
|
Flask==2.0.2
|
||||||
|
requests==2.27.1
|
||||||
|
iteration-utilities==0.11.0
|
||||||
|
dvc==2.9.3
|
||||||
|
dvc[ssh]
|
||||||
58
scripts/client_mock.py
Normal file
58
scripts/client_mock.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from operator import itemgetter
|
||||||
|
|
||||||
|
import pdf2image
|
||||||
|
import requests
|
||||||
|
from PIL import ImageDraw
|
||||||
|
|
||||||
|
|
||||||
|
def draw_coco_box(draw: ImageDraw.Draw, bbox, klass):
|
||||||
|
x1, y1, x2, y2 = itemgetter("x1", "y1", "x2", "y2")(bbox)
|
||||||
|
draw.rectangle(((x1, y1), (x2, y2)), outline="red")
|
||||||
|
draw.text((x1, y1), text=klass, fill=(0, 0, 0, 100))
|
||||||
|
|
||||||
|
|
||||||
|
def draw_coco_boxes(image, bboxes, classes):
|
||||||
|
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
for bbox, klass in zip(bboxes, classes):
|
||||||
|
draw_coco_box(draw, bbox, klass)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def annotate(pdf_path, predictions):
|
||||||
|
pages = pdf2image.convert_from_path(pdf_path)
|
||||||
|
|
||||||
|
for prd in predictions:
|
||||||
|
page_idx, boxes, classes = itemgetter("page_idx", "bboxes", "classes")(prd)
|
||||||
|
page = pages[page_idx]
|
||||||
|
image = draw_coco_boxes(page, boxes, classes)
|
||||||
|
image.save(f"/tmp/serv_out/{page_idx}.png")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--pdf_path", required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
|
||||||
|
response = requests.post("http://0.0.0.0:8080", data=open(args.pdf_path, "rb"))
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
predictions = response.json()
|
||||||
|
|
||||||
|
print(json.dumps(predictions, indent=2))
|
||||||
|
|
||||||
|
annotate(args.pdf_path, predictions)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = parse_args()
|
||||||
|
main(args)
|
||||||
35
scripts/flask_test.py
Normal file
35
scripts/flask_test.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.before_first_request
|
||||||
|
def init():
|
||||||
|
from fb_detr.predictor import Predictor
|
||||||
|
|
||||||
|
global PRED
|
||||||
|
|
||||||
|
PRED = Predictor(args.resume)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/", methods=["GET", "POST"])
|
||||||
|
def predict_request():
|
||||||
|
if request.method == "POST":
|
||||||
|
image_folder_path = request.form.get("image_folder_path")
|
||||||
|
images = list(map(Image.open, Path(image_folder_path).glob("*.png")))
|
||||||
|
results = PRED.predict(images, format_output=True)
|
||||||
|
for result in results:
|
||||||
|
return jsonify(result)
|
||||||
|
if request.method == "GET":
|
||||||
|
return "Not implemented"
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--resume", required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
app.run()
|
||||||
58
scripts/predict.py
Normal file
58
scripts/predict.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from detr.test import draw_boxes
|
||||||
|
from pdf2image import pdf2image
|
||||||
|
|
||||||
|
from fb_detr.predictor import Predictor
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--resume", required=True)
|
||||||
|
parser.add_argument("--output_dir", required=True)
|
||||||
|
parser.add_argument("--pdf_path")
|
||||||
|
parser.add_argument("--draw_boxes", default=False, action="store_true")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def build_image_paths(image_root_dir):
|
||||||
|
return [*map(str, Path(image_root_dir).glob("*.png"))]
|
||||||
|
|
||||||
|
|
||||||
|
def pdf_to_pages(pdf_path):
|
||||||
|
pages = pdf2image.convert_from_path(pdf_path)
|
||||||
|
return pages
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
# TDOO: de-hardcode
|
||||||
|
|
||||||
|
classes = {1: "logo", 2: "other", 3: "formula", 4: "signature", 5: "handwriting_other"}
|
||||||
|
|
||||||
|
args = parse_args()
|
||||||
|
predictor = Predictor(args.resume, classes=classes, rejection_class="other")
|
||||||
|
|
||||||
|
images = pdf_to_pages(args.pdf_path)
|
||||||
|
outputs = predictor.predict(images, 0.5)
|
||||||
|
|
||||||
|
if args.draw_boxes:
|
||||||
|
for im, o in zip(images, outputs):
|
||||||
|
if len(o["bboxes"]):
|
||||||
|
draw_boxes(image=im, **o, output_path=args.output_dir)
|
||||||
|
|
||||||
|
else:
|
||||||
|
outputs = predictor.format_predictions(outputs)
|
||||||
|
outputs = predictor.filter_predictions(outputs)
|
||||||
|
for o in outputs:
|
||||||
|
print(json.dumps(o, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
13
setup.py
Normal file
13
setup.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from distutils.core import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="fb_detr",
|
||||||
|
version="0.1.0",
|
||||||
|
description="",
|
||||||
|
author="",
|
||||||
|
author_email="",
|
||||||
|
url="",
|
||||||
|
packages=["fb_detr"],
|
||||||
|
)
|
||||||
14
setup/docker.sh
Executable file
14
setup/docker.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
python3 -m venv build_venv
|
||||||
|
source build_venv/bin/activate
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
|
||||||
|
pip install dvc
|
||||||
|
pip install 'dvc[ssh]'
|
||||||
|
dvc pull
|
||||||
|
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
docker build -t detr-server .
|
||||||
8
setup/docker_local.sh
Executable file
8
setup/docker_local.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
pip install -e .
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
cd incl/detr
|
||||||
|
pip install -e .
|
||||||
66
src/run_service.py
Normal file
66
src/run_service.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
|
||||||
|
from fb_detr.locations import DATA_DIR
|
||||||
|
from fb_detr.locations import TORCH_HOME
|
||||||
|
from fb_detr.predictor import Predictor
|
||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from pdf2image import pdf2image
|
||||||
|
from fb_detr.utils.config import read_config
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--resume")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def load_classes():
|
||||||
|
classes = read_config("classes")
|
||||||
|
id2class = dict(zip(range(1, len(classes) + 1), classes))
|
||||||
|
return id2class
|
||||||
|
|
||||||
|
|
||||||
|
def get_checkpoint():
|
||||||
|
return DATA_DIR / read_config("checkpoint")
|
||||||
|
|
||||||
|
|
||||||
|
def set_torch_env():
|
||||||
|
os.environ["TORCH_HOME"] = str(TORCH_HOME)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
set_torch_env()
|
||||||
|
|
||||||
|
def initialize_predictor():
|
||||||
|
checkpoint = get_checkpoint() if not args.resume else args.resume
|
||||||
|
predictor = Predictor(checkpoint, classes=load_classes(), rejection_class=read_config("rejection_class"))
|
||||||
|
return predictor
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/", methods=["POST"])
|
||||||
|
def predict_request():
|
||||||
|
|
||||||
|
pdf = request.data
|
||||||
|
|
||||||
|
pages = pdf2image.convert_from_bytes(pdf)
|
||||||
|
predictions = predictor.predict(pages, format_output=True)
|
||||||
|
|
||||||
|
return jsonify(list(predictions))
|
||||||
|
|
||||||
|
@app.route("/status", methods=["GET"])
|
||||||
|
def status():
|
||||||
|
response = "OK"
|
||||||
|
return jsonify(response)
|
||||||
|
|
||||||
|
predictor = initialize_predictor()
|
||||||
|
|
||||||
|
app.run(host="0.0.0.0", port=8080)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = parse_args()
|
||||||
|
main(args)
|
||||||
Loading…
x
Reference in New Issue
Block a user