Skip to content

Commit

Permalink
Adding ordering option image view
Browse files Browse the repository at this point in the history
  • Loading branch information
jsbroks committed Apr 17, 2019
1 parent 3d29d9b commit 7043ca5
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 42 deletions.
2 changes: 1 addition & 1 deletion backend/config/config.py
Expand Up @@ -9,7 +9,7 @@ def get_tag():

class Config:

NAME = "COCO Annotator"
NAME = os.getenv("NAME", "COCO Annotator")
VERSION = get_tag()

### File Watcher
Expand Down
63 changes: 34 additions & 29 deletions backend/webserver/api/datasets.py
Expand Up @@ -34,6 +34,7 @@
page_data.add_argument('page', default=1, type=int)
page_data.add_argument('limit', default=20, type=int)
page_data.add_argument('folder', default='', help='Folder for data')
page_data.add_argument('order', default='file_name', help='Order to display images')

delete_data = reqparse.RequestParser()
delete_data.add_argument('fully', default=False, type=bool,
Expand Down Expand Up @@ -285,7 +286,6 @@ def get(self):
"categories": query_util.fix_ids(current_user.categories.filter(deleted=False).all())
}


@api.route('/<int:dataset_id>/data')
class DatasetDataId(Resource):

Expand All @@ -295,35 +295,19 @@ class DatasetDataId(Resource):
def get(self, dataset_id):
""" Endpoint called by image viewer client """

args = page_data.parse_args()
limit = args['limit']
page = args['page']
folder = args['folder']
parsed_args = page_data.parse_args()
per_page = parsed_args.get('limit')
page = parsed_args.get('page') - 1
folder = parsed_args.get('folder')
order = parsed_args.get('order')

args = dict(request.args)
if args.get('limit') != None:
del args['limit']
if args.get('page') != None:
del args['page']
if args.get('folder') != None:
del args['folder']

query = {}
for key, value in args.items():
lower = value.lower()
if lower in ["true", "false"]:
value = json.loads(lower)

if len(lower) != 0:
query[key] = value

# print(query, flush=True)

# Check if dataset exists
dataset = current_user.datasets.filter(id=dataset_id, deleted=False).first()
if dataset is None:
return {'message', 'Invalid dataset id'}, 400

# Make sure folder starts with is in proper format
if len(folder) > 0:
folder = folder[0].strip('/') + folder[1:]
Expand All @@ -335,21 +319,39 @@ def get(self, dataset_id):
if not os.path.exists(directory):
return {'message': 'Directory does not exist.'}, 400

images = ImageModel.objects(dataset_id=dataset_id, path__startswith=directory, deleted=False, **query) \
.order_by('file_name').only('id', 'file_name', 'annotating')
# Remove parsed arguments
for key in parsed_args:
args.pop(key, None)

# Generate query from remaining arugments
query = {}
for key, value in args.items():
lower = value.lower()
if lower in ["true", "false"]:
value = json.loads(lower)

if len(lower) != 0:
query[key] = value

pagination = Pagination(images.count(), limit, page)
images = images[pagination.start:pagination.end]
images = current_user.images \
.filter(dataset_id=dataset_id, path__startswith=directory, deleted=False, **query) \
.order_by(order).only('id', 'file_name', 'annotating')

total = images.count()
pages = int(total/per_page) + 1

images = images.skip(page*per_page).limit(per_page)

images_json = []
for image in images:
image_json = query_util.fix_ids(image)

query = AnnotationModel.objects(image_id=image.id, deleted=False)
category_ids = query.distinct('category_id')
categories = CategoryModel.objects(id__in=category_ids).only('name', 'color')

image_json['annotations'] = query.count()
image_json['categories'] = query_util.fix_ids(CategoryModel.objects(id__in=category_ids).only('name', 'color'))
image_json['categories'] = query_util.fix_ids(categories)
image_json['permissions'] = image.permissions(current_user)

images_json.append(image_json)
Expand All @@ -361,7 +363,10 @@ def get(self, dataset_id):
categories = CategoryModel.objects(id__in=dataset.categories).only('id', 'name')

return {
"pagination": pagination.export(),
"total": total,
"per_page": per_page,
"pages": pages,
"page": page,
"images": images_json,
"folder": folder,
"directory": directory,
Expand Down
2 changes: 1 addition & 1 deletion backend/webserver/api/images.py
Expand Up @@ -22,7 +22,7 @@
image_all = reqparse.RequestParser()
image_all.add_argument('fields', required=False, type=str)
image_all.add_argument('page', default=1, type=int)
image_all.add_argument('perPage', default=50, type=int, required=False)
image_all.add_argument('per_page', default=50, type=int, required=False)

image_upload = reqparse.RequestParser()
image_upload.add_argument('image', location='files',
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/PanelInputDropdown.vue
Expand Up @@ -11,7 +11,7 @@

<script>
export default {
name: "PanelInputString",
name: "PanelInputDropdown",
model: {
prop: "value",
event: "update"
Expand Down
37 changes: 27 additions & 10 deletions client/src/views/Dataset.vue
Expand Up @@ -252,6 +252,7 @@
<PanelString name="Contains" v-model="query.file_name__icontains" @submit="updatePage" />
<PanelToggle name="Show Annotated" v-model="panel.showAnnotated" />
<PanelToggle name="Show Not Annotated" v-model="panel.showNotAnnotated" />
<PanelDropdown name="Order" v-model="order" :values="orderTypes" />
</div>
</div>

Expand Down Expand Up @@ -406,6 +407,7 @@ import ImageCard from "@/components/cards/ImageCard";
import Pagination from "@/components/Pagination";
import PanelString from "@/components/PanelInputString";
import PanelToggle from "@/components/PanelToggle";
import PanelDropdown from "@/components/PanelInputDropdown"
import JQuery from "jquery";
import TagsInput from "@/components/TagsInput";
Expand All @@ -420,6 +422,7 @@ export default {
Pagination,
PanelString,
PanelToggle,
PanelDropdown,
TagsInput
},
mixins: [toastrs],
Expand Down Expand Up @@ -450,7 +453,7 @@ export default {
mouseDown: false,
sidebar: {
drag: false,
width: 300,
width: window.innerWidth * 0.2,
canResize: false
},
scan: {
Expand All @@ -472,6 +475,12 @@ export default {
},
datasetExports: [],
tab: "images",
order: "file_name",
orderTypes: {
file_name: "File Name",
id: "Id",
path: "File Path"
},
query: {
file_name__icontains: "",
...this.$route.query
Expand Down Expand Up @@ -502,7 +511,8 @@ export default {
limit: this.limit,
folder: this.folders.join("/"),
...this.query,
annotated: this.queryAnnotated
annotated: this.queryAnnotated,
order: this.order
})
.then(response => {
let data = response.data;
Expand All @@ -511,8 +521,8 @@ export default {
this.dataset = data.dataset;
this.categories = data.categories;
this.imageCount = data.pagination.total;
this.pages = data.pagination.pages;
this.imageCount = data.total;
this.pages = data.pages;
this.subdirectories = data.subdirectories;
// this.scan.id = data.scanId;
Expand Down Expand Up @@ -617,7 +627,8 @@ export default {
if (this.sidebar.canResize) {
event.preventDefault();
let max = window.innerWidth * 0.5;
this.sidebar.width = Math.min(Math.max(event.x, 200), max);
this.sidebar.width = Math.min(Math.max(event.x, 150), max);
localStorage.setItem("dataset/sideWidth", this.sidebar.width)
}
},
startDrag() {
Expand Down Expand Up @@ -684,6 +695,10 @@ export default {
if (tab == "statistics") this.getStats();
if (tab == "exports") this.getExports();
},
order(order) {
localStorage.setItem("dataset/order", order);
this.updatePage();
},
queryAnnotated() {
this.updatePage();
},
Expand Down Expand Up @@ -732,18 +747,20 @@ export default {
this.updatePage();
},
created() {
this.sidebar.width = window.innerWidth * 0.2;
if (this.sidebar.width < 90) this.sidebar.width = 0;
let tab = localStorage.getItem("dataset/tab");
let order = localStorage.getItem("dataset/order");
let sideWidth = localStorage.getItem("dataset/sideWidth");
if (sideWidth !== null) this.sidebar.width = parseInt(sideWidth);
if (tab !== null) this.tab = tab;
if (order !== null) this.order = order;
this.dataset.id = parseInt(this.identifier);
this.updatePage();
},
mounted() {
window.addEventListener("mouseup", this.stopDrag);
window.addEventListener("mousedown", this.startDrag);
let tab = localStorage.getItem("dataset/tab");
if (tab !== null) this.tab = tab;
},
destroyed() {
window.removeEventListener("mouseup", this.stopDrag);
Expand Down
1 change: 1 addition & 0 deletions docker-compose.build.yml
Expand Up @@ -20,6 +20,7 @@ services:
environment:
- SECRET_KEY=RandomSecretKeyHere
- FILE_WATCHER=true
- NAME=Test Annotator
volumes:
- "./datasets:/datasets"
- "./models:/models"
Expand Down

0 comments on commit 7043ca5

Please sign in to comment.