diff --git a/.idea/ISAT_with_segment_anything.iml b/.idea/ISAT_with_segment_anything.iml index d0876a7..e7438cb 100644 --- a/.idea/ISAT_with_segment_anything.iml +++ b/.idea/ISAT_with_segment_anything.iml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 999906c..3f589e5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4441eb5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,16 @@ + + Copyright 2023 yatengLG + + https://github.com/yatengLG/ISAT_with_segment_anything + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README-CN.md b/README-CN.md index c690bff..c31940f 100644 --- a/README-CN.md +++ b/README-CN.md @@ -12,9 +12,54 @@ segment anything只是协助生成目标掩码,最终标注以多边形呈现,通过拖拽多边形顶点,可快速修改标注区域。 +## 安装 +### 1. 源码运行 +```shell +# 创建虚拟环境 +conda create -n ISAT_with_segment_anything python==3.8 +conda activate ISAT_with_segment_anything +``` + +```shell +# 安装Segment anything +git clone git@github.com:facebookresearch/segment-anything.git +cd segment-anything +pip install -e . +cd .. +``` + +```shell +# 安装ISAT_with_segment_anything +git clone https://github.com/yatengLG/ISAT_with_segment_anything.git +cd ISAT_with_segment_anything +pip install -r requirements.txt +``` + +```text +# 下载Segment anything预训练模型 +下载任一模型,并将模型存放于ISAT_with_segment_anything/segment_any目录下 +模型链接: + https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth + https://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pth + https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth +h模型最大,效果也最好; +b模型最小,效果也最差; +请按照硬件下载合适的模型,h模型在示例样本上的显存需求约8G. +``` + +```shell +# 运行软件 +python main.py +``` + + ## 标注操作 1. 通过鼠标左键(或右键)提示感兴趣区域(或不感兴趣区域),自动形成目标分割掩码 2. 可通过多次左右键提示,提升掩码质量 -3. 回车键确认掩码,选择类别,得到多边形标注区域 +3. E键结束标注,选择类别,得到多边形标注区域 4. 拖拽多边形顶点,精细化调整标注 + +## 注意事项 +1. 自动分割效果受segment anything模型分割效果限制,如需更为精确的分割效果,可通过手动绘制多边形实现。 +2. 如只需要使用手动绘制多边形标注,推荐使用[ISAT](https://github.com/yatengLG/ISAT)。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b1e753 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# ISAT图像分割标注工具 + +![examples/demo/标注组合图.png](examples/demo/标注组合图.png) + +基于多边形的图像分割标注工具,支持实例分割与语义分割。 + +## 特点 +主要对语义标注过程中存在标注重复部分进行优化。 +自己标注过分割样本,或者使用coco分割数据集的朋友,肯定遇到过标注多边形之间存在覆盖的问题。 +本项目通过引入多边形图层高低的方式,让上层的多边形覆盖下层多边形,从而保证每一个像素的类别都是单一的,降低数据的干扰。 + +* 支持对多边形图层进行调整(图层置顶或置底)。 +* 标注文件转png单通道图(支持实例与语义)。 +* 支持滚轮缩放,左键拖动图片。 +* 类别标签导入与导出,方便不同任务之间快速切换。 +## 安装 +### 1. 源码运行 +```shell +git clone https://github.com/yatengLG/ISAT.git +cd ISAT +conda create -n ISAT python==3.8 +conda activate ISAT +pip install -r requirements.txt +python main.py +``` +### 2. 下载打包好的exe +- 2.1 点击[链接](https://github.com/yatengLG/ISAT/releases/download/v1.0.0/ISAT_windows.zip)下载ISAT_windows.zip +- 2.2 解压 +- 2.3 双击ISAT/main.exe运行 + +## 标注结果 + +### 标注文件与标签图片 +ISAT提供了**json格式标注文件**,可以方便的进行传输与二次修改;同时,软件也提供将标注文件转换为**png单通道标签图片**的功能。 + +#### 1. json格式标注文件 +主要用于传输、备份以及二次修改。但不方便直接参与模型训练等过程。 + +存储信息包括:图片名、图片尺寸、图片额外说明、标注目标类别、标注目标实例id、标注目标多边形顶点等。 + +#### 2. png单通道标签图片 +主要用于模型的训练、测试等过程。 + +转换后的单通道标签图片具有与原图一致的分辨率,**参与模型训练时,直接读取像素值作为标签即可(图片为单通道图,像素值为单一的值,不是rgb)。** + +> 部分软件查看png单通道图片时,存在对颜色边界处进行调整的情况。具体表现为,如 (0, 5, 0)到(0, 255, 0)过渡时,边缘会出现(0, 125, 0)的情况。https://github.com/yatengLG/ISAT/issues/2#issue-1662058434 + +**最终的标签是图像的像素值,而非颜色值** +这种情况不会对标签图片造成影响,请放心使用。 + + +### 导出png单通道标签图片 +软件内置了,将json标注文件转换为png单通道标签图片的工具。 + +转换时,区分**语义分割**与**实例分割**: +- 语义分割 + + 转换后的语义分割png单通道标签图片中,每个像素值为对应的类别id,具体的类别含义与标注时类别设置相一致,同时在转换目录中也会留存一份classesition.txt,便于查看类别与id对应关系。 +- 实例分割 + + 转换后的实例分割png单通道标签图片中,每个像素值为对应的组id。 + +![examples/demo/将标注结果导出为png单通道图.png](examples/demo/将标注结果导出为png单通道图.png) diff --git a/annotation.py b/annotation.py new file mode 100644 index 0000000..013681b --- /dev/null +++ b/annotation.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +import os +import cv2 +from json import load, dump +from typing import List + + +class Object: + def __init__(self, category:str, group:int, segmentation, area, layer, bbox, iscrowd=0, note=''): + self.category = category + self.group = group + self.segmentation = segmentation + self.area = area + self.layer = layer + self.bbox = bbox + self.iscrowd = iscrowd + self.note = note + + +class Annotation: + def __init__(self, image_path, label_path): + img_folder, img_name = os.path.split(image_path) + self.description = 'ISAT' + self.img_folder = img_folder + self.img_name = img_name + self.label_path = label_path + self.note = '' + image = cv2.imread(image_path) + self.height, self.width, self.depth = image.shape + del image + + self.objects:List[Object,...] = [] + + def load_annotation(self): + if os.path.exists(self.label_path): + with open(self.label_path, 'r') as f: + dataset = load(f) + info = dataset.get('info', {}) + objects = dataset.get('objects', []) + + self.img_name = info.get('name', '') + self.width = info.get('width', 0) + self.height = info.get('height', 0) + self.depth = info.get('depth', 0) + self.note = info.get('note', '') + for obj in objects: + category = obj.get('category', 'unknow') + group = obj.get('group', '') + segmentation = obj.get('segmentation', []) + iscrowd = obj.get('iscrowd', 0) + note = obj.get('note', '') + area = obj.get('area', 0) + layer = obj.get('layer', 1) + bbox = obj.get('bbox', []) + obj = Object(category, group, segmentation, area, layer, bbox, iscrowd, note) + self.objects.append(obj) + + def save_annotation(self): + dataset = {} + dataset['info'] = {} + dataset['info']['description'] = self.description + dataset['info']['folder'] = self.img_folder + dataset['info']['name'] = self.img_name + dataset['info']['width'] = self.width + dataset['info']['height'] = self.height + dataset['info']['depth'] = self.depth + dataset['info']['note'] = self.note + dataset['objects'] = [] + for obj in self.objects: + object = {} + object['category'] = obj.category + object['group'] = obj.group + object['segmentation'] = obj.segmentation + object['area'] = obj.area + object['layer'] = obj.layer + object['bbox'] = obj.bbox + object['iscrowd'] = obj.iscrowd + object['note'] = obj.note + dataset['objects'].append(object) + with open(self.label_path, 'w') as f: + dump(dataset, f, indent=4) + return True diff --git a/configs.py b/configs.py new file mode 100644 index 0000000..8cab9f6 --- /dev/null +++ b/configs.py @@ -0,0 +1,35 @@ +import yaml +from enum import Enum + + +DEFAULT_CONFIG_FILE = 'default.yaml' +CONFIG_FILE = 'isat.yaml' + +def load_config(file): + with open(file, 'rb')as f: + cfg = yaml.load(f.read(), Loader=yaml.FullLoader) + return cfg + +def save_config(cfg, file): + s = yaml.dump(cfg) + with open(file, 'w') as f: + f.write(s) + return True + +class STATUSMode(Enum): + VIEW = 0 + CREATE = 1 + EDIT = 2 + +class DRAWMode(Enum): + POLYGON = 0 + SEGMENTANYTHING = 1 + +class CLICKMode(Enum): + POSITIVE = 0 + NEGATIVE = 1 + +class MAPMode(Enum): + LABEL = 0 + SEMANTIC = 1 + INSTANCE = 2 \ No newline at end of file diff --git a/default.yaml b/default.yaml new file mode 100644 index 0000000..130b2a5 --- /dev/null +++ b/default.yaml @@ -0,0 +1,3 @@ +label: +- color: '#000000' + name: __background__ diff --git a/example/images/000000000113.jpg b/example/images/000000000113.jpg new file mode 100644 index 0000000..17f27ee Binary files /dev/null and b/example/images/000000000113.jpg differ diff --git a/example/images/000000000113.json b/example/images/000000000113.json new file mode 100644 index 0000000..9d5e5e7 --- /dev/null +++ b/example/images/000000000113.json @@ -0,0 +1,2917 @@ +{ + "info": { + "description": "ISAT", + "folder": "/home/super/PycharmProjects/ISAT_with_segment_anything/example/images", + "name": "000000000113.jpg", + "width": 416, + "height": 640, + "depth": 3, + "note": "" + }, + "objects": [ + { + "category": "person", + "group": "1", + "segmentation": [ + [ + 99, + 36 + ], + [ + 95, + 37 + ], + [ + 92, + 38 + ], + [ + 86, + 41 + ], + [ + 83, + 43 + ], + [ + 81, + 45 + ], + [ + 79, + 48 + ], + [ + 77, + 51 + ], + [ + 76, + 53 + ], + [ + 72, + 65 + ], + [ + 71, + 71 + ], + [ + 71, + 82 + ], + [ + 73, + 86 + ], + [ + 72, + 96 + ], + [ + 73, + 99 + ], + [ + 75, + 102 + ], + [ + 76, + 105 + ], + [ + 77, + 108 + ], + [ + 77, + 111 + ], + [ + 75, + 115 + ], + [ + 64, + 125 + ], + [ + 61, + 127 + ], + [ + 56, + 129 + ], + [ + 51, + 133 + ], + [ + 46, + 135 + ], + [ + 38, + 140 + ], + [ + 29, + 146 + ], + [ + 17, + 158 + ], + [ + 15, + 161 + ], + [ + 14, + 163 + ], + [ + 12, + 168 + ], + [ + 12, + 172 + ], + [ + 10, + 176 + ], + [ + 9, + 185 + ], + [ + 9, + 202 + ], + [ + 7, + 218 + ], + [ + 8, + 237 + ], + [ + 8, + 244 + ], + [ + 7, + 269 + ], + [ + 9, + 274 + ], + [ + 9, + 279 + ], + [ + 12, + 288 + ], + [ + 12, + 293 + ], + [ + 13, + 297 + ], + [ + 14, + 300 + ], + [ + 17, + 308 + ], + [ + 19, + 310 + ], + [ + 27, + 327 + ], + [ + 31, + 338 + ], + [ + 31, + 341 + ], + [ + 30, + 347 + ], + [ + 31, + 353 + ], + [ + 34, + 363 + ], + [ + 34, + 369 + ], + [ + 35, + 373 + ], + [ + 39, + 377 + ], + [ + 40, + 379 + ], + [ + 41, + 382 + ], + [ + 42, + 385 + ], + [ + 42, + 389 + ], + [ + 43, + 390 + ], + [ + 43, + 393 + ], + [ + 40, + 400 + ], + [ + 40, + 422 + ], + [ + 41, + 430 + ], + [ + 43, + 434 + ], + [ + 43, + 442 + ], + [ + 42, + 445 + ], + [ + 39, + 451 + ], + [ + 39, + 455 + ], + [ + 37, + 459 + ], + [ + 36, + 464 + ], + [ + 35, + 469 + ], + [ + 35, + 480 + ], + [ + 38, + 480 + ], + [ + 41, + 479 + ], + [ + 44, + 478 + ], + [ + 46, + 477 + ], + [ + 46, + 472 + ], + [ + 42, + 465 + ], + [ + 42, + 463 + ], + [ + 44, + 461 + ], + [ + 46, + 460 + ], + [ + 51, + 458 + ], + [ + 62, + 454 + ], + [ + 66, + 453 + ], + [ + 77, + 450 + ], + [ + 85, + 449 + ], + [ + 87, + 448 + ], + [ + 89, + 446 + ], + [ + 89, + 438 + ], + [ + 88, + 426 + ], + [ + 86, + 417 + ], + [ + 86, + 415 + ], + [ + 87, + 412 + ], + [ + 89, + 410 + ], + [ + 94, + 408 + ], + [ + 98, + 407 + ], + [ + 117, + 402 + ], + [ + 122, + 402 + ], + [ + 131, + 400 + ], + [ + 140, + 397 + ], + [ + 141, + 395 + ], + [ + 142, + 392 + ], + [ + 143, + 387 + ], + [ + 145, + 377 + ], + [ + 146, + 370 + ], + [ + 147, + 356 + ], + [ + 147, + 336 + ], + [ + 146, + 323 + ], + [ + 144, + 318 + ], + [ + 144, + 310 + ], + [ + 147, + 304 + ], + [ + 150, + 301 + ], + [ + 152, + 298 + ], + [ + 153, + 292 + ], + [ + 154, + 286 + ], + [ + 155, + 278 + ], + [ + 154, + 238 + ], + [ + 155, + 219 + ], + [ + 155, + 207 + ], + [ + 154, + 199 + ], + [ + 153, + 190 + ], + [ + 151, + 185 + ], + [ + 150, + 174 + ], + [ + 148, + 165 + ], + [ + 147, + 161 + ], + [ + 145, + 156 + ], + [ + 139, + 144 + ], + [ + 137, + 142 + ], + [ + 137, + 141 + ], + [ + 136, + 140 + ], + [ + 132, + 137 + ], + [ + 127, + 135 + ], + [ + 125, + 133 + ], + [ + 125, + 130 + ], + [ + 129, + 125 + ], + [ + 133, + 117 + ], + [ + 134, + 114 + ], + [ + 135, + 109 + ], + [ + 135, + 85 + ], + [ + 137, + 80 + ], + [ + 138, + 74 + ], + [ + 138, + 63 + ], + [ + 137, + 58 + ], + [ + 136, + 55 + ], + [ + 135, + 53 + ], + [ + 128, + 46 + ], + [ + 124, + 44 + ], + [ + 119, + 41 + ], + [ + 111, + 37 + ], + [ + 107, + 36 + ] + ], + "area": 43212.5, + "layer": 1.0, + "bbox": [ + 7.0, + 36.0, + 155.0, + 480.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "1", + "segmentation": [ + [ + 34, + 510 + ], + [ + 34, + 527 + ], + [ + 36, + 540 + ], + [ + 36, + 558 + ], + [ + 38, + 561 + ], + [ + 38, + 573 + ], + [ + 39, + 577 + ], + [ + 40, + 579 + ], + [ + 41, + 581 + ], + [ + 45, + 586 + ], + [ + 50, + 591 + ], + [ + 53, + 596 + ], + [ + 58, + 600 + ], + [ + 59, + 604 + ], + [ + 60, + 606 + ], + [ + 67, + 612 + ], + [ + 68, + 613 + ], + [ + 69, + 615 + ], + [ + 71, + 620 + ], + [ + 76, + 625 + ], + [ + 78, + 628 + ], + [ + 79, + 631 + ], + [ + 83, + 636 + ], + [ + 86, + 639 + ], + [ + 95, + 639 + ], + [ + 95, + 637 + ], + [ + 96, + 636 + ], + [ + 97, + 617 + ], + [ + 97, + 599 + ], + [ + 96, + 595 + ], + [ + 94, + 590 + ], + [ + 91, + 586 + ], + [ + 88, + 583 + ], + [ + 87, + 583 + ], + [ + 84, + 580 + ], + [ + 83, + 577 + ], + [ + 82, + 574 + ], + [ + 81, + 569 + ], + [ + 81, + 562 + ], + [ + 79, + 559 + ], + [ + 73, + 552 + ], + [ + 68, + 546 + ], + [ + 61, + 538 + ], + [ + 56, + 534 + ], + [ + 52, + 529 + ], + [ + 48, + 523 + ], + [ + 39, + 513 + ], + [ + 36, + 510 + ] + ], + "area": 3881.0, + "layer": 2.0, + "bbox": [ + 34.0, + 510.0, + 97.0, + 639.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "2", + "segmentation": [ + [ + 227, + 53 + ], + [ + 222, + 55 + ], + [ + 216, + 58 + ], + [ + 208, + 63 + ], + [ + 205, + 65 + ], + [ + 202, + 68 + ], + [ + 200, + 71 + ], + [ + 198, + 74 + ], + [ + 197, + 76 + ], + [ + 195, + 83 + ], + [ + 195, + 88 + ], + [ + 194, + 91 + ], + [ + 191, + 94 + ], + [ + 190, + 96 + ], + [ + 189, + 98 + ], + [ + 189, + 100 + ], + [ + 188, + 102 + ], + [ + 189, + 106 + ], + [ + 193, + 117 + ], + [ + 193, + 123 + ], + [ + 195, + 126 + ], + [ + 196, + 129 + ], + [ + 199, + 131 + ], + [ + 199, + 133 + ], + [ + 201, + 133 + ], + [ + 204, + 134 + ], + [ + 206, + 135 + ], + [ + 208, + 136 + ], + [ + 209, + 137 + ], + [ + 212, + 141 + ], + [ + 214, + 146 + ], + [ + 215, + 149 + ], + [ + 216, + 153 + ], + [ + 216, + 161 + ], + [ + 214, + 164 + ], + [ + 211, + 167 + ], + [ + 207, + 167 + ], + [ + 202, + 170 + ], + [ + 199, + 171 + ], + [ + 196, + 171 + ], + [ + 193, + 172 + ], + [ + 189, + 175 + ], + [ + 174, + 181 + ], + [ + 170, + 185 + ], + [ + 166, + 187 + ], + [ + 165, + 189 + ], + [ + 165, + 192 + ], + [ + 163, + 196 + ], + [ + 163, + 200 + ], + [ + 160, + 207 + ], + [ + 158, + 216 + ], + [ + 158, + 281 + ], + [ + 156, + 286 + ], + [ + 156, + 297 + ], + [ + 157, + 299 + ], + [ + 159, + 301 + ], + [ + 160, + 304 + ], + [ + 161, + 305 + ], + [ + 161, + 306 + ], + [ + 162, + 308 + ], + [ + 161, + 318 + ], + [ + 160, + 326 + ], + [ + 158, + 330 + ], + [ + 158, + 336 + ], + [ + 156, + 341 + ], + [ + 155, + 346 + ], + [ + 155, + 359 + ], + [ + 153, + 362 + ], + [ + 152, + 370 + ], + [ + 151, + 378 + ], + [ + 150, + 391 + ], + [ + 151, + 394 + ], + [ + 159, + 393 + ], + [ + 164, + 391 + ], + [ + 171, + 391 + ], + [ + 175, + 389 + ], + [ + 180, + 388 + ], + [ + 192, + 388 + ], + [ + 197, + 387 + ], + [ + 200, + 385 + ], + [ + 205, + 384 + ], + [ + 210, + 383 + ], + [ + 218, + 383 + ], + [ + 222, + 381 + ], + [ + 227, + 381 + ], + [ + 230, + 379 + ], + [ + 235, + 379 + ], + [ + 237, + 381 + ], + [ + 238, + 381 + ], + [ + 239, + 382 + ], + [ + 240, + 384 + ], + [ + 241, + 392 + ], + [ + 241, + 403 + ], + [ + 242, + 405 + ], + [ + 249, + 406 + ], + [ + 251, + 404 + ], + [ + 254, + 407 + ], + [ + 256, + 411 + ], + [ + 261, + 411 + ], + [ + 262, + 416 + ], + [ + 262, + 423 + ], + [ + 263, + 427 + ], + [ + 265, + 429 + ], + [ + 269, + 428 + ], + [ + 270, + 425 + ], + [ + 270, + 421 + ], + [ + 269, + 419 + ], + [ + 267, + 417 + ], + [ + 267, + 409 + ], + [ + 266, + 406 + ], + [ + 264, + 404 + ], + [ + 263, + 396 + ], + [ + 259, + 392 + ], + [ + 257, + 389 + ], + [ + 257, + 385 + ], + [ + 255, + 383 + ], + [ + 254, + 380 + ], + [ + 251, + 378 + ], + [ + 251, + 376 + ], + [ + 252, + 373 + ], + [ + 254, + 369 + ], + [ + 255, + 367 + ], + [ + 258, + 367 + ], + [ + 258, + 368 + ], + [ + 260, + 370 + ], + [ + 260, + 374 + ], + [ + 261, + 377 + ], + [ + 262, + 379 + ], + [ + 265, + 382 + ], + [ + 269, + 383 + ], + [ + 270, + 385 + ], + [ + 271, + 387 + ], + [ + 271, + 389 + ], + [ + 272, + 391 + ], + [ + 275, + 395 + ], + [ + 275, + 397 + ], + [ + 279, + 401 + ], + [ + 279, + 403 + ], + [ + 281, + 405 + ], + [ + 284, + 407 + ], + [ + 286, + 408 + ], + [ + 288, + 406 + ], + [ + 294, + 406 + ], + [ + 297, + 405 + ], + [ + 302, + 402 + ], + [ + 304, + 402 + ], + [ + 306, + 401 + ], + [ + 307, + 380 + ], + [ + 306, + 371 + ], + [ + 303, + 359 + ], + [ + 302, + 351 + ], + [ + 302, + 349 + ], + [ + 303, + 339 + ], + [ + 304, + 336 + ], + [ + 310, + 323 + ], + [ + 311, + 320 + ], + [ + 315, + 300 + ], + [ + 316, + 297 + ], + [ + 317, + 294 + ], + [ + 318, + 292 + ], + [ + 324, + 291 + ], + [ + 328, + 290 + ], + [ + 332, + 288 + ], + [ + 336, + 288 + ], + [ + 338, + 286 + ], + [ + 338, + 283 + ], + [ + 337, + 282 + ], + [ + 336, + 273 + ], + [ + 331, + 254 + ], + [ + 329, + 244 + ], + [ + 328, + 234 + ], + [ + 327, + 229 + ], + [ + 326, + 224 + ], + [ + 324, + 220 + ], + [ + 323, + 216 + ], + [ + 323, + 208 + ], + [ + 322, + 204 + ], + [ + 321, + 201 + ], + [ + 320, + 198 + ], + [ + 318, + 195 + ], + [ + 317, + 192 + ], + [ + 316, + 186 + ], + [ + 313, + 180 + ], + [ + 310, + 177 + ], + [ + 302, + 173 + ], + [ + 299, + 172 + ], + [ + 296, + 171 + ], + [ + 293, + 171 + ], + [ + 290, + 170 + ], + [ + 287, + 168 + ], + [ + 284, + 168 + ], + [ + 281, + 166 + ], + [ + 277, + 166 + ], + [ + 272, + 163 + ], + [ + 265, + 162 + ], + [ + 264, + 159 + ], + [ + 260, + 158 + ], + [ + 258, + 157 + ], + [ + 256, + 155 + ], + [ + 255, + 153 + ], + [ + 255, + 150 + ], + [ + 256, + 147 + ], + [ + 258, + 142 + ], + [ + 261, + 135 + ], + [ + 262, + 133 + ], + [ + 265, + 130 + ], + [ + 266, + 130 + ], + [ + 268, + 128 + ], + [ + 269, + 125 + ], + [ + 272, + 122 + ], + [ + 273, + 120 + ], + [ + 274, + 118 + ], + [ + 275, + 105 + ], + [ + 275, + 97 + ], + [ + 274, + 88 + ], + [ + 273, + 82 + ], + [ + 272, + 79 + ], + [ + 271, + 77 + ], + [ + 266, + 69 + ], + [ + 264, + 66 + ], + [ + 259, + 61 + ], + [ + 255, + 58 + ], + [ + 253, + 57 + ], + [ + 251, + 56 + ], + [ + 248, + 55 + ], + [ + 241, + 53 + ] + ], + "area": 42806.0, + "layer": 3.0, + "bbox": [ + 150.0, + 53.0, + 338.0, + 429.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cup", + "group": "3", + "segmentation": [ + [ + 293, + 61 + ], + [ + 293, + 65 + ], + [ + 291, + 67 + ], + [ + 285, + 72 + ], + [ + 284, + 74 + ], + [ + 283, + 78 + ], + [ + 284, + 80 + ], + [ + 286, + 82 + ], + [ + 289, + 83 + ], + [ + 296, + 89 + ], + [ + 302, + 90 + ], + [ + 304, + 90 + ], + [ + 308, + 86 + ], + [ + 309, + 84 + ], + [ + 309, + 79 + ], + [ + 304, + 74 + ], + [ + 304, + 72 + ], + [ + 303, + 70 + ], + [ + 298, + 65 + ], + [ + 297, + 65 + ] + ], + "area": 438.5, + "layer": 4.0, + "bbox": [ + 283.0, + 61.0, + 309.0, + 90.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cup", + "group": "4", + "segmentation": [ + [ + 292, + 94 + ], + [ + 292, + 99 + ], + [ + 286, + 105 + ], + [ + 285, + 107 + ], + [ + 284, + 109 + ], + [ + 284, + 113 + ], + [ + 285, + 115 + ], + [ + 289, + 118 + ], + [ + 301, + 122 + ], + [ + 303, + 122 + ], + [ + 305, + 120 + ], + [ + 306, + 120 + ], + [ + 307, + 119 + ], + [ + 308, + 117 + ], + [ + 309, + 115 + ], + [ + 308, + 112 + ], + [ + 307, + 109 + ], + [ + 302, + 105 + ], + [ + 302, + 102 + ], + [ + 298, + 98 + ], + [ + 295, + 97 + ], + [ + 294, + 95 + ] + ], + "area": 418.43876946539604, + "layer": 5.0, + "bbox": [ + 283.78775389307975, + 93.57550778615949, + 309.3632616792392, + 121.57550778615949 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cup", + "group": "5", + "segmentation": [ + [ + 350, + 100 + ], + [ + 346, + 102 + ], + [ + 344, + 106 + ], + [ + 343, + 110 + ], + [ + 344, + 114 + ], + [ + 360, + 122 + ], + [ + 366, + 121 + ], + [ + 368, + 117 + ], + [ + 369, + 113 + ], + [ + 369, + 111 + ], + [ + 361, + 107 + ], + [ + 360, + 101 + ], + [ + 358, + 98 + ], + [ + 353, + 96 + ], + [ + 352, + 99 + ], + [ + 353, + 102 + ], + [ + 353, + 102 + ] + ], + "area": 401.1895807542678, + "layer": 6.0, + "bbox": [ + 343.4606973827665, + 96.10597495572824, + 368.6688219613182, + 122.10185342735966 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cup", + "group": "6", + "segmentation": [ + [ + 98, + 458 + ], + [ + 94, + 459 + ], + [ + 91, + 460 + ], + [ + 89, + 461 + ], + [ + 87, + 462 + ], + [ + 83, + 466 + ], + [ + 80, + 468 + ], + [ + 78, + 468 + ], + [ + 76, + 469 + ], + [ + 75, + 470 + ], + [ + 75, + 471 + ], + [ + 73, + 473 + ], + [ + 72, + 475 + ], + [ + 72, + 487 + ], + [ + 73, + 489 + ], + [ + 74, + 491 + ], + [ + 76, + 494 + ], + [ + 79, + 495 + ], + [ + 82, + 494 + ], + [ + 82, + 510 + ], + [ + 83, + 513 + ], + [ + 86, + 516 + ], + [ + 89, + 517 + ], + [ + 95, + 518 + ], + [ + 100, + 519 + ], + [ + 106, + 519 + ], + [ + 111, + 518 + ], + [ + 114, + 517 + ], + [ + 116, + 516 + ], + [ + 119, + 513 + ], + [ + 120, + 511 + ], + [ + 121, + 509 + ], + [ + 122, + 486 + ], + [ + 122, + 469 + ], + [ + 121, + 464 + ], + [ + 118, + 461 + ], + [ + 116, + 460 + ], + [ + 112, + 459 + ], + [ + 103, + 458 + ] + ], + "area": 2483.5, + "layer": 7.0, + "bbox": [ + 72.0, + 458.0, + 122.0, + 519.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cake", + "group": "7", + "segmentation": [ + [ + 274, + 430 + ], + [ + 270, + 432 + ], + [ + 266, + 432 + ], + [ + 262, + 433 + ], + [ + 249, + 438 + ], + [ + 244, + 438 + ], + [ + 237, + 440 + ], + [ + 221, + 445 + ], + [ + 213, + 448 + ], + [ + 208, + 451 + ], + [ + 202, + 452 + ], + [ + 199, + 453 + ], + [ + 185, + 458 + ], + [ + 180, + 460 + ], + [ + 178, + 461 + ], + [ + 176, + 463 + ], + [ + 169, + 465 + ], + [ + 164, + 468 + ], + [ + 161, + 470 + ], + [ + 157, + 473 + ], + [ + 155, + 476 + ], + [ + 153, + 479 + ], + [ + 151, + 484 + ], + [ + 151, + 488 + ], + [ + 153, + 491 + ], + [ + 159, + 495 + ], + [ + 163, + 498 + ], + [ + 165, + 498 + ], + [ + 169, + 502 + ], + [ + 176, + 506 + ], + [ + 179, + 508 + ], + [ + 180, + 509 + ], + [ + 180, + 510 + ], + [ + 181, + 511 + ], + [ + 184, + 513 + ], + [ + 188, + 516 + ], + [ + 190, + 516 + ], + [ + 195, + 521 + ], + [ + 198, + 523 + ], + [ + 204, + 526 + ], + [ + 207, + 528 + ], + [ + 214, + 534 + ], + [ + 218, + 537 + ], + [ + 220, + 537 + ], + [ + 223, + 541 + ], + [ + 225, + 541 + ], + [ + 231, + 546 + ], + [ + 234, + 548 + ], + [ + 237, + 549 + ], + [ + 237, + 550 + ], + [ + 240, + 551 + ], + [ + 244, + 554 + ], + [ + 248, + 558 + ], + [ + 250, + 558 + ], + [ + 253, + 561 + ], + [ + 255, + 561 + ], + [ + 256, + 563 + ], + [ + 259, + 564 + ], + [ + 264, + 568 + ], + [ + 269, + 569 + ], + [ + 273, + 568 + ], + [ + 275, + 566 + ], + [ + 278, + 566 + ], + [ + 285, + 563 + ], + [ + 287, + 561 + ], + [ + 289, + 561 + ], + [ + 297, + 556 + ], + [ + 305, + 553 + ], + [ + 312, + 548 + ], + [ + 314, + 548 + ], + [ + 316, + 546 + ], + [ + 324, + 543 + ], + [ + 332, + 538 + ], + [ + 334, + 538 + ], + [ + 336, + 536 + ], + [ + 346, + 531 + ], + [ + 348, + 531 + ], + [ + 358, + 526 + ], + [ + 368, + 521 + ], + [ + 389, + 509 + ], + [ + 393, + 508 + ], + [ + 396, + 506 + ], + [ + 401, + 503 + ], + [ + 403, + 500 + ], + [ + 402, + 495 + ], + [ + 404, + 489 + ], + [ + 400, + 485 + ], + [ + 396, + 483 + ], + [ + 391, + 480 + ], + [ + 389, + 479 + ], + [ + 387, + 478 + ], + [ + 385, + 478 + ], + [ + 383, + 477 + ], + [ + 379, + 474 + ], + [ + 377, + 473 + ], + [ + 375, + 473 + ], + [ + 371, + 470 + ], + [ + 365, + 468 + ], + [ + 361, + 465 + ], + [ + 359, + 464 + ], + [ + 357, + 463 + ], + [ + 354, + 463 + ], + [ + 349, + 460 + ], + [ + 344, + 459 + ], + [ + 331, + 452 + ], + [ + 318, + 447 + ], + [ + 311, + 442 + ], + [ + 309, + 442 + ], + [ + 305, + 439 + ], + [ + 303, + 438 + ], + [ + 299, + 438 + ], + [ + 299, + 440 + ], + [ + 300, + 441 + ], + [ + 300, + 444 + ], + [ + 302, + 446 + ], + [ + 302, + 450 + ], + [ + 298, + 450 + ], + [ + 292, + 447 + ], + [ + 289, + 444 + ], + [ + 284, + 437 + ], + [ + 283, + 434 + ], + [ + 281, + 432 + ], + [ + 281, + 431 + ] + ], + "area": 20160.5, + "layer": 8.0, + "bbox": [ + 151.0, + 430.0, + 404.0, + 569.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "knife", + "group": "8", + "segmentation": [ + [ + 255, + 366 + ], + [ + 253, + 376 + ], + [ + 256, + 379 + ], + [ + 257, + 381 + ], + [ + 257, + 383 + ], + [ + 261, + 388 + ], + [ + 261, + 390 + ], + [ + 264, + 393 + ], + [ + 265, + 397 + ], + [ + 264, + 398 + ], + [ + 264, + 400 + ], + [ + 265, + 402 + ], + [ + 266, + 404 + ], + [ + 269, + 409 + ], + [ + 275, + 416 + ], + [ + 280, + 424 + ], + [ + 286, + 436 + ], + [ + 288, + 439 + ], + [ + 290, + 442 + ], + [ + 293, + 446 + ], + [ + 299, + 449 + ], + [ + 301, + 449 + ], + [ + 300, + 446 + ], + [ + 297, + 441 + ], + [ + 297, + 439 + ], + [ + 292, + 428 + ], + [ + 291, + 426 + ], + [ + 290, + 424 + ], + [ + 284, + 415 + ], + [ + 283, + 413 + ], + [ + 282, + 411 + ], + [ + 282, + 408 + ], + [ + 277, + 404 + ], + [ + 273, + 397 + ], + [ + 269, + 387 + ], + [ + 268, + 385 + ], + [ + 265, + 385 + ], + [ + 263, + 384 + ], + [ + 261, + 382 + ], + [ + 260, + 380 + ], + [ + 259, + 377 + ], + [ + 258, + 369 + ], + [ + 257, + 367 + ] + ], + "area": 684.0, + "layer": 9.0, + "bbox": [ + 253.0, + 366.0, + 301.0, + 449.0 + ], + "iscrowd": 0, + "note": "" + } + ] +} \ No newline at end of file diff --git a/example/images/000000000144.jpg b/example/images/000000000144.jpg new file mode 100644 index 0000000..8d59a04 Binary files /dev/null and b/example/images/000000000144.jpg differ diff --git a/example/images/000000000144.json b/example/images/000000000144.json new file mode 100644 index 0000000..043e62b --- /dev/null +++ b/example/images/000000000144.json @@ -0,0 +1,813 @@ +{ + "info": { + "description": "ISAT", + "folder": "C:/Users/lg/PycharmProjects/ISAT_with_segment_anything/example/images", + "name": "000000000144.jpg", + "width": 640, + "height": 480, + "depth": 3, + "note": "" + }, + "objects": [ + { + "category": "fence", + "group": "1", + "segmentation": [ + [ + 20, + 239 + ], + [ + 17, + 240 + ], + [ + 15, + 241 + ], + [ + 13, + 242 + ], + [ + 11, + 244 + ], + [ + 10, + 244 + ], + [ + 9, + 245 + ], + [ + 6, + 249 + ], + [ + 5, + 251 + ], + [ + 4, + 255 + ], + [ + 0, + 261 + ], + [ + 0, + 280 + ], + [ + 1, + 277 + ], + [ + 6, + 268 + ], + [ + 9, + 259 + ], + [ + 13, + 254 + ], + [ + 13, + 252 + ], + [ + 15, + 250 + ], + [ + 18, + 248 + ], + [ + 20, + 247 + ], + [ + 24, + 247 + ], + [ + 26, + 248 + ], + [ + 30, + 252 + ], + [ + 33, + 256 + ], + [ + 35, + 260 + ], + [ + 38, + 266 + ], + [ + 41, + 273 + ], + [ + 43, + 280 + ], + [ + 50, + 294 + ], + [ + 53, + 297 + ], + [ + 54, + 297 + ], + [ + 59, + 301 + ], + [ + 61, + 303 + ], + [ + 62, + 316 + ], + [ + 63, + 341 + ], + [ + 63, + 382 + ], + [ + 64, + 405 + ], + [ + 66, + 414 + ], + [ + 71, + 413 + ], + [ + 72, + 402 + ], + [ + 72, + 399 + ], + [ + 71, + 359 + ], + [ + 69, + 324 + ], + [ + 70, + 300 + ], + [ + 73, + 299 + ], + [ + 78, + 294 + ], + [ + 80, + 291 + ], + [ + 81, + 289 + ], + [ + 83, + 283 + ], + [ + 85, + 278 + ], + [ + 86, + 272 + ], + [ + 91, + 258 + ], + [ + 94, + 252 + ], + [ + 98, + 248 + ], + [ + 105, + 248 + ], + [ + 107, + 249 + ], + [ + 111, + 253 + ], + [ + 116, + 261 + ], + [ + 118, + 265 + ], + [ + 121, + 271 + ], + [ + 128, + 288 + ], + [ + 130, + 291 + ], + [ + 135, + 296 + ], + [ + 138, + 298 + ], + [ + 140, + 299 + ], + [ + 143, + 300 + ], + [ + 148, + 300 + ], + [ + 151, + 299 + ], + [ + 153, + 298 + ], + [ + 156, + 296 + ], + [ + 159, + 293 + ], + [ + 161, + 290 + ], + [ + 164, + 284 + ], + [ + 179, + 255 + ], + [ + 180, + 253 + ], + [ + 180, + 251 + ], + [ + 181, + 249 + ], + [ + 183, + 247 + ], + [ + 186, + 248 + ], + [ + 187, + 259 + ], + [ + 188, + 282 + ], + [ + 188, + 303 + ], + [ + 190, + 320 + ], + [ + 190, + 343 + ], + [ + 191, + 355 + ], + [ + 192, + 357 + ], + [ + 196, + 358 + ], + [ + 198, + 357 + ], + [ + 200, + 353 + ], + [ + 200, + 341 + ], + [ + 198, + 321 + ], + [ + 197, + 300 + ], + [ + 196, + 279 + ], + [ + 195, + 252 + ], + [ + 195, + 250 + ], + [ + 196, + 248 + ], + [ + 200, + 248 + ], + [ + 200, + 249 + ], + [ + 202, + 251 + ], + [ + 207, + 260 + ], + [ + 208, + 262 + ], + [ + 208, + 264 + ], + [ + 210, + 266 + ], + [ + 212, + 273 + ], + [ + 215, + 279 + ], + [ + 217, + 281 + ], + [ + 218, + 283 + ], + [ + 219, + 287 + ], + [ + 221, + 290 + ], + [ + 225, + 294 + ], + [ + 227, + 295 + ], + [ + 230, + 296 + ], + [ + 235, + 296 + ], + [ + 239, + 295 + ], + [ + 241, + 294 + ], + [ + 245, + 290 + ], + [ + 246, + 288 + ], + [ + 247, + 286 + ], + [ + 248, + 283 + ], + [ + 248, + 279 + ], + [ + 245, + 281 + ], + [ + 244, + 283 + ], + [ + 244, + 285 + ], + [ + 243, + 287 + ], + [ + 238, + 292 + ], + [ + 230, + 292 + ], + [ + 228, + 291 + ], + [ + 224, + 287 + ], + [ + 222, + 284 + ], + [ + 219, + 278 + ], + [ + 214, + 268 + ], + [ + 214, + 266 + ], + [ + 207, + 252 + ], + [ + 205, + 249 + ], + [ + 201, + 245 + ], + [ + 198, + 243 + ], + [ + 194, + 242 + ], + [ + 188, + 242 + ], + [ + 183, + 243 + ], + [ + 180, + 244 + ], + [ + 176, + 246 + ], + [ + 174, + 249 + ], + [ + 172, + 252 + ], + [ + 170, + 256 + ], + [ + 169, + 260 + ], + [ + 168, + 262 + ], + [ + 166, + 264 + ], + [ + 165, + 266 + ], + [ + 164, + 268 + ], + [ + 161, + 276 + ], + [ + 156, + 286 + ], + [ + 153, + 290 + ], + [ + 152, + 291 + ], + [ + 151, + 291 + ], + [ + 149, + 293 + ], + [ + 147, + 293 + ], + [ + 144, + 293 + ], + [ + 142, + 293 + ], + [ + 140, + 292 + ], + [ + 138, + 290 + ], + [ + 136, + 287 + ], + [ + 133, + 281 + ], + [ + 125, + 263 + ], + [ + 123, + 259 + ], + [ + 120, + 253 + ], + [ + 117, + 248 + ], + [ + 112, + 243 + ], + [ + 110, + 242 + ], + [ + 107, + 241 + ], + [ + 98, + 241 + ], + [ + 96, + 242 + ], + [ + 94, + 243 + ], + [ + 89, + 248 + ], + [ + 85, + 256 + ], + [ + 83, + 261 + ], + [ + 81, + 269 + ], + [ + 78, + 274 + ], + [ + 76, + 282 + ], + [ + 74, + 287 + ], + [ + 73, + 289 + ], + [ + 67, + 295 + ], + [ + 63, + 295 + ], + [ + 61, + 294 + ], + [ + 55, + 288 + ], + [ + 53, + 284 + ], + [ + 50, + 278 + ], + [ + 49, + 273 + ], + [ + 41, + 254 + ], + [ + 40, + 252 + ], + [ + 38, + 249 + ], + [ + 35, + 246 + ], + [ + 35, + 245 + ], + [ + 33, + 243 + ], + [ + 30, + 241 + ], + [ + 28, + 240 + ], + [ + 24, + 239 + ] + ], + "area": 4485.0, + "layer": 1.0, + "bbox": [ + 0.0, + 239.0, + 248.0, + 414.0 + ], + "iscrowd": 0, + "note": "" + } + ] +} \ No newline at end of file diff --git a/example/images/000000000308.jpg b/example/images/000000000308.jpg new file mode 100644 index 0000000..b298688 Binary files /dev/null and b/example/images/000000000308.jpg differ diff --git a/example/images/000000000308.json b/example/images/000000000308.json new file mode 100644 index 0000000..265297a --- /dev/null +++ b/example/images/000000000308.json @@ -0,0 +1,1617 @@ +{ + "info": { + "description": "ISAT", + "folder": "/home/super/PycharmProjects/ISAT_with_segment_anything/example/images", + "name": "000000000308.jpg", + "width": 640, + "height": 426, + "depth": 3, + "note": "" + }, + "objects": [ + { + "category": "table", + "group": "1", + "segmentation": [ + [ + 387, + 252 + ], + [ + 385, + 253 + ], + [ + 384, + 254 + ], + [ + 382, + 257 + ], + [ + 381, + 257 + ], + [ + 380, + 271 + ], + [ + 382, + 273 + ], + [ + 385, + 274 + ], + [ + 389, + 278 + ], + [ + 388, + 282 + ], + [ + 387, + 282 + ], + [ + 385, + 284 + ], + [ + 381, + 285 + ], + [ + 375, + 285 + ], + [ + 372, + 284 + ], + [ + 370, + 283 + ], + [ + 368, + 282 + ], + [ + 367, + 279 + ], + [ + 368, + 277 + ], + [ + 370, + 275 + ], + [ + 374, + 273 + ], + [ + 375, + 271 + ], + [ + 375, + 266 + ], + [ + 374, + 260 + ], + [ + 372, + 257 + ], + [ + 367, + 253 + ], + [ + 364, + 254 + ], + [ + 364, + 256 + ], + [ + 361, + 261 + ], + [ + 360, + 262 + ], + [ + 359, + 263 + ], + [ + 346, + 265 + ], + [ + 343, + 265 + ], + [ + 329, + 264 + ], + [ + 327, + 262 + ], + [ + 328, + 259 + ], + [ + 330, + 256 + ], + [ + 329, + 253 + ], + [ + 320, + 253 + ], + [ + 313, + 254 + ], + [ + 295, + 257 + ], + [ + 290, + 258 + ], + [ + 285, + 259 + ], + [ + 274, + 262 + ], + [ + 264, + 265 + ], + [ + 259, + 268 + ], + [ + 256, + 269 + ], + [ + 253, + 269 + ], + [ + 248, + 271 + ], + [ + 242, + 274 + ], + [ + 237, + 278 + ], + [ + 232, + 280 + ], + [ + 229, + 282 + ], + [ + 225, + 285 + ], + [ + 219, + 291 + ], + [ + 217, + 294 + ], + [ + 214, + 299 + ], + [ + 213, + 302 + ], + [ + 212, + 307 + ], + [ + 212, + 314 + ], + [ + 213, + 318 + ], + [ + 216, + 324 + ], + [ + 218, + 327 + ], + [ + 224, + 333 + ], + [ + 228, + 336 + ], + [ + 233, + 339 + ], + [ + 237, + 340 + ], + [ + 240, + 343 + ], + [ + 242, + 344 + ], + [ + 247, + 345 + ], + [ + 252, + 347 + ], + [ + 254, + 348 + ], + [ + 257, + 351 + ], + [ + 255, + 358 + ], + [ + 254, + 368 + ], + [ + 253, + 398 + ], + [ + 253, + 417 + ], + [ + 255, + 424 + ], + [ + 446, + 423 + ], + [ + 447, + 415 + ], + [ + 446, + 390 + ], + [ + 445, + 380 + ], + [ + 444, + 371 + ], + [ + 443, + 366 + ], + [ + 442, + 360 + ], + [ + 439, + 352 + ], + [ + 438, + 348 + ], + [ + 436, + 336 + ], + [ + 435, + 335 + ], + [ + 435, + 333 + ], + [ + 439, + 329 + ], + [ + 444, + 326 + ], + [ + 449, + 324 + ], + [ + 454, + 320 + ], + [ + 466, + 308 + ], + [ + 469, + 303 + ], + [ + 470, + 300 + ], + [ + 470, + 291 + ], + [ + 467, + 285 + ], + [ + 465, + 282 + ], + [ + 463, + 280 + ], + [ + 460, + 278 + ], + [ + 458, + 276 + ], + [ + 458, + 278 + ], + [ + 456, + 280 + ], + [ + 456, + 282 + ], + [ + 455, + 284 + ], + [ + 451, + 288 + ], + [ + 449, + 289 + ], + [ + 428, + 289 + ], + [ + 424, + 288 + ], + [ + 422, + 287 + ], + [ + 420, + 285 + ], + [ + 418, + 285 + ], + [ + 416, + 284 + ], + [ + 411, + 285 + ], + [ + 408, + 287 + ], + [ + 406, + 287 + ], + [ + 404, + 286 + ], + [ + 403, + 285 + ], + [ + 401, + 283 + ], + [ + 400, + 277 + ], + [ + 401, + 274 + ], + [ + 404, + 270 + ], + [ + 404, + 264 + ], + [ + 405, + 261 + ], + [ + 407, + 254 + ], + [ + 404, + 253 + ], + [ + 396, + 252 + ] + ], + "area": 32913.0, + "layer": 1.0, + "bbox": [ + 212.0, + 252.0, + 470.0, + 424.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "2", + "segmentation": [ + [ + 196, + 30 + ], + [ + 191, + 31 + ], + [ + 189, + 32 + ], + [ + 187, + 33 + ], + [ + 181, + 39 + ], + [ + 179, + 42 + ], + [ + 178, + 44 + ], + [ + 177, + 48 + ], + [ + 179, + 61 + ], + [ + 178, + 69 + ], + [ + 179, + 72 + ], + [ + 183, + 79 + ], + [ + 183, + 85 + ], + [ + 182, + 87 + ], + [ + 179, + 88 + ], + [ + 176, + 91 + ], + [ + 174, + 95 + ], + [ + 172, + 97 + ], + [ + 168, + 99 + ], + [ + 153, + 106 + ], + [ + 150, + 108 + ], + [ + 147, + 110 + ], + [ + 142, + 115 + ], + [ + 140, + 118 + ], + [ + 138, + 121 + ], + [ + 137, + 124 + ], + [ + 136, + 134 + ], + [ + 135, + 148 + ], + [ + 136, + 154 + ], + [ + 135, + 163 + ], + [ + 136, + 169 + ], + [ + 137, + 174 + ], + [ + 138, + 178 + ], + [ + 140, + 180 + ], + [ + 141, + 187 + ], + [ + 143, + 190 + ], + [ + 144, + 193 + ], + [ + 144, + 197 + ], + [ + 145, + 200 + ], + [ + 148, + 204 + ], + [ + 149, + 208 + ], + [ + 156, + 208 + ], + [ + 154, + 206 + ], + [ + 154, + 204 + ], + [ + 152, + 201 + ], + [ + 149, + 198 + ], + [ + 148, + 196 + ], + [ + 148, + 190 + ], + [ + 146, + 188 + ], + [ + 146, + 168 + ], + [ + 147, + 161 + ], + [ + 150, + 158 + ], + [ + 153, + 157 + ], + [ + 158, + 156 + ], + [ + 163, + 155 + ], + [ + 179, + 156 + ], + [ + 182, + 161 + ], + [ + 183, + 164 + ], + [ + 187, + 176 + ], + [ + 188, + 180 + ], + [ + 189, + 188 + ], + [ + 188, + 194 + ], + [ + 185, + 200 + ], + [ + 180, + 206 + ], + [ + 179, + 208 + ], + [ + 179, + 211 + ], + [ + 182, + 214 + ], + [ + 183, + 217 + ], + [ + 182, + 233 + ], + [ + 183, + 239 + ], + [ + 185, + 240 + ], + [ + 190, + 240 + ], + [ + 192, + 242 + ], + [ + 193, + 242 + ], + [ + 194, + 247 + ], + [ + 192, + 249 + ], + [ + 190, + 250 + ], + [ + 188, + 251 + ], + [ + 185, + 252 + ], + [ + 178, + 254 + ], + [ + 172, + 255 + ], + [ + 170, + 255 + ], + [ + 165, + 254 + ], + [ + 163, + 255 + ], + [ + 162, + 258 + ], + [ + 164, + 260 + ], + [ + 166, + 261 + ], + [ + 171, + 262 + ], + [ + 178, + 268 + ], + [ + 181, + 271 + ], + [ + 182, + 273 + ], + [ + 182, + 276 + ], + [ + 181, + 277 + ], + [ + 182, + 280 + ], + [ + 181, + 282 + ], + [ + 169, + 294 + ], + [ + 169, + 296 + ], + [ + 171, + 302 + ], + [ + 178, + 315 + ], + [ + 179, + 321 + ], + [ + 179, + 344 + ], + [ + 181, + 354 + ], + [ + 181, + 371 + ], + [ + 182, + 382 + ], + [ + 183, + 388 + ], + [ + 184, + 392 + ], + [ + 185, + 396 + ], + [ + 187, + 400 + ], + [ + 188, + 404 + ], + [ + 188, + 409 + ], + [ + 190, + 414 + ], + [ + 191, + 420 + ], + [ + 191, + 424 + ], + [ + 215, + 424 + ], + [ + 217, + 422 + ], + [ + 218, + 419 + ], + [ + 220, + 413 + ], + [ + 221, + 407 + ], + [ + 220, + 398 + ], + [ + 216, + 385 + ], + [ + 214, + 376 + ], + [ + 214, + 368 + ], + [ + 212, + 362 + ], + [ + 211, + 355 + ], + [ + 210, + 315 + ], + [ + 210, + 306 + ], + [ + 211, + 302 + ], + [ + 212, + 299 + ], + [ + 213, + 297 + ], + [ + 214, + 295 + ], + [ + 216, + 292 + ], + [ + 221, + 286 + ], + [ + 223, + 284 + ], + [ + 228, + 280 + ], + [ + 231, + 278 + ], + [ + 236, + 275 + ], + [ + 243, + 271 + ], + [ + 245, + 270 + ], + [ + 247, + 269 + ], + [ + 254, + 267 + ], + [ + 258, + 265 + ], + [ + 258, + 256 + ], + [ + 256, + 250 + ], + [ + 255, + 248 + ], + [ + 256, + 243 + ], + [ + 258, + 238 + ], + [ + 258, + 224 + ], + [ + 257, + 221 + ], + [ + 256, + 218 + ], + [ + 253, + 215 + ], + [ + 252, + 213 + ], + [ + 252, + 210 + ], + [ + 250, + 206 + ], + [ + 248, + 204 + ], + [ + 246, + 204 + ], + [ + 244, + 202 + ], + [ + 244, + 201 + ], + [ + 242, + 199 + ], + [ + 247, + 195 + ], + [ + 248, + 193 + ], + [ + 248, + 191 + ], + [ + 248, + 189 + ], + [ + 247, + 186 + ], + [ + 245, + 184 + ], + [ + 242, + 183 + ], + [ + 240, + 181 + ], + [ + 239, + 181 + ], + [ + 238, + 180 + ], + [ + 237, + 178 + ], + [ + 236, + 176 + ], + [ + 235, + 172 + ], + [ + 235, + 168 + ], + [ + 236, + 167 + ], + [ + 236, + 162 + ], + [ + 237, + 159 + ], + [ + 238, + 156 + ], + [ + 239, + 154 + ], + [ + 240, + 152 + ], + [ + 244, + 149 + ], + [ + 245, + 140 + ], + [ + 244, + 131 + ], + [ + 243, + 128 + ], + [ + 242, + 125 + ], + [ + 239, + 118 + ], + [ + 236, + 112 + ], + [ + 230, + 106 + ], + [ + 221, + 101 + ], + [ + 219, + 101 + ], + [ + 216, + 98 + ], + [ + 216, + 93 + ], + [ + 219, + 87 + ], + [ + 220, + 84 + ], + [ + 221, + 77 + ], + [ + 223, + 74 + ], + [ + 222, + 63 + ], + [ + 222, + 57 + ], + [ + 223, + 43 + ], + [ + 217, + 37 + ], + [ + 209, + 32 + ], + [ + 206, + 31 + ], + [ + 201, + 30 + ] + ], + "area": 21741.5, + "layer": 2.0, + "bbox": [ + 135.0, + 30.0, + 258.0, + 424.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "2", + "segmentation": [ + [ + 239, + 345 + ], + [ + 238, + 347 + ], + [ + 239, + 370 + ], + [ + 239, + 374 + ], + [ + 238, + 383 + ], + [ + 236, + 388 + ], + [ + 236, + 396 + ], + [ + 239, + 399 + ], + [ + 241, + 400 + ], + [ + 248, + 401 + ], + [ + 249, + 402 + ], + [ + 251, + 402 + ], + [ + 252, + 400 + ], + [ + 251, + 393 + ], + [ + 251, + 389 + ], + [ + 252, + 370 + ], + [ + 254, + 358 + ], + [ + 253, + 350 + ], + [ + 251, + 349 + ], + [ + 249, + 348 + ], + [ + 244, + 347 + ], + [ + 241, + 345 + ] + ], + "area": 760.0, + "layer": 3.0, + "bbox": [ + 236.0, + 345.0, + 254.0, + 402.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "cup", + "group": "3", + "segmentation": [ + [ + 375, + 223 + ], + [ + 370, + 224 + ], + [ + 368, + 225 + ], + [ + 366, + 227 + ], + [ + 365, + 234 + ], + [ + 365, + 244 + ], + [ + 366, + 247 + ], + [ + 367, + 250 + ], + [ + 368, + 252 + ], + [ + 374, + 256 + ], + [ + 376, + 258 + ], + [ + 375, + 276 + ], + [ + 369, + 278 + ], + [ + 369, + 281 + ], + [ + 371, + 282 + ], + [ + 373, + 283 + ], + [ + 383, + 283 + ], + [ + 387, + 281 + ], + [ + 387, + 280 + ], + [ + 387, + 277 + ], + [ + 385, + 276 + ], + [ + 382, + 276 + ], + [ + 379, + 275 + ], + [ + 377, + 273 + ], + [ + 377, + 258 + ], + [ + 379, + 256 + ], + [ + 385, + 251 + ], + [ + 386, + 249 + ], + [ + 387, + 246 + ], + [ + 387, + 237 + ], + [ + 386, + 232 + ], + [ + 385, + 227 + ], + [ + 381, + 223 + ] + ], + "area": 766.0, + "layer": 4.0, + "bbox": [ + 365.0, + 223.0, + 387.0, + 283.0 + ], + "iscrowd": 0, + "note": "" + } + ] +} \ No newline at end of file diff --git a/example/images/000000000872.jpg b/example/images/000000000872.jpg new file mode 100644 index 0000000..2eac5c2 Binary files /dev/null and b/example/images/000000000872.jpg differ diff --git a/example/images/000000000872.json b/example/images/000000000872.json new file mode 100644 index 0000000..09ce1b7 --- /dev/null +++ b/example/images/000000000872.json @@ -0,0 +1,2341 @@ +{ + "info": { + "description": "ISAT", + "folder": "/home/super/PycharmProjects/ISAT_with_segment_anything/example/images", + "name": "000000000872.jpg", + "width": 621, + "height": 640, + "depth": 3, + "note": "" + }, + "objects": [ + { + "category": "person", + "group": "1", + "segmentation": [ + [ + 331, + 102 + ], + [ + 322, + 106 + ], + [ + 315, + 113 + ], + [ + 312, + 118 + ], + [ + 311, + 120 + ], + [ + 310, + 123 + ], + [ + 310, + 132 + ], + [ + 313, + 137 + ], + [ + 318, + 151 + ], + [ + 319, + 154 + ], + [ + 319, + 162 + ], + [ + 318, + 166 + ], + [ + 316, + 169 + ], + [ + 314, + 171 + ], + [ + 305, + 179 + ], + [ + 303, + 182 + ], + [ + 302, + 185 + ], + [ + 301, + 188 + ], + [ + 300, + 193 + ], + [ + 299, + 199 + ], + [ + 300, + 206 + ], + [ + 301, + 208 + ], + [ + 309, + 215 + ], + [ + 314, + 221 + ], + [ + 317, + 225 + ], + [ + 319, + 228 + ], + [ + 322, + 233 + ], + [ + 324, + 237 + ], + [ + 327, + 243 + ], + [ + 328, + 246 + ], + [ + 328, + 251 + ], + [ + 329, + 255 + ], + [ + 330, + 258 + ], + [ + 337, + 275 + ], + [ + 337, + 285 + ], + [ + 337, + 287 + ], + [ + 339, + 290 + ], + [ + 340, + 294 + ], + [ + 340, + 298 + ], + [ + 339, + 299 + ], + [ + 339, + 304 + ], + [ + 338, + 308 + ], + [ + 335, + 313 + ], + [ + 335, + 316 + ], + [ + 332, + 320 + ], + [ + 332, + 325 + ], + [ + 333, + 329 + ], + [ + 337, + 337 + ], + [ + 337, + 343 + ], + [ + 336, + 344 + ], + [ + 336, + 350 + ], + [ + 337, + 352 + ], + [ + 338, + 354 + ], + [ + 342, + 360 + ], + [ + 345, + 366 + ], + [ + 346, + 369 + ], + [ + 347, + 373 + ], + [ + 348, + 377 + ], + [ + 348, + 398 + ], + [ + 350, + 402 + ], + [ + 352, + 401 + ], + [ + 357, + 400 + ], + [ + 359, + 399 + ], + [ + 363, + 395 + ], + [ + 364, + 393 + ], + [ + 365, + 390 + ], + [ + 365, + 373 + ], + [ + 364, + 365 + ], + [ + 362, + 354 + ], + [ + 361, + 349 + ], + [ + 358, + 340 + ], + [ + 357, + 330 + ], + [ + 357, + 324 + ], + [ + 357, + 314 + ], + [ + 357, + 310 + ], + [ + 360, + 300 + ], + [ + 361, + 289 + ], + [ + 362, + 284 + ], + [ + 364, + 279 + ], + [ + 365, + 274 + ], + [ + 369, + 253 + ], + [ + 370, + 246 + ], + [ + 371, + 239 + ], + [ + 371, + 232 + ], + [ + 373, + 230 + ], + [ + 379, + 230 + ], + [ + 380, + 229 + ], + [ + 385, + 229 + ], + [ + 394, + 230 + ], + [ + 402, + 229 + ], + [ + 405, + 228 + ], + [ + 416, + 218 + ], + [ + 421, + 213 + ], + [ + 424, + 209 + ], + [ + 426, + 206 + ], + [ + 428, + 203 + ], + [ + 430, + 199 + ], + [ + 433, + 193 + ], + [ + 433, + 180 + ], + [ + 431, + 175 + ], + [ + 430, + 173 + ], + [ + 429, + 171 + ], + [ + 424, + 166 + ], + [ + 421, + 164 + ], + [ + 415, + 161 + ], + [ + 410, + 160 + ], + [ + 402, + 159 + ], + [ + 391, + 159 + ], + [ + 386, + 160 + ], + [ + 382, + 161 + ], + [ + 374, + 166 + ], + [ + 373, + 168 + ], + [ + 373, + 172 + ], + [ + 373, + 173 + ], + [ + 374, + 174 + ], + [ + 380, + 179 + ], + [ + 381, + 185 + ], + [ + 382, + 188 + ], + [ + 388, + 193 + ], + [ + 379, + 194 + ], + [ + 376, + 193 + ], + [ + 370, + 190 + ], + [ + 367, + 188 + ], + [ + 364, + 185 + ], + [ + 360, + 183 + ], + [ + 353, + 180 + ], + [ + 350, + 177 + ], + [ + 350, + 172 + ], + [ + 352, + 167 + ], + [ + 356, + 163 + ], + [ + 363, + 157 + ], + [ + 365, + 152 + ], + [ + 366, + 149 + ], + [ + 367, + 144 + ], + [ + 367, + 134 + ], + [ + 371, + 130 + ], + [ + 374, + 129 + ], + [ + 377, + 126 + ], + [ + 378, + 124 + ], + [ + 378, + 118 + ], + [ + 376, + 116 + ], + [ + 373, + 115 + ], + [ + 361, + 115 + ], + [ + 358, + 113 + ], + [ + 349, + 104 + ], + [ + 347, + 103 + ], + [ + 343, + 102 + ] + ], + "area": 14809.0, + "layer": 1.0, + "bbox": [ + 299.0, + 102.0, + 433.0, + 402.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "1", + "segmentation": [ + [ + 354, + 467 + ], + [ + 353, + 467 + ], + [ + 351, + 469 + ], + [ + 346, + 471 + ], + [ + 342, + 474 + ], + [ + 337, + 479 + ], + [ + 333, + 482 + ], + [ + 329, + 485 + ], + [ + 326, + 487 + ], + [ + 319, + 491 + ], + [ + 315, + 492 + ], + [ + 310, + 496 + ], + [ + 307, + 497 + ], + [ + 305, + 498 + ], + [ + 304, + 499 + ], + [ + 304, + 500 + ], + [ + 302, + 502 + ], + [ + 296, + 516 + ], + [ + 295, + 518 + ], + [ + 293, + 520 + ], + [ + 292, + 522 + ], + [ + 292, + 528 + ], + [ + 290, + 531 + ], + [ + 289, + 535 + ], + [ + 288, + 541 + ], + [ + 287, + 547 + ], + [ + 287, + 549 + ], + [ + 288, + 551 + ], + [ + 289, + 552 + ], + [ + 291, + 553 + ], + [ + 306, + 554 + ], + [ + 326, + 554 + ], + [ + 346, + 553 + ], + [ + 354, + 552 + ], + [ + 356, + 551 + ], + [ + 356, + 548 + ], + [ + 353, + 545 + ], + [ + 351, + 544 + ], + [ + 347, + 543 + ], + [ + 343, + 543 + ], + [ + 341, + 541 + ], + [ + 339, + 541 + ], + [ + 337, + 540 + ], + [ + 331, + 534 + ], + [ + 331, + 532 + ], + [ + 332, + 531 + ], + [ + 333, + 523 + ], + [ + 335, + 519 + ], + [ + 339, + 510 + ], + [ + 344, + 503 + ], + [ + 345, + 500 + ], + [ + 348, + 489 + ], + [ + 351, + 484 + ], + [ + 351, + 481 + ], + [ + 353, + 478 + ], + [ + 354, + 474 + ], + [ + 354, + 470 + ], + [ + 356, + 466 + ] + ], + "area": 3224.5, + "layer": 2.0, + "bbox": [ + 287.0, + 466.0, + 356.0, + 554.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "1", + "segmentation": [ + [ + 206, + 450 + ], + [ + 204, + 451 + ], + [ + 200, + 453 + ], + [ + 197, + 455 + ], + [ + 194, + 457 + ], + [ + 190, + 461 + ], + [ + 189, + 461 + ], + [ + 186, + 464 + ], + [ + 184, + 467 + ], + [ + 183, + 470 + ], + [ + 178, + 477 + ], + [ + 176, + 479 + ], + [ + 174, + 480 + ], + [ + 168, + 481 + ], + [ + 159, + 485 + ], + [ + 157, + 486 + ], + [ + 155, + 487 + ], + [ + 152, + 490 + ], + [ + 152, + 497 + ], + [ + 155, + 504 + ], + [ + 157, + 508 + ], + [ + 160, + 512 + ], + [ + 161, + 514 + ], + [ + 162, + 519 + ], + [ + 162, + 524 + ], + [ + 163, + 528 + ], + [ + 167, + 536 + ], + [ + 172, + 542 + ], + [ + 173, + 543 + ], + [ + 175, + 544 + ], + [ + 177, + 545 + ], + [ + 184, + 545 + ], + [ + 188, + 543 + ], + [ + 189, + 540 + ], + [ + 188, + 522 + ], + [ + 189, + 516 + ], + [ + 190, + 512 + ], + [ + 192, + 507 + ], + [ + 194, + 503 + ], + [ + 197, + 502 + ], + [ + 206, + 493 + ], + [ + 207, + 491 + ], + [ + 208, + 486 + ], + [ + 208, + 481 + ] + ], + "area": 2793.5, + "layer": 3.0, + "bbox": [ + 152.0, + 450.0, + 208.0, + 545.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "person", + "group": "2", + "segmentation": [ + [ + 242, + 132 + ], + [ + 237, + 133 + ], + [ + 232, + 135 + ], + [ + 226, + 138 + ], + [ + 222, + 142 + ], + [ + 219, + 146 + ], + [ + 217, + 149 + ], + [ + 215, + 154 + ], + [ + 211, + 158 + ], + [ + 205, + 161 + ], + [ + 203, + 161 + ], + [ + 201, + 162 + ], + [ + 199, + 163 + ], + [ + 198, + 166 + ], + [ + 200, + 168 + ], + [ + 203, + 168 + ], + [ + 206, + 170 + ], + [ + 209, + 170 + ], + [ + 211, + 171 + ], + [ + 213, + 172 + ], + [ + 215, + 177 + ], + [ + 215, + 179 + ], + [ + 212, + 184 + ], + [ + 211, + 187 + ], + [ + 211, + 189 + ], + [ + 216, + 194 + ], + [ + 217, + 197 + ], + [ + 218, + 200 + ], + [ + 218, + 204 + ], + [ + 223, + 209 + ], + [ + 226, + 211 + ], + [ + 229, + 213 + ], + [ + 231, + 214 + ], + [ + 235, + 215 + ], + [ + 237, + 216 + ], + [ + 239, + 218 + ], + [ + 238, + 221 + ], + [ + 236, + 223 + ], + [ + 233, + 230 + ], + [ + 232, + 233 + ], + [ + 232, + 236 + ], + [ + 231, + 239 + ], + [ + 229, + 242 + ], + [ + 228, + 245 + ], + [ + 227, + 251 + ], + [ + 226, + 257 + ], + [ + 226, + 270 + ], + [ + 227, + 277 + ], + [ + 228, + 278 + ], + [ + 228, + 283 + ], + [ + 225, + 287 + ], + [ + 220, + 292 + ], + [ + 213, + 301 + ], + [ + 211, + 305 + ], + [ + 198, + 317 + ], + [ + 190, + 325 + ], + [ + 188, + 327 + ], + [ + 188, + 328 + ], + [ + 186, + 330 + ], + [ + 183, + 331 + ], + [ + 179, + 335 + ], + [ + 176, + 336 + ], + [ + 171, + 341 + ], + [ + 168, + 346 + ], + [ + 167, + 349 + ], + [ + 167, + 358 + ], + [ + 168, + 362 + ], + [ + 169, + 364 + ], + [ + 171, + 366 + ], + [ + 171, + 367 + ], + [ + 172, + 368 + ], + [ + 174, + 369 + ], + [ + 180, + 368 + ], + [ + 181, + 366 + ], + [ + 181, + 361 + ], + [ + 182, + 359 + ], + [ + 187, + 354 + ], + [ + 188, + 354 + ], + [ + 194, + 348 + ], + [ + 198, + 346 + ], + [ + 202, + 340 + ], + [ + 203, + 339 + ], + [ + 205, + 338 + ], + [ + 209, + 338 + ], + [ + 213, + 336 + ], + [ + 218, + 334 + ], + [ + 225, + 330 + ], + [ + 228, + 328 + ], + [ + 231, + 331 + ], + [ + 231, + 338 + ], + [ + 234, + 344 + ], + [ + 238, + 349 + ], + [ + 239, + 351 + ], + [ + 240, + 354 + ], + [ + 239, + 360 + ], + [ + 225, + 373 + ], + [ + 223, + 376 + ], + [ + 218, + 385 + ], + [ + 215, + 392 + ], + [ + 214, + 395 + ], + [ + 213, + 398 + ], + [ + 212, + 403 + ], + [ + 211, + 411 + ], + [ + 211, + 430 + ], + [ + 209, + 440 + ], + [ + 208, + 448 + ], + [ + 209, + 486 + ], + [ + 210, + 495 + ], + [ + 211, + 500 + ], + [ + 212, + 504 + ], + [ + 213, + 509 + ], + [ + 215, + 511 + ], + [ + 218, + 520 + ], + [ + 220, + 527 + ], + [ + 221, + 532 + ], + [ + 220, + 550 + ], + [ + 220, + 558 + ], + [ + 223, + 567 + ], + [ + 228, + 577 + ], + [ + 228, + 582 + ], + [ + 226, + 584 + ], + [ + 218, + 588 + ], + [ + 213, + 590 + ], + [ + 210, + 591 + ], + [ + 207, + 592 + ], + [ + 200, + 593 + ], + [ + 197, + 594 + ], + [ + 195, + 595 + ], + [ + 192, + 598 + ], + [ + 191, + 601 + ], + [ + 194, + 604 + ], + [ + 196, + 605 + ], + [ + 200, + 606 + ], + [ + 226, + 606 + ], + [ + 230, + 604 + ], + [ + 255, + 605 + ], + [ + 262, + 605 + ], + [ + 268, + 604 + ], + [ + 270, + 603 + ], + [ + 273, + 600 + ], + [ + 273, + 594 + ], + [ + 272, + 590 + ], + [ + 271, + 586 + ], + [ + 270, + 583 + ], + [ + 266, + 576 + ], + [ + 265, + 567 + ], + [ + 265, + 560 + ], + [ + 264, + 551 + ], + [ + 262, + 546 + ], + [ + 262, + 532 + ], + [ + 263, + 516 + ], + [ + 262, + 510 + ], + [ + 261, + 505 + ], + [ + 260, + 500 + ], + [ + 259, + 496 + ], + [ + 258, + 491 + ], + [ + 256, + 486 + ], + [ + 252, + 479 + ], + [ + 252, + 477 + ], + [ + 251, + 475 + ], + [ + 253, + 470 + ], + [ + 253, + 465 + ], + [ + 254, + 462 + ], + [ + 255, + 460 + ], + [ + 261, + 454 + ], + [ + 265, + 454 + ], + [ + 266, + 456 + ], + [ + 267, + 458 + ], + [ + 268, + 463 + ], + [ + 268, + 467 + ], + [ + 269, + 471 + ], + [ + 270, + 475 + ], + [ + 272, + 481 + ], + [ + 273, + 484 + ], + [ + 276, + 489 + ], + [ + 278, + 492 + ], + [ + 282, + 496 + ], + [ + 284, + 497 + ], + [ + 286, + 498 + ], + [ + 290, + 499 + ], + [ + 297, + 499 + ], + [ + 301, + 498 + ], + [ + 306, + 496 + ], + [ + 308, + 495 + ], + [ + 313, + 491 + ], + [ + 321, + 488 + ], + [ + 328, + 484 + ], + [ + 338, + 477 + ], + [ + 346, + 470 + ], + [ + 348, + 469 + ], + [ + 350, + 469 + ], + [ + 352, + 468 + ], + [ + 353, + 467 + ], + [ + 355, + 465 + ], + [ + 356, + 464 + ], + [ + 357, + 462 + ], + [ + 358, + 459 + ], + [ + 361, + 455 + ], + [ + 376, + 440 + ], + [ + 378, + 439 + ], + [ + 381, + 441 + ], + [ + 388, + 439 + ], + [ + 390, + 443 + ], + [ + 391, + 444 + ], + [ + 393, + 445 + ], + [ + 396, + 446 + ], + [ + 399, + 448 + ], + [ + 402, + 450 + ], + [ + 406, + 454 + ], + [ + 411, + 458 + ], + [ + 418, + 458 + ], + [ + 420, + 455 + ], + [ + 420, + 440 + ], + [ + 418, + 438 + ], + [ + 418, + 432 + ], + [ + 416, + 430 + ], + [ + 415, + 430 + ], + [ + 412, + 427 + ], + [ + 410, + 423 + ], + [ + 408, + 421 + ], + [ + 406, + 420 + ], + [ + 404, + 419 + ], + [ + 400, + 418 + ], + [ + 400, + 415 + ], + [ + 398, + 413 + ], + [ + 398, + 411 + ], + [ + 393, + 406 + ], + [ + 391, + 403 + ], + [ + 391, + 402 + ], + [ + 390, + 401 + ], + [ + 389, + 401 + ], + [ + 387, + 399 + ], + [ + 383, + 398 + ], + [ + 384, + 395 + ], + [ + 383, + 393 + ], + [ + 381, + 391 + ], + [ + 378, + 391 + ], + [ + 379, + 393 + ], + [ + 377, + 395 + ], + [ + 373, + 394 + ], + [ + 371, + 394 + ], + [ + 370, + 401 + ], + [ + 368, + 402 + ], + [ + 360, + 402 + ], + [ + 357, + 405 + ], + [ + 354, + 405 + ], + [ + 352, + 406 + ], + [ + 347, + 408 + ], + [ + 347, + 405 + ], + [ + 343, + 398 + ], + [ + 344, + 394 + ], + [ + 346, + 389 + ], + [ + 346, + 380 + ], + [ + 345, + 375 + ], + [ + 344, + 370 + ], + [ + 343, + 367 + ], + [ + 338, + 359 + ], + [ + 338, + 357 + ], + [ + 337, + 355 + ], + [ + 334, + 351 + ], + [ + 332, + 347 + ], + [ + 332, + 345 + ], + [ + 333, + 337 + ], + [ + 332, + 333 + ], + [ + 331, + 329 + ], + [ + 329, + 326 + ], + [ + 329, + 319 + ], + [ + 330, + 317 + ], + [ + 332, + 315 + ], + [ + 333, + 313 + ], + [ + 337, + 302 + ], + [ + 337, + 292 + ], + [ + 334, + 287 + ], + [ + 335, + 279 + ], + [ + 335, + 277 + ], + [ + 334, + 274 + ], + [ + 332, + 271 + ], + [ + 331, + 268 + ], + [ + 331, + 265 + ], + [ + 330, + 262 + ], + [ + 328, + 259 + ], + [ + 327, + 256 + ], + [ + 326, + 252 + ], + [ + 326, + 247 + ], + [ + 325, + 244 + ], + [ + 323, + 240 + ], + [ + 320, + 234 + ], + [ + 315, + 226 + ], + [ + 311, + 221 + ], + [ + 310, + 220 + ], + [ + 306, + 217 + ], + [ + 305, + 215 + ], + [ + 303, + 213 + ], + [ + 297, + 208 + ], + [ + 294, + 206 + ], + [ + 291, + 204 + ], + [ + 287, + 202 + ], + [ + 281, + 199 + ], + [ + 276, + 198 + ], + [ + 275, + 196 + ], + [ + 274, + 194 + ], + [ + 273, + 188 + ], + [ + 273, + 185 + ], + [ + 274, + 183 + ], + [ + 275, + 181 + ], + [ + 279, + 178 + ], + [ + 280, + 175 + ], + [ + 282, + 173 + ], + [ + 282, + 157 + ], + [ + 281, + 152 + ], + [ + 280, + 149 + ], + [ + 279, + 147 + ], + [ + 277, + 144 + ], + [ + 269, + 136 + ], + [ + 267, + 135 + ], + [ + 262, + 133 + ], + [ + 257, + 132 + ] + ], + "area": 46936.0, + "layer": 4.0, + "bbox": [ + 167.0, + 132.0, + 420.0, + 606.0 + ], + "iscrowd": 0, + "note": "" + } + ] +} \ No newline at end of file diff --git a/example/images/000000002592.jpg b/example/images/000000002592.jpg new file mode 100644 index 0000000..90f824a Binary files /dev/null and b/example/images/000000002592.jpg differ diff --git a/example/images/000000002592.json b/example/images/000000002592.json new file mode 100644 index 0000000..a4463c7 --- /dev/null +++ b/example/images/000000002592.json @@ -0,0 +1,1145 @@ +{ + "info": { + "description": "ISAT", + "folder": "/home/super/PycharmProjects/ISAT_with_segment_anything/example/images", + "name": "000000002592.jpg", + "width": 640, + "height": 366, + "depth": 3, + "note": "" + }, + "objects": [ + { + "category": "cup", + "group": "1", + "segmentation": [ + [ + 287, + 35 + ], + [ + 279, + 36 + ], + [ + 273, + 37 + ], + [ + 269, + 38 + ], + [ + 265, + 39 + ], + [ + 262, + 40 + ], + [ + 254, + 43 + ], + [ + 248, + 46 + ], + [ + 243, + 49 + ], + [ + 239, + 52 + ], + [ + 228, + 63 + ], + [ + 225, + 69 + ], + [ + 224, + 72 + ], + [ + 223, + 79 + ], + [ + 223, + 85 + ], + [ + 224, + 99 + ], + [ + 226, + 111 + ], + [ + 226, + 123 + ], + [ + 228, + 134 + ], + [ + 229, + 157 + ], + [ + 232, + 186 + ], + [ + 233, + 195 + ], + [ + 234, + 200 + ], + [ + 238, + 212 + ], + [ + 239, + 214 + ], + [ + 242, + 217 + ], + [ + 243, + 220 + ], + [ + 252, + 229 + ], + [ + 257, + 231 + ], + [ + 260, + 234 + ], + [ + 265, + 237 + ], + [ + 268, + 238 + ], + [ + 281, + 242 + ], + [ + 286, + 243 + ], + [ + 293, + 244 + ], + [ + 309, + 244 + ], + [ + 317, + 243 + ], + [ + 320, + 241 + ], + [ + 328, + 240 + ], + [ + 331, + 239 + ], + [ + 334, + 238 + ], + [ + 338, + 236 + ], + [ + 344, + 233 + ], + [ + 347, + 231 + ], + [ + 351, + 228 + ], + [ + 359, + 220 + ], + [ + 362, + 216 + ], + [ + 366, + 208 + ], + [ + 367, + 204 + ], + [ + 368, + 198 + ], + [ + 368, + 191 + ], + [ + 369, + 186 + ], + [ + 371, + 184 + ], + [ + 376, + 184 + ], + [ + 393, + 185 + ], + [ + 397, + 184 + ], + [ + 400, + 183 + ], + [ + 406, + 180 + ], + [ + 409, + 178 + ], + [ + 412, + 175 + ], + [ + 413, + 175 + ], + [ + 415, + 173 + ], + [ + 415, + 172 + ], + [ + 418, + 169 + ], + [ + 421, + 164 + ], + [ + 424, + 158 + ], + [ + 426, + 153 + ], + [ + 427, + 149 + ], + [ + 428, + 144 + ], + [ + 429, + 139 + ], + [ + 430, + 129 + ], + [ + 430, + 127 + ], + [ + 429, + 119 + ], + [ + 428, + 114 + ], + [ + 427, + 110 + ], + [ + 426, + 107 + ], + [ + 424, + 102 + ], + [ + 423, + 100 + ], + [ + 422, + 98 + ], + [ + 420, + 95 + ], + [ + 416, + 91 + ], + [ + 412, + 88 + ], + [ + 406, + 85 + ], + [ + 401, + 85 + ], + [ + 400, + 84 + ], + [ + 396, + 84 + ], + [ + 395, + 85 + ], + [ + 389, + 86 + ], + [ + 383, + 87 + ], + [ + 379, + 86 + ], + [ + 378, + 81 + ], + [ + 378, + 75 + ], + [ + 377, + 72 + ], + [ + 376, + 69 + ], + [ + 375, + 67 + ], + [ + 374, + 65 + ], + [ + 371, + 61 + ], + [ + 363, + 53 + ], + [ + 357, + 49 + ], + [ + 354, + 47 + ], + [ + 352, + 47 + ], + [ + 348, + 44 + ], + [ + 346, + 43 + ], + [ + 334, + 39 + ], + [ + 330, + 38 + ], + [ + 325, + 37 + ], + [ + 320, + 36 + ], + [ + 313, + 35 + ] + ], + "area": 32316.5, + "layer": 1.0, + "bbox": [ + 223.0, + 35.0, + 430.0, + 244.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "__background__", + "group": "0", + "segmentation": [ + [ + 400, + 106 + ], + [ + 398, + 108 + ], + [ + 394, + 109 + ], + [ + 391, + 109 + ], + [ + 389, + 112 + ], + [ + 388, + 115 + ], + [ + 381, + 121 + ], + [ + 379, + 123 + ], + [ + 378, + 125 + ], + [ + 377, + 128 + ], + [ + 376, + 135 + ], + [ + 375, + 141 + ], + [ + 375, + 149 + ], + [ + 376, + 151 + ], + [ + 377, + 153 + ], + [ + 379, + 155 + ], + [ + 380, + 157 + ], + [ + 381, + 160 + ], + [ + 382, + 164 + ], + [ + 384, + 165 + ], + [ + 392, + 165 + ], + [ + 397, + 164 + ], + [ + 401, + 160 + ], + [ + 404, + 159 + ], + [ + 405, + 158 + ], + [ + 408, + 154 + ], + [ + 409, + 151 + ], + [ + 411, + 148 + ], + [ + 412, + 141 + ], + [ + 414, + 138 + ], + [ + 414, + 131 + ], + [ + 416, + 129 + ], + [ + 416, + 127 + ], + [ + 415, + 121 + ], + [ + 415, + 119 + ], + [ + 409, + 117 + ], + [ + 411, + 113 + ], + [ + 409, + 111 + ], + [ + 408, + 111 + ], + [ + 406, + 109 + ], + [ + 406, + 107 + ], + [ + 402, + 106 + ] + ], + "area": 1751.5, + "layer": 2.0, + "bbox": [ + 375.0, + 106.0, + 416.0, + 165.0 + ], + "iscrowd": 0, + "note": "" + }, + { + "category": "knife", + "group": "2", + "segmentation": [ + [ + 580, + 220 + ], + [ + 567, + 221 + ], + [ + 547, + 223 + ], + [ + 516, + 227 + ], + [ + 472, + 231 + ], + [ + 461, + 231 + ], + [ + 449, + 232 + ], + [ + 441, + 233 + ], + [ + 434, + 234 + ], + [ + 429, + 235 + ], + [ + 424, + 236 + ], + [ + 419, + 238 + ], + [ + 404, + 241 + ], + [ + 397, + 242 + ], + [ + 389, + 242 + ], + [ + 386, + 243 + ], + [ + 383, + 245 + ], + [ + 381, + 249 + ], + [ + 379, + 251 + ], + [ + 371, + 252 + ], + [ + 363, + 252 + ], + [ + 355, + 254 + ], + [ + 347, + 255 + ], + [ + 330, + 257 + ], + [ + 305, + 259 + ], + [ + 281, + 262 + ], + [ + 274, + 263 + ], + [ + 249, + 268 + ], + [ + 205, + 274 + ], + [ + 180, + 279 + ], + [ + 173, + 280 + ], + [ + 159, + 281 + ], + [ + 152, + 283 + ], + [ + 145, + 284 + ], + [ + 137, + 284 + ], + [ + 115, + 288 + ], + [ + 83, + 292 + ], + [ + 49, + 295 + ], + [ + 41, + 296 + ], + [ + 34, + 297 + ], + [ + 33, + 298 + ], + [ + 30, + 298 + ], + [ + 32, + 301 + ], + [ + 35, + 303 + ], + [ + 41, + 306 + ], + [ + 46, + 308 + ], + [ + 49, + 309 + ], + [ + 52, + 310 + ], + [ + 59, + 312 + ], + [ + 63, + 313 + ], + [ + 68, + 314 + ], + [ + 102, + 314 + ], + [ + 118, + 313 + ], + [ + 132, + 312 + ], + [ + 139, + 310 + ], + [ + 148, + 310 + ], + [ + 154, + 308 + ], + [ + 165, + 308 + ], + [ + 172, + 306 + ], + [ + 184, + 306 + ], + [ + 190, + 304 + ], + [ + 202, + 304 + ], + [ + 209, + 302 + ], + [ + 232, + 301 + ], + [ + 239, + 299 + ], + [ + 250, + 299 + ], + [ + 258, + 297 + ], + [ + 267, + 297 + ], + [ + 275, + 295 + ], + [ + 284, + 295 + ], + [ + 292, + 293 + ], + [ + 303, + 293 + ], + [ + 313, + 291 + ], + [ + 335, + 290 + ], + [ + 343, + 288 + ], + [ + 347, + 288 + ], + [ + 359, + 289 + ], + [ + 368, + 288 + ], + [ + 386, + 285 + ], + [ + 396, + 284 + ], + [ + 398, + 285 + ], + [ + 400, + 287 + ], + [ + 403, + 288 + ], + [ + 410, + 290 + ], + [ + 415, + 290 + ], + [ + 417, + 288 + ], + [ + 418, + 286 + ], + [ + 418, + 283 + ], + [ + 419, + 280 + ], + [ + 424, + 275 + ], + [ + 427, + 274 + ], + [ + 430, + 273 + ], + [ + 439, + 272 + ], + [ + 488, + 272 + ], + [ + 502, + 271 + ], + [ + 511, + 270 + ], + [ + 518, + 269 + ], + [ + 531, + 267 + ], + [ + 546, + 264 + ], + [ + 551, + 262 + ], + [ + 566, + 259 + ], + [ + 574, + 259 + ], + [ + 578, + 260 + ], + [ + 581, + 261 + ], + [ + 587, + 264 + ], + [ + 593, + 264 + ], + [ + 599, + 261 + ], + [ + 604, + 257 + ], + [ + 609, + 251 + ], + [ + 611, + 248 + ], + [ + 612, + 246 + ], + [ + 613, + 244 + ], + [ + 613, + 234 + ], + [ + 612, + 232 + ], + [ + 611, + 230 + ], + [ + 609, + 227 + ], + [ + 605, + 224 + ], + [ + 603, + 223 + ], + [ + 601, + 222 + ], + [ + 598, + 221 + ], + [ + 593, + 220 + ] + ], + "area": 19183.0, + "layer": 3.0, + "bbox": [ + 30.0, + 220.0, + 613.0, + 314.0 + ], + "iscrowd": 0, + "note": "" + } + ] +} \ No newline at end of file diff --git a/example/images/000000117425.jpg b/example/images/000000117425.jpg new file mode 100644 index 0000000..ea74f13 Binary files /dev/null and b/example/images/000000117425.jpg differ diff --git a/example/instance/000000000113.png b/example/instance/000000000113.png new file mode 100644 index 0000000..5023441 Binary files /dev/null and b/example/instance/000000000113.png differ diff --git a/example/instance/000000000144.png b/example/instance/000000000144.png new file mode 100644 index 0000000..0f35145 Binary files /dev/null and b/example/instance/000000000144.png differ diff --git a/example/instance/000000000308.png b/example/instance/000000000308.png new file mode 100644 index 0000000..415f360 Binary files /dev/null and b/example/instance/000000000308.png differ diff --git a/example/instance/000000000872.png b/example/instance/000000000872.png new file mode 100644 index 0000000..91071c2 Binary files /dev/null and b/example/instance/000000000872.png differ diff --git a/example/instance/000000002592.png b/example/instance/000000002592.png new file mode 100644 index 0000000..0709abd Binary files /dev/null and b/example/instance/000000002592.png differ diff --git a/example/segment/000000000113.png b/example/segment/000000000113.png new file mode 100644 index 0000000..4ef37bd Binary files /dev/null and b/example/segment/000000000113.png differ diff --git a/example/segment/000000000144.png b/example/segment/000000000144.png new file mode 100644 index 0000000..e0baafd Binary files /dev/null and b/example/segment/000000000144.png differ diff --git a/example/segment/000000000308.png b/example/segment/000000000308.png new file mode 100644 index 0000000..2a98043 Binary files /dev/null and b/example/segment/000000000308.png differ diff --git a/example/segment/000000000872.png b/example/segment/000000000872.png new file mode 100644 index 0000000..2ce4e47 Binary files /dev/null and b/example/segment/000000000872.png differ diff --git a/example/segment/000000002592.png b/example/segment/000000002592.png new file mode 100644 index 0000000..e4983c9 Binary files /dev/null and b/example/segment/000000002592.png differ diff --git a/example/segment/classesition.txt b/example/segment/classesition.txt new file mode 100644 index 0000000..25af240 --- /dev/null +++ b/example/segment/classesition.txt @@ -0,0 +1,10 @@ +__background__ 0 +person 1 +knife 2 +fork 3 +cup 4 +giraffe 5 +plate 6 +table 7 +cake 8 +fence 9 diff --git a/icons.py b/icons.py new file mode 100644 index 0000000..a369e0c --- /dev/null +++ b/icons.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT/icons.qrc' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + diff --git a/icons.qrc b/icons.qrc new file mode 100644 index 0000000..5012bf2 --- /dev/null +++ b/icons.qrc @@ -0,0 +1,37 @@ + + + icons/semantic.png + icons/M_Favicon.ico + icons/instance.png + icons/转换文件夹1_folder-conversion-one.svg + icons/转换文件1_file-conversion-one.svg + icons/照片_pic.svg + icons/一对一_one-to-one.svg + icons/校验_check-one.svg + icons/下一步_next.svg + icons/我的_me.svg + icons/文件夹-开_folder-open.svg + icons/缩小_zoom-out.svg + icons/设置_setting-two.svg + icons/上一步_back.svg + icons/删除_delete.svg + icons/删除_delete-two.svg + icons/全宽_fullwidth.svg + icons/去顶部_to-top.svg + icons/去底部_to-bottom.svg + icons/锚点_anchor.svg + icons/列表_list.svg + icons/列表_list-middle.svg + icons/开关_power.svg + icons/键盘_keyboard-one.svg + icons/关闭_close-one.svg + icons/放大_zoom-in.svg + icons/翻译_translate.svg + icons/传入3_afferent-three.svg + icons/传出3_efferent-three.svg + icons/编辑文件_file-editing.svg + icons/编辑_edit.svg + icons/保存硬盘_save-one.svg + icons/保存_save.svg + + diff --git a/icons_rc.py b/icons_rc.py new file mode 100644 index 0000000..a5559bc --- /dev/null +++ b/icons_rc.py @@ -0,0 +1,1825 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2) +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore + +qt_resource_data = b"\ +\x00\x00\x02\xbf\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\ +\x20\x37\x48\x36\x43\x34\x2e\x38\x39\x35\x34\x33\x20\x37\x20\x34\ +\x20\x37\x2e\x38\x39\x35\x34\x33\x20\x34\x20\x39\x56\x33\x39\x43\ +\x34\x20\x34\x30\x2e\x31\x30\x34\x36\x20\x34\x2e\x38\x39\x35\x34\ +\x33\x20\x34\x31\x20\x36\x20\x34\x31\x48\x34\x32\x43\x34\x33\x2e\ +\x31\x30\x34\x36\x20\x34\x31\x20\x34\x34\x20\x34\x30\x2e\x31\x30\ +\x34\x36\x20\x34\x34\x20\x33\x39\x56\x39\x43\x34\x34\x20\x37\x2e\ +\x38\x39\x35\x34\x33\x20\x34\x33\x2e\x31\x30\x34\x36\x20\x37\x20\ +\x34\x32\x20\x37\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\ +\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\ +\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ +\x3d\x22\x33\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\ +\x31\x32\x20\x32\x30\x2e\x35\x37\x39\x39\x4c\x31\x36\x20\x31\x38\ +\x56\x33\x30\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\ +\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ +\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\ +\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\ +\x22\x4d\x33\x31\x20\x32\x30\x2e\x35\x37\x39\x39\x4c\x33\x35\x20\ +\x31\x38\x56\x33\x30\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x32\x34\x20\x32\x30\x56\x32\x31\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\ +\x73\x71\x75\x61\x72\x65\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x4d\x32\x34\x20\x32\x37\x56\x32\x38\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x01\x33\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\ +\x20\x36\x56\x34\x32\x4d\x31\x37\x20\x31\x39\x4c\x31\x32\x20\x32\ +\x34\x4d\x31\x32\x20\x32\x34\x4c\x31\x37\x20\x32\x39\x4d\x31\x32\ +\x20\x32\x34\x48\x33\x36\x4d\x33\x31\x20\x31\x39\x4c\x33\x36\x20\ +\x32\x34\x4d\x33\x36\x20\x32\x34\x4c\x33\x31\x20\x32\x39\x4d\x36\ +\x20\x36\x4c\x36\x20\x34\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\ +\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\ +\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\ +\x67\x3e\ +\x00\x00\x02\xa9\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x31\ +\x20\x33\x38\x43\x33\x30\x2e\x33\x38\x38\x38\x20\x33\x38\x20\x33\ +\x38\x20\x33\x30\x2e\x33\x38\x38\x38\x20\x33\x38\x20\x32\x31\x43\ +\x33\x38\x20\x31\x31\x2e\x36\x31\x31\x32\x20\x33\x30\x2e\x33\x38\ +\x38\x38\x20\x34\x20\x32\x31\x20\x34\x43\x31\x31\x2e\x36\x31\x31\ +\x32\x20\x34\x20\x34\x20\x31\x31\x2e\x36\x31\x31\x32\x20\x34\x20\ +\x32\x31\x43\x34\x20\x33\x30\x2e\x33\x38\x38\x38\x20\x31\x31\x2e\ +\x36\x31\x31\x32\x20\x33\x38\x20\x32\x31\x20\x33\x38\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x32\x31\x20\x31\x35\x4c\x32\x31\x20\x32\x37\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\ +\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\ +\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x35\x2e\x30\x31\ +\x35\x36\x20\x32\x31\x2e\x30\x31\x35\x36\x4c\x32\x37\x20\x32\x31\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\ +\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\ +\x33\x2e\x32\x32\x31\x36\x20\x33\x33\x2e\x32\x32\x31\x37\x4c\x34\ +\x31\x2e\x37\x30\x36\x39\x20\x34\x31\x2e\x37\x30\x37\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ +\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\ +\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x02\x4e\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\ +\x20\x34\x34\x48\x33\x38\x43\x33\x39\x2e\x31\x30\x34\x36\x20\x34\ +\x34\x20\x34\x30\x20\x34\x33\x2e\x31\x30\x34\x36\x20\x34\x30\x20\ +\x34\x32\x56\x31\x34\x48\x33\x30\x56\x34\x48\x31\x30\x43\x38\x2e\ +\x38\x39\x35\x34\x33\x20\x34\x20\x38\x20\x34\x2e\x38\x39\x35\x34\ +\x33\x20\x38\x20\x36\x56\x34\x32\x43\x38\x20\x34\x33\x2e\x31\x30\ +\x34\x36\x20\x38\x2e\x38\x39\x35\x34\x33\x20\x34\x34\x20\x31\x30\ +\x20\x34\x34\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\ +\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\ +\x30\x20\x34\x4c\x34\x30\x20\x31\x34\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\ +\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x31\x20\x33\x35\x4c\x33\x31\ +\x20\x32\x35\x4c\x32\x37\x20\x32\x31\x4c\x31\x37\x20\x33\x31\x56\ +\x33\x35\x48\x32\x31\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\ +\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\x57\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x30\x00\x00\x00\x30\x08\x06\x00\x00\x00\x57\x02\xf9\x87\ +\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\ +\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\ +\x0d\xd7\x01\x42\x28\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\ +\xe7\x04\x13\x03\x14\x20\x67\x3f\x96\xef\x00\x00\x02\xe4\x49\x44\ +\x41\x54\x68\x43\xed\x58\x3b\x8b\x15\x31\x18\x3d\xd7\x07\xae\x95\ +\x62\x25\xb6\xa2\x8d\x0f\x2c\xc4\x46\x10\x41\x41\xf4\x07\x58\x59\ +\x89\x28\x58\x5a\x2c\xba\x6b\x71\x41\x57\xc4\xc2\xce\x42\xb9\x68\ +\x6f\x69\x23\x88\x8d\x62\x6f\x21\x82\x22\x5a\xa8\x20\x56\x6b\x25\ +\x17\x5f\xf1\x7c\x3b\xe6\x92\xc9\x24\x33\xc9\x24\xb3\xc3\xe2\x64\ +\x77\xd8\x9b\xef\x79\xce\x97\x2f\x99\xec\x05\x86\x31\x54\x60\xa8\ +\xc0\x50\x81\x3e\x2b\x30\x72\x25\xbf\x06\xec\x5c\x0f\x1c\x57\xc0\ +\x56\x97\xbe\x07\xd9\xf2\x3a\xe0\xe9\x15\xe0\x83\x9d\xbb\x42\x60\ +\x09\x38\x4b\xa3\x3b\x7c\xe6\x6c\xe3\x9e\xe7\x53\x82\xbd\xb8\x00\ +\x3c\x30\x71\x94\x08\x48\xe5\xc9\xf4\x35\x0d\x36\xf5\x0c\xd6\x97\ +\x7e\x4a\x7c\x7b\xcc\x95\xd8\x60\x5a\x52\x79\x4c\x83\x67\xfb\xbc\ +\x24\xbb\x27\xbe\x48\xab\x2c\x3f\xc1\x7c\x07\xf8\xcc\xfd\x61\x6b\ +\xf3\xef\x3d\x9d\xbf\x44\x80\xc2\x1d\x5a\x41\xf0\x8f\x16\x81\xf1\ +\x2a\x03\x75\xa6\x63\x5b\x4f\xa9\x10\x02\x32\x66\x18\x65\xc2\xa2\ +\xaf\xed\xb1\xe6\x09\xd8\x2d\x14\xb4\x1c\xdc\x1f\xfc\x2d\x06\x5b\ +\xad\x72\x92\x05\x05\xc9\x64\x14\xbd\x02\x26\x78\xc1\x60\xcf\x33\ +\xe1\x0a\x0e\x13\x45\xc0\x07\xd6\x27\x0f\x46\x91\x60\x18\x45\x20\ +\x21\x4f\x67\xae\xff\x17\x01\xdf\x86\xf5\xc9\x3b\x2b\xbb\x11\x38\ +\x7a\x05\x6c\xb0\xf6\xdc\x06\xcd\xfd\x41\x13\x25\xdb\x44\x3d\x04\ +\x78\x47\xcc\x3b\xa2\x09\x48\x7a\x01\xad\x9f\x26\x38\x23\x28\xbe\ +\xfd\x8b\x71\x1a\xea\xd7\x2d\x60\x7b\x93\x4f\x8c\xbe\x15\x81\xf0\ +\x04\x52\xf9\xf2\x98\x87\xfa\x72\x03\x38\x6c\xcb\xdb\xce\x5b\x11\ +\x18\xcb\x15\x44\x15\x3f\x2b\x9f\x9d\xa3\x0a\x5e\x9b\x2d\x40\xbd\ +\x90\x96\x2a\xda\xcb\xe9\x1c\x2c\xf4\x24\xf7\xfb\x0b\xe0\xb1\xc2\ +\x6f\x6d\x21\x9f\x29\xb3\xfe\xf1\xf1\x83\x37\x23\x4b\x7b\xdd\x04\ +\xb6\xf8\xb3\x35\x6b\xa2\x08\x48\xc5\x4c\xf0\x06\x89\x65\xde\x18\ +\xf7\x16\xf3\x30\xf0\xda\xf7\x32\xd4\xb7\x62\x93\x37\x83\x75\x59\ +\x04\x13\x18\xb3\xf2\x23\x85\xd9\x86\xb4\x83\x2d\x2a\xbc\x4a\x01\ +\xd2\xd6\x37\x88\x80\x80\x77\x55\xde\x26\x01\x95\x7a\xaf\x53\xea\ +\x36\xb0\xb9\x12\xb7\x46\xd0\x48\x20\x18\xbc\x4e\x92\x48\xe2\x12\ +\xd4\x77\x9e\x52\xbb\x6b\x30\x97\x54\xb5\x04\xa2\xc1\x67\x22\xc1\ +\x53\xea\x6d\x68\x4b\x79\x09\xf8\x36\x6c\x68\x65\xd2\xdb\x49\x32\ +\x29\x75\x17\xd8\x58\x97\xd3\x4b\x80\xdd\x7c\xaa\xce\x31\x48\x97\ +\xd8\x4e\x92\xe3\x02\xd4\x0f\x82\xf4\x7e\x3f\xe5\x25\x40\xdf\x83\ +\x41\x20\x9b\x8c\x32\x90\xe0\xd1\x77\xde\x97\xa6\x44\x20\xc7\x9b\ +\xd1\x99\x28\x9d\xc4\xec\x64\xb2\x2b\x5e\x9a\xb3\x6d\xf6\x39\x01\ +\xe4\x10\xa6\x93\xd0\x28\xf6\x9b\x70\x6c\x42\xdb\x0c\xe5\x9b\x1c\ +\xb8\x4b\x31\xda\x93\xf8\xac\xe3\xb0\x9d\x4c\x8c\xbe\x8b\xd8\x8a\ +\xf9\xd7\xec\x04\x24\x60\x3b\x12\xef\x7d\x58\xec\x15\xf0\xd9\xe5\ +\x95\xb7\x23\xe1\xc4\xd0\x0f\x81\xf6\x2b\x51\x21\x61\x7f\xb1\xf5\ +\xc9\xb0\x38\xb4\x34\xc2\xe3\x8a\x47\x56\x41\xf0\xdd\xe9\xa8\x4e\ +\x4b\x8f\x8f\x26\x84\x12\x01\xbe\xf2\x26\x3f\x81\x33\xff\x0c\xe4\ +\xe8\x3a\x99\x15\x6f\x86\x60\xdc\xc4\x13\x33\x4c\xa9\x85\xe6\x81\ +\x67\x14\xdc\xcf\x90\xa7\xab\x10\x93\xab\xc0\x73\x33\xb8\x73\x0d\ +\xaf\x03\x47\x48\xe4\x1c\x5f\x6c\xbb\xba\x42\x12\x13\x97\x20\xdf\ +\x49\xe5\x6d\xf0\x31\x31\x06\xdb\xa1\x02\x43\x05\x86\x0a\x74\x53\ +\x81\xbf\x22\x47\x9c\xdf\xb5\xb4\xa1\x9c\x00\x00\x00\x00\x49\x45\ +\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x02\x8d\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x34\ +\x2e\x35\x20\x38\x43\x31\x33\x2e\x38\x34\x30\x36\x20\x38\x2e\x33\ +\x37\x36\x35\x32\x20\x31\x33\x2e\x32\x30\x36\x32\x20\x38\x2e\x37\ +\x39\x31\x30\x33\x20\x31\x32\x2e\x36\x20\x39\x2e\x32\x34\x30\x35\ +\x31\x43\x31\x31\x2e\x35\x36\x32\x35\x20\x31\x30\x2e\x30\x30\x39\ +\x37\x20\x31\x30\x2e\x36\x30\x37\x34\x20\x31\x30\x2e\x38\x38\x31\ +\x34\x20\x39\x2e\x37\x35\x20\x31\x31\x2e\x38\x34\x30\x32\x43\x36\ +\x2e\x37\x39\x33\x37\x37\x20\x31\x35\x2e\x31\x34\x36\x33\x20\x35\ +\x20\x31\x39\x2e\x34\x38\x39\x31\x20\x35\x20\x32\x34\x2e\x32\x34\ +\x35\x35\x43\x35\x20\x33\x34\x2e\x36\x30\x33\x33\x20\x31\x33\x2e\ +\x35\x30\x36\x36\x20\x34\x33\x20\x32\x34\x20\x34\x33\x43\x33\x34\ +\x2e\x34\x39\x33\x34\x20\x34\x33\x20\x34\x33\x20\x33\x34\x2e\x36\ +\x30\x33\x33\x20\x34\x33\x20\x32\x34\x2e\x32\x34\x35\x35\x43\x34\ +\x33\x20\x31\x39\x2e\x34\x38\x39\x31\x20\x34\x31\x2e\x32\x30\x36\ +\x32\x20\x31\x35\x2e\x31\x34\x36\x33\x20\x33\x38\x2e\x32\x35\x20\ +\x31\x31\x2e\x38\x34\x30\x32\x43\x33\x37\x2e\x33\x39\x32\x36\x20\ +\x31\x30\x2e\x38\x38\x31\x34\x20\x33\x36\x2e\x34\x33\x37\x35\x20\ +\x31\x30\x2e\x30\x30\x39\x37\x20\x33\x35\x2e\x34\x20\x39\x2e\x32\ +\x34\x30\x35\x31\x43\x33\x34\x2e\x37\x39\x33\x38\x20\x38\x2e\x37\ +\x39\x31\x30\x33\x20\x33\x34\x2e\x31\x35\x39\x34\x20\x38\x2e\x33\ +\x37\x36\x35\x32\x20\x33\x33\x2e\x35\x20\x38\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\x20\x34\x56\x32\ +\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\ +\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ +\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\ +\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\x43\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x2d\x72\ +\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\x63\x6c\ +\x69\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\ +\x22\x20\x64\x3d\x22\x4d\x35\x20\x31\x30\x43\x35\x20\x38\x2e\x38\ +\x39\x35\x34\x33\x20\x35\x2e\x38\x39\x35\x34\x33\x20\x38\x20\x37\ +\x20\x38\x4c\x34\x31\x20\x38\x43\x34\x32\x2e\x31\x30\x34\x36\x20\ +\x38\x20\x34\x33\x20\x38\x2e\x38\x39\x35\x34\x33\x20\x34\x33\x20\ +\x31\x30\x56\x33\x38\x43\x34\x33\x20\x33\x39\x2e\x31\x30\x34\x36\ +\x20\x34\x32\x2e\x31\x30\x34\x36\x20\x34\x30\x20\x34\x31\x20\x34\ +\x30\x48\x37\x43\x35\x2e\x38\x39\x35\x34\x33\x20\x34\x30\x20\x35\ +\x20\x33\x39\x2e\x31\x30\x34\x36\x20\x35\x20\x33\x38\x56\x31\x30\ +\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\ +\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ +\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\ +\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\ +\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\ +\x63\x6c\x69\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\ +\x64\x64\x22\x20\x64\x3d\x22\x4d\x31\x34\x2e\x35\x20\x31\x38\x43\ +\x31\x35\x2e\x33\x32\x38\x34\x20\x31\x38\x20\x31\x36\x20\x31\x37\ +\x2e\x33\x32\x38\x34\x20\x31\x36\x20\x31\x36\x2e\x35\x43\x31\x36\ +\x20\x31\x35\x2e\x36\x37\x31\x36\x20\x31\x35\x2e\x33\x32\x38\x34\ +\x20\x31\x35\x20\x31\x34\x2e\x35\x20\x31\x35\x43\x31\x33\x2e\x36\ +\x37\x31\x36\x20\x31\x35\x20\x31\x33\x20\x31\x35\x2e\x36\x37\x31\ +\x36\x20\x31\x33\x20\x31\x36\x2e\x35\x43\x31\x33\x20\x31\x37\x2e\ +\x33\x32\x38\x34\x20\x31\x33\x2e\x36\x37\x31\x36\x20\x31\x38\x20\ +\x31\x34\x2e\x35\x20\x31\x38\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\ +\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\ +\x74\x68\x20\x64\x3d\x22\x4d\x31\x35\x20\x32\x34\x4c\x32\x30\x20\ +\x32\x38\x4c\x32\x36\x20\x32\x31\x4c\x34\x33\x20\x33\x34\x56\x33\ +\x38\x43\x34\x33\x20\x33\x39\x2e\x31\x30\x34\x36\x20\x34\x32\x2e\ +\x31\x30\x34\x36\x20\x34\x30\x20\x34\x31\x20\x34\x30\x48\x37\x43\ +\x35\x2e\x38\x39\x35\x34\x33\x20\x34\x30\x20\x35\x20\x33\x39\x2e\ +\x31\x30\x34\x36\x20\x35\x20\x33\x38\x56\x33\x34\x4c\x31\x35\x20\ +\x32\x34\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\ +\x67\x3e\ +\x00\x00\x02\x48\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\ +\x20\x34\x34\x43\x33\x35\x2e\x30\x34\x35\x37\x20\x34\x34\x20\x34\ +\x34\x20\x33\x35\x2e\x30\x34\x35\x37\x20\x34\x34\x20\x32\x34\x43\ +\x34\x34\x20\x31\x32\x2e\x39\x35\x34\x33\x20\x33\x35\x2e\x30\x34\ +\x35\x37\x20\x34\x20\x32\x34\x20\x34\x43\x31\x32\x2e\x39\x35\x34\ +\x33\x20\x34\x20\x34\x20\x31\x32\x2e\x39\x35\x34\x33\x20\x34\x20\ +\x32\x34\x43\x34\x20\x33\x35\x2e\x30\x34\x35\x37\x20\x31\x32\x2e\ +\x39\x35\x34\x33\x20\x34\x34\x20\x32\x34\x20\x34\x34\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x32\x39\x2e\x36\x35\x36\x37\x20\x31\x38\x2e\x33\x34\x33\x32\ +\x4c\x31\x38\x2e\x33\x34\x33\x20\x32\x39\x2e\x36\x35\x36\x39\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x38\ +\x2e\x33\x34\x33\x33\x20\x31\x38\x2e\x33\x34\x33\x32\x4c\x32\x39\ +\x2e\x36\x35\x37\x20\x32\x39\x2e\x36\x35\x36\x39\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\ +\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\ +\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x01\x7a\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x37\x20\ +\x34\x32\x48\x34\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x31\x31\x20\x32\x36\x2e\x37\x31\x39\x39\x56\x33\ +\x34\x48\x31\x38\x2e\x33\x31\x37\x32\x4c\x33\x39\x20\x31\x33\x2e\ +\x33\x30\x38\x31\x4c\x33\x31\x2e\x36\x39\x35\x31\x20\x36\x4c\x31\ +\x31\x20\x32\x36\x2e\x37\x31\x39\x39\x5a\x22\x20\x66\x69\x6c\x6c\ +\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\xca\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x36\x20\ +\x39\x43\x36\x20\x37\x2e\x33\x34\x33\x31\x35\x20\x37\x2e\x33\x34\ +\x33\x31\x35\x20\x36\x20\x39\x20\x36\x48\x33\x34\x2e\x32\x38\x31\ +\x34\x4c\x34\x32\x20\x31\x33\x2e\x32\x30\x36\x35\x56\x33\x39\x43\ +\x34\x32\x20\x34\x30\x2e\x36\x35\x36\x39\x20\x34\x30\x2e\x36\x35\ +\x36\x39\x20\x34\x32\x20\x33\x39\x20\x34\x32\x48\x39\x43\x37\x2e\ +\x33\x34\x33\x31\x35\x20\x34\x32\x20\x36\x20\x34\x30\x2e\x36\x35\ +\x36\x39\x20\x36\x20\x33\x39\x56\x39\x5a\x22\x20\x66\x69\x6c\x6c\ +\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x2d\x72\x75\ +\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\x63\x6c\x69\ +\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\ +\x20\x64\x3d\x22\x4d\x32\x34\x2e\x30\x30\x38\x33\x20\x36\x4c\x32\ +\x34\x20\x31\x33\x2e\x33\x38\x34\x36\x43\x32\x34\x20\x31\x33\x2e\ +\x37\x32\x34\x35\x20\x32\x33\x2e\x35\x35\x32\x33\x20\x31\x34\x20\ +\x32\x33\x20\x31\x34\x48\x31\x35\x43\x31\x34\x2e\x34\x34\x37\x37\ +\x20\x31\x34\x20\x31\x34\x20\x31\x33\x2e\x37\x32\x34\x35\x20\x31\ +\x34\x20\x31\x33\x2e\x33\x38\x34\x36\x4c\x31\x34\x20\x36\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x2f\x3e\x3c\x70\x61\ +\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\x2e\x30\x30\x38\x33\x20\x36\ +\x4c\x32\x34\x20\x31\x33\x2e\x33\x38\x34\x36\x43\x32\x34\x20\x31\ +\x33\x2e\x37\x32\x34\x35\x20\x32\x33\x2e\x35\x35\x32\x33\x20\x31\ +\x34\x20\x32\x33\x20\x31\x34\x48\x31\x35\x43\x31\x34\x2e\x34\x34\ +\x37\x37\x20\x31\x34\x20\x31\x34\x20\x31\x33\x2e\x37\x32\x34\x35\ +\x20\x31\x34\x20\x31\x33\x2e\x33\x38\x34\x36\x4c\x31\x34\x20\x36\ +\x48\x32\x34\x2e\x30\x30\x38\x33\x5a\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\ +\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\ +\x39\x20\x36\x48\x33\x34\x2e\x32\x38\x31\x34\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x34\x20\x32\x36\x48\ +\x33\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x31\x34\x20\x33\x34\x48\x32\x34\x2e\x30\x30\x38\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\x06\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x2d\x72\ +\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\x63\x6c\ +\x69\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\ +\x22\x20\x64\x3d\x22\x4d\x32\x34\x20\x34\x34\x43\x33\x35\x2e\x30\ +\x34\x35\x37\x20\x34\x34\x20\x34\x34\x20\x33\x35\x2e\x30\x34\x35\ +\x37\x20\x34\x34\x20\x32\x34\x43\x34\x34\x20\x31\x32\x2e\x39\x35\ +\x34\x33\x20\x33\x35\x2e\x30\x34\x35\x37\x20\x34\x20\x32\x34\x20\ +\x34\x43\x31\x32\x2e\x39\x35\x34\x33\x20\x34\x20\x34\x20\x31\x32\ +\x2e\x39\x35\x34\x33\x20\x34\x20\x32\x34\x43\x34\x20\x33\x35\x2e\ +\x30\x34\x35\x37\x20\x31\x32\x2e\x39\x35\x34\x33\x20\x34\x34\x20\ +\x32\x34\x20\x34\x34\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x4d\x32\x34\x20\x32\x33\x43\x32\x36\x2e\x37\x36\ +\x31\x34\x20\x32\x33\x20\x32\x39\x20\x32\x30\x2e\x37\x36\x31\x34\ +\x20\x32\x39\x20\x31\x38\x43\x32\x39\x20\x31\x35\x2e\x32\x33\x38\ +\x36\x20\x32\x36\x2e\x37\x36\x31\x34\x20\x31\x33\x20\x32\x34\x20\ +\x31\x33\x43\x32\x31\x2e\x32\x33\x38\x36\x20\x31\x33\x20\x31\x39\ +\x20\x31\x35\x2e\x32\x33\x38\x36\x20\x31\x39\x20\x31\x38\x43\x31\ +\x39\x20\x32\x30\x2e\x37\x36\x31\x34\x20\x32\x31\x2e\x32\x33\x38\ +\x36\x20\x32\x33\x20\x32\x34\x20\x32\x33\x5a\x22\x20\x66\x69\x6c\ +\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\ +\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\ +\x2e\x30\x32\x32\x20\x33\x38\x2e\x33\x33\x32\x43\x31\x30\x2e\x33\ +\x36\x35\x37\x20\x33\x33\x2e\x31\x32\x30\x36\x20\x31\x34\x2e\x37\ +\x30\x31\x36\x20\x32\x39\x20\x32\x30\x20\x32\x39\x48\x32\x38\x43\ +\x33\x33\x2e\x32\x39\x31\x34\x20\x32\x39\x20\x33\x37\x2e\x36\x32\ +\x32\x39\x20\x33\x33\x2e\x31\x30\x39\x37\x20\x33\x37\x2e\x39\x37\ +\x36\x37\x20\x33\x38\x2e\x33\x31\x31\x33\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\ +\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\ +\x2f\x73\x76\x67\x3e\ +\x00\x00\x01\xd7\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\ +\x2e\x30\x30\x38\x33\x20\x31\x34\x2e\x31\x30\x30\x36\x56\x34\x32\ +\x2e\x30\x30\x30\x31\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x31\x32\x20\x32\x36\x4c\x32\x34\x20\x31\x34\x4c\ +\x33\x36\x20\x32\x36\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x31\x32\x20\x36\x48\x33\x36\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x02\x95\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x39\x20\ +\x31\x30\x56\x34\x34\x48\x33\x39\x56\x31\x30\x48\x39\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x32\x30\x20\x32\x30\x56\x33\x33\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\ +\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x38\x20\x32\x30\x56\x33\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\ +\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\ +\x20\x31\x30\x48\x34\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x4d\x31\x36\x20\x31\x30\x4c\x31\x39\x2e\x32\x38\ +\x39\x20\x34\x48\x32\x38\x2e\x37\x37\x37\x31\x4c\x33\x32\x20\x31\ +\x30\x48\x31\x36\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\ +\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\ +\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ +\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\ +\x73\x76\x67\x3e\ +\x00\x00\x01\xe4\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x34\ +\x20\x31\x31\x4c\x34\x20\x32\x34\x4c\x31\x34\x20\x33\x37\x48\x34\ +\x34\x56\x31\x31\x48\x31\x34\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\ +\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\ +\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\ +\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x4d\x32\x31\x20\x31\x39\x4c\x33\x31\x20\x32\x39\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x31\x20\ +\x31\x39\x4c\x32\x31\x20\x32\x39\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\ +\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\ +\x76\x67\x3e\ +\x00\x00\x01\x10\ +\x00\ +\x00\x04\x42\x78\x9c\xc5\x93\x51\x6e\x83\x30\x0c\x86\xaf\x62\x79\ +\xcf\x25\x29\xa0\x0a\x4d\x84\x4a\x7d\xe8\x09\xb6\x03\x54\x34\x40\ +\x36\x9a\x74\x21\x23\x70\xfb\x39\x1b\x74\xe3\x71\x5a\xc5\xa4\x48\ +\xb1\xad\xe8\xfb\x13\xfb\x4f\xbe\x1f\x2e\x2d\xf4\xd2\x76\xca\x68\ +\x81\xdb\x88\x23\x48\x5d\x9a\xb3\xd2\xb5\xc0\xe7\xa7\xe3\x26\xc3\ +\x7d\x91\x77\x7d\x0d\x5e\x9d\x5d\x23\x30\x89\x11\x1a\xa9\xea\xc6\ +\x7d\xc5\xbd\x92\xfe\x60\x06\x81\x1c\x38\xa4\x19\x2d\x84\x4a\xb5\ +\xad\x40\x6d\xb4\x44\x20\xbe\xee\x04\x36\xce\x5d\x1f\x19\xf3\xde\ +\x47\x3e\x89\x8c\xad\x59\xcc\x39\x67\x04\xc6\x22\x6f\x95\x96\x30\ +\x6c\x49\x3f\x45\x18\x69\x27\xc6\x10\x13\x3f\xa4\xf1\x67\xda\x39\ +\x6b\x5e\xa5\xc0\x07\xce\x77\x69\x55\xcd\x85\xcd\x7c\xab\x5b\x21\ +\xb0\xca\xd3\x55\x60\xf7\xf6\x7e\xb2\x12\xd9\xfa\xf8\x94\x2f\xf9\ +\x21\xff\x8b\x80\x95\xa5\x03\xea\x70\xb2\x23\x1e\xe1\x70\x9e\x45\ +\xf6\x3d\x0a\x0a\x2d\x1d\x89\x97\xcd\xff\x95\xea\x8b\x51\x64\x81\ +\x8b\x72\xd2\xfe\x54\x4d\xff\x43\x74\x7a\x6a\xd8\xd6\x7f\xeb\x5a\ +\xaa\x37\xe3\x04\x83\x8c\x93\x81\x86\xc9\x30\xe3\x64\xa0\xbb\x38\ +\x33\x5b\xf2\xb3\xfb\xe0\xc3\xef\x2d\x3e\x00\x2f\xe9\x4b\x1d\ +\x00\x00\x03\x09\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x35\x20\ +\x31\x30\x4c\x38\x20\x31\x33\x4c\x31\x34\x20\x37\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\ +\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\ +\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x35\x20\x32\x34\x4c\ +\x38\x20\x32\x37\x4c\x31\x34\x20\x32\x31\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\ +\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\ +\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x35\x20\x33\x38\x4c\x38\x20\ +\x34\x31\x4c\x31\x34\x20\x33\x35\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\ +\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\ +\x74\x68\x20\x64\x3d\x22\x4d\x32\x31\x20\x32\x34\x48\x34\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x31\ +\x20\x33\x38\x48\x34\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x4d\x32\x31\x20\x31\x30\x48\x34\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ +\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\ +\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x02\xf5\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x33\ +\x20\x32\x33\x56\x31\x34\x43\x34\x33\x20\x31\x32\x2e\x38\x39\x35\ +\x34\x20\x34\x32\x2e\x31\x30\x34\x36\x20\x31\x32\x20\x34\x31\x20\ +\x31\x32\x48\x32\x34\x4c\x31\x39\x20\x36\x48\x37\x43\x35\x2e\x38\ +\x39\x35\x34\x33\x20\x36\x20\x35\x20\x36\x2e\x38\x39\x35\x34\x33\ +\x20\x35\x20\x38\x56\x34\x30\x43\x35\x20\x34\x31\x2e\x31\x30\x34\ +\x36\x20\x35\x2e\x38\x39\x35\x34\x33\x20\x34\x32\x20\x37\x20\x34\ +\x32\x48\x32\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\ +\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\ +\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x4d\x32\x37\x20\x33\x31\x4c\x34\x31\x20\x33\x31\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x37\x20\ +\x33\x37\x48\x34\x31\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x34\x31\x20\x33\x31\x4c\x33\x36\x20\x32\x36\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x32\ +\x20\x34\x32\x4c\x32\x37\x20\x33\x37\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\ +\x73\x76\x67\x3e\ +\x00\x00\x03\x2f\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x30\x00\x00\x00\x30\x08\x06\x00\x00\x00\x57\x02\xf9\x87\ +\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\ +\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\ +\x0d\xd7\x01\x42\x28\x9b\x78\x00\x00\x00\x07\x74\x49\x4d\x45\x07\ +\xe6\x0a\x19\x03\x13\x1b\x82\xa4\x64\xac\x00\x00\x02\xbc\x49\x44\ +\x41\x54\x68\x43\xed\x58\xbf\x6b\x14\x41\x18\x7d\xab\x06\x63\xa5\ +\x58\x89\x85\x4d\xd0\xc6\x1f\xa4\x10\x0b\x0b\x09\x28\x88\xfe\x01\ +\x56\x56\x22\x0a\x96\x16\x41\x93\x14\x07\x1a\x91\x14\xe9\x52\x44\ +\x0e\xed\x2d\x6d\x04\xb1\x31\x85\xad\x85\x04\x22\xa2\x45\x14\xc4\ +\x2a\x56\xe1\x88\x3f\xc6\x37\x7b\x3b\xcb\xec\x64\x67\x77\xe6\x76\ +\x99\xdd\x23\xfb\x85\x25\x37\xf3\x7d\x33\xdf\x7b\x6f\xbe\x99\x9d\ +\x3b\xa0\xb3\x4e\x81\x4e\x81\x4e\x81\x26\x15\x88\xf2\x92\x3f\x02\ +\xa6\xf6\x03\x57\x04\x70\x24\xcf\xdf\x40\xdf\xd6\x3e\xe0\xed\x43\ +\xe0\xab\x99\x7b\x17\x81\x45\xe0\x16\x83\x56\xf8\x4c\x9a\xc1\x0d\ +\xb7\x07\x04\x7b\x6f\x0e\x78\xa1\xe3\xc8\x10\x90\xca\x93\xe9\x3a\ +\x03\x0e\x36\x0c\xd6\x96\x7e\x40\x7c\xa7\xf5\x95\x38\xa0\x47\xd2\ +\x79\x59\x81\x67\xf9\x7c\x20\xbb\x37\xb6\x99\x02\xf7\x5f\x65\xbe\ +\x69\x3e\x93\xff\x58\xda\xfc\xff\x4c\xe5\xcf\x10\x60\xe7\x71\xe5\ +\x20\xf8\x57\xf3\x40\x2f\x30\xd0\xdc\x74\x2c\xeb\x01\x1d\x92\x80\ +\xb4\x14\xa3\x6c\x50\xf4\xf1\xb6\xb1\x27\x60\x96\x90\xd3\x72\x88\ +\xf7\xe0\x16\x19\x5a\x74\x11\xbb\x4e\x32\xa7\x49\x6a\x0a\xf2\x5e\ +\x81\x18\xfc\x26\xb3\x27\x8f\x4e\xa6\x26\x4c\x5e\xd3\x78\x11\x48\ +\xc1\xeb\x29\x48\xa4\x49\x12\x5e\x04\xbc\xa4\x09\x14\xbc\xb7\x08\ +\xc4\x1b\xf6\x84\x21\x2d\xdb\x4d\x6e\x64\xef\x15\x48\x49\x48\x22\ +\x0e\xe0\x79\x5c\x45\xdc\xf6\xf1\xdf\x4b\x80\x77\xc4\x7a\xcd\x9b\ +\x80\x4c\x2f\x49\xa8\xa7\x0c\x4e\x24\xc0\xb7\xff\xd0\x6e\x08\xfc\ +\x59\x02\x8e\x95\x8d\xf1\xf1\x8f\x44\xc0\x39\x81\xd4\xdd\xb0\x59\ +\x81\x1f\xf1\x7a\xd4\x64\x23\x11\xe8\xc9\x2b\x48\x52\x16\xf1\xe7\ +\x3c\x2b\x03\x49\x7f\x5c\x5e\x15\x2d\x3f\x79\xc1\xa4\x12\x70\x4f\ +\xe0\xaf\x0a\x91\x9f\xd9\x97\xfd\xe2\x53\x06\x3e\x19\x2c\xcb\xeb\ +\x29\x70\xb8\x20\x5d\xa9\xcb\x8b\x80\x54\x4c\x07\xaf\x91\xd8\xe2\ +\x8d\xf1\x4c\xdc\x76\x04\xaf\xc6\x3e\x10\xf8\xe5\x3b\x46\x67\xe5\ +\x4c\xa0\x47\xe5\xf5\x0d\x69\x4a\x33\x2f\xf0\xb1\x0a\x90\x51\xc7\ +\x3a\x11\x90\xe0\xf3\x94\x37\x49\x54\x6e\x73\xf5\x96\x81\x43\x3e\ +\xf3\x94\x12\x08\x06\x3e\x41\x7d\x5f\x60\xfb\x09\x70\xca\x95\x44\ +\x21\x81\xd0\xe0\x15\xe8\x39\x81\x4f\xae\x25\x65\x25\x60\xdb\xb0\ +\xae\xca\xd4\x12\xc7\x92\x5a\x05\x26\x8a\xe6\xb2\x12\xe0\x01\x7d\ +\xbd\x68\x60\x28\xdf\x5d\x81\x1d\x82\xb4\xfe\x3e\x65\x25\x40\x80\ +\xe7\x43\x81\x2c\xcb\xc3\xbb\xc8\x1d\x5b\x4c\x86\x40\x1d\x6f\x46\ +\x5b\xa2\x8a\xfd\xe9\xc9\x64\x2a\x9e\x69\xb3\x6c\xce\x56\x4c\x14\ +\x62\xf8\x39\x3d\x89\x49\xe8\xa8\xe6\xdc\x08\x81\xc6\x31\xc7\x77\ +\x15\xc7\x72\xd2\x31\x5a\x2e\x62\xc3\xe8\x9f\x8e\x93\x87\x08\xfb\ +\x62\x4b\x62\xae\x80\x2d\xae\xb5\xfd\x63\x4f\xc0\xfc\x61\xeb\x9b\ +\x26\xf5\x85\xc5\x08\xaf\x5b\x22\xfd\x8c\xc2\xc1\x83\x66\x53\xc7\ +\x94\x21\xc0\x57\x5e\xff\x37\x70\x33\x09\x90\x47\xd7\xb5\x96\x10\ +\x48\x61\x70\x13\xf7\x75\x4c\x99\x12\x9a\x05\xde\xb1\xe3\x79\xdb\ +\x40\x6b\x78\xfa\x0b\xc0\x9a\x8e\x2f\xf7\x2b\xdd\x63\xe0\x12\x89\ +\xdc\xe6\x8b\xed\x64\x1b\xc8\x10\xe4\x67\xa9\xbc\x09\xbe\x0d\xd8\ +\x3a\x0c\x9d\x02\x9d\x02\x7b\x5d\x81\xff\xd4\x3b\x9a\x8c\xa1\x62\ +\xf3\x6f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x03\x69\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x38\ +\x2e\x32\x38\x35\x37\x20\x33\x37\x48\x33\x39\x2e\x37\x31\x34\x33\ +\x4d\x34\x32\x20\x34\x32\x4c\x33\x39\x2e\x37\x31\x34\x33\x20\x33\ +\x37\x4c\x34\x32\x20\x34\x32\x5a\x4d\x32\x36\x20\x34\x32\x4c\x32\ +\x38\x2e\x32\x38\x35\x37\x20\x33\x37\x4c\x32\x36\x20\x34\x32\x5a\ +\x4d\x32\x38\x2e\x32\x38\x35\x37\x20\x33\x37\x4c\x33\x34\x20\x32\ +\x34\x4c\x33\x39\x2e\x37\x31\x34\x33\x20\x33\x37\x48\x32\x38\x2e\ +\x32\x38\x35\x37\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x31\x36\x20\x36\x4c\x31\x37\x20\x39\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ +\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\ +\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x36\x20\x31\x31\ +\x48\x32\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\ +\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ +\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\ +\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\ +\x22\x4d\x31\x30\x20\x31\x36\x43\x31\x30\x20\x31\x36\x20\x31\x31\ +\x2e\x37\x38\x39\x35\x20\x32\x32\x2e\x32\x36\x30\x39\x20\x31\x36\ +\x2e\x32\x36\x33\x32\x20\x32\x35\x2e\x37\x33\x39\x31\x43\x32\x30\ +\x2e\x37\x33\x36\x38\x20\x32\x39\x2e\x32\x31\x37\x34\x20\x32\x38\ +\x20\x33\x32\x20\x32\x38\x20\x33\x32\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\ +\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\x20\x31\x31\x43\x32\x34\ +\x20\x31\x31\x20\x32\x32\x2e\x32\x31\x30\x35\x20\x31\x39\x2e\x32\ +\x31\x37\x34\x20\x31\x37\x2e\x37\x33\x36\x38\x20\x32\x33\x2e\x37\ +\x38\x32\x36\x43\x31\x33\x2e\x32\x36\x33\x32\x20\x32\x38\x2e\x33\ +\x34\x37\x38\x20\x36\x20\x33\x32\x20\x36\x20\x33\x32\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ +\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\ +\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x02\x35\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x31\ +\x20\x33\x38\x43\x33\x30\x2e\x33\x38\x38\x38\x20\x33\x38\x20\x33\ +\x38\x20\x33\x30\x2e\x33\x38\x38\x38\x20\x33\x38\x20\x32\x31\x43\ +\x33\x38\x20\x31\x31\x2e\x36\x31\x31\x32\x20\x33\x30\x2e\x33\x38\ +\x38\x38\x20\x34\x20\x32\x31\x20\x34\x43\x31\x31\x2e\x36\x31\x31\ +\x32\x20\x34\x20\x34\x20\x31\x31\x2e\x36\x31\x31\x32\x20\x34\x20\ +\x32\x31\x43\x34\x20\x33\x30\x2e\x33\x38\x38\x38\x20\x31\x31\x2e\ +\x36\x31\x31\x32\x20\x33\x38\x20\x32\x31\x20\x33\x38\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x31\x35\x20\x32\x31\x4c\x32\x37\x20\x32\x31\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\ +\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\ +\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x33\x2e\x32\x32\ +\x31\x36\x20\x33\x33\x2e\x32\x32\x31\x37\x4c\x34\x31\x2e\x37\x30\ +\x36\x39\x20\x34\x31\x2e\x37\x30\x37\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\ +\x73\x76\x67\x3e\ +\x00\x00\x02\x2b\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x39\ +\x20\x36\x48\x39\x43\x37\x2e\x33\x34\x33\x31\x35\x20\x36\x20\x36\ +\x20\x37\x2e\x33\x34\x33\x31\x35\x20\x36\x20\x39\x56\x33\x39\x43\ +\x36\x20\x34\x30\x2e\x36\x35\x36\x39\x20\x37\x2e\x33\x34\x33\x31\ +\x35\x20\x34\x32\x20\x39\x20\x34\x32\x48\x33\x39\x43\x34\x30\x2e\ +\x36\x35\x36\x39\x20\x34\x32\x20\x34\x32\x20\x34\x30\x2e\x36\x35\ +\x36\x39\x20\x34\x32\x20\x33\x39\x56\x32\x39\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\x20\x31\x39\x4c\ +\x33\x38\x20\x37\x4c\x32\x36\x20\x31\x31\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\ +\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\ +\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x38\x20\x37\x43\x33\x33\ +\x20\x32\x32\x20\x33\x30\x20\x32\x35\x20\x32\x30\x20\x32\x39\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\xee\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x38\x20\ +\x32\x38\x43\x31\x30\x2e\x32\x30\x39\x31\x20\x32\x38\x20\x31\x32\ +\x20\x32\x36\x2e\x32\x30\x39\x31\x20\x31\x32\x20\x32\x34\x43\x31\ +\x32\x20\x32\x31\x2e\x37\x39\x30\x39\x20\x31\x30\x2e\x32\x30\x39\ +\x31\x20\x32\x30\x20\x38\x20\x32\x30\x43\x35\x2e\x37\x39\x30\x38\ +\x36\x20\x32\x30\x20\x34\x20\x32\x31\x2e\x37\x39\x30\x39\x20\x34\ +\x20\x32\x34\x43\x34\x20\x32\x36\x2e\x32\x30\x39\x31\x20\x35\x2e\ +\x37\x39\x30\x38\x36\x20\x32\x38\x20\x38\x20\x32\x38\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x38\x20\x31\x32\x43\x39\x2e\x31\x30\x34\x35\x37\x20\x31\x32\ +\x20\x31\x30\x20\x31\x31\x2e\x31\x30\x34\x36\x20\x31\x30\x20\x31\ +\x30\x43\x31\x30\x20\x38\x2e\x38\x39\x35\x34\x33\x20\x39\x2e\x31\ +\x30\x34\x35\x37\x20\x38\x20\x38\x20\x38\x43\x36\x2e\x38\x39\x35\ +\x34\x33\x20\x38\x20\x36\x20\x38\x2e\x38\x39\x35\x34\x33\x20\x36\ +\x20\x31\x30\x43\x36\x20\x31\x31\x2e\x31\x30\x34\x36\x20\x36\x2e\ +\x38\x39\x35\x34\x33\x20\x31\x32\x20\x38\x20\x31\x32\x5a\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x4d\x38\x20\x34\x30\x43\x39\x2e\x31\x30\x34\x35\ +\x37\x20\x34\x30\x20\x31\x30\x20\x33\x39\x2e\x31\x30\x34\x36\x20\ +\x31\x30\x20\x33\x38\x43\x31\x30\x20\x33\x36\x2e\x38\x39\x35\x34\ +\x20\x39\x2e\x31\x30\x34\x35\x37\x20\x33\x36\x20\x38\x20\x33\x36\ +\x43\x36\x2e\x38\x39\x35\x34\x33\x20\x33\x36\x20\x36\x20\x33\x36\ +\x2e\x38\x39\x35\x34\x20\x36\x20\x33\x38\x43\x36\x20\x33\x39\x2e\ +\x31\x30\x34\x36\x20\x36\x2e\x38\x39\x35\x34\x33\x20\x34\x30\x20\ +\x38\x20\x34\x30\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\ +\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x30\x20\x32\ +\x34\x48\x34\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\ +\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\ +\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x4d\x32\x30\x20\x33\x38\x48\x34\x34\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x30\x20\x31\x30\x48\ +\x34\x34\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\x3e\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x30\ +\x20\x32\x33\x56\x31\x34\x4c\x33\x31\x20\x34\x48\x31\x30\x43\x38\ +\x2e\x38\x39\x35\x34\x33\x20\x34\x20\x38\x20\x34\x2e\x38\x39\x35\ +\x34\x33\x20\x38\x20\x36\x56\x34\x32\x43\x38\x20\x34\x33\x2e\x31\ +\x30\x34\x36\x20\x38\x2e\x38\x39\x35\x34\x33\x20\x34\x34\x20\x31\ +\x30\x20\x34\x34\x48\x32\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\ +\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\ +\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\ +\x68\x20\x64\x3d\x22\x4d\x32\x37\x20\x33\x33\x48\x34\x31\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x37\x20\ +\x33\x39\x48\x34\x31\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ +\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x4d\x34\x31\x20\x33\x33\x4c\x33\x36\x20\x32\x38\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x32\ +\x20\x34\x34\x4c\x32\x37\x20\x33\x39\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\ +\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\ +\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x30\x20\x34\x56\x31\x34\x48\ +\x34\x30\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x01\xd2\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\ +\x2e\x30\x30\x38\x33\x20\x33\x33\x2e\x38\x39\x39\x35\x56\x36\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x36\ +\x20\x32\x32\x4c\x32\x34\x20\x33\x34\x4c\x31\x32\x20\x32\x32\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\ +\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x36\ +\x20\x34\x32\x48\x31\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\ +\x3e\ +\x00\x00\x06\x28\ +\x00\ +\x00\x15\xb6\x78\x9c\xed\x58\x4b\x6f\x1b\x55\x14\x3e\x1e\xcf\xd8\ +\x5e\x40\x95\xa2\x4a\x6c\x90\x1a\x81\x40\xdd\x20\xaa\x82\xd8\x20\ +\xa1\x6c\x40\x6c\x40\x65\xd1\x56\x6a\x41\x8a\xda\xc4\xb1\x13\x37\ +\x71\x92\x26\xe4\xe1\x24\xe3\x84\x1f\x90\x0a\xba\xa8\x5a\xa1\xb0\ +\x40\x42\x48\x88\x2c\x2a\xba\x01\xe1\x1d\x20\x2a\x6a\x21\x84\x8a\ +\x08\xf1\xf8\x11\xe7\x65\xd7\x93\xc4\x8f\x38\xb6\x7a\xf9\xce\x8c\ +\xc7\x8d\x5d\xdb\x6d\x61\xd1\x05\xb9\xd2\xa7\xf1\x3c\xce\x7c\xdf\ +\x39\xf7\xde\x73\xce\x98\xc8\x46\x12\xb5\xb7\x13\x8e\xed\x74\xec\ +\x30\xd1\x4b\x44\xd4\xd6\x66\x9e\x7b\x64\xa2\xf7\x70\xed\x18\xae\ +\xe1\x11\xea\x20\xf3\xba\x31\xda\xe8\x60\x1c\x8c\x83\xd1\x62\x14\ +\x54\x6a\x2f\xcd\x51\x07\x63\x4f\xa5\xe3\xff\xf5\x7d\x99\x31\x6a\ +\xcf\x8c\xc9\x1d\x8c\xec\x44\xf3\xf7\x31\x57\x69\x96\x42\x80\xa8\ +\x43\xf8\xdf\xe8\x58\xf5\xbb\xda\x37\x86\xe4\x50\xfa\x92\x5d\xdc\ +\x1d\xb1\x0b\xfd\x23\x49\xec\x4c\x48\x22\x1f\xb0\x69\x85\x80\x91\ +\x16\x6a\xb8\xf7\x82\xa4\x03\xa2\x14\x7c\x80\x9f\xa1\x97\xe7\xe8\ +\xe4\xa3\x72\x27\xfc\xca\xf1\xf5\x41\x59\xdf\x18\x94\xc5\xe6\x90\ +\x5c\xc3\x9f\x0b\xd8\x44\x7e\xca\x26\x10\xe7\xaa\x86\xa2\x6a\xf8\ +\x28\x98\x7f\xaf\x31\x3f\xeb\xd2\x1f\x25\x0e\x11\x3f\xb5\xad\xfa\ +\x15\x6d\x6d\x40\x11\xeb\x7e\x93\x3f\x33\x6a\xf1\xdb\x0c\xfe\xdd\ +\x19\x83\x47\xb3\x7c\xdf\x9d\xc6\x39\xf8\x8b\xa6\x06\xbd\x18\x24\ +\x75\x6f\x96\x3a\xeb\xe7\x03\xf7\xc2\x42\x6d\x9d\x45\x93\xfd\xf2\ +\x62\xb2\x5f\x11\x0c\xe6\x4f\x0d\xdb\x01\x79\x1e\x1a\x4e\x6e\x8f\ +\x4b\x61\xe6\x2f\x4c\x9b\x71\xe6\x98\xe2\xb7\xca\xfc\x0c\x83\x5f\ +\x25\x7f\xcd\xdc\xcc\xd1\x42\x8d\x06\x95\xe6\x9b\xc6\xbd\x57\xe9\ +\x4c\xf8\x1c\x82\xb1\x72\xd1\xd4\xb0\x31\xa4\x74\x5a\xf7\x33\xd0\ +\x0e\x7e\x9d\xfd\xaf\xc4\x54\xcd\x06\x28\x94\x0b\x10\xd6\x05\x89\ +\xc2\x14\x89\x7a\xff\xf8\x9c\xd7\xa0\xc5\xcf\xb6\xd9\x06\xf3\xc0\ +\x71\x8f\xf7\x39\xf4\x58\xaf\xc5\xef\x10\x49\xbf\xf2\x80\xd6\x5c\ +\x40\x5a\x28\x4c\xdb\x2c\x7f\x42\xcc\xbf\x33\x41\xc2\xd2\xd0\xc8\ +\x2f\x63\x6f\x04\xab\x73\x80\xf8\xd9\x42\xf5\xcf\xc4\xfa\x1c\x0b\ +\xcc\xcd\x88\x7a\x9d\x02\x5a\xb4\x46\xef\xca\x4d\x4b\x2a\xfb\xc0\ +\xb1\x66\xfe\x9d\x71\x03\x62\x1b\xe0\x63\xb3\xd8\x72\xac\x2c\x0d\ +\x46\x0c\xa6\xa8\x1a\xd7\xb8\xcf\xd5\xa1\x79\x9c\xc2\x00\xb8\x0d\ +\x7e\x5c\x6b\xc6\x9f\x87\xff\x16\xbf\x3e\x46\xa1\xcc\x08\xf8\xc7\ +\x48\xe8\xa3\xcd\xf9\x2b\x1a\xc2\x96\x86\xec\xa4\x54\xf5\x0f\xbc\ +\x4b\xcc\x1d\xe9\x31\x35\x44\x3c\xce\xa6\x6b\x64\x27\x00\x7e\xec\ +\xbf\xca\x3e\x0b\xa5\x47\x68\xfe\xee\x25\x12\xe9\x61\x93\x9f\xf3\ +\x55\x53\x7e\xec\xd9\x52\x25\x47\xb0\xfe\xad\x09\x49\x8d\xfb\x9c\ +\xdf\x44\xbd\x2e\xc3\xef\x0a\xbf\xce\x6b\xa1\x29\xff\xa4\x6d\x91\ +\xfd\xdf\x9d\x31\x34\x2c\x6c\xfa\xc9\x0f\x88\xd4\x20\x30\x04\xfe\ +\xe1\xd6\x79\x66\x17\xeb\xdf\xd2\x80\x7c\xb2\x15\xeb\x75\xde\x63\ +\x7e\x06\xfc\xc6\xfc\xbb\x3a\x5b\xd9\x67\x03\xb6\x30\x73\x1b\x6b\ +\x00\x73\x0a\xee\x8e\xb5\x7e\x12\xeb\x03\x24\xf8\x08\x1d\x4d\x63\ +\xc7\x83\xf7\x03\xd6\xa3\xc6\x73\xb0\x36\x20\x8b\xa8\xc7\x9c\x6f\ +\xe6\x5f\xf1\x39\x7f\x6f\x65\x6b\xec\xbf\x29\xd3\x77\x63\xfe\xe7\ +\xcc\x1c\xb8\x36\x40\x7a\xb2\x0f\xef\xbb\x48\x02\x47\xbd\xd5\x3b\ +\x78\xec\x20\x7f\x73\x2e\x8b\x7a\x1c\x15\x38\x0d\xac\xf8\x1c\x67\ +\x5a\xfa\x8e\x35\x6b\xc5\x9e\xf9\xad\xbd\x9e\xf0\xd2\x02\x20\x56\ +\x7a\x4d\xc4\x3c\xf7\xd7\x76\xa3\x01\x8d\x47\x63\x1e\x45\x44\x7b\ +\x94\xaa\x86\xa4\xcf\xf1\xd3\xc3\x74\xf3\xbe\xad\xfa\x1e\xa4\x45\ +\xeb\x7a\xdc\x43\x1d\x80\x60\x0d\x51\x37\x09\xfc\xd6\x22\x9d\xcd\ +\xd7\x90\xe6\xb6\x67\xa2\x3d\xb2\xc9\x0f\xac\xf8\x14\xb1\x3d\x21\ +\x8d\xb7\xe4\xc6\xda\xb5\xb8\x8d\x3c\x3b\x5b\xeb\x23\x7c\x0e\xc5\ +\x7a\x4c\xfe\x48\x97\x71\x5c\x68\xc8\xdd\x2d\x2d\x81\x5f\x68\x6e\ +\xd9\x00\xeb\xe0\xb9\xe0\x9c\xd6\x28\x2f\x5a\x83\x6b\x5c\xf1\x7e\ +\x8d\xd1\xea\xef\x47\xba\xe9\xb8\xd6\x6d\x72\xef\xc3\x62\xc4\x63\ +\xee\x47\xfc\x3e\x03\xee\x0c\x00\x5e\x86\xdd\xc0\xfa\x80\x74\x27\ +\x3b\x69\xe6\x6e\xec\x8d\x86\x35\x92\xf7\xd9\x3e\x6e\x51\x52\x6b\ +\xeb\x7f\x55\x43\x17\xa9\x75\xfc\x06\x34\x0b\xdd\xb6\x0a\x24\x03\ +\x31\x8f\xb4\xc4\x76\xc8\x9b\xe1\xfc\x94\x99\x17\xc1\xa1\x03\xaa\ +\xd1\x3f\x21\xc6\x80\x66\xd5\xf5\x4a\x7f\xd1\x72\x7f\x81\x6f\xa1\ +\x29\xbf\x01\x53\x43\xd4\x6d\x5b\xb2\x6c\x32\xc8\x37\xb9\x49\x0a\ +\x1b\x75\xbc\x59\xff\xc0\xb5\x63\xae\xf1\x9c\x36\xd0\xe0\x07\xf4\ +\xc6\xfc\x74\x0f\xbe\x5f\xaf\xb7\xe1\xbd\x5d\x9c\xae\xad\xd5\x75\ +\xfd\x8b\xfa\x28\xdc\x55\x0d\x58\xff\x15\x1d\x8b\xe0\x4c\x00\x4b\ +\xc0\xf5\xe5\x0b\x74\xb4\x95\x5d\xa5\x97\x9b\xaf\xf4\x2e\x21\xc4\ +\xdf\xcf\x3d\xed\xe3\x70\x1f\x8c\x83\xf1\x7f\x19\xfc\x3f\x09\x17\ +\x9a\x76\xda\xf7\x3f\x89\xfc\xc4\xe4\x3c\x74\xa0\x66\x4b\x8c\xc7\ +\x7d\x4e\x5c\x25\x05\x39\xf9\x1d\xe4\x84\xcb\xe5\x20\x7d\x0a\xbc\ +\x8b\xfb\x8e\x07\xec\x4e\x91\x1d\xdf\x6e\x6f\xa7\x2f\xc9\x97\xb7\ +\xc6\xa4\x2b\xf9\x49\x7a\x9f\x9f\x43\xaf\x74\x0a\x48\xc2\xbe\x0c\ +\x94\x80\x14\x72\x4b\x57\xbd\x96\xd5\x7e\xc7\x69\x7c\xf7\xac\xe1\ +\xbb\xb3\x8c\xef\x9d\x3d\xf4\x9a\x29\xe4\xa3\x0f\x91\x9b\xbf\x2d\ +\xce\x50\x11\xb5\x21\x58\x9e\xa5\x0f\x60\x7f\x07\xf6\x51\x1c\xdf\ +\xb0\x6c\xe3\x3e\xc7\xcb\xe8\x61\xfe\x58\x1d\x50\xf2\x9b\xc3\x72\ +\x70\x7b\xdc\xde\x8d\xba\x9a\xc6\x33\xdf\xe7\x26\x28\x8e\xef\x83\ +\x24\x6a\xdc\xf3\xfc\x2c\xf4\x9f\xc2\xf5\x2d\xbc\xef\x6b\x31\x4a\ +\x4f\x23\x5f\xba\xf0\x0d\xf0\x99\xf9\xfd\xe1\xbc\xc2\xe7\x69\x95\ +\x0e\xc1\xfe\x3b\xe4\xde\x15\xf4\xd9\x09\xf4\xd8\x89\xfc\x28\x3d\ +\x57\x89\x8f\x83\x6b\x11\xb4\x65\xf1\x0d\x76\x0e\x3d\xcc\x69\xf4\ +\xb0\x59\xe0\x76\xa2\xcf\xc9\x7f\xa9\xd1\x86\x4a\x4f\xc1\xfe\x06\ +\x38\x92\xe9\x21\xfa\x19\x3d\x72\x4a\x1f\xa1\x13\x96\xde\xdd\x39\ +\x7a\x91\x7b\xf2\xec\x94\xed\x4f\xf4\xa1\xcb\xe8\x7d\x77\x35\x8f\ +\xeb\xbc\x75\x7f\x5b\xa5\x23\xe8\xb7\x6e\x71\xed\x47\x6f\x79\x15\ +\xfd\x5d\x79\xdd\x47\x9e\xfd\xf1\xc2\xbd\xb3\x88\x55\x8e\x7b\xc8\ +\x98\xd7\x79\x33\xea\xa5\xc3\xd6\x3d\xd4\xb4\xd7\xc0\x9f\xc2\x33\ +\x9f\x27\xbd\x74\x32\xee\xa5\x2d\xf4\x46\x3f\x2c\x77\xd1\xb3\xd5\ +\x98\xb9\xed\x67\xd1\x8b\xe5\xe2\xbd\x4a\x69\x7d\x50\x71\xef\x9f\ +\xff\xc2\x8c\x34\x07\xdb\x6d\xcc\xdb\xb9\xbf\x2e\xd2\x21\xf4\x34\ +\x5f\xa1\xc7\x28\xa3\xa6\x5c\x8e\xb8\xe9\x18\x7a\x8e\xce\xa8\x5b\ +\x8a\xa1\x8f\x28\xa5\x86\xa4\x0c\x7a\x88\x9b\xf0\xe9\x05\xd8\xca\ +\xf0\xeb\x2d\xd8\xc6\x60\x7b\x03\xe7\xcf\xf0\x3b\x35\x37\x9d\x80\ +\xed\x6d\xa0\x8c\x5a\xb4\x09\x14\x50\x8b\xf7\xd0\x8f\x5c\x43\x7c\ +\xcf\x20\x8e\x7f\x23\x9e\xbf\xa2\xce\x7e\x89\xb9\x59\xc5\xef\xdf\ +\xf6\x3e\xa6\xd7\xf7\xfb\xbb\x7c\x9e\x5e\x81\x86\x4f\x60\x7b\x1b\ +\xf8\x91\x6b\x1c\xfb\x2c\x04\xd9\x50\xa7\xde\x44\xfd\xfa\x02\xdc\ +\xbf\x60\x8d\x5c\xc3\xfa\x78\xb5\xd1\xda\xbe\xe5\x26\x25\xe9\xa6\ +\x23\xf1\x0b\xf4\x8c\xe0\x6d\x5b\xbb\xee\x5d\xac\xb7\xd1\xda\x7e\ +\x92\xe3\x1f\x0b\x0c\xb3\x17\ +\x00\x00\x02\x7e\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x34\ +\x20\x34\x34\x43\x32\x39\x2e\x35\x32\x32\x38\x20\x34\x34\x20\x33\ +\x34\x2e\x35\x32\x32\x38\x20\x34\x31\x2e\x37\x36\x31\x34\x20\x33\ +\x38\x2e\x31\x34\x32\x31\x20\x33\x38\x2e\x31\x34\x32\x31\x43\x34\ +\x31\x2e\x37\x36\x31\x34\x20\x33\x34\x2e\x35\x32\x32\x38\x20\x34\ +\x34\x20\x32\x39\x2e\x35\x32\x32\x38\x20\x34\x34\x20\x32\x34\x43\ +\x34\x34\x20\x31\x38\x2e\x34\x37\x37\x32\x20\x34\x31\x2e\x37\x36\ +\x31\x34\x20\x31\x33\x2e\x34\x37\x37\x32\x20\x33\x38\x2e\x31\x34\ +\x32\x31\x20\x39\x2e\x38\x35\x37\x38\x36\x43\x33\x34\x2e\x35\x32\ +\x32\x38\x20\x36\x2e\x32\x33\x38\x35\x38\x20\x32\x39\x2e\x35\x32\ +\x32\x38\x20\x34\x20\x32\x34\x20\x34\x43\x31\x38\x2e\x34\x37\x37\ +\x32\x20\x34\x20\x31\x33\x2e\x34\x37\x37\x32\x20\x36\x2e\x32\x33\ +\x38\x35\x38\x20\x39\x2e\x38\x35\x37\x38\x36\x20\x39\x2e\x38\x35\ +\x37\x38\x36\x43\x36\x2e\x32\x33\x38\x35\x38\x20\x31\x33\x2e\x34\ +\x37\x37\x32\x20\x34\x20\x31\x38\x2e\x34\x37\x37\x32\x20\x34\x20\ +\x32\x34\x43\x34\x20\x32\x39\x2e\x35\x32\x32\x38\x20\x36\x2e\x32\ +\x33\x38\x35\x38\x20\x33\x34\x2e\x35\x32\x32\x38\x20\x39\x2e\x38\ +\x35\x37\x38\x36\x20\x33\x38\x2e\x31\x34\x32\x31\x43\x31\x33\x2e\ +\x34\x37\x37\x32\x20\x34\x31\x2e\x37\x36\x31\x34\x20\x31\x38\x2e\ +\x34\x37\x37\x32\x20\x34\x34\x20\x32\x34\x20\x34\x34\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x4d\x31\x36\x20\x32\x34\x4c\x32\x32\x20\x33\x30\x4c\x33\x34\x20\ +\x31\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\ +\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x02\x2c\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x39\ +\x20\x36\x48\x39\x43\x37\x2e\x33\x34\x33\x31\x35\x20\x36\x20\x36\ +\x20\x37\x2e\x33\x34\x33\x31\x35\x20\x36\x20\x39\x56\x33\x39\x43\ +\x36\x20\x34\x30\x2e\x36\x35\x36\x39\x20\x37\x2e\x33\x34\x33\x31\ +\x35\x20\x34\x32\x20\x39\x20\x34\x32\x48\x33\x39\x43\x34\x30\x2e\ +\x36\x35\x36\x39\x20\x34\x32\x20\x34\x32\x20\x34\x30\x2e\x36\x35\ +\x36\x39\x20\x34\x32\x20\x33\x39\x56\x32\x39\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x38\x20\x31\x37\x4c\ +\x32\x32\x20\x32\x39\x4c\x33\x34\x20\x32\x35\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\ +\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x32\x20\x32\x39\x43\ +\x32\x37\x20\x31\x34\x20\x33\x30\x20\x31\x31\x20\x34\x30\x20\x37\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\ +\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x03\xe2\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x34\x22\x20\ +\x79\x3d\x22\x31\x38\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x34\x30\ +\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x34\x22\x20\x72\x78\ +\x3d\x22\x32\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\ +\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ +\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x31\x34\x22\x20\ +\x63\x79\x3d\x22\x32\x34\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\ +\x6c\x6c\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x63\ +\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x31\x36\x22\x20\x63\x79\ +\x3d\x22\x33\x30\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\x6c\x6c\ +\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x63\x69\x72\ +\x63\x6c\x65\x20\x63\x78\x3d\x22\x31\x30\x22\x20\x63\x79\x3d\x22\ +\x33\x30\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\x6c\x6c\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x63\x69\x72\x63\x6c\ +\x65\x20\x63\x78\x3d\x22\x32\x30\x22\x20\x63\x79\x3d\x22\x32\x34\ +\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x30\ +\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x63\x69\x72\x63\x6c\x65\x20\ +\x63\x78\x3d\x22\x32\x32\x22\x20\x63\x79\x3d\x22\x33\x30\x22\x20\ +\x72\x3d\x22\x32\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x30\x30\x36\ +\x34\x66\x66\x22\x2f\x3e\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\ +\x3d\x22\x32\x36\x22\x20\x63\x79\x3d\x22\x32\x34\x22\x20\x72\x3d\ +\x22\x32\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x2f\x3e\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\ +\x32\x38\x22\x20\x63\x79\x3d\x22\x33\x30\x22\x20\x72\x3d\x22\x32\ +\x22\x20\x66\x69\x6c\x6c\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x2f\x3e\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x33\x32\ +\x22\x20\x63\x79\x3d\x22\x32\x34\x22\x20\x72\x3d\x22\x32\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\ +\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x33\x34\x22\x20\ +\x63\x79\x3d\x22\x33\x30\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\ +\x6c\x6c\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x63\ +\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x33\x38\x22\x20\x63\x79\ +\x3d\x22\x32\x34\x22\x20\x72\x3d\x22\x32\x22\x20\x66\x69\x6c\x6c\ +\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x2f\x3e\x3c\x70\x61\x74\ +\x68\x20\x64\x3d\x22\x4d\x31\x37\x20\x33\x36\x48\x33\x31\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x33\x20\ +\x31\x38\x56\x31\x33\x2e\x31\x32\x35\x43\x33\x33\x20\x31\x32\x2e\ +\x35\x37\x32\x37\x20\x33\x33\x2e\x34\x34\x37\x37\x20\x31\x32\x2e\ +\x31\x32\x35\x20\x33\x34\x20\x31\x32\x2e\x31\x32\x35\x48\x33\x39\ +\x43\x33\x39\x2e\x35\x35\x32\x33\x20\x31\x32\x2e\x31\x32\x35\x20\ +\x34\x30\x20\x31\x31\x2e\x36\x37\x37\x33\x20\x34\x30\x20\x31\x31\ +\x2e\x31\x32\x35\x56\x36\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\x67\ +\x3e\ +\x00\x00\x01\xe3\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x2d\x72\ +\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\x63\x6c\ +\x69\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\ +\x22\x20\x64\x3d\x22\x4d\x34\x20\x34\x30\x2e\x38\x33\x36\x31\x43\ +\x38\x2e\x38\x39\x33\x30\x37\x20\x33\x34\x2e\x38\x36\x33\x32\x20\ +\x31\x33\x2e\x32\x33\x38\x33\x20\x33\x31\x2e\x34\x37\x33\x39\x20\ +\x31\x37\x2e\x30\x33\x35\x36\x20\x33\x30\x2e\x36\x36\x38\x32\x43\ +\x32\x30\x2e\x38\x33\x32\x39\x20\x32\x39\x2e\x38\x36\x32\x35\x20\ +\x32\x34\x2e\x34\x34\x38\x33\x20\x32\x39\x2e\x37\x34\x30\x38\x20\ +\x32\x37\x2e\x38\x38\x31\x38\x20\x33\x30\x2e\x33\x30\x33\x56\x34\ +\x31\x4c\x34\x34\x20\x32\x33\x2e\x35\x34\x35\x33\x4c\x32\x37\x2e\ +\x38\x38\x31\x38\x20\x37\x56\x31\x37\x2e\x31\x36\x37\x43\x32\x31\ +\x2e\x35\x33\x33\x33\x20\x31\x37\x2e\x32\x31\x37\x32\x20\x31\x36\ +\x2e\x31\x33\x36\x32\x20\x31\x39\x2e\x34\x39\x34\x38\x20\x31\x31\ +\x2e\x36\x39\x30\x35\x20\x32\x34\x43\x37\x2e\x32\x34\x34\x37\x34\ +\x20\x32\x38\x2e\x35\x30\x35\x32\x20\x34\x2e\x36\x38\x31\x32\x36\ +\x20\x33\x34\x2e\x31\x31\x37\x32\x20\x34\x20\x34\x30\x2e\x38\x33\ +\x36\x31\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\ +\x67\x3e\ +\x00\x00\x01\xc6\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x20\ +\x39\x56\x34\x31\x4c\x39\x20\x32\x31\x48\x33\x39\x2e\x35\x56\x31\ +\x35\x43\x33\x39\x2e\x35\x20\x31\x33\x2e\x38\x39\x35\x34\x20\x33\ +\x38\x2e\x36\x30\x34\x36\x20\x31\x33\x20\x33\x37\x2e\x35\x20\x31\ +\x33\x48\x32\x34\x4c\x31\x39\x20\x37\x48\x36\x43\x34\x2e\x38\x39\ +\x35\x34\x33\x20\x37\x20\x34\x20\x37\x2e\x38\x39\x35\x34\x33\x20\ +\x34\x20\x39\x5a\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\ +\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\ +\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x4d\x34\x30\x20\x34\x31\x4c\x34\x34\x20\x32\x31\x48\x38\ +\x2e\x38\x31\x32\x35\x4c\x34\x20\x34\x31\x48\x34\x30\x5a\x22\x20\ +\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\ +\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\ +\x75\x61\x72\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\ +\x2f\x73\x76\x67\x3e\ +\x00\x00\x01\xe4\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x2d\x72\ +\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\x22\x20\x63\x6c\ +\x69\x70\x2d\x72\x75\x6c\x65\x3d\x22\x65\x76\x65\x6e\x6f\x64\x64\ +\x22\x20\x64\x3d\x22\x4d\x34\x34\x20\x34\x30\x2e\x38\x33\x36\x31\ +\x43\x33\x39\x2e\x31\x30\x36\x39\x20\x33\x34\x2e\x38\x36\x33\x32\ +\x20\x33\x34\x2e\x37\x36\x31\x37\x20\x33\x31\x2e\x34\x37\x33\x39\ +\x20\x33\x30\x2e\x39\x36\x34\x34\x20\x33\x30\x2e\x36\x36\x38\x32\ +\x43\x32\x37\x2e\x31\x36\x37\x31\x20\x32\x39\x2e\x38\x36\x32\x35\ +\x20\x32\x33\x2e\x35\x35\x31\x37\x20\x32\x39\x2e\x37\x34\x30\x38\ +\x20\x32\x30\x2e\x31\x31\x38\x32\x20\x33\x30\x2e\x33\x30\x33\x56\ +\x34\x31\x4c\x34\x20\x32\x33\x2e\x35\x34\x35\x33\x4c\x32\x30\x2e\ +\x31\x31\x38\x32\x20\x37\x56\x31\x37\x2e\x31\x36\x37\x43\x32\x36\ +\x2e\x34\x36\x36\x37\x20\x31\x37\x2e\x32\x31\x37\x32\x20\x33\x31\ +\x2e\x38\x36\x33\x38\x20\x31\x39\x2e\x34\x39\x34\x38\x20\x33\x36\ +\x2e\x33\x30\x39\x35\x20\x32\x34\x43\x34\x30\x2e\x37\x35\x35\x33\ +\x20\x32\x38\x2e\x35\x30\x35\x32\x20\x34\x33\x2e\x33\x31\x38\x37\ +\x20\x33\x34\x2e\x31\x31\x37\x32\x20\x34\x34\x20\x34\x30\x2e\x38\ +\x33\x36\x31\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\ +\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\ +\x76\x67\x3e\ +\x00\x00\x05\xa3\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x38\ +\x2e\x32\x38\x33\x38\x20\x34\x33\x2e\x31\x37\x31\x33\x43\x31\x34\ +\x2e\x39\x33\x32\x37\x20\x34\x32\x2e\x31\x37\x33\x36\x20\x31\x31\ +\x2e\x39\x34\x39\x38\x20\x34\x30\x2e\x33\x32\x31\x33\x20\x39\x2e\ +\x35\x38\x37\x38\x37\x20\x33\x37\x2e\x38\x36\x37\x43\x31\x30\x2e\ +\x34\x36\x39\x20\x33\x36\x2e\x38\x32\x32\x37\x20\x31\x31\x20\x33\ +\x35\x2e\x34\x37\x33\x34\x20\x31\x31\x20\x33\x34\x2e\x30\x30\x30\ +\x31\x43\x31\x31\x20\x33\x30\x2e\x36\x38\x36\x34\x20\x38\x2e\x33\ +\x31\x33\x37\x31\x20\x32\x38\x2e\x30\x30\x30\x31\x20\x35\x20\x32\ +\x38\x2e\x30\x30\x30\x31\x43\x34\x2e\x37\x39\x39\x35\x35\x20\x32\ +\x38\x2e\x30\x30\x30\x31\x20\x34\x2e\x36\x30\x31\x33\x39\x20\x32\ +\x38\x2e\x30\x31\x20\x34\x2e\x34\x30\x35\x39\x39\x20\x32\x38\x2e\ +\x30\x32\x39\x32\x43\x34\x2e\x31\x33\x39\x37\x39\x20\x32\x36\x2e\ +\x37\x32\x37\x37\x20\x34\x20\x32\x35\x2e\x33\x38\x30\x33\x20\x34\ +\x20\x32\x34\x2e\x30\x30\x30\x31\x43\x34\x20\x32\x31\x2e\x39\x30\ +\x39\x35\x20\x34\x2e\x33\x32\x30\x37\x37\x20\x31\x39\x2e\x38\x39\ +\x33\x38\x20\x34\x2e\x39\x31\x35\x37\x39\x20\x31\x37\x2e\x39\x39\ +\x39\x35\x43\x34\x2e\x39\x34\x33\x38\x31\x20\x31\x37\x2e\x39\x39\ +\x39\x39\x20\x34\x2e\x39\x37\x31\x38\x38\x20\x31\x38\x2e\x30\x30\ +\x30\x31\x20\x35\x20\x31\x38\x2e\x30\x30\x30\x31\x43\x38\x2e\x33\ +\x31\x33\x37\x31\x20\x31\x38\x2e\x30\x30\x30\x31\x20\x31\x31\x20\ +\x31\x35\x2e\x33\x31\x33\x38\x20\x31\x31\x20\x31\x32\x2e\x30\x30\ +\x30\x31\x43\x31\x31\x20\x31\x31\x2e\x30\x34\x38\x38\x20\x31\x30\ +\x2e\x37\x37\x38\x36\x20\x31\x30\x2e\x31\x34\x39\x33\x20\x31\x30\ +\x2e\x33\x38\x34\x36\x20\x39\x2e\x33\x35\x30\x31\x31\x43\x31\x32\ +\x2e\x36\x39\x37\x35\x20\x37\x2e\x31\x39\x39\x35\x20\x31\x35\x2e\ +\x35\x32\x30\x35\x20\x35\x2e\x35\x39\x30\x30\x32\x20\x31\x38\x2e\ +\x36\x35\x32\x31\x20\x34\x2e\x37\x32\x33\x31\x34\x43\x31\x39\x2e\ +\x36\x34\x34\x34\x20\x36\x2e\x36\x36\x38\x31\x39\x20\x32\x31\x2e\ +\x36\x36\x36\x37\x20\x38\x2e\x30\x30\x30\x31\x33\x20\x32\x34\x20\ +\x38\x2e\x30\x30\x30\x31\x33\x43\x32\x36\x2e\x33\x33\x33\x33\x20\ +\x38\x2e\x30\x30\x30\x31\x33\x20\x32\x38\x2e\x33\x35\x35\x36\x20\ +\x36\x2e\x36\x36\x38\x31\x39\x20\x32\x39\x2e\x33\x34\x37\x39\x20\ +\x34\x2e\x37\x32\x33\x31\x34\x43\x33\x32\x2e\x34\x37\x39\x35\x20\ +\x35\x2e\x35\x39\x30\x30\x32\x20\x33\x35\x2e\x33\x30\x32\x35\x20\ +\x37\x2e\x31\x39\x39\x35\x20\x33\x37\x2e\x36\x31\x35\x34\x20\x39\ +\x2e\x33\x35\x30\x31\x31\x43\x33\x37\x2e\x32\x32\x31\x34\x20\x31\ +\x30\x2e\x31\x34\x39\x33\x20\x33\x37\x20\x31\x31\x2e\x30\x34\x38\ +\x38\x20\x33\x37\x20\x31\x32\x2e\x30\x30\x30\x31\x43\x33\x37\x20\ +\x31\x35\x2e\x33\x31\x33\x38\x20\x33\x39\x2e\x36\x38\x36\x33\x20\ +\x31\x38\x2e\x30\x30\x30\x31\x20\x34\x33\x20\x31\x38\x2e\x30\x30\ +\x30\x31\x43\x34\x33\x2e\x30\x32\x38\x31\x20\x31\x38\x2e\x30\x30\ +\x30\x31\x20\x34\x33\x2e\x30\x35\x36\x32\x20\x31\x37\x2e\x39\x39\ +\x39\x39\x20\x34\x33\x2e\x30\x38\x34\x32\x20\x31\x37\x2e\x39\x39\ +\x39\x35\x43\x34\x33\x2e\x36\x37\x39\x32\x20\x31\x39\x2e\x38\x39\ +\x33\x38\x20\x34\x34\x20\x32\x31\x2e\x39\x30\x39\x35\x20\x34\x34\ +\x20\x32\x34\x2e\x30\x30\x30\x31\x43\x34\x34\x20\x32\x35\x2e\x33\ +\x38\x30\x33\x20\x34\x33\x2e\x38\x36\x30\x32\x20\x32\x36\x2e\x37\ +\x32\x37\x37\x20\x34\x33\x2e\x35\x39\x34\x20\x32\x38\x2e\x30\x32\ +\x39\x32\x43\x34\x33\x2e\x33\x39\x38\x36\x20\x32\x38\x2e\x30\x31\ +\x20\x34\x33\x2e\x32\x30\x30\x35\x20\x32\x38\x2e\x30\x30\x30\x31\ +\x20\x34\x33\x20\x32\x38\x2e\x30\x30\x30\x31\x43\x33\x39\x2e\x36\ +\x38\x36\x33\x20\x32\x38\x2e\x30\x30\x30\x31\x20\x33\x37\x20\x33\ +\x30\x2e\x36\x38\x36\x34\x20\x33\x37\x20\x33\x34\x2e\x30\x30\x30\ +\x31\x43\x33\x37\x20\x33\x35\x2e\x34\x37\x33\x34\x20\x33\x37\x2e\ +\x35\x33\x31\x20\x33\x36\x2e\x38\x32\x32\x37\x20\x33\x38\x2e\x34\ +\x31\x32\x31\x20\x33\x37\x2e\x38\x36\x37\x43\x33\x36\x2e\x30\x35\ +\x30\x32\x20\x34\x30\x2e\x33\x32\x31\x33\x20\x33\x33\x2e\x30\x36\ +\x37\x33\x20\x34\x32\x2e\x31\x37\x33\x36\x20\x32\x39\x2e\x37\x31\ +\x36\x32\x20\x34\x33\x2e\x31\x37\x31\x33\x43\x32\x38\x2e\x39\x34\ +\x32\x38\x20\x34\x30\x2e\x37\x35\x32\x20\x32\x36\x2e\x36\x37\x36\ +\x20\x33\x39\x2e\x30\x30\x30\x31\x20\x32\x34\x20\x33\x39\x2e\x30\ +\x30\x30\x31\x43\x32\x31\x2e\x33\x32\x34\x20\x33\x39\x2e\x30\x30\ +\x30\x31\x20\x31\x39\x2e\x30\x35\x37\x32\x20\x34\x30\x2e\x37\x35\ +\x32\x20\x31\x38\x2e\x32\x38\x33\x38\x20\x34\x33\x2e\x31\x37\x31\ +\x33\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x4d\x32\x34\x20\x33\x31\x43\x32\x37\x2e\x38\x36\ +\x36\x20\x33\x31\x20\x33\x31\x20\x32\x37\x2e\x38\x36\x36\x20\x33\ +\x31\x20\x32\x34\x43\x33\x31\x20\x32\x30\x2e\x31\x33\x34\x20\x32\ +\x37\x2e\x38\x36\x36\x20\x31\x37\x20\x32\x34\x20\x31\x37\x43\x32\ +\x30\x2e\x31\x33\x34\x20\x31\x37\x20\x31\x37\x20\x32\x30\x2e\x31\ +\x33\x34\x20\x31\x37\x20\x32\x34\x43\x31\x37\x20\x32\x37\x2e\x38\ +\x36\x36\x20\x32\x30\x2e\x31\x33\x34\x20\x33\x31\x20\x32\x34\x20\ +\x33\x31\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\ +\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\x3c\x2f\x73\x76\ +\x67\x3e\ +\x00\x00\x02\x71\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x3f\x3e\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\ +\x22\x33\x32\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x32\x22\ +\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x34\x38\ +\x20\x34\x38\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ +\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\ +\x76\x67\x22\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x39\ +\x2e\x33\x20\x36\x48\x38\x2e\x37\x43\x37\x2e\x32\x30\x38\x38\x33\ +\x20\x36\x20\x36\x20\x37\x2e\x32\x30\x38\x38\x33\x20\x36\x20\x38\ +\x2e\x37\x56\x33\x39\x2e\x33\x43\x36\x20\x34\x30\x2e\x37\x39\x31\ +\x32\x20\x37\x2e\x32\x30\x38\x38\x33\x20\x34\x32\x20\x38\x2e\x37\ +\x20\x34\x32\x48\x33\x39\x2e\x33\x43\x34\x30\x2e\x37\x39\x31\x32\ +\x20\x34\x32\x20\x34\x32\x20\x34\x30\x2e\x37\x39\x31\x32\x20\x34\ +\x32\x20\x33\x39\x2e\x33\x56\x38\x2e\x37\x43\x34\x32\x20\x37\x2e\ +\x32\x30\x38\x38\x33\x20\x34\x30\x2e\x37\x39\x31\x32\x20\x36\x20\ +\x33\x39\x2e\x33\x20\x36\x5a\x22\x20\x66\x69\x6c\x6c\x3d\x22\x6e\ +\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\ +\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ +\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\x22\x2f\x3e\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x33\x32\x20\x36\x56\x32\ +\x34\x48\x31\x35\x56\x36\x48\x33\x32\x5a\x22\x20\x66\x69\x6c\x6c\ +\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\ +\x23\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x22\x6d\x69\x74\x65\x72\ +\x22\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x36\x20\ +\x31\x33\x56\x31\x37\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\ +\x30\x30\x36\x34\x66\x66\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x33\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x63\x61\x70\x3d\x22\x73\x71\x75\x61\x72\x65\x22\ +\x2f\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x30\x2e\x39\ +\x39\x37\x31\x20\x36\x48\x33\x35\x2e\x39\x39\x38\x36\x22\x20\x73\ +\x74\x72\x6f\x6b\x65\x3d\x22\x23\x30\x30\x36\x34\x66\x66\x22\x20\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x33\x22\ +\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ +\x22\x73\x71\x75\x61\x72\x65\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\ +\ +" + +qt_resource_name = b"\ +\x00\x04\ +\x00\x06\xfa\x5e\ +\x00\x69\ +\x00\x63\x00\x6f\x00\x6e\ +\x00\x05\ +\x00\x6f\xa6\x53\ +\x00\x69\ +\x00\x63\x00\x6f\x00\x6e\x00\x73\ +\x00\x12\ +\x01\xac\xf2\xe7\ +\x4e\x00\ +\x5b\xf9\x4e\x00\x00\x5f\x00\x6f\x00\x6e\x00\x65\x00\x2d\x00\x74\x00\x6f\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ +\x00\x10\ +\x05\x64\x2c\x67\ +\x51\x68\ +\x5b\xbd\x00\x5f\x00\x66\x00\x75\x00\x6c\x00\x6c\x00\x77\x00\x69\x00\x64\x00\x74\x00\x68\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0e\ +\x09\x39\xda\xe7\ +\x65\x3e\ +\x59\x27\x00\x5f\x00\x7a\x00\x6f\x00\x6f\x00\x6d\x00\x2d\x00\x69\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x15\ +\x0b\x6d\xc7\x27\ +\x7f\x16\ +\x8f\x91\x65\x87\x4e\xf6\x00\x5f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x2d\x00\x65\x00\x64\x00\x69\x00\x74\x00\x69\x00\x6e\x00\x67\ +\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0c\ +\x0a\x9f\x02\x47\ +\x00\x69\ +\x00\x6e\x00\x73\x00\x74\x00\x61\x00\x6e\x00\x63\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x0c\ +\x0f\x37\x8d\x07\ +\x5f\x00\ +\x51\x73\x00\x5f\x00\x70\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0a\ +\x09\xe7\x20\x07\ +\x71\x67\ +\x72\x47\x00\x5f\x00\x70\x00\x69\x00\x63\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x10\ +\x00\xa1\xff\xa7\ +\x51\x73\ +\x95\xed\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0b\ +\x0b\x19\xb3\x87\ +\x7f\x16\ +\x8f\x91\x00\x5f\x00\x65\x00\x64\x00\x69\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0b\ +\x03\xe5\x96\xa7\ +\x4f\xdd\ +\x5b\x58\x00\x5f\x00\x73\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x09\ +\x06\xe6\xa9\x87\ +\x62\x11\ +\x76\x84\x00\x5f\x00\x6d\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0e\ +\x02\xb9\x42\x87\ +\x53\xbb\ +\x98\x76\x90\xe8\x00\x5f\x00\x74\x00\x6f\x00\x2d\x00\x74\x00\x6f\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0d\ +\x01\xee\x64\x87\ +\x52\x20\ +\x96\x64\x00\x5f\x00\x64\x00\x65\x00\x6c\x00\x65\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x11\ +\x05\xa5\x86\x27\ +\x52\x20\ +\x96\x64\x00\x5f\x00\x64\x00\x65\x00\x6c\x00\x65\x00\x74\x00\x65\x00\x2d\x00\x74\x00\x77\x00\x6f\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ +\x00\x0d\ +\x04\x8d\xa3\x67\ +\x95\x1a\ +\x70\xb9\x00\x5f\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x6f\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0b\ +\x05\x9c\x97\xc7\ +\x52\x17\ +\x88\x68\x00\x5f\x00\x6c\x00\x69\x00\x73\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x20\ +\x0d\x45\x1a\xe7\ +\x8f\x6c\ +\x63\x62\x65\x87\x4e\xf6\x59\x39\x00\x31\x00\x5f\x00\x66\x00\x6f\x00\x6c\x00\x64\x00\x65\x00\x72\x00\x2d\x00\x63\x00\x6f\x00\x6e\ +\x00\x76\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0c\ +\x05\xce\x27\xe7\ +\x00\x73\ +\x00\x65\x00\x6d\x00\x61\x00\x6e\x00\x74\x00\x69\x00\x63\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x10\ +\x0d\x82\xeb\x67\ +\x7f\xfb\ +\x8b\xd1\x00\x5f\x00\x74\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x6c\x00\x61\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0f\ +\x0a\xf8\x43\x87\ +\x7f\x29\ +\x5c\x0f\x00\x5f\x00\x7a\x00\x6f\x00\x6f\x00\x6d\x00\x2d\x00\x6f\x00\x75\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x16\ +\x04\xf6\x11\xe7\ +\x4f\x20\ +\x51\xfa\x00\x33\x00\x5f\x00\x65\x00\x66\x00\x66\x00\x65\x00\x72\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x74\x00\x68\x00\x72\x00\x65\ +\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x12\ +\x08\x89\x84\xe7\ +\x52\x17\ +\x88\x68\x00\x5f\x00\x6c\x00\x69\x00\x73\x00\x74\x00\x2d\x00\x6d\x00\x69\x00\x64\x00\x64\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ +\x00\x1d\ +\x05\xba\x83\xc7\ +\x8f\x6c\ +\x63\x62\x65\x87\x4e\xf6\x00\x31\x00\x5f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x2d\x00\x63\x00\x6f\x00\x6e\x00\x76\x00\x65\x00\x72\ +\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x11\ +\x04\x4f\x8c\xc7\ +\x53\xbb\ +\x5e\x95\x90\xe8\x00\x5f\x00\x74\x00\x6f\x00\x2d\x00\x62\x00\x6f\x00\x74\x00\x74\x00\x6f\x00\x6d\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ +\x00\x0d\ +\x00\x58\x57\x5f\ +\x00\x4d\ +\x00\x5f\x00\x46\x00\x61\x00\x76\x00\x69\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x69\x00\x63\x00\x6f\ +\x00\x10\ +\x0d\xe5\xef\x87\ +\x68\x21\ +\x9a\x8c\x00\x5f\x00\x63\x00\x68\x00\x65\x00\x63\x00\x6b\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x16\ +\x07\xf2\xb9\xe7\ +\x4f\x20\ +\x51\x65\x00\x33\x00\x5f\x00\x61\x00\x66\x00\x66\x00\x65\x00\x72\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x74\x00\x68\x00\x72\x00\x65\ +\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x13\ +\x0b\x6d\xc3\x67\ +\x95\x2e\ +\x76\xd8\x00\x5f\x00\x6b\x00\x65\x00\x79\x00\x62\x00\x6f\x00\x61\x00\x72\x00\x64\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\ +\x00\x76\x00\x67\ +\x00\x0c\ +\x06\x3a\xda\x87\ +\x4e\x0b\ +\x4e\x00\x6b\x65\x00\x5f\x00\x6e\x00\x65\x00\x78\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x15\ +\x0c\x16\xe9\x47\ +\x65\x87\ +\x4e\xf6\x59\x39\x00\x2d\x5f\x00\x00\x5f\x00\x66\x00\x6f\x00\x6c\x00\x64\x00\x65\x00\x72\x00\x2d\x00\x6f\x00\x70\x00\x65\x00\x6e\ +\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0c\ +\x0d\x33\x25\x07\ +\x4e\x0a\ +\x4e\x00\x6b\x65\x00\x5f\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x12\ +\x01\xf3\xd8\xa7\ +\x8b\xbe\ +\x7f\x6e\x00\x5f\x00\x73\x00\x65\x00\x74\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x2d\x00\x74\x00\x77\x00\x6f\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ +\x00\x11\ +\x03\x40\xb4\x67\ +\x4f\xdd\ +\x5b\x58\x78\x6c\x76\xd8\x00\x5f\x00\x73\x00\x61\x00\x76\x00\x65\x00\x2d\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x0e\x00\x02\x00\x00\x00\x21\x00\x00\x00\x03\ +\x00\x00\x03\xa4\x00\x01\x00\x00\x00\x01\x00\x00\x3e\x56\ +\x00\x00\x01\x16\x00\x00\x00\x00\x00\x01\x00\x00\x12\x2c\ +\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xa9\ +\x00\x00\x04\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x52\xb3\ +\x00\x00\x01\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\xce\ +\x00\x00\x04\xde\x00\x00\x00\x00\x00\x01\x00\x00\x58\x5a\ +\x00\x00\x01\x58\x00\x00\x00\x00\x00\x01\x00\x00\x15\xf6\ +\x00\x00\x03\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x80\ +\x00\x00\x01\xf6\x00\x01\x00\x00\x00\x01\x00\x00\x23\x2a\ +\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x33\x1d\ +\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x02\xc3\ +\x00\x00\x02\x16\x00\x00\x00\x00\x00\x01\x00\x00\x24\x3e\ +\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x21\x42\ +\x00\x00\x03\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x39\x3e\ +\x00\x00\x02\x78\x00\x00\x00\x00\x00\x01\x00\x00\x2a\x44\ +\x00\x00\x04\x48\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x1a\ +\x00\x00\x01\x74\x00\x00\x00\x00\x00\x01\x00\x00\x19\xc4\ +\x00\x00\x03\xea\x00\x00\x00\x00\x00\x01\x00\x00\x47\x04\ +\x00\x00\x03\x12\x00\x00\x00\x00\x00\x01\x00\x00\x35\x4c\ +\x00\x00\x00\x6e\x00\x00\x00\x00\x00\x01\x00\x00\x03\xfa\ +\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xe5\ +\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x08\xf9\ +\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe4\ +\x00\x00\x01\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x14\x78\ +\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x49\x34\ +\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x06\xa7\ +\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x4f\x01\ +\x00\x00\x04\x96\x00\x00\x00\x00\x00\x01\x00\x00\x50\xcb\ +\x00\x00\x02\x32\x00\x00\x00\x00\x00\x01\x00\x00\x27\x4b\ +\x00\x00\x02\x96\x00\x00\x00\x00\x00\x01\x00\x00\x2d\x77\ +\x00\x00\x03\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x44\x82\ +\x00\x00\x00\xde\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x54\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x0e\x00\x02\x00\x00\x00\x21\x00\x00\x00\x03\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xa4\x00\x01\x00\x00\x00\x01\x00\x00\x3e\x56\ +\x00\x00\x01\x87\x97\x2b\x5f\xbb\ +\x00\x00\x01\x16\x00\x00\x00\x00\x00\x01\x00\x00\x12\x2c\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xa9\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x04\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x52\xb3\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\xce\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x04\xde\x00\x00\x00\x00\x00\x01\x00\x00\x58\x5a\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\x58\x00\x00\x00\x00\x00\x01\x00\x00\x15\xf6\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x03\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x80\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\xf6\x00\x01\x00\x00\x00\x01\x00\x00\x23\x2a\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x33\x1d\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x02\xc3\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x02\x16\x00\x00\x00\x00\x00\x01\x00\x00\x24\x3e\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x21\x42\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x03\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x39\x3e\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x02\x78\x00\x00\x00\x00\x00\x01\x00\x00\x2a\x44\ +\x00\x00\x01\x84\x0d\x26\xf2\x18\ +\x00\x00\x04\x48\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x1a\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\x74\x00\x00\x00\x00\x00\x01\x00\x00\x19\xc4\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x03\xea\x00\x00\x00\x00\x00\x01\x00\x00\x47\x04\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x03\x12\x00\x00\x00\x00\x00\x01\x00\x00\x35\x4c\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\x6e\x00\x00\x00\x00\x00\x01\x00\x00\x03\xfa\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xe5\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x08\xf9\ +\x00\x00\x01\x87\x97\x87\x31\xdf\ +\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe4\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x01\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x14\x78\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x49\x34\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x06\xa7\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x4f\x01\ +\x00\x00\x01\x87\x97\xe8\xe9\x66\ +\x00\x00\x04\x96\x00\x00\x00\x00\x00\x01\x00\x00\x50\xcb\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x02\x32\x00\x00\x00\x00\x00\x01\x00\x00\x27\x4b\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x02\x96\x00\x00\x00\x00\x00\x01\x00\x00\x2d\x77\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x03\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x44\x82\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +\x00\x00\x00\xde\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x54\ +\x00\x00\x01\x87\x95\xe0\x3e\x90\ +" + +qt_version = [int(v) for v in QtCore.qVersion().split('.')] +if qt_version < [5, 8, 0]: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/isat.yaml b/isat.yaml new file mode 100644 index 0000000..9376fac --- /dev/null +++ b/isat.yaml @@ -0,0 +1,22 @@ +label: +- color: '#000000' + name: __background__ +- color: '#ef2929' + name: person +- color: '#fcaf3e' + name: knife +- color: '#fce94f' + name: fork +- color: '#8ae234' + name: cup +- color: '#729fcf' + name: giraffe +- color: '#ad7fa8' + name: plate +- color: '#e9b96e' + name: table +- color: '#a40000' + name: cake +- color: '#5c3566' + name: fence +language: zh diff --git a/main.py b/main.py index 5596b44..6791910 100644 --- a/main.py +++ b/main.py @@ -1,16 +1,16 @@ -# This is a sample Python script. +# -*- coding: utf-8 -*- +# @Author : LG +# import os -# Press Shift+F10 to execute it or replace it with your code. -# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. +from PyQt5 import QtWidgets +from widgets.mainwindow import MainWindow +import sys -def print_hi(name): - # Use a breakpoint in the code line below to debug your script. - print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. - - -# Press the green button in the gutter to run the script. if __name__ == '__main__': - print_hi('PyCharm') -# See PyCharm help at https://www.jetbrains.com/help/pycharm/ + app = QtWidgets.QApplication(['']) + mainwindow = MainWindow() + mainwindow.show() + sys.exit(app.exec_()) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2a4a3c4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +imgviz==1.2.6 +mahotas==1.4.13 +numpy==1.21.4 +opencv_python_headless==4.5.3.56 +Pillow==9.2.0 +PyQt5==5.15.7 +PyYAML==6.0 +torch==1.8.1 +torchvision==0.9.1 diff --git a/segment_any/segment_any.py b/segment_any/segment_any.py new file mode 100644 index 0000000..0a04e5f --- /dev/null +++ b/segment_any/segment_any.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from segment_anything import sam_model_registry, SamPredictor +import torch +import numpy as np + + +class SegAny: + def __init__(self, checkpoint): + if 'vit_b' in checkpoint: + model_type = "vit_b" + elif 'vit_l' in checkpoint: + model_type = "vit_l" + elif 'vit_h' in checkpoint: + model_type = "vit_h" + else: + raise ValueError('The checkpoint named {} is not supported.'.format(checkpoint)) + + device = 'cuda' if torch.cuda.is_available() else 'cpu' + sam = sam_model_registry[model_type](checkpoint=checkpoint) + sam.to(device=device) + self.predictor = SamPredictor(sam) + self.image = None + + def set_image(self, image): + self.predictor.set_image(image) + + def reset_image(self): + self.predictor.reset_image() + self.image = None + + def predict(self, input_point, input_label): + input_point = np.array(input_point) + input_label = np.array(input_label) + + masks, scores, logits = self.predictor.predict( + point_coords=input_point, + point_labels=input_label, + multimask_output=True, + ) + mask_input = logits[np.argmax(scores), :, :] # Choose the model's best mask + masks, _, _ = self.predictor.predict( + point_coords=input_point, + point_labels=input_label, + mask_input=mask_input[None, :, :], + multimask_output=False, + ) + print('masks: {}'.format(masks)) + return masks diff --git a/tools/label_convert.py b/tools/label_convert.py new file mode 100644 index 0000000..b782507 --- /dev/null +++ b/tools/label_convert.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from json import load +import numpy as np +from PIL import Image, ImageDraw, ImageColor +import mahotas +import imgviz + +class Converter: + def __init__(self, cfg, is_segmentation): + self.is_segmentation = is_segmentation + + labels = cfg.get('label', []) + self.category_dict = {} + if self.is_segmentation: + self.cmap = imgviz.label_colormap() + else: + self.cmap = np.zeros((len(labels), 3), dtype=np.uint8) + for index, label_dict in enumerate(labels): + category = label_dict.get('name', 'unknow') + color = label_dict.get('color', '#000000') + self.category_dict[category] = {'index': index, 'color': color} + self.cmap[index] = (ImageColor.getrgb(color)) + + def convert(self, from_path:str, to_path:str): + assert from_path.endswith('.json') + + with open(from_path, 'r') as f: + dataset = load(f) + info = dataset.get('info', {}) + objects = dataset.get('objects', []) + + img_name = info.get('name', '') + width = info.get('width', 0) + height = info.get('height', 0) + depth = info.get('depth', 0) + note = info.get('note', '') + img = np.zeros(shape=(height, width), dtype=np.uint8) + + objects = sorted(objects, key=lambda obj:obj.get('layer', 1)) + + for obj in objects: + category = obj.get('category', 'unknow') + group = obj.get('group', '') + segmentation = obj.get('segmentation', []) + iscrowd = obj.get('iscrowd', 0) + note = obj.get('note', '') + area = obj.get('area', 0) + layer = obj.get('layer', 1) + bbox = obj.get('bbox', []) + segmentation = [(p[1], p[0]) for p in segmentation] + + if self.is_segmentation and group != '': + mahotas.polygon.fill_polygon(segmentation, img, color=int(group)) + else: + mahotas.polygon.fill_polygon(segmentation, img, color=self.category_dict.get(category, {}).get('index', 0)) + img = Image.fromarray(img.astype(np.uint8), mode='P') + img.putpalette(self.cmap.flatten()) + img.save(to_path) + return True + diff --git a/ui/MainWindow.py b/ui/MainWindow.py new file mode 100644 index 0000000..89c9517 --- /dev/null +++ b/ui/MainWindow.py @@ -0,0 +1,400 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/MainWindow.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1280, 760) + MainWindow.setMinimumSize(QtCore.QSize(800, 600)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + MainWindow.setFont(font) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icons/icons/isat_bg_50x25.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + MainWindow.setWindowIcon(icon) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setSpacing(0) + self.verticalLayout.setObjectName("verticalLayout") + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setEnabled(True) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 24)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menubar.setFont(font) + self.menubar.setAutoFillBackground(False) + self.menubar.setDefaultUp(False) + self.menubar.setNativeMenuBar(True) + self.menubar.setObjectName("menubar") + self.menuFile = QtWidgets.QMenu(self.menubar) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menuFile.setFont(font) + self.menuFile.setObjectName("menuFile") + self.menuView = QtWidgets.QMenu(self.menubar) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menuView.setFont(font) + self.menuView.setObjectName("menuView") + self.menuAbout = QtWidgets.QMenu(self.menubar) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menuAbout.setFont(font) + self.menuAbout.setObjectName("menuAbout") + self.menuLaguage = QtWidgets.QMenu(self.menuAbout) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icon/icons/翻译_translate.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.menuLaguage.setIcon(icon1) + self.menuLaguage.setObjectName("menuLaguage") + self.menuTools = QtWidgets.QMenu(self.menubar) + self.menuTools.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menuTools.setFont(font) + self.menuTools.setObjectName("menuTools") + self.menuEdit = QtWidgets.QMenu(self.menubar) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.menuEdit.setFont(font) + self.menuEdit.setObjectName("menuEdit") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setLayoutDirection(QtCore.Qt.LeftToRight) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.toolBar = QtWidgets.QToolBar(MainWindow) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.toolBar.setFont(font) + self.toolBar.setIconSize(QtCore.QSize(24, 24)) + self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) + self.toolBar.setFloatable(False) + self.toolBar.setObjectName("toolBar") + MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) + self.info_dock = QtWidgets.QDockWidget(MainWindow) + self.info_dock.setMinimumSize(QtCore.QSize(80, 38)) + self.info_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures) + self.info_dock.setObjectName("info_dock") + self.dockWidgetContents_2 = QtWidgets.QWidget() + self.dockWidgetContents_2.setObjectName("dockWidgetContents_2") + self.info_dock.setWidget(self.dockWidgetContents_2) + MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.info_dock) + self.labels_dock = QtWidgets.QDockWidget(MainWindow) + self.labels_dock.setMinimumSize(QtCore.QSize(80, 38)) + self.labels_dock.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures) + self.labels_dock.setObjectName("labels_dock") + self.dockWidgetContents_3 = QtWidgets.QWidget() + self.dockWidgetContents_3.setObjectName("dockWidgetContents_3") + self.labels_dock.setWidget(self.dockWidgetContents_3) + MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.labels_dock) + self.files_dock = QtWidgets.QDockWidget(MainWindow) + self.files_dock.setObjectName("files_dock") + self.dockWidgetContents = QtWidgets.QWidget() + self.dockWidgetContents.setObjectName("dockWidgetContents") + self.files_dock.setWidget(self.dockWidgetContents) + MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.files_dock) + self.actionOpen_dir = QtWidgets.QAction(MainWindow) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/icon/icons/照片_pic.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionOpen_dir.setIcon(icon2) + self.actionOpen_dir.setObjectName("actionOpen_dir") + self.actionZoom_in = QtWidgets.QAction(MainWindow) + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(":/icon/icons/放大_zoom-in.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionZoom_in.setIcon(icon3) + self.actionZoom_in.setObjectName("actionZoom_in") + self.actionZoom_out = QtWidgets.QAction(MainWindow) + icon4 = QtGui.QIcon() + icon4.addPixmap(QtGui.QPixmap(":/icon/icons/缩小_zoom-out.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionZoom_out.setIcon(icon4) + self.actionZoom_out.setObjectName("actionZoom_out") + self.actionFit_wiondow = QtWidgets.QAction(MainWindow) + icon5 = QtGui.QIcon() + icon5.addPixmap(QtGui.QPixmap(":/icon/icons/全宽_fullwidth.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionFit_wiondow.setIcon(icon5) + self.actionFit_wiondow.setObjectName("actionFit_wiondow") + self.actionSetting = QtWidgets.QAction(MainWindow) + icon6 = QtGui.QIcon() + icon6.addPixmap(QtGui.QPixmap(":/icon/icons/设置_setting-two.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionSetting.setIcon(icon6) + self.actionSetting.setObjectName("actionSetting") + self.actionExit = QtWidgets.QAction(MainWindow) + icon7 = QtGui.QIcon() + icon7.addPixmap(QtGui.QPixmap(":/icon/icons/开关_power.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionExit.setIcon(icon7) + self.actionExit.setObjectName("actionExit") + self.actionSave_dir = QtWidgets.QAction(MainWindow) + icon8 = QtGui.QIcon() + icon8.addPixmap(QtGui.QPixmap(":/icon/icons/文件夹-开_folder-open.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionSave_dir.setIcon(icon8) + self.actionSave_dir.setObjectName("actionSave_dir") + self.actionSave = QtWidgets.QAction(MainWindow) + icon9 = QtGui.QIcon() + icon9.addPixmap(QtGui.QPixmap(":/icon/icons/保存_save.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionSave.setIcon(icon9) + self.actionSave.setObjectName("actionSave") + self.actionPrev = QtWidgets.QAction(MainWindow) + self.actionPrev.setCheckable(False) + icon10 = QtGui.QIcon() + icon10.addPixmap(QtGui.QPixmap(":/icon/icons/上一步_back.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionPrev.setIcon(icon10) + self.actionPrev.setMenuRole(QtWidgets.QAction.TextHeuristicRole) + self.actionPrev.setPriority(QtWidgets.QAction.NormalPriority) + self.actionPrev.setObjectName("actionPrev") + self.actionNext = QtWidgets.QAction(MainWindow) + icon11 = QtGui.QIcon() + icon11.addPixmap(QtGui.QPixmap(":/icon/icons/下一步_next.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionNext.setIcon(icon11) + self.actionNext.setObjectName("actionNext") + self.actionShortcut = QtWidgets.QAction(MainWindow) + icon12 = QtGui.QIcon() + icon12.addPixmap(QtGui.QPixmap(":/icon/icons/键盘_keyboard-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionShortcut.setIcon(icon12) + self.actionShortcut.setObjectName("actionShortcut") + self.actionAbout = QtWidgets.QAction(MainWindow) + icon13 = QtGui.QIcon() + icon13.addPixmap(QtGui.QPixmap(":/icon/icons/我的_me.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionAbout.setIcon(icon13) + self.actionAbout.setObjectName("actionAbout") + self.actionSegment_anything = QtWidgets.QAction(MainWindow) + icon14 = QtGui.QIcon() + icon14.addPixmap(QtGui.QPixmap(":/icon/icons/M_Favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionSegment_anything.setIcon(icon14) + self.actionSegment_anything.setObjectName("actionSegment_anything") + self.actionDelete = QtWidgets.QAction(MainWindow) + self.actionDelete.setEnabled(False) + icon15 = QtGui.QIcon() + icon15.addPixmap(QtGui.QPixmap(":/icon/icons/删除_delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionDelete.setIcon(icon15) + self.actionDelete.setObjectName("actionDelete") + self.actionBit_map = QtWidgets.QAction(MainWindow) + self.actionBit_map.setCheckable(False) + self.actionBit_map.setIcon(icon2) + self.actionBit_map.setObjectName("actionBit_map") + self.actionEdit = QtWidgets.QAction(MainWindow) + self.actionEdit.setEnabled(False) + icon16 = QtGui.QIcon() + icon16.addPixmap(QtGui.QPixmap(":/icon/icons/编辑_edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionEdit.setIcon(icon16) + self.actionEdit.setObjectName("actionEdit") + self.actionTo_top = QtWidgets.QAction(MainWindow) + self.actionTo_top.setEnabled(False) + icon17 = QtGui.QIcon() + icon17.addPixmap(QtGui.QPixmap(":/icon/icons/去顶部_to-top.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionTo_top.setIcon(icon17) + self.actionTo_top.setObjectName("actionTo_top") + self.actionTo_bottom = QtWidgets.QAction(MainWindow) + self.actionTo_bottom.setEnabled(False) + icon18 = QtGui.QIcon() + icon18.addPixmap(QtGui.QPixmap(":/icon/icons/去底部_to-bottom.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionTo_bottom.setIcon(icon18) + self.actionTo_bottom.setObjectName("actionTo_bottom") + self.actionConverter = QtWidgets.QAction(MainWindow) + icon19 = QtGui.QIcon() + icon19.addPixmap(QtGui.QPixmap(":/icon/icons/转换文件夹1_folder-conversion-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionConverter.setIcon(icon19) + self.actionConverter.setWhatsThis("") + self.actionConverter.setObjectName("actionConverter") + self.actionChinese = QtWidgets.QAction(MainWindow) + self.actionChinese.setCheckable(True) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.actionChinese.setFont(font) + self.actionChinese.setObjectName("actionChinese") + self.actionEnglish = QtWidgets.QAction(MainWindow) + self.actionEnglish.setCheckable(True) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.actionEnglish.setFont(font) + self.actionEnglish.setObjectName("actionEnglish") + self.actionBackspace = QtWidgets.QAction(MainWindow) + icon20 = QtGui.QIcon() + icon20.addPixmap(QtGui.QPixmap(":/icon/icons/删除_delete-two.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionBackspace.setIcon(icon20) + self.actionBackspace.setObjectName("actionBackspace") + self.actionCancel = QtWidgets.QAction(MainWindow) + icon21 = QtGui.QIcon() + icon21.addPixmap(QtGui.QPixmap(":/icon/icons/关闭_close-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionCancel.setIcon(icon21) + self.actionCancel.setObjectName("actionCancel") + self.actionFinish = QtWidgets.QAction(MainWindow) + icon22 = QtGui.QIcon() + icon22.addPixmap(QtGui.QPixmap(":/icon/icons/校验_check-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionFinish.setIcon(icon22) + self.actionFinish.setObjectName("actionFinish") + self.actionPolygon = QtWidgets.QAction(MainWindow) + icon23 = QtGui.QIcon() + icon23.addPixmap(QtGui.QPixmap(":/icon/icons/锚点_anchor.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionPolygon.setIcon(icon23) + self.actionPolygon.setObjectName("actionPolygon") + self.menuFile.addAction(self.actionOpen_dir) + self.menuFile.addAction(self.actionSave_dir) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionPrev) + self.menuFile.addAction(self.actionNext) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionSetting) + self.menuFile.addAction(self.actionExit) + self.menuView.addSeparator() + self.menuView.addAction(self.actionZoom_in) + self.menuView.addAction(self.actionZoom_out) + self.menuView.addAction(self.actionFit_wiondow) + self.menuView.addSeparator() + self.menuView.addAction(self.actionBit_map) + self.menuView.addSeparator() + self.menuLaguage.addAction(self.actionChinese) + self.menuLaguage.addAction(self.actionEnglish) + self.menuAbout.addAction(self.menuLaguage.menuAction()) + self.menuAbout.addAction(self.actionShortcut) + self.menuAbout.addAction(self.actionAbout) + self.menuTools.addAction(self.actionConverter) + self.menuEdit.addAction(self.actionSegment_anything) + self.menuEdit.addAction(self.actionPolygon) + self.menuEdit.addAction(self.actionBackspace) + self.menuEdit.addAction(self.actionFinish) + self.menuEdit.addAction(self.actionCancel) + self.menuEdit.addSeparator() + self.menuEdit.addAction(self.actionTo_top) + self.menuEdit.addAction(self.actionTo_bottom) + self.menuEdit.addSeparator() + self.menuEdit.addAction(self.actionEdit) + self.menuEdit.addAction(self.actionDelete) + self.menuEdit.addAction(self.actionSave) + self.menubar.addAction(self.menuFile.menuAction()) + self.menubar.addAction(self.menuEdit.menuAction()) + self.menubar.addAction(self.menuView.menuAction()) + self.menubar.addAction(self.menuTools.menuAction()) + self.menubar.addAction(self.menuAbout.menuAction()) + self.toolBar.addAction(self.actionPrev) + self.toolBar.addAction(self.actionNext) + self.toolBar.addSeparator() + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionSegment_anything) + self.toolBar.addAction(self.actionPolygon) + self.toolBar.addAction(self.actionBackspace) + self.toolBar.addAction(self.actionFinish) + self.toolBar.addAction(self.actionCancel) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionTo_top) + self.toolBar.addAction(self.actionTo_bottom) + self.toolBar.addAction(self.actionEdit) + self.toolBar.addAction(self.actionDelete) + self.toolBar.addAction(self.actionSave) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionZoom_in) + self.toolBar.addAction(self.actionZoom_out) + self.toolBar.addAction(self.actionFit_wiondow) + self.toolBar.addAction(self.actionBit_map) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "ISAT")) + self.menuFile.setTitle(_translate("MainWindow", "File")) + self.menuView.setTitle(_translate("MainWindow", "View")) + self.menuAbout.setTitle(_translate("MainWindow", "Help")) + self.menuLaguage.setTitle(_translate("MainWindow", "Laguage")) + self.menuTools.setTitle(_translate("MainWindow", "Tools")) + self.menuEdit.setTitle(_translate("MainWindow", "Edit")) + self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) + self.info_dock.setWindowTitle(_translate("MainWindow", "Info")) + self.labels_dock.setWindowTitle(_translate("MainWindow", "Labels")) + self.files_dock.setWindowTitle(_translate("MainWindow", "Files")) + self.actionOpen_dir.setText(_translate("MainWindow", "Images dir")) + self.actionOpen_dir.setStatusTip(_translate("MainWindow", "Open images dir.")) + self.actionZoom_in.setText(_translate("MainWindow", "Zoom in")) + self.actionZoom_in.setStatusTip(_translate("MainWindow", "Zoom in.")) + self.actionZoom_out.setText(_translate("MainWindow", "Zoom out")) + self.actionZoom_out.setStatusTip(_translate("MainWindow", "Zoom out.")) + self.actionFit_wiondow.setText(_translate("MainWindow", "Fit window")) + self.actionFit_wiondow.setToolTip(_translate("MainWindow", "Fit window")) + self.actionFit_wiondow.setStatusTip(_translate("MainWindow", "Fit window.")) + self.actionFit_wiondow.setShortcut(_translate("MainWindow", "F")) + self.actionSetting.setText(_translate("MainWindow", "Setting")) + self.actionSetting.setStatusTip(_translate("MainWindow", "Setting.")) + self.actionExit.setText(_translate("MainWindow", "Exit")) + self.actionExit.setToolTip(_translate("MainWindow", "Exit")) + self.actionExit.setStatusTip(_translate("MainWindow", "Exit.")) + self.actionSave_dir.setText(_translate("MainWindow", "Label dir")) + self.actionSave_dir.setStatusTip(_translate("MainWindow", "Open label dir.")) + self.actionSave.setText(_translate("MainWindow", "Save")) + self.actionSave.setStatusTip(_translate("MainWindow", "Save annotation.")) + self.actionSave.setShortcut(_translate("MainWindow", "S")) + self.actionPrev.setText(_translate("MainWindow", "Prev image")) + self.actionPrev.setToolTip(_translate("MainWindow", "Prev image")) + self.actionPrev.setStatusTip(_translate("MainWindow", "Prev image.")) + self.actionPrev.setShortcut(_translate("MainWindow", "A")) + self.actionNext.setText(_translate("MainWindow", "Next image")) + self.actionNext.setToolTip(_translate("MainWindow", "Next image")) + self.actionNext.setStatusTip(_translate("MainWindow", "Next image.")) + self.actionNext.setShortcut(_translate("MainWindow", "D")) + self.actionShortcut.setText(_translate("MainWindow", "Shortcut")) + self.actionAbout.setText(_translate("MainWindow", "About")) + self.actionSegment_anything.setText(_translate("MainWindow", "Segment anything")) + self.actionSegment_anything.setToolTip(_translate("MainWindow", "Segment anything")) + self.actionSegment_anything.setStatusTip(_translate("MainWindow", "Quick annotate using Segment anything.")) + self.actionSegment_anything.setShortcut(_translate("MainWindow", "Q")) + self.actionDelete.setText(_translate("MainWindow", "Delete")) + self.actionDelete.setToolTip(_translate("MainWindow", "Delete polygon")) + self.actionDelete.setStatusTip(_translate("MainWindow", "Delete polygon.")) + self.actionDelete.setShortcut(_translate("MainWindow", "Del")) + self.actionBit_map.setText(_translate("MainWindow", "Bit map")) + self.actionBit_map.setStatusTip(_translate("MainWindow", "Show instance or segmeent state.")) + self.actionBit_map.setShortcut(_translate("MainWindow", "Space")) + self.actionEdit.setText(_translate("MainWindow", "Edit")) + self.actionEdit.setToolTip(_translate("MainWindow", "Edit polygon")) + self.actionEdit.setStatusTip(_translate("MainWindow", "Edit polygon attribute.")) + self.actionTo_top.setText(_translate("MainWindow", "To top")) + self.actionTo_top.setToolTip(_translate("MainWindow", "Move polygon to top layer")) + self.actionTo_top.setStatusTip(_translate("MainWindow", "Move polygon to top layer.")) + self.actionTo_top.setShortcut(_translate("MainWindow", "T")) + self.actionTo_bottom.setText(_translate("MainWindow", "To bottom")) + self.actionTo_bottom.setToolTip(_translate("MainWindow", "Move polygon to bottom layer")) + self.actionTo_bottom.setStatusTip(_translate("MainWindow", "Move polygon to bottom layer.")) + self.actionTo_bottom.setShortcut(_translate("MainWindow", "B")) + self.actionConverter.setText(_translate("MainWindow", "Label converter")) + self.actionConverter.setStatusTip(_translate("MainWindow", "Convert annotations to png image.")) + self.actionChinese.setText(_translate("MainWindow", "中文")) + self.actionEnglish.setText(_translate("MainWindow", "English")) + self.actionBackspace.setText(_translate("MainWindow", "Backspace")) + self.actionBackspace.setToolTip(_translate("MainWindow", "Backspace")) + self.actionBackspace.setStatusTip(_translate("MainWindow", "Backspace.")) + self.actionBackspace.setShortcut(_translate("MainWindow", "Z")) + self.actionCancel.setText(_translate("MainWindow", "Cancel")) + self.actionCancel.setToolTip(_translate("MainWindow", "Annotate canceled")) + self.actionCancel.setStatusTip(_translate("MainWindow", "Annotate canceled.")) + self.actionCancel.setShortcut(_translate("MainWindow", "Esc")) + self.actionFinish.setText(_translate("MainWindow", "Finish")) + self.actionFinish.setToolTip(_translate("MainWindow", "Annotate finished")) + self.actionFinish.setStatusTip(_translate("MainWindow", "Annotate finished.")) + self.actionFinish.setShortcut(_translate("MainWindow", "E")) + self.actionPolygon.setText(_translate("MainWindow", "Polygon")) + self.actionPolygon.setToolTip(_translate("MainWindow", "Draw polygon")) + self.actionPolygon.setStatusTip(_translate("MainWindow", "Accurately annotate by drawing polygon. ")) + self.actionPolygon.setShortcut(_translate("MainWindow", "C")) +import icons_rc diff --git a/ui/MainWindow.ui b/ui/MainWindow.ui new file mode 100644 index 0000000..9b350da --- /dev/null +++ b/ui/MainWindow.ui @@ -0,0 +1,691 @@ + + + MainWindow + + + + 0 + 0 + 1280 + 760 + + + + + 800 + 600 + + + + + Times New Roman + 12 + + + + ISAT + + + + :/icons/icons/isat_bg_50x25.png:/icons/icons/isat_bg_50x25.png + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + true + + + + 0 + 0 + 1280 + 24 + + + + + Times New Roman + 12 + + + + false + + + false + + + true + + + + + Times New Roman + 12 + + + + File + + + + + + + + + + + + + + Times New Roman + 12 + + + + View + + + + + + + + + + + + + Times New Roman + 12 + + + + Help + + + + Laguage + + + + :/icon/icons/翻译_translate.svg:/icon/icons/翻译_translate.svg + + + + + + + + + + + true + + + + Times New Roman + 12 + + + + Tools + + + + + + + Times New Roman + 12 + + + + Edit + + + + + + + + + + + + + + + + + + + + + + + Qt::LeftToRight + + + + + + Times New Roman + 12 + + + + toolBar + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + false + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + 80 + 38 + + + + QDockWidget::AllDockWidgetFeatures + + + Info + + + 2 + + + + + + + 80 + 38 + + + + QDockWidget::AllDockWidgetFeatures + + + Labels + + + 2 + + + + + + Files + + + 2 + + + + + + + :/icon/icons/照片_pic.svg:/icon/icons/照片_pic.svg + + + Images dir + + + Open images dir. + + + + + + :/icon/icons/放大_zoom-in.svg:/icon/icons/放大_zoom-in.svg + + + Zoom in + + + Zoom in. + + + + + + :/icon/icons/缩小_zoom-out.svg:/icon/icons/缩小_zoom-out.svg + + + Zoom out + + + Zoom out. + + + + + + :/icon/icons/全宽_fullwidth.svg:/icon/icons/全宽_fullwidth.svg + + + Fit window + + + Fit window + + + Fit window. + + + F + + + + + + :/icon/icons/设置_setting-two.svg:/icon/icons/设置_setting-two.svg + + + Setting + + + Setting. + + + + + + :/icon/icons/开关_power.svg:/icon/icons/开关_power.svg + + + Exit + + + Exit + + + Exit. + + + + + + :/icon/icons/文件夹-开_folder-open.svg:/icon/icons/文件夹-开_folder-open.svg + + + Label dir + + + Open label dir. + + + + + + :/icon/icons/保存_save.svg:/icon/icons/保存_save.svg + + + Save + + + Save annotation. + + + S + + + + + false + + + + :/icon/icons/上一步_back.svg:/icon/icons/上一步_back.svg + + + Prev image + + + Prev image + + + Prev image. + + + A + + + QAction::TextHeuristicRole + + + QAction::NormalPriority + + + + + + :/icon/icons/下一步_next.svg:/icon/icons/下一步_next.svg + + + Next image + + + Next image + + + Next image. + + + D + + + + + + :/icon/icons/键盘_keyboard-one.svg:/icon/icons/键盘_keyboard-one.svg + + + Shortcut + + + + + + :/icon/icons/我的_me.svg:/icon/icons/我的_me.svg + + + About + + + + + + :/icon/icons/M_Favicon.ico:/icon/icons/M_Favicon.ico + + + Segment anything + + + Segment anything + + + Quick annotate using Segment anything. + + + Q + + + + + false + + + + :/icon/icons/删除_delete.svg:/icon/icons/删除_delete.svg + + + Delete + + + Delete polygon + + + Delete polygon. + + + Del + + + + + false + + + + :/icon/icons/照片_pic.svg:/icon/icons/照片_pic.svg + + + Bit map + + + Show instance or segmeent state. + + + Space + + + + + false + + + + :/icon/icons/编辑_edit.svg:/icon/icons/编辑_edit.svg + + + Edit + + + Edit polygon + + + Edit polygon attribute. + + + + + false + + + + :/icon/icons/去顶部_to-top.svg:/icon/icons/去顶部_to-top.svg + + + To top + + + Move polygon to top layer + + + Move polygon to top layer. + + + T + + + + + false + + + + :/icon/icons/去底部_to-bottom.svg:/icon/icons/去底部_to-bottom.svg + + + To bottom + + + Move polygon to bottom layer + + + Move polygon to bottom layer. + + + B + + + + + + :/icon/icons/转换文件夹1_folder-conversion-one.svg:/icon/icons/转换文件夹1_folder-conversion-one.svg + + + Label converter + + + Convert annotations to png image. + + + + + + + + true + + + 中文 + + + + Times New Roman + 12 + + + + + + true + + + English + + + + Times New Roman + 12 + + + + + + + :/icon/icons/删除_delete-two.svg:/icon/icons/删除_delete-two.svg + + + Backspace + + + Backspace + + + Backspace. + + + Z + + + + + + :/icon/icons/关闭_close-one.svg:/icon/icons/关闭_close-one.svg + + + Cancel + + + Annotate canceled + + + Annotate canceled. + + + Esc + + + + + + :/icon/icons/校验_check-one.svg:/icon/icons/校验_check-one.svg + + + Finish + + + Annotate finished + + + Annotate finished. + + + E + + + + + + :/icon/icons/锚点_anchor.svg:/icon/icons/锚点_anchor.svg + + + Polygon + + + Draw polygon + + + Accurately annotate by drawing polygon. + + + C + + + + + + + + diff --git a/ui/about_dialog.py b/ui/about_dialog.py new file mode 100644 index 0000000..62e5a56 --- /dev/null +++ b/ui/about_dialog.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/about_dialog.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(550, 280) + Dialog.setMinimumSize(QtCore.QSize(550, 280)) + Dialog.setMaximumSize(QtCore.QSize(550, 280)) + self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout.setObjectName("verticalLayout") + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setObjectName("widget") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setSpacing(0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.widget_2 = QtWidgets.QWidget(self.widget) + self.widget_2.setMaximumSize(QtCore.QSize(16777215, 40)) + self.widget_2.setObjectName("widget_2") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_2) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget_2) + self.label.setMaximumSize(QtCore.QSize(16777215, 50)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(20) + self.label.setFont(font) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.verticalLayout_2.addWidget(self.widget_2) + self.widget_3 = QtWidgets.QWidget(self.widget) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.widget_3.setFont(font) + self.widget_3.setObjectName("widget_3") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget_3) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.label_2 = QtWidgets.QLabel(self.widget_3) + font = QtGui.QFont() + font.setPointSize(18) + self.label_2.setFont(font) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_3.addWidget(self.label_2) + self.label_4 = QtWidgets.QLabel(self.widget_3) + self.label_4.setMaximumSize(QtCore.QSize(16777215, 40)) + self.label_4.setLayoutDirection(QtCore.Qt.LeftToRight) + self.label_4.setStyleSheet("color: rgb(133, 0, 0);") + self.label_4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_4.setObjectName("label_4") + self.verticalLayout_3.addWidget(self.label_4) + self.verticalLayout_2.addWidget(self.widget_3) + self.verticalLayout.addWidget(self.widget) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "about")) + self.label.setText(_translate("Dialog", "About")) + self.label_2.setText(_translate("Dialog", "ISAT with Segment anything.")) + self.label_4.setText(_translate("Dialog", "ISAT Copyright (C) 2022 yatengLG.\n" +"http://www.yatenglg.cn/isat")) +import icons_rc diff --git a/ui/about_dialog.ui b/ui/about_dialog.ui new file mode 100644 index 0000000..ba52b1e --- /dev/null +++ b/ui/about_dialog.ui @@ -0,0 +1,137 @@ + + + Dialog + + + + 0 + 0 + 550 + 280 + + + + + 550 + 280 + + + + + 550 + 280 + + + + about + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 16777215 + 40 + + + + + + + + 16777215 + 50 + + + + + Times New Roman + 20 + + + + About + + + + + + + + + + + Times New Roman + 12 + + + + + + + + 18 + + + + ISAT with Segment anything. + + + Qt::AlignCenter + + + + + + + + 16777215 + 40 + + + + Qt::LeftToRight + + + color: rgb(133, 0, 0); + + + ISAT Copyright (C) 2022 yatengLG. +http://www.yatenglg.cn/isat + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + diff --git a/ui/category_choice.py b/ui/category_choice.py new file mode 100644 index 0000000..0b20779 --- /dev/null +++ b/ui/category_choice.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/category_choice.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(350, 400) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + Dialog.setFont(font) + Dialog.setWindowTitle("") + self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout.setObjectName("verticalLayout") + self.listWidget = QtWidgets.QListWidget(Dialog) + self.listWidget.setObjectName("listWidget") + self.verticalLayout.addWidget(self.listWidget) + self.widget_3 = QtWidgets.QWidget(Dialog) + self.widget_3.setObjectName("widget_3") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_3) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_2 = QtWidgets.QLabel(self.widget_3) + self.label_2.setMinimumSize(QtCore.QSize(60, 0)) + self.label_2.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_2.setObjectName("label_2") + self.horizontalLayout_3.addWidget(self.label_2) + self.lineEdit_category = QtWidgets.QLineEdit(self.widget_3) + self.lineEdit_category.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.lineEdit_category.setReadOnly(True) + self.lineEdit_category.setObjectName("lineEdit_category") + self.horizontalLayout_3.addWidget(self.lineEdit_category) + self.label = QtWidgets.QLabel(self.widget_3) + self.label.setMinimumSize(QtCore.QSize(50, 0)) + self.label.setMaximumSize(QtCore.QSize(50, 16777215)) + self.label.setObjectName("label") + self.horizontalLayout_3.addWidget(self.label) + self.lineEdit_group = QtWidgets.QLineEdit(self.widget_3) + self.lineEdit_group.setMinimumSize(QtCore.QSize(60, 0)) + self.lineEdit_group.setMaximumSize(QtCore.QSize(60, 16777215)) + self.lineEdit_group.setInputMethodHints(QtCore.Qt.ImhDigitsOnly) + self.lineEdit_group.setText("") + self.lineEdit_group.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.lineEdit_group.setObjectName("lineEdit_group") + self.horizontalLayout_3.addWidget(self.lineEdit_group) + self.verticalLayout.addWidget(self.widget_3) + self.widget_5 = QtWidgets.QWidget(Dialog) + self.widget_5.setObjectName("widget_5") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.widget_5) + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.label_3 = QtWidgets.QLabel(self.widget_5) + self.label_3.setMinimumSize(QtCore.QSize(60, 0)) + self.label_3.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_3.setObjectName("label_3") + self.horizontalLayout_5.addWidget(self.label_3) + self.lineEdit_note = QtWidgets.QLineEdit(self.widget_5) + self.lineEdit_note.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.lineEdit_note.setObjectName("lineEdit_note") + self.horizontalLayout_5.addWidget(self.lineEdit_note) + self.label_4 = QtWidgets.QLabel(self.widget_5) + self.label_4.setMinimumSize(QtCore.QSize(50, 0)) + self.label_4.setMaximumSize(QtCore.QSize(50, 16777215)) + self.label_4.setObjectName("label_4") + self.horizontalLayout_5.addWidget(self.label_4) + self.label_layer = QtWidgets.QLabel(self.widget_5) + self.label_layer.setMinimumSize(QtCore.QSize(60, 0)) + self.label_layer.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_layer.setText("") + self.label_layer.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_layer.setObjectName("label_layer") + self.horizontalLayout_5.addWidget(self.label_layer) + self.verticalLayout.addWidget(self.widget_5) + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setObjectName("widget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout.addWidget(self.widget) + self.widget_2 = QtWidgets.QWidget(Dialog) + self.widget_2.setObjectName("widget_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget_2) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.checkBox_iscrowded = QtWidgets.QCheckBox(self.widget_2) + self.checkBox_iscrowded.setObjectName("checkBox_iscrowded") + self.horizontalLayout_2.addWidget(self.checkBox_iscrowded) + spacerItem = QtWidgets.QSpacerItem(97, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem) + self.pushButton_cache = QtWidgets.QPushButton(self.widget_2) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icons/icons/关闭_close-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_cache.setIcon(icon) + self.pushButton_cache.setObjectName("pushButton_cache") + self.horizontalLayout_2.addWidget(self.pushButton_cache) + self.pushButton_apply = QtWidgets.QPushButton(self.widget_2) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icons/icons/校验_check-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_apply.setIcon(icon1) + self.pushButton_apply.setObjectName("pushButton_apply") + self.horizontalLayout_2.addWidget(self.pushButton_apply) + self.verticalLayout.addWidget(self.widget_2) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + self.label_2.setText(_translate("Dialog", "category:")) + self.label.setText(_translate("Dialog", "group:")) + self.lineEdit_group.setPlaceholderText(_translate("Dialog", "group id")) + self.label_3.setText(_translate("Dialog", "note:")) + self.lineEdit_note.setPlaceholderText(_translate("Dialog", "add extra note here")) + self.label_4.setText(_translate("Dialog", "layer:")) + self.checkBox_iscrowded.setText(_translate("Dialog", "is crowded")) + self.pushButton_cache.setText(_translate("Dialog", "cache")) + self.pushButton_apply.setText(_translate("Dialog", "apply")) +import icons_rc diff --git a/ui/category_choice.ui b/ui/category_choice.ui new file mode 100644 index 0000000..a43af56 --- /dev/null +++ b/ui/category_choice.ui @@ -0,0 +1,292 @@ + + + Dialog + + + + 0 + 0 + 350 + 400 + + + + + Times New Roman + 12 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + category: + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + group: + + + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + Qt::ImhDigitsOnly + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + group id + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + note: + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + add extra note here + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + layer: + + + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + is crowded + + + + + + + Qt::Horizontal + + + + 97 + 20 + + + + + + + + cache + + + + :/icons/icons/关闭_close-one.svg:/icons/icons/关闭_close-one.svg + + + + + + + apply + + + + :/icons/icons/校验_check-one.svg:/icons/icons/校验_check-one.svg + + + + + + + + + + + + + diff --git a/ui/convert_dialog.py b/ui/convert_dialog.py new file mode 100644 index 0000000..5a4f5ff --- /dev/null +++ b/ui/convert_dialog.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/convert_dialog.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.setWindowModality(QtCore.Qt.NonModal) + Dialog.resize(450, 175) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + Dialog.setFont(font) + Dialog.setSizeGripEnabled(False) + Dialog.setModal(False) + self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout.setObjectName("verticalLayout") + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setObjectName("widget") + self.gridLayout = QtWidgets.QGridLayout(self.widget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.lineEdit_save_root = QtWidgets.QLineEdit(self.widget) + self.lineEdit_save_root.setEnabled(True) + self.lineEdit_save_root.setReadOnly(True) + self.lineEdit_save_root.setObjectName("lineEdit_save_root") + self.gridLayout.addWidget(self.lineEdit_save_root, 3, 0, 1, 1) + self.pushButton_save_root = QtWidgets.QPushButton(self.widget) + self.pushButton_save_root.setObjectName("pushButton_save_root") + self.gridLayout.addWidget(self.pushButton_save_root, 3, 1, 1, 1) + self.checkBox_is_instance = QtWidgets.QCheckBox(self.widget) + self.checkBox_is_instance.setToolTip("") + self.checkBox_is_instance.setAccessibleName("") + self.checkBox_is_instance.setAccessibleDescription("") + self.checkBox_is_instance.setObjectName("checkBox_is_instance") + self.gridLayout.addWidget(self.checkBox_is_instance, 4, 1, 1, 1) + self.lineEdit_label_root = QtWidgets.QLineEdit(self.widget) + self.lineEdit_label_root.setEnabled(True) + self.lineEdit_label_root.setReadOnly(True) + self.lineEdit_label_root.setObjectName("lineEdit_label_root") + self.gridLayout.addWidget(self.lineEdit_label_root, 2, 0, 1, 1) + self.pushButton_label_root = QtWidgets.QPushButton(self.widget) + self.pushButton_label_root.setObjectName("pushButton_label_root") + self.gridLayout.addWidget(self.pushButton_label_root, 2, 1, 1, 1) + self.verticalLayout.addWidget(self.widget) + self.widget_process = QtWidgets.QWidget(Dialog) + self.widget_process.setObjectName("widget_process") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget_process) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.progressBar = QtWidgets.QProgressBar(self.widget_process) + self.progressBar.setProperty("value", 0) + self.progressBar.setObjectName("progressBar") + self.horizontalLayout_2.addWidget(self.progressBar) + self.current_num = QtWidgets.QLabel(self.widget_process) + self.current_num.setText("") + self.current_num.setObjectName("current_num") + self.horizontalLayout_2.addWidget(self.current_num) + self.label_3 = QtWidgets.QLabel(self.widget_process) + self.label_3.setObjectName("label_3") + self.horizontalLayout_2.addWidget(self.label_3) + self.all_num = QtWidgets.QLabel(self.widget_process) + self.all_num.setText("") + self.all_num.setObjectName("all_num") + self.horizontalLayout_2.addWidget(self.all_num) + self.verticalLayout.addWidget(self.widget_process) + self.widget_2 = QtWidgets.QWidget(Dialog) + self.widget_2.setObjectName("widget_2") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_2) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget_2) + self.label.setStyleSheet("color: rgb(255, 0, 0);") + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.pushButton_cache = QtWidgets.QPushButton(self.widget_2) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icons/icons/关闭_close-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_cache.setIcon(icon) + self.pushButton_cache.setObjectName("pushButton_cache") + self.horizontalLayout.addWidget(self.pushButton_cache) + self.pushButton_apply = QtWidgets.QPushButton(self.widget_2) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icons/icons/校验_check-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_apply.setIcon(icon1) + self.pushButton_apply.setObjectName("pushButton_apply") + self.horizontalLayout.addWidget(self.pushButton_apply) + self.verticalLayout.addWidget(self.widget_2) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "ISAT to png converter")) + self.lineEdit_save_root.setPlaceholderText(_translate("Dialog", "png save root")) + self.pushButton_save_root.setText(_translate("Dialog", "Save root")) + self.checkBox_is_instance.setText(_translate("Dialog", "Is Instance")) + self.lineEdit_label_root.setPlaceholderText(_translate("Dialog", "ISAT annotations root")) + self.pushButton_label_root.setText(_translate("Dialog", "Label root")) + self.label_3.setAccessibleName(_translate("Dialog", "aaa")) + self.label_3.setText(_translate("Dialog", "/")) + self.label.setText(_translate("Dialog", "Convert ISAT annotations to png.")) + self.pushButton_cache.setText(_translate("Dialog", "cache")) + self.pushButton_apply.setText(_translate("Dialog", "convert")) +import icons_rc diff --git a/ui/convert_dialog.ui b/ui/convert_dialog.ui new file mode 100644 index 0000000..f2c26eb --- /dev/null +++ b/ui/convert_dialog.ui @@ -0,0 +1,224 @@ + + + Dialog + + + Qt::NonModal + + + + 0 + 0 + 450 + 175 + + + + + Times New Roman + 12 + + + + ISAT to png converter + + + false + + + false + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + true + + + png save root + + + + + + + Save root + + + + + + + + + + + + + + + + Is Instance + + + + + + + true + + + true + + + ISAT annotations root + + + + + + + Label root + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + + + + + aaa + + + / + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + color: rgb(255, 0, 0); + + + Convert ISAT annotations to png. + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + cache + + + + :/icons/icons/关闭_close-one.svg:/icons/icons/关闭_close-one.svg + + + + + + + convert + + + + :/icons/icons/校验_check-one.svg:/icons/icons/校验_check-one.svg + + + + + + + + + + + + + diff --git a/ui/en.ts b/ui/en.ts new file mode 100644 index 0000000..ec94158 --- /dev/null +++ b/ui/en.ts @@ -0,0 +1,724 @@ + + + + + Dialog + + + category: + + + + + group: + + + + + group id + + + + + note: + + + + + add extra note here + + + + + is crowded + + + + + layer: + + + + + cache + + + + + apply + + + + + ISAT to png converter + + + + + png save root + + + + + Save root + + + + + ISAT annotations root + + + + + Label root + + + + + aaa + + + + + / + + + + + Convert ISAT annotations to png. + + + + + convert + + + + + help + + + + + E + + + + + Del + + + + + S + + + + + Save annotation + + + + + T + + + + + Delete polygon + + + + + B + + + + + Next image + + + + + D + + + + + A + + + + + Bit map + + + + + Space + + + + + F + + + + + Label + + + + + Apply + + + + + Cache + + + + + about + + + + + About + + + + + ISAT with Segment anything. + + + + + ISAT Copyright (C) 2022 yatengLG. +http://www.yatenglg.cn/isat + + + + + Is Instance + + + + + Setting + + + + + Add new label + + + + + Import + + + + + Export + + + + + Shortcut + + + + + Prior image + + + + + To top + + + + + To bottom + + + + + Zoom fit + + + + + Draw polygon + + + + + Segment anything + + + + + Q + + + + + Backspace + + + + + Z + + + + + Annotate finish + + + + + Annotate cancel + + + + + Esc + + + + + Form + + + Form + + + + + / + + + + + width : + + + + + height: + + + + + depth : + + + + + note: + + + + + add extra image note here + + + + + Jump to the image. Input name or index. + + + + + Jump to the image. + + + + + MainWindow + + + ISAT + + + + + File + + + + + View + + + + + Help + + + + + Tools + + + + + Edit + + + + + toolBar + + + + + Info + + + + + Labels + + + + + Files + + + + + Zoom in + + + + + Zoom out + + + + + Fit window + + + + + F + + + + + Setting + + + + + Exit + + + + + Save + + + + + S + + + + + Prev image + + + + + A + + + + + Next image + + + + + D + + + + + About + + + + + C + + + + + Delete + + + + + Delete polygon + + + + + Del + + + + + Bit map + + + + + Space + + + + + Edit polygon + + + + + E + + + + + To top + + + + + Move polygon to top layer + + + + + T + + + + + To bottom + + + + + Move polygon to bottom layer + + + + + B + + + + + Label converter + + + + + Convert annotations to png image. + + + + + Laguage + + + + + Images dir + + + + + Open images dir. + + + + + Zoom in. + + + + + Zoom out. + + + + + Fit window. + + + + + Setting. + + + + + Exit. + + + + + Label dir + + + + + Open label dir. + + + + + Save annotation. + + + + + Prev image. + + + + + Next image. + + + + + Shortcut + + + + + Segment anything + + + + + Quick annotate using Segment anything. + + + + + Q + + + + + Delete polygon. + + + + + Show instance or segmeent state. + + + + + Edit polygon attribute. + + + + + Move polygon to top layer. + + + + + Move polygon to bottom layer. + + + + + 中文 + + + + + English + + + + + Backspace + + + + + Backspace. + + + + + Z + + + + + Cancel + + + + + Annotate canceled + + + + + Annotate canceled. + + + + + Esc + + + + + Finish + + + + + Annotate finished + + + + + Annotate finished. + + + + + Polygon + + + + + Draw polygon + + + + + Accurately annotate by drawing polygon. + + + + diff --git a/ui/file_dock.py b/ui/file_dock.py new file mode 100644 index 0000000..b0edad2 --- /dev/null +++ b/ui/file_dock.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT/ui/file_dock.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(264, 341) + self.verticalLayout = QtWidgets.QVBoxLayout(Form) + self.verticalLayout.setContentsMargins(9, 9, 9, 9) + self.verticalLayout.setSpacing(6) + self.verticalLayout.setObjectName("verticalLayout") + self.listWidget = QtWidgets.QListWidget(Form) + self.listWidget.setObjectName("listWidget") + self.verticalLayout.addWidget(self.listWidget) + self.widget_num = QtWidgets.QWidget(Form) + self.widget_num.setObjectName("widget_num") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_num) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.lineEdit_jump = QtWidgets.QLineEdit(self.widget_num) + self.lineEdit_jump.setObjectName("lineEdit_jump") + self.horizontalLayout.addWidget(self.lineEdit_jump) + self.label_current = QtWidgets.QLabel(self.widget_num) + self.label_current.setText("") + self.label_current.setObjectName("label_current") + self.horizontalLayout.addWidget(self.label_current) + self.label = QtWidgets.QLabel(self.widget_num) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.label_all = QtWidgets.QLabel(self.widget_num) + self.label_all.setText("") + self.label_all.setObjectName("label_all") + self.horizontalLayout.addWidget(self.label_all) + self.verticalLayout.addWidget(self.widget_num) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) + self.lineEdit_jump.setToolTip(_translate("Form", "Jump to the image. Input name or index.")) + self.lineEdit_jump.setPlaceholderText(_translate("Form", "Jump to the image.")) + self.label.setText(_translate("Form", "/")) diff --git a/ui/file_dock.ui b/ui/file_dock.ui new file mode 100644 index 0000000..71df6cd --- /dev/null +++ b/ui/file_dock.ui @@ -0,0 +1,88 @@ + + + Form + + + + 0 + 0 + 264 + 341 + + + + Form + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Jump to the image. Input name or index. + + + Jump to the image. + + + + + + + + + + + + + + / + + + + + + + + + + + + + + + + + + diff --git a/ui/info_dock.py b/ui/info_dock.py new file mode 100644 index 0000000..9be64e8 --- /dev/null +++ b/ui/info_dock.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT/ui/info_dock.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(347, 156) + Form.setMinimumSize(QtCore.QSize(0, 100)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + Form.setFont(font) + self.verticalLayout = QtWidgets.QVBoxLayout(Form) + self.verticalLayout.setObjectName("verticalLayout") + self.widget = QtWidgets.QWidget(Form) + self.widget.setObjectName("widget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout.setContentsMargins(9, 0, 9, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget) + self.label.setMinimumSize(QtCore.QSize(0, 0)) + self.label.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.label_width = QtWidgets.QLabel(self.widget) + self.label_width.setText("") + self.label_width.setObjectName("label_width") + self.horizontalLayout.addWidget(self.label_width) + self.verticalLayout.addWidget(self.widget) + self.widget_2 = QtWidgets.QWidget(Form) + self.widget_2.setObjectName("widget_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget_2) + self.horizontalLayout_2.setContentsMargins(9, 0, 9, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_2 = QtWidgets.QLabel(self.widget_2) + self.label_2.setMinimumSize(QtCore.QSize(0, 0)) + self.label_2.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_2.setObjectName("label_2") + self.horizontalLayout_2.addWidget(self.label_2) + self.label_height = QtWidgets.QLabel(self.widget_2) + self.label_height.setText("") + self.label_height.setObjectName("label_height") + self.horizontalLayout_2.addWidget(self.label_height) + self.verticalLayout.addWidget(self.widget_2) + self.widget_4 = QtWidgets.QWidget(Form) + self.widget_4.setObjectName("widget_4") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget_4) + self.horizontalLayout_4.setContentsMargins(9, 0, 9, 0) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_3 = QtWidgets.QLabel(self.widget_4) + self.label_3.setMaximumSize(QtCore.QSize(60, 16777215)) + self.label_3.setObjectName("label_3") + self.horizontalLayout_4.addWidget(self.label_3) + self.label_depth = QtWidgets.QLabel(self.widget_4) + self.label_depth.setText("") + self.label_depth.setObjectName("label_depth") + self.horizontalLayout_4.addWidget(self.label_depth) + self.verticalLayout.addWidget(self.widget_4) + self.widget_3 = QtWidgets.QWidget(Form) + self.widget_3.setObjectName("widget_3") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_3) + self.horizontalLayout_3.setContentsMargins(9, 0, 9, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_5 = QtWidgets.QLabel(self.widget_3) + self.label_5.setObjectName("label_5") + self.horizontalLayout_3.addWidget(self.label_5) + self.lineEdit_note = QtWidgets.QLineEdit(self.widget_3) + self.lineEdit_note.setMinimumSize(QtCore.QSize(200, 0)) + self.lineEdit_note.setObjectName("lineEdit_note") + self.horizontalLayout_3.addWidget(self.lineEdit_note) + self.verticalLayout.addWidget(self.widget_3) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) + self.label.setText(_translate("Form", "width :")) + self.label_2.setText(_translate("Form", "height:")) + self.label_3.setText(_translate("Form", "depth :")) + self.label_5.setText(_translate("Form", "note:")) + self.lineEdit_note.setPlaceholderText(_translate("Form", "add extra image note here")) diff --git a/ui/info_dock.ui b/ui/info_dock.ui new file mode 100644 index 0000000..b5f475f --- /dev/null +++ b/ui/info_dock.ui @@ -0,0 +1,197 @@ + + + Form + + + + 0 + 0 + 347 + 156 + + + + + 0 + 100 + + + + + Times New Roman + 12 + + + + Form + + + + + + + 9 + + + 0 + + + 9 + + + 0 + + + + + + 0 + 0 + + + + + 60 + 16777215 + + + + width : + + + + + + + + + + + + + + + + + + 9 + + + 0 + + + 9 + + + 0 + + + + + + 0 + 0 + + + + + 60 + 16777215 + + + + height: + + + + + + + + + + + + + + + + + + 9 + + + 0 + + + 9 + + + 0 + + + + + + 60 + 16777215 + + + + depth : + + + + + + + + + + + + + + + + + + 9 + + + 0 + + + 9 + + + 0 + + + + + note: + + + + + + + + 200 + 0 + + + + add extra image note here + + + + + + + + + + + diff --git a/ui/label_dock.py b/ui/label_dock.py new file mode 100644 index 0000000..2f829de --- /dev/null +++ b/ui/label_dock.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT/ui/label_dock.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(250, 304) + self.verticalLayout = QtWidgets.QVBoxLayout(Form) + self.verticalLayout.setContentsMargins(2, 2, 2, 2) + self.verticalLayout.setSpacing(0) + self.verticalLayout.setObjectName("verticalLayout") + self.listWidget = QtWidgets.QListWidget(Form) + self.listWidget.setObjectName("listWidget") + self.verticalLayout.addWidget(self.listWidget) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) diff --git a/ui/label_dock.ui b/ui/label_dock.ui new file mode 100644 index 0000000..3aaf6d4 --- /dev/null +++ b/ui/label_dock.ui @@ -0,0 +1,39 @@ + + + Form + + + + 0 + 0 + 250 + 304 + + + + Form + + + + 0 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + + diff --git a/ui/setting_dialog.py b/ui/setting_dialog.py new file mode 100644 index 0000000..25c48ab --- /dev/null +++ b/ui/setting_dialog.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/setting_dialog.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(607, 369) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + Dialog.setFont(font) + self.verticalLayout_2 = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setObjectName("widget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.widget) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.widget) + font = QtGui.QFont() + font.setPointSize(20) + self.label.setFont(font) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.category_list_widget = QtWidgets.QListWidget(self.widget) + self.category_list_widget.setObjectName("category_list_widget") + self.verticalLayout.addWidget(self.category_list_widget) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.category_input = QtWidgets.QLineEdit(self.widget) + self.category_input.setObjectName("category_input") + self.horizontalLayout.addWidget(self.category_input) + self.color_button = QtWidgets.QToolButton(self.widget) + self.color_button.setStyleSheet("background-color: rgb(0, 255, 0);") + self.color_button.setText("") + self.color_button.setObjectName("color_button") + self.horizontalLayout.addWidget(self.color_button) + self.add_button = QtWidgets.QPushButton(self.widget) + self.add_button.setMinimumSize(QtCore.QSize(150, 0)) + self.add_button.setSizeIncrement(QtCore.QSize(0, 0)) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/icons/icons/书签_bookmark-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.add_button.setIcon(icon) + self.add_button.setObjectName("add_button") + self.horizontalLayout.addWidget(self.add_button) + self.verticalLayout.addLayout(self.horizontalLayout) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.pushButton_import = QtWidgets.QPushButton(self.widget) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/icons/icons/传入3_afferent-three.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_import.setIcon(icon1) + self.pushButton_import.setObjectName("pushButton_import") + self.horizontalLayout_2.addWidget(self.pushButton_import) + self.pushButton_export = QtWidgets.QPushButton(self.widget) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/icons/icons/传出3_efferent-three.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.pushButton_export.setIcon(icon2) + self.pushButton_export.setObjectName("pushButton_export") + self.horizontalLayout_2.addWidget(self.pushButton_export) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem) + self.cache_button = QtWidgets.QPushButton(self.widget) + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(":/icons/icons/关闭_close-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.cache_button.setIcon(icon3) + self.cache_button.setObjectName("cache_button") + self.horizontalLayout_2.addWidget(self.cache_button) + self.apply_button = QtWidgets.QPushButton(self.widget) + icon4 = QtGui.QIcon() + icon4.addPixmap(QtGui.QPixmap(":/icons/icons/校验_check-one.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.apply_button.setIcon(icon4) + self.apply_button.setObjectName("apply_button") + self.horizontalLayout_2.addWidget(self.apply_button) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.verticalLayout_2.addWidget(self.widget) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "Setting")) + self.label.setText(_translate("Dialog", "Label")) + self.add_button.setText(_translate("Dialog", "Add new label")) + self.pushButton_import.setText(_translate("Dialog", "Import")) + self.pushButton_export.setText(_translate("Dialog", "Export")) + self.cache_button.setText(_translate("Dialog", "Cache")) + self.apply_button.setText(_translate("Dialog", "Apply")) +import icons_rc diff --git a/ui/setting_dialog.ui b/ui/setting_dialog.ui new file mode 100644 index 0000000..d653de5 --- /dev/null +++ b/ui/setting_dialog.ui @@ -0,0 +1,151 @@ + + + Dialog + + + + 0 + 0 + 607 + 369 + + + + + Times New Roman + 12 + + + + Setting + + + + + + + + + + 20 + + + + Label + + + + + + + + + + + + + + + background-color: rgb(0, 255, 0); + + + + + + + + + + + 150 + 0 + + + + + 0 + 0 + + + + Add new label + + + + :/icons/icons/书签_bookmark-one.svg:/icons/icons/书签_bookmark-one.svg + + + + + + + + + + + Import + + + + :/icons/icons/传入3_afferent-three.svg:/icons/icons/传入3_afferent-three.svg + + + + + + + Export + + + + :/icons/icons/传出3_efferent-three.svg:/icons/icons/传出3_efferent-three.svg + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cache + + + + :/icons/icons/关闭_close-one.svg:/icons/icons/关闭_close-one.svg + + + + + + + Apply + + + + :/icons/icons/校验_check-one.svg:/icons/icons/校验_check-one.svg + + + + + + + + + + + + + + + diff --git a/ui/shortcut_dialog.py b/ui/shortcut_dialog.py new file mode 100644 index 0000000..f6b95cc --- /dev/null +++ b/ui/shortcut_dialog.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/super/PycharmProjects/ISAT_with_segment_anything/ui/shortcut_dialog.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(600, 300) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth()) + Dialog.setSizePolicy(sizePolicy) + Dialog.setMinimumSize(QtCore.QSize(600, 300)) + Dialog.setMaximumSize(QtCore.QSize(600, 300)) + font = QtGui.QFont() + font.setKerning(True) + Dialog.setFont(font) + self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout.setObjectName("verticalLayout") + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setMinimumSize(QtCore.QSize(0, 60)) + self.widget.setMaximumSize(QtCore.QSize(16777215, 60)) + self.widget.setObjectName("widget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(20) + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + self.label.setFont(font) + self.label.setTextFormat(QtCore.Qt.AutoText) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.verticalLayout.addWidget(self.widget) + self.widget_2 = QtWidgets.QWidget(Dialog) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + self.widget_2.setFont(font) + self.widget_2.setObjectName("widget_2") + self.gridLayout = QtWidgets.QGridLayout(self.widget_2) + self.gridLayout.setObjectName("gridLayout") + self.label_20 = QtWidgets.QLabel(self.widget_2) + self.label_20.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_20.setFont(font) + self.label_20.setStyleSheet("color: rgb(133, 0, 0);") + self.label_20.setObjectName("label_20") + self.gridLayout.addWidget(self.label_20, 5, 3, 1, 1) + self.label_19 = QtWidgets.QLabel(self.widget_2) + self.label_19.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_19.setFont(font) + self.label_19.setStyleSheet("color: rgb(133, 0, 0);") + self.label_19.setObjectName("label_19") + self.gridLayout.addWidget(self.label_19, 4, 3, 1, 1) + self.label_17 = QtWidgets.QLabel(self.widget_2) + self.label_17.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_17.setFont(font) + self.label_17.setStyleSheet("color: rgb(133, 0, 0);") + self.label_17.setObjectName("label_17") + self.gridLayout.addWidget(self.label_17, 0, 3, 1, 1) + self.label_15 = QtWidgets.QLabel(self.widget_2) + self.label_15.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_15.setFont(font) + self.label_15.setStyleSheet("color: rgb(133, 0, 0);") + self.label_15.setObjectName("label_15") + self.gridLayout.addWidget(self.label_15, 5, 1, 1, 1) + self.label_7 = QtWidgets.QLabel(self.widget_2) + self.label_7.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_7.setFont(font) + self.label_7.setStyleSheet("color: rgb(133, 0, 0);") + self.label_7.setObjectName("label_7") + self.gridLayout.addWidget(self.label_7, 0, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_2.setFont(font) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) + self.label_10 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_10.setFont(font) + self.label_10.setObjectName("label_10") + self.gridLayout.addWidget(self.label_10, 4, 2, 1, 1) + self.label_18 = QtWidgets.QLabel(self.widget_2) + self.label_18.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_18.setFont(font) + self.label_18.setStyleSheet("color: rgb(133, 0, 0);") + self.label_18.setObjectName("label_18") + self.gridLayout.addWidget(self.label_18, 1, 3, 1, 1) + self.label_5 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_5.setFont(font) + self.label_5.setObjectName("label_5") + self.gridLayout.addWidget(self.label_5, 1, 2, 1, 1) + self.label_14 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_14.setFont(font) + self.label_14.setObjectName("label_14") + self.gridLayout.addWidget(self.label_14, 6, 0, 1, 1) + self.label_16 = QtWidgets.QLabel(self.widget_2) + self.label_16.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_16.setFont(font) + self.label_16.setStyleSheet("color: rgb(133, 0, 0);") + self.label_16.setObjectName("label_16") + self.gridLayout.addWidget(self.label_16, 6, 1, 1, 1) + self.label_11 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_11.setFont(font) + self.label_11.setObjectName("label_11") + self.gridLayout.addWidget(self.label_11, 6, 2, 1, 1) + self.label_21 = QtWidgets.QLabel(self.widget_2) + self.label_21.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_21.setFont(font) + self.label_21.setStyleSheet("color: rgb(133, 0, 0);") + self.label_21.setObjectName("label_21") + self.gridLayout.addWidget(self.label_21, 6, 3, 1, 1) + self.label_4 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_4.setFont(font) + self.label_4.setObjectName("label_4") + self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) + self.label_9 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_9.setFont(font) + self.label_9.setObjectName("label_9") + self.gridLayout.addWidget(self.label_9, 5, 2, 1, 1) + self.label_6 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_6.setFont(font) + self.label_6.setObjectName("label_6") + self.gridLayout.addWidget(self.label_6, 4, 0, 1, 1) + self.label_13 = QtWidgets.QLabel(self.widget_2) + self.label_13.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_13.setFont(font) + self.label_13.setStyleSheet("color: rgb(133, 0, 0);") + self.label_13.setObjectName("label_13") + self.gridLayout.addWidget(self.label_13, 4, 1, 1, 1) + self.label_12 = QtWidgets.QLabel(self.widget_2) + self.label_12.setMaximumSize(QtCore.QSize(80, 16777215)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_12.setFont(font) + self.label_12.setStyleSheet("color: rgb(133, 0, 0);") + self.label_12.setObjectName("label_12") + self.gridLayout.addWidget(self.label_12, 1, 1, 1, 1) + self.label_3 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_3.setFont(font) + self.label_3.setObjectName("label_3") + self.gridLayout.addWidget(self.label_3, 0, 2, 1, 1) + self.label_22 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_22.setFont(font) + self.label_22.setObjectName("label_22") + self.gridLayout.addWidget(self.label_22, 2, 0, 1, 1) + self.label_23 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_23.setFont(font) + self.label_23.setStyleSheet("color: rgb(133, 0, 0);") + self.label_23.setObjectName("label_23") + self.gridLayout.addWidget(self.label_23, 2, 1, 1, 1) + self.label_25 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_25.setFont(font) + self.label_25.setStyleSheet("color: rgb(133, 0, 0);") + self.label_25.setObjectName("label_25") + self.gridLayout.addWidget(self.label_25, 2, 3, 1, 1) + self.label_24 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_24.setFont(font) + self.label_24.setObjectName("label_24") + self.gridLayout.addWidget(self.label_24, 2, 2, 1, 1) + self.label_26 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_26.setFont(font) + self.label_26.setObjectName("label_26") + self.gridLayout.addWidget(self.label_26, 3, 0, 1, 1) + self.label_27 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_27.setFont(font) + self.label_27.setStyleSheet("color: rgb(133, 0, 0);") + self.label_27.setObjectName("label_27") + self.gridLayout.addWidget(self.label_27, 3, 1, 1, 1) + self.label_8 = QtWidgets.QLabel(self.widget_2) + font = QtGui.QFont() + font.setPointSize(12) + self.label_8.setFont(font) + self.label_8.setObjectName("label_8") + self.gridLayout.addWidget(self.label_8, 5, 0, 1, 1) + self.verticalLayout.addWidget(self.widget_2) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "help")) + self.label.setText(_translate("Dialog", "Shortcut")) + self.label_20.setText(_translate("Dialog", "B")) + self.label_19.setText(_translate("Dialog", "S")) + self.label_17.setText(_translate("Dialog", "D")) + self.label_15.setText(_translate("Dialog", "T")) + self.label_7.setText(_translate("Dialog", "A")) + self.label_2.setText(_translate("Dialog", "Prior image")) + self.label_10.setText(_translate("Dialog", "Save annotation")) + self.label_18.setText(_translate("Dialog", "E")) + self.label_5.setText(_translate("Dialog", "Draw polygon")) + self.label_14.setText(_translate("Dialog", "Bit map")) + self.label_16.setText(_translate("Dialog", "Space")) + self.label_11.setText(_translate("Dialog", "Zoom fit")) + self.label_21.setText(_translate("Dialog", "F")) + self.label_4.setText(_translate("Dialog", "Segment anything")) + self.label_9.setText(_translate("Dialog", "To bottom")) + self.label_6.setText(_translate("Dialog", "Delete polygon")) + self.label_13.setText(_translate("Dialog", "Del")) + self.label_12.setText(_translate("Dialog", "Q")) + self.label_3.setText(_translate("Dialog", "Next image")) + self.label_22.setText(_translate("Dialog", "Backspace")) + self.label_23.setText(_translate("Dialog", "Z")) + self.label_25.setText(_translate("Dialog", "E")) + self.label_24.setText(_translate("Dialog", "Annotate finish")) + self.label_26.setText(_translate("Dialog", "Annotate cancel")) + self.label_27.setText(_translate("Dialog", "Esc")) + self.label_8.setText(_translate("Dialog", "To top")) +import icons_rc diff --git a/ui/shortcut_dialog.ui b/ui/shortcut_dialog.ui new file mode 100644 index 0000000..c525f0d --- /dev/null +++ b/ui/shortcut_dialog.ui @@ -0,0 +1,506 @@ + + + Dialog + + + + 0 + 0 + 600 + 300 + + + + + 0 + 0 + + + + + 600 + 300 + + + + + 600 + 300 + + + + + true + + + + help + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + + + + Times New Roman + 20 + 50 + false + false + + + + Shortcut + + + Qt::AutoText + + + + + + + + + + + Times New Roman + 12 + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + B + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + S + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + D + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + T + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + A + + + + + + + + 12 + + + + Prior image + + + + + + + + 12 + + + + Save annotation + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + E + + + + + + + + 12 + + + + Draw polygon + + + + + + + + 12 + + + + Bit map + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + Space + + + + + + + + 12 + + + + Zoom fit + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + F + + + + + + + + 12 + + + + Segment anything + + + + + + + + 12 + + + + To bottom + + + + + + + + 12 + + + + Delete polygon + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + Del + + + + + + + + 80 + 16777215 + + + + + 12 + + + + color: rgb(133, 0, 0); + + + Q + + + + + + + + 12 + + + + Next image + + + + + + + + 12 + + + + Backspace + + + + + + + + 12 + + + + color: rgb(133, 0, 0); + + + Z + + + + + + + + 12 + + + + color: rgb(133, 0, 0); + + + E + + + + + + + + 12 + + + + Annotate finish + + + + + + + + 12 + + + + Annotate cancel + + + + + + + + 12 + + + + color: rgb(133, 0, 0); + + + Esc + + + + + + + + 12 + + + + To top + + + + + + + + + + + + + diff --git a/ui/zh_CN.qm b/ui/zh_CN.qm new file mode 100644 index 0000000..e6d7e89 Binary files /dev/null and b/ui/zh_CN.qm differ diff --git a/ui/zh_CN.ts b/ui/zh_CN.ts new file mode 100644 index 0000000..867d027 --- /dev/null +++ b/ui/zh_CN.ts @@ -0,0 +1,904 @@ + + + + + Dialog + + + category: + 类别: + + + + group: + 组: + + + + group id + id + + + + note: + 注释: + + + + add extra note here + 为标签添加额外注释 + + + + is crowded + 拥挤 + + + + layer: + 图层: + + + + cache + 取消 + + + + apply + 应用 + + + + ISAT to png converter + ISAT标签文件转png + + + + png save root + png保存路径 + + + + Save root + 保存路径 + + + + Is Instance + 实例分割 + + + + ISAT annotations root + ISAT标注文件路径 + + + + Label root + 标注路径 + + + + aaa + + + + + / + + + + + Convert ISAT annotations to png. + 将ISAT标注文件转换为png图片. + + + + convert + 转换 + + + + help + 帮助 + + + + ISAT + ISAT 图片分割标注工具 + + + + Polygon + 多边形 + + + + Move polygon to bottom + 多边形置于底层 + + + + E + + + + + Create polygon + 创建多边形 + + + + Move polygon to top + 多边形置于顶层 + + + + Del + + + + + S + + + + + Save annotation + 保存标注文件 + + + + T + + + + + Delete polygon + 删除多边形 + + + + Edit polygon + 编辑多边形 + + + + B + + + + + File + 文件 + + + + Next image + 下一张图片 + + + + D + + + + + Prev image + 上一张图片 + + + + A + + + + + Open annotations dir + 标签保存位置 + + + + Open images dir + 打开图片文件夹 + + + + Open image + 打开图片 + + + + View + 视图 + + + + Bit map + 位图 + + + + Space + + + + + F + + + + + Zoom out + 缩小 + + + + Fit window + 窗口大小 + + + + Zoom in + 放大 + + + + Move image + 移动图片 + + + + Mouse(press left button) or ←↑→↓ + 鼠标左键拖动或←↑→↓ + + + + Display + 显示 + + + + Label + 标签 + + + + nohover size + 非悬停时尺寸 + + + + hover alpha + 悬停时透明度 + + + + Vertex + 顶点 + + + + hover size + 悬停时尺寸 + + + + nohover alpha + 非悬停时透明度 + + + + Add new category + 添加新类别 + + + + Add + 添加 + + + + Apply + 应用 + + + + Cache + 取消 + + + + Setting + 设置 + + + + Import + 导入 + + + + Export + 导出 + + + + about + 关于 + + + + About + 关于 + + + + ISAT with Segment anything. + ISAT集成Segment anything. + + + + ISAT Copyright (C) 2022 yatengLG. +http://www.yatenglg.cn/isat + + + + + Add new label + 添加新类别 + + + + Shortcut + 快捷键 + + + + Prior image + 上一张图片 + + + + To top + 置顶 + + + + To bottom + 置底 + + + + Zoom fit + 适应窗口 + + + + Draw polygon + 绘制多边形 + + + + Segment anything + + + + + Q + + + + + Backspace + 回退 + + + + Z + + + + + Annotate finish + 标注完成 + + + + Annotate cancel + 标注取消 + + + + Esc + + + + + Form + + + Form + + + + + / + + + + + width : + 宽: + + + + height: + 高: + + + + depth : + 通道: + + + + note: + 注释: + + + + add extra image note here + 为图片添加额外注释 + + + + Jump to the image. Input name or index. + 跳转到指定图片,输入图片名或序号. + + + + Jump to the image. + 跳转到指定图片. + + + + MainWindow + + + ISAT + ISAT 图片分割标注工具 + + + + File + 文件 + + + + View + 视图 + + + + Help + 帮助 + + + + Tools + 工具 + + + + Edit + 编辑 + + + + toolBar + 工具栏 + + + + Info + 图片信息 + + + + Labels + 标签列表 + + + + Files + 文件列表 + + + + Open image + 打开图片 + + + + Open images dir + 打开图片文件夹 + + + + Zoom in + 放大 + + + + Zoom out + 缩小 + + + + Fit window + 适应窗口 + + + + F + + + + + Setting + 设置 + + + + Exit + 退出 + + + + Open annotations dir + 标签保存位置 + + + + Save + 保存 + + + + S + + + + + Prev + 上一张 + + + + Prev image + 上一张图片 + + + + A + + + + + Next + 下一张 + + + + Next image + 下一张图片 + + + + D + + + + + About + 关于 + + + + Create + 创建 + + + + Create polygon + 创建多边形 + + + + C + + + + + Delete + 删除 + + + + Delete polygon + 删除多边形 + + + + Del + + + + + Bit map + 位图 + + + + Space + + + + + Edit polygon + 编辑多边形 + + + + E + + + + + To top + 置顶 + + + + Move polygon to top layer + 移动多边形到顶层 + + + + T + + + + + To bottom + 置底 + + + + Move polygon to bottom layer + 移动多边形到底层 + + + + B + + + + + Label converter + 标注文件转换器 + + + + Convert annotations to png image. + 将ISAT标注文件转换为png图片. + + + + Laguage + 语言 + + + + Shortcut + 快捷键 + + + + Chinese + 中文 + + + + English + + + + + 中文 + + + + + Images dir + 图片文件夹 + + + + Open images dir. + 打开图片文件夹. + + + + Zoom in. + 放大. + + + + Zoom out. + 缩小. + + + + Fit window. + 适应窗口. + + + + Label dir + 标签文件夹 + + + + Open label dir. + 打开标签文件夹. + + + + Save annotation. + 保存. + + + + Priro image + 上一张图片 + + + + Prior image. + 打开上一张图片. + + + + Next image. + 下一张图片. + + + + Draw polygon. + 打开下一张图片. + + + + Delete polygon. + 删除多边形. + + + + Show instance or segmeent state. + 显示语义与实例结果. + + + + Edit polygon attribute. + 编辑多边形属性. + + + + Move polygon to top layer. + 将多边形移动到最上层. + + + + Move polygon to bottom layer. + 将多边形移动到最下层. + + + + Setting. + 设置. + + + + Exit. + 退出. + + + + Prev image. + 前一张图片. + + + + Segment anything + + + + + Quick annotate using Segment anything. + 使用Segment anything进行快速标注. + + + + Q + + + + + Backspace + 回退 + + + + Backspace. + 回退. + + + + Z + + + + + Cancel + 取消 + + + + Annotate canceled + 标注取消 + + + + Annotate canceled. + 标注取消. + + + + Esc + + + + + Finish + 完成 + + + + Annotate finished + 标注完成 + + + + Annotate finished. + 标注完成. + + + + Polygon + 多边形 + + + + Draw polygon + 绘制多边形 + + + + Accurately annotate by drawing polygon. + 通过手动绘制多边形,进行精细标注. + + + diff --git a/widgets/about_dialog.py b/widgets/about_dialog.py new file mode 100644 index 0000000..8b8b386 --- /dev/null +++ b/widgets/about_dialog.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.about_dialog import Ui_Dialog + +class AboutDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent): + super(AboutDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) diff --git a/widgets/canvas.py b/widgets/canvas.py new file mode 100644 index 0000000..4c3a54d --- /dev/null +++ b/widgets/canvas.py @@ -0,0 +1,432 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtGui, QtCore +from enum import Enum +from widgets.polygon import Polygon +from configs import STATUSMode, CLICKMode, DRAWMode +from PIL import Image +import numpy as np +import cv2 + + +class AnnotationScene(QtWidgets.QGraphicsScene): + def __init__(self, mainwindow): + super(AnnotationScene, self).__init__() + self.mainwindow = mainwindow + self.image_item:QtWidgets.QGraphicsPixmapItem = None + self.image_data = None + self.current_graph:Polygon = None + self.mode = STATUSMode.VIEW + self.click = CLICKMode.POSITIVE + self.draw_mode = DRAWMode.SEGMENTANYTHING # 默认使用segment anything进行快速标注 + self.click_points = [] + self.click_points_mode = [] + self.masks:np.ndarray = None + self.top_layer = 1 + + self.guide_line_x:QtWidgets.QGraphicsLineItem = None + self.guide_line_y:QtWidgets.QGraphicsLineItem = None + + def load_image(self, image_path:str): + self.clear() + + self.image_data = np.array(Image.open(image_path)) + if self.mainwindow.use_segment_anything: + self.mainwindow.segany.reset_image() + + if self.image_data.ndim == 3 and self.image_data.shape[-1] == 3: + self.mainwindow.segany.set_image(self.image_data) + elif self.image_data.ndim == 2 and image_path.endswith('.png'): + # 单通道图标签图 + pass + else: + QtWidgets.QMessageBox.warning(self.mainwindow, 'Warning', 'Segment anything only support 3 channel rgb image.') + + self.image_item = QtWidgets.QGraphicsPixmapItem() + self.image_item.setZValue(0) + self.addItem(self.image_item) + self.mask_item = QtWidgets.QGraphicsPixmapItem() + self.mask_item.setZValue(1) + self.addItem(self.mask_item) + + self.image_item.setPixmap(QtGui.QPixmap(image_path)) + self.setSceneRect(self.image_item.boundingRect()) + self.change_mode_to_view() + + def change_mode_to_create(self): + if self.image_item is None: + return + self.mode = STATUSMode.CREATE + self.image_item.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.CrossCursor)) + self.mainwindow.actionPrev.setEnabled(False) + self.mainwindow.actionNext.setEnabled(False) + + self.mainwindow.actionSegment_anything.setEnabled(False) + self.mainwindow.actionPolygon.setEnabled(False) + self.mainwindow.actionBackspace.setEnabled(True) + self.mainwindow.actionFinish.setEnabled(True) + self.mainwindow.actionCancel.setEnabled(True) + + self.mainwindow.actionTo_top.setEnabled(False) + self.mainwindow.actionTo_bottom.setEnabled(False) + self.mainwindow.actionEdit.setEnabled(False) + self.mainwindow.actionDelete.setEnabled(False) + self.mainwindow.actionSave.setEnabled(False) + + def change_mode_to_view(self): + self.mode = STATUSMode.VIEW + self.image_item.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ArrowCursor)) + + self.mainwindow.actionPrev.setEnabled(True) + self.mainwindow.actionNext.setEnabled(True) + + self.mainwindow.actionSegment_anything.setEnabled(self.mainwindow.use_segment_anything) + self.mainwindow.actionPolygon.setEnabled(True) + self.mainwindow.actionBackspace.setEnabled(False) + self.mainwindow.actionFinish.setEnabled(False) + self.mainwindow.actionCancel.setEnabled(False) + + self.mainwindow.actionTo_top.setEnabled(False) + self.mainwindow.actionTo_bottom.setEnabled(False) + self.mainwindow.actionEdit.setEnabled(False) + self.mainwindow.actionDelete.setEnabled(False) + self.mainwindow.actionSave.setEnabled(True) + + def change_mode_to_edit(self): + self.mode = STATUSMode.EDIT + self.image_item.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.CrossCursor)) + + self.mainwindow.actionPrev.setEnabled(False) + self.mainwindow.actionNext.setEnabled(False) + + self.mainwindow.actionSegment_anything.setEnabled(False) + self.mainwindow.actionPolygon.setEnabled(False) + self.mainwindow.actionBackspace.setEnabled(False) + self.mainwindow.actionFinish.setEnabled(False) + self.mainwindow.actionCancel.setEnabled(False) + + self.mainwindow.actionTo_top.setEnabled(True) + self.mainwindow.actionTo_bottom.setEnabled(True) + self.mainwindow.actionEdit.setEnabled(True) + self.mainwindow.actionDelete.setEnabled(True) + self.mainwindow.actionSave.setEnabled(True) + + def change_click_to_positive(self): + self.click = CLICKMode.POSITIVE + + def change_click_to_negative(self): + self.click = CLICKMode.NEGATIVE + + def start_segment_anything(self): + self.draw_mode = DRAWMode.SEGMENTANYTHING + self.start_draw() + + def start_draw_polygon(self): + self.draw_mode = DRAWMode.POLYGON + self.start_draw() + + def start_draw(self): + # 只有view模式时,才能切换create模式 + if self.mode != STATUSMode.VIEW: + return + # 否则,切换到绘图模式 + self.change_mode_to_create() + # 绘图模式 + if self.mode == STATUSMode.CREATE: + self.current_graph = Polygon() + self.addItem(self.current_graph) + + def finish_draw(self): + + if self.current_graph is None: + return + + self.change_mode_to_view() + + if self.draw_mode == DRAWMode.SEGMENTANYTHING: + # mask to polygon + # -------------- + if self.masks is not None: + masks = self.masks + masks = masks.astype('uint8') * 255 + h, w = masks.shape[-2:] + masks = masks.reshape(h, w) + + contours, _ = cv2.findContours(masks, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS) + + # 这里取轮廓点数最多的(可能返回多个轮廓) + contour = contours[0] + for cont in contours: + if len(cont) > len(contour): + contour = cont + + for point in contour: + x, y = point[0] + self.current_graph.addPoint(QtCore.QPointF(x, y)) + + elif self.draw_mode == DRAWMode.POLYGON: + if len(self.current_graph.points) < 1: + return + + # 移除鼠标移动点 + # self.current_graph.removePoint(len(self.current_graph.points) - 1) + + # 单点,删除 + if len(self.current_graph.points) < 2: + self.current_graph.delete() + self.removeItem(self.current_graph) + self.change_mode_to_view() + return + + # 两点,默认矩形 + if len(self.current_graph.points) == 2: + first_point = self.current_graph.points[0] + last_point = self.current_graph.points[-1] + self.current_graph.removePoint(len(self.current_graph.points) - 1) + self.current_graph.addPoint(QtCore.QPointF(first_point.x(), last_point.y())) + self.current_graph.addPoint(last_point) + self.current_graph.addPoint(QtCore.QPointF(last_point.x(), first_point.y())) + + # 选择类别 + self.mainwindow.category_choice_widget.load_cfg() + self.mainwindow.category_choice_widget.show() + + # mask清空 + self.click_points.clear() + self.click_points_mode.clear() + self.update_mask() + + def cancel_draw(self): + if self.current_graph is None: + return + self.current_graph.delete() # 清除所有路径 + self.removeItem(self.current_graph) + + self.current_graph = None + + self.change_mode_to_view() + + self.click_points.clear() + self.click_points_mode.clear() + self.update_mask() + + def delete_selected_graph(self): + deleted_layer = None + for item in self.selectedItems(): + if item in self.mainwindow.polygons: + self.mainwindow.polygons.remove(item) + item.delete() + self.removeItem(item) + deleted_layer = item.zValue() + del item + if deleted_layer is not None: + for p in self.mainwindow.polygons: + if p.zValue() > deleted_layer: + p.setZValue(p.zValue() - 1) + self.mainwindow.labels_dock_widget.update_listwidget() + + def edit_polygon(self): + selectd_items = self.selectedItems() + if len(selectd_items) < 1: + return + item = selectd_items[0] + if not item: + return + self.mainwindow.category_edit_widget.polygon = item + self.mainwindow.category_edit_widget.load_cfg() + self.mainwindow.category_edit_widget.show() + + def move_polygon_to_top(self): + selectd_items = self.selectedItems() + if len(selectd_items) < 1: + return + current_polygon = selectd_items[0] + max_layer = len(self.mainwindow.polygons) + + current_layer = current_polygon.zValue() + for p in self.mainwindow.polygons: + if p.zValue() > current_layer: + p.setZValue(p.zValue() - 1) + + current_polygon.setZValue(max_layer) + for vertex in current_polygon.vertexs: + vertex.setZValue(max_layer) + self.mainwindow.set_saved_state(False) + + def move_polygon_to_bottom(self): + selectd_items = self.selectedItems() + if len(selectd_items) < 1: + return + current_polygon = selectd_items[0] + + if current_polygon is not None: + current_layer = current_polygon.zValue() + + for p in self.mainwindow.polygons: + if p.zValue() < current_layer: + p.setZValue(p.zValue() + 1) + + current_polygon.setZValue(1) + for vertex in current_polygon.vertexs: + vertex.setZValue(1) + self.mainwindow.set_saved_state(False) + + def mousePressEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'): + if self.mode == STATUSMode.CREATE: + sceneX, sceneY = event.scenePos().x(), event.scenePos().y() + sceneX = 0 if sceneX < 0 else sceneX + sceneX = self.width() if sceneX > self.width() else sceneX + sceneY = 0 if sceneY < 0 else sceneY + sceneY = self.height() if sceneY > self.height() else sceneY + + if event.button() == QtCore.Qt.MouseButton.LeftButton: + if self.draw_mode == DRAWMode.SEGMENTANYTHING: + self.click_points.append([sceneX, sceneY]) + self.click_points_mode.append(1) + elif self.draw_mode == DRAWMode.POLYGON: + # 移除随鼠标移动的点 + self.current_graph.removePoint(len(self.current_graph.points) - 1) + # 添加当前点 + self.current_graph.addPoint(QtCore.QPointF(sceneX, sceneY)) + # 添加随鼠标移动的点 + self.current_graph.addPoint(QtCore.QPointF(sceneX, sceneY)) + else: + raise ValueError('The draw mode named {} not supported.') + if event.button() == QtCore.Qt.MouseButton.RightButton: + if self.draw_mode == DRAWMode.SEGMENTANYTHING: + self.click_points.append([sceneX, sceneY]) + self.click_points_mode.append(0) + elif self.draw_mode == DRAWMode.POLYGON: + pass + else: + raise ValueError('The draw mode named {} not supported.') + if self.draw_mode == DRAWMode.SEGMENTANYTHING: + self.update_mask() + super(AnnotationScene, self).mousePressEvent(event) + + def mouseMoveEvent(self, event: 'QtWidgets.QGraphicsSceneMouseEvent'): + # 辅助线 + if self.guide_line_x is not None and self.guide_line_y is not None: + if self.guide_line_x in self.items(): + self.removeItem(self.guide_line_x) + + if self.guide_line_y in self.items(): + self.removeItem(self.guide_line_y) + + self.guide_line_x = None + self.guide_line_y = None + + pos = event.scenePos() + if pos.x() < 0: pos.setX(0) + if pos.x() > self.width(): pos.setX(self.width()) + if pos.y() < 0: pos.setY(0) + if pos.y() > self.height(): pos.setY(self.height()) + # 限制在图片范围内 + + if self.mode == STATUSMode.CREATE: + if self.draw_mode == DRAWMode.POLYGON: + # 随鼠标位置实时更新多边形 + self.current_graph.movePoint(len(self.current_graph.points)-1, pos) + + # 辅助线 + if self.guide_line_x is None and self.width()>0 and self.height()>0: + self.guide_line_x = QtWidgets.QGraphicsLineItem(QtCore.QLineF(pos.x(), 0, pos.x(), self.height())) + self.guide_line_x.setZValue(1) + self.addItem(self.guide_line_x) + if self.guide_line_y is None and self.width()>0 and self.height()>0: + self.guide_line_y = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, pos.y(), self.width(), pos.y())) + self.guide_line_y.setZValue(1) + self.addItem(self.guide_line_y) + + # 状态栏,显示当前坐标 + if self.image_data is not None: + x, y = round(pos.x()), round(pos.y()) + self.mainwindow.labelCoordinates.setText('({}, {}) [{}]'.format(x, y, self.image_data[y-1][x-1])) + super(AnnotationScene, self).mouseMoveEvent(event) + + def update_mask(self): + if not self.mainwindow.use_segment_anything: + return + if not (self.image_data.ndim == 3 and self.image_data.shape[-1] == 3): + return + + if len(self.click_points) > 0 and len(self.click_points_mode) > 0: + masks = self.mainwindow.segany.predict(self.click_points, self.click_points_mode) + self.masks = masks + color = np.array([0, 0, 255]) + h, w = masks.shape[-2:] + mask_image = masks.reshape(h, w, 1) * color.reshape(1, 1, -1) + mask_image = mask_image.astype("uint8") + mask_image = cv2.cvtColor(mask_image, cv2.COLOR_BGR2RGB) + mask_image = cv2.addWeighted(self.image_data, 0.5, mask_image, 0.9, 0) + mask_image = QtGui.QImage(mask_image[:], mask_image.shape[1], mask_image.shape[0], mask_image.shape[1] * 3, + QtGui.QImage.Format_RGB888) + mask_pixmap = QtGui.QPixmap(mask_image) + self.mask_item.setPixmap(mask_pixmap) + else: + mask_image = np.zeros(self.image_data.shape, dtype=np.uint8) + mask_image = cv2.addWeighted(self.image_data, 1, mask_image, 0, 0) + mask_image = QtGui.QImage(mask_image[:], mask_image.shape[1], mask_image.shape[0], mask_image.shape[1] * 3, + QtGui.QImage.Format_RGB888) + mask_pixmap = QtGui.QPixmap(mask_image) + self.mask_item.setPixmap(mask_pixmap) + + def backspace(self): + if self.mode != STATUSMode.CREATE: + return + # 返回上一步操作 + if self.draw_mode == DRAWMode.SEGMENTANYTHING: + if len(self.click_points) > 0: + self.click_points.pop() + if len(self.click_points_mode) > 0: + self.click_points_mode.pop() + self.update_mask() + elif self.draw_mode == DRAWMode.POLYGON: + if len(self.current_graph.points) < 2: + return + # 移除随鼠标移动的点 + self.current_graph.removePoint(len(self.current_graph.points) - 2) + + +class AnnotationView(QtWidgets.QGraphicsView): + def __init__(self, parent=None): + super(AnnotationView, self).__init__(parent) + self.setMouseTracking(True) + self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOn) + self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOn) + self.setDragMode(QtWidgets.QGraphicsView.DragMode.ScrollHandDrag) + self.factor = 1.2 + + def wheelEvent(self, event: QtGui.QWheelEvent): + angel = event.angleDelta() + angelX, angelY = angel.x(), angel.y() + point = event.pos() # 当前鼠标位置 + if angelY > 0: + self.zoom(self.factor, point) + else: + self.zoom(1 / self.factor, point) + + def zoom_in(self): + self.zoom(self.factor) + + def zoom_out(self): + self.zoom(1/self.factor) + + def zoomfit(self): + self.fitInView(0, 0, self.scene().width(), self.scene().height(), QtCore.Qt.AspectRatioMode.KeepAspectRatio) + + def zoom(self, factor, point=None): + mouse_old = self.mapToScene(point) if point is not None else None + # 缩放比例 + + pix_widget = self.transform().scale(factor, factor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width() + if pix_widget > 3 or pix_widget < 0.01: + return + + self.scale(factor, factor) + if point is not None: + mouse_now = self.mapToScene(point) + center_now = self.mapToScene(self.viewport().width() // 2, self.viewport().height() // 2) + center_new = mouse_old - mouse_now + center_now + self.centerOn(center_new) diff --git a/widgets/category_choice_dialog.py b/widgets/category_choice_dialog.py new file mode 100644 index 0000000..b959179 --- /dev/null +++ b/widgets/category_choice_dialog.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# @Author : LG + + +from ui.category_choice import Ui_Dialog +from PyQt5 import QtWidgets, QtGui, QtCore +from configs import load_config, CONFIG_FILE, DEFAULT_CONFIG_FILE +import os + + +class CategoryChoiceDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent, mainwindow, scene): + super(CategoryChoiceDialog, self).__init__(parent) + + self.setupUi(self) + self.mainwindow = mainwindow + self.scene = scene + + self.lineEdit_group.setValidator(QtGui.QIntValidator(0, 1000)) + + self.listWidget.itemClicked.connect(self.get_category) + self.pushButton_apply.clicked.connect(self.apply) + self.pushButton_cache.clicked.connect(self.cache) + + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) + + def load_cfg(self): + self.listWidget.clear() + + labels = self.mainwindow.cfg.get('label', []) + + for label in labels: + name = label.get('name', 'UNKNOW') + color = label.get('color', '#000000') + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(200, 30)) + widget = QtWidgets.QWidget() + + layout = QtWidgets.QHBoxLayout() + layout.setContentsMargins(9, 1, 9, 1) + label_category = QtWidgets.QLabel() + label_category.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + label_category.setText(name) + label_category.setObjectName('label_category') + + label_color = QtWidgets.QLabel() + label_color.setFixedWidth(10) + label_color.setStyleSheet("background-color: {};".format(color)) + label_color.setObjectName('label_color') + + layout.addWidget(label_color) + layout.addWidget(label_category) + widget.setLayout(layout) + + self.listWidget.addItem(item) + self.listWidget.setItemWidget(item, widget) + + self.lineEdit_group.clear() + self.lineEdit_category.clear() + self.checkBox_iscrowded.setCheckState(False) + self.label_layer.setText('{}'.format(len(self.mainwindow.polygons)+1)) + + if self.listWidget.count() == 0: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Please set categorys before tagging.') + + def get_category(self, item): + widget = self.listWidget.itemWidget(item) + label_category = widget.findChild(QtWidgets.QLabel, 'label_category') + self.lineEdit_category.setText(label_category.text()) + self.lineEdit_category.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + + def apply(self): + category = self.lineEdit_category.text() + group = self.lineEdit_group.text() + is_crowd = int(self.checkBox_iscrowded.isChecked()) + note = self.lineEdit_note.text() + if not category: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Please select one category before submitting.') + return + + # 设置polygon 属性 + self.scene.current_graph.set_drawed(category, group, is_crowd, note, + QtGui.QColor(self.mainwindow.category_color_dict[category]), self.scene.top_layer) + # 添加新polygon + self.mainwindow.polygons.append(self.scene.current_graph) + # 设置为最高图层 + self.scene.current_graph.setZValue(len(self.mainwindow.polygons)) + for vertex in self.scene.current_graph.vertexs: + vertex.setZValue(len(self.mainwindow.polygons)) + + self.mainwindow.labels_dock_widget.update_listwidget() + + self.scene.current_graph = None + self.scene.change_mode_to_view() + self.close() + + def cache(self): + self.scene.cancel_draw() + self.close() + + def closeEvent(self, a0: QtGui.QCloseEvent): + self.cache() + + def reject(self): + self.cache() diff --git a/widgets/category_edit_dialog.py b/widgets/category_edit_dialog.py new file mode 100644 index 0000000..1824b65 --- /dev/null +++ b/widgets/category_edit_dialog.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# @Author : LG + + +from ui.category_choice import Ui_Dialog +from PyQt5 import QtWidgets, QtGui, QtCore +from configs import load_config, CONFIG_FILE, DEFAULT_CONFIG_FILE +import os + + +class CategoryEditDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent, mainwindow, scene): + super(CategoryEditDialog, self).__init__(parent) + + self.setupUi(self) + self.mainwindow = mainwindow + self.scene = scene + self.polygon = None + + self.lineEdit_group.setValidator(QtGui.QIntValidator(0,1000)) + + self.listWidget.itemClicked.connect(self.get_category) + self.pushButton_apply.clicked.connect(self.apply) + self.pushButton_cache.clicked.connect(self.cache) + + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) + + def load_cfg(self): + self.listWidget.clear() + + labels = self.mainwindow.cfg.get('label', []) + + for label in labels: + name = label.get('name', 'UNKNOW') + color = label.get('color', '#000000') + # item = QtWidgets.QListWidgetItem() + # item.setText(name) + # item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + # self.listWidget.addItem(item) + + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(200, 30)) + widget = QtWidgets.QWidget() + + layout = QtWidgets.QHBoxLayout() + layout.setContentsMargins(9, 1, 9, 1) + label_category = QtWidgets.QLabel() + label_category.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + label_category.setText(name) + label_category.setObjectName('label_category') + + label_color = QtWidgets.QLabel() + label_color.setFixedWidth(10) + label_color.setStyleSheet("background-color: {};".format(color)) + label_color.setObjectName('label_color') + + layout.addWidget(label_color) + layout.addWidget(label_category) + widget.setLayout(layout) + + self.listWidget.addItem(item) + self.listWidget.setItemWidget(item, widget) + + if self.polygon is not None and self.polygon.category == name: + self.listWidget.setCurrentItem(item) + + if self.polygon is None: + self.lineEdit_group.clear() + self.lineEdit_category.clear() + self.checkBox_iscrowded.setCheckState(False) + self.lineEdit_note.clear() + self.label_layer.setText('{}'.format('')) + else: + self.lineEdit_category.setText('{}'.format(self.polygon.category)) + self.lineEdit_category.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.lineEdit_group.setText('{}'.format(self.polygon.group)) + iscrowd = QtCore.Qt.CheckState.Checked if self.polygon.iscrowd == 1 else QtCore.Qt.CheckState.Unchecked + self.checkBox_iscrowded.setCheckState(iscrowd) + self.lineEdit_note.setText('{}'.format(self.polygon.note)) + self.label_layer.setText('{}'.format(self.polygon.zValue())) + if self.listWidget.count() == 0: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Please set categorys before tagging.') + + def get_category(self, item): + widget = self.listWidget.itemWidget(item) + label_category = widget.findChild(QtWidgets.QLabel, 'label_category') + self.lineEdit_category.setText(label_category.text()) + self.lineEdit_category.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + + def apply(self): + category = self.lineEdit_category.text() + group = self.lineEdit_group.text() + is_crowd = int(self.checkBox_iscrowded.isChecked()) + note = self.lineEdit_note.text() + if not category: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Please select one category before submitting.') + return + + # 设置polygon 属性 + self.polygon.set_drawed(category, group, is_crowd, note, + QtGui.QColor(self.mainwindow.category_color_dict.get(category, '#000000'))) + self.mainwindow.labels_dock_widget.update_listwidget() + + self.polygon = None + self.scene.change_mode_to_view() + self.close() + + def cache(self): + self.scene.cancel_draw() + self.close() + + def closeEvent(self, a0: QtGui.QCloseEvent): + self.cache() + + def reject(self): + self.cache() diff --git a/widgets/converter.py b/widgets/converter.py new file mode 100644 index 0000000..cffdd37 --- /dev/null +++ b/widgets/converter.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.convert_dialog import Ui_Dialog +from tools.label_convert import Converter +import os + + +class ConvertDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent, mainwindow): + super(ConvertDialog, self).__init__(parent) + self.setupUi(self) + self.mainwindow = mainwindow + self.label_root = None + self.save_root = None + self.pause = False + + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) + + self.init_connect() + + def reset_gui(self): + self.widget_process.setVisible(False) + self.lineEdit_label_root.clear() + self.lineEdit_save_root.clear() + + def _label_root(self): + dir = QtWidgets.QFileDialog.getExistingDirectory(self) + if dir: + self.label_root = dir + self.lineEdit_label_root.setText(dir) + else: + self.lineEdit_label_root.clear() + + def _save_root(self): + dir = QtWidgets.QFileDialog.getExistingDirectory(self) + if dir: + self.save_root = dir + self.lineEdit_save_root.setText(dir) + else: + self.lineEdit_save_root.clear() + + def cache(self): + self.pause = True + self.close() + + def apply(self): + self.pause = False + if self.label_root is None or self.save_root is None: + return + # 语义分割,保存类别文件 + if not self.checkBox_is_instance.isChecked(): + with open(os.path.join(self.save_root, 'classesition.txt'), 'w') as f: + for index, label in enumerate(self.mainwindow.cfg.get('label', [])): + f.write('{} {}\n'.format(label.get('name'), index)) + + converter = Converter(self.mainwindow.cfg, self.checkBox_is_instance.isChecked()) + jsons = [f for f in os.listdir(self.label_root) if f.endswith('.json')] + + self.pushButton_label_root.setEnabled(False) + self.pushButton_save_root.setEnabled(False) + self.checkBox_is_instance.setEnabled(False) + + self.widget_process.setVisible(True) + self.progressBar.setMaximum(len(jsons)) + self.all_num.setText('{}'.format(len(jsons))) + + for index, json in enumerate(jsons): + if self.pause: + break + label_path = os.path.join(self.label_root, json) + save_path = os.path.join(self.save_root, json[:-5]+'.png') + converter.convert(label_path, save_path) + self.progressBar.setValue(index+1) + self.current_num.setText('{}'.format(index+1)) + + self.pushButton_label_root.setEnabled(True) + self.pushButton_save_root.setEnabled(True) + self.checkBox_is_instance.setEnabled(True) + + def init_connect(self): + self.pushButton_label_root.clicked.connect(self._label_root) + self.pushButton_save_root.clicked.connect(self._save_root) + self.pushButton_apply.clicked.connect(self.apply) + self.pushButton_cache.clicked.connect(self.cache) \ No newline at end of file diff --git a/widgets/files_dock_widget.py b/widgets/files_dock_widget.py new file mode 100644 index 0000000..81352a0 --- /dev/null +++ b/widgets/files_dock_widget.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.file_dock import Ui_Form +import os + + +class FilesDockWidget(QtWidgets.QWidget, Ui_Form): + def __init__(self, mainwindow): + super(FilesDockWidget, self).__init__() + self.setupUi(self) + self.mainwindow = mainwindow + self.listWidget.clicked.connect(self.listwidget_doubleclick) + self.lineEdit_jump.returnPressed.connect(self.mainwindow.jump_to) + + def update_widget(self): + self.listWidget.clear() + if self.mainwindow.files_list is None: + return + + for file_path in self.mainwindow.files_list: + _, file_name = os.path.split(file_path) + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(200, 30)) + + item.setText(file_name) + self.listWidget.addItem(item) + + self.label_all.setText('{}'.format(len(self.mainwindow.files_list))) + + def set_select(self, row): + self.listWidget.setCurrentRow(row) + + def listwidget_doubleclick(self): + row = self.listWidget.currentRow() + self.mainwindow.show_image(row) diff --git a/widgets/info_dock_widget.py b/widgets/info_dock_widget.py new file mode 100644 index 0000000..f5b66e5 --- /dev/null +++ b/widgets/info_dock_widget.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.info_dock import Ui_Form + +class InfoDockWidget(QtWidgets.QWidget, Ui_Form): + def __init__(self, mainwindow): + super(InfoDockWidget, self).__init__() + self.setupUi(self) + self.mainwindow = mainwindow + + self.lineEdit_note.textChanged.connect(self.note_changed) + + def note_changed(self): + if self.mainwindow.load_finished: + self.mainwindow.set_saved_state(False) + + def update_widget(self): + if self.mainwindow.current_label is not None: + self.label_width.setText('{}'.format(self.mainwindow.current_label.width)) + self.label_height.setText('{}'.format(self.mainwindow.current_label.height)) + self.label_depth.setText('{}'.format(self.mainwindow.current_label.depth)) + self.lineEdit_note.setText(self.mainwindow.current_label.note) diff --git a/widgets/labels_dock_widget.py b/widgets/labels_dock_widget.py new file mode 100644 index 0000000..d2a0258 --- /dev/null +++ b/widgets/labels_dock_widget.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.label_dock import Ui_Form +import functools + + +class LabelsDockWidget(QtWidgets.QWidget, Ui_Form): + def __init__(self, mainwindow): + super(LabelsDockWidget, self).__init__() + self.setupUi(self) + self.mainwindow = mainwindow + self.polygon_item_dict = {} + + self.listWidget.itemSelectionChanged.connect(self.set_polygon_selected) + + self.listWidget.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) + self.listWidget.customContextMenuRequested.connect( + self.right_button_menu) + + def right_button_menu(self, point): + self.mainwindow.right_button_menu.exec_(self.listWidget.mapToGlobal(point)) + + def generate_item_and_itemwidget(self, polygon): + color = self.mainwindow.category_color_dict.get(polygon.category, '#000000') + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(200, 30)) + item_widget = QtWidgets.QWidget() + layout = QtWidgets.QHBoxLayout() + layout.setContentsMargins(9, 1, 9, 1) + check_box = QtWidgets.QCheckBox() + check_box.setFixedWidth(20) + check_box.setChecked(polygon.isVisible()) + check_box.stateChanged.connect(functools.partial(self.set_polygon_show, polygon)) + layout.addWidget(check_box) + + label_color = QtWidgets.QLabel() + label_color.setFixedWidth(10) + label_color.setStyleSheet("background-color: {};".format(color)) + layout.addWidget(label_color) + + category = QtWidgets.QLabel(polygon.category) + + group = QtWidgets.QLabel('{}'.format(polygon.group)) + + note = QtWidgets.QLabel('{}'.format(polygon.note)) + + label_iscrowd = QtWidgets.QLabel() + label_iscrowd.setFixedWidth(3) + if polygon.iscrowd == 1: + label_iscrowd.setStyleSheet("background-color: {};".format('#000000')) + + layout.addWidget(category) + layout.addWidget(group) + layout.addWidget(note) + layout.addWidget(label_iscrowd, alignment=QtCore.Qt.AlignmentFlag.AlignRight) + + item_widget.setLayout(layout) + return item, item_widget + + def update_listwidget(self): + self.listWidget.clear() + self.polygon_item_dict.clear() + + for polygon in self.mainwindow.polygons: + item, item_widget = self.generate_item_and_itemwidget(polygon) + self.listWidget.addItem(item) + self.listWidget.setItemWidget(item, item_widget) + self.polygon_item_dict[polygon] = item + + if self.mainwindow.load_finished: + self.mainwindow.set_saved_state(False) + + def set_selected(self, polygon): + item = self.polygon_item_dict[polygon] + if polygon.isSelected(): + if not item.isSelected(): + item.setSelected(True) + if not polygon.isSelected(): + if item.isSelected(): + item.setSelected(False) + + def set_polygon_selected(self): + items = self.listWidget.selectedItems() + + have_selected = True if items else False + if have_selected: + self.mainwindow.scene.change_mode_to_edit() + else: + self.mainwindow.scene.change_mode_to_view() + + for index, polygon in enumerate(self.mainwindow.polygons): + if self.polygon_item_dict[polygon] in items: + if not polygon.isSelected(): + polygon.setSelected(True) + else: + if polygon.isSelected(): + polygon.setSelected(False) + + def set_polygon_show(self, polygon): + for vertex in polygon.vertexs: + vertex.setVisible(self.sender().checkState()) + polygon.setVisible(self.sender().checkState()) diff --git a/widgets/mainwindow.py b/widgets/mainwindow.py new file mode 100644 index 0000000..ccb8fef --- /dev/null +++ b/widgets/mainwindow.py @@ -0,0 +1,476 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.MainWindow import Ui_MainWindow +from widgets.setting_dialog import SettingDialog +from widgets.category_choice_dialog import CategoryChoiceDialog +from widgets.category_edit_dialog import CategoryEditDialog +from widgets.labels_dock_widget import LabelsDockWidget +from widgets.files_dock_widget import FilesDockWidget +from widgets.info_dock_widget import InfoDockWidget +from widgets.right_button_menu import RightButtonMenu +from widgets.shortcut_dialog import ShortcutDialog +from widgets.about_dialog import AboutDialog +from widgets.converter import ConvertDialog +from widgets.canvas import AnnotationScene, AnnotationView +from configs import STATUSMode, MAPMode, load_config, save_config, CONFIG_FILE, DEFAULT_CONFIG_FILE +from annotation import Object, Annotation +from widgets.polygon import Polygon +import os +from PIL import Image +import imgviz +from segment_any.segment_any import SegAny +import icons_rc + + +class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): + def __init__(self): + super(MainWindow, self).__init__() + self.setupUi(self) + self.init_ui() + self.image_root: str = None + self.label_root:str = None + + self.files_list: list = [] + self.current_index = None + self.current_file_index: int = None + + self.config_file = CONFIG_FILE if os.path.exists(CONFIG_FILE) else DEFAULT_CONFIG_FILE + self.saved = True + self.load_finished = False + self.polygons:list = [] + + self.png_palette = None # 图像拥有调色盘,说明是单通道的标注png文件 + self.instance_cmap = imgviz.label_colormap() + self.map_mode = MAPMode.LABEL + # 标注目标 + self.current_label:Annotation = None + + self.reload_cfg() + + self.init_connect() + self.reset_action() + self.init_segment_anything() + + def init_segment_anything(self): + if os.path.exists('./segment_any/sam_vit_h_4b8939.pth'): + self.statusbar.showMessage('Find the checkpoint named {}.'.format('sam_vit_h_4b8939.pth')) + self.segany = SegAny('./segment_any/sam_vit_h_4b8939.pth') + self.use_segment_anything = True + elif os.path.exists('./segment_any/sam_vit_l_0b3195.pth'): + self.statusbar.showMessage('Find the checkpoint named {}.'.format('sam_vit_l_0b3195.pth')) + self.segany = SegAny('./segment_any/sam_vit_l_0b3195.pth') + self.use_segment_anything = True + elif os.path.exists('./segment_any/sam_vit_b_01ec64.pth'): + self.statusbar.showMessage('Find the checkpoint named {}.'.format('sam_vit_b_01ec64.pth')) + self.segany = SegAny('./segment_any/sam_vit_b_01ec64.pth') + self.use_segment_anything = True + self.statusbar.showMessage() + else: + QtWidgets.QMessageBox.warning(self, 'Warning', 'The checkpoint of [Segment anything] not existed. If you want use quick annotate, please download from {}'.format('https://github.com/facebookresearch/segment-anything#model-checkpoints')) + self.use_segment_anything = False + + def init_ui(self): + self.setting_dialog = SettingDialog(parent=self, mainwindow=self) + + self.labels_dock_widget = LabelsDockWidget(mainwindow=self) + self.labels_dock.setWidget(self.labels_dock_widget) + + self.files_dock_widget = FilesDockWidget(mainwindow=self) + self.files_dock.setWidget(self.files_dock_widget) + + self.info_dock_widget = InfoDockWidget(mainwindow=self) + self.info_dock.setWidget(self.info_dock_widget) + + self.scene = AnnotationScene(mainwindow=self) + self.category_choice_widget = CategoryChoiceDialog(self, mainwindow=self, scene=self.scene) + self.category_edit_widget = CategoryEditDialog(self, self, self.scene) + + self.convert_dialog = ConvertDialog(self, mainwindow=self) + + self.view = AnnotationView(parent=self) + self.view.setScene(self.scene) + self.setCentralWidget(self.view) + + self.right_button_menu = RightButtonMenu(mainwindow=self) + self.right_button_menu.addAction(self.actionEdit) + self.right_button_menu.addAction(self.actionTo_top) + self.right_button_menu.addAction(self.actionTo_bottom) + + self.shortcut_dialog = ShortcutDialog(self) + self.about_dialog = AboutDialog(self) + + self.labelCoordinates = QtWidgets.QLabel('') + self.statusbar.addPermanentWidget(self.labelCoordinates) + + self.trans = QtCore.QTranslator() + + def translate(self, language='zh'): + if language == 'zh': + self.trans.load('ui/zh_CN') + else: + self.trans.load('ui/en') + self.actionChinese.setChecked(language=='zh') + self.actionEnglish.setChecked(language=='en') + _app = QtWidgets.QApplication.instance() + _app.installTranslator(self.trans) + self.retranslateUi(self) + self.info_dock_widget.retranslateUi(self.info_dock_widget) + self.labels_dock_widget.retranslateUi(self.labels_dock_widget) + self.files_dock_widget.retranslateUi(self.files_dock_widget) + self.category_choice_widget.retranslateUi(self.category_choice_widget) + self.category_edit_widget.retranslateUi(self.category_edit_widget) + self.setting_dialog.retranslateUi(self.setting_dialog) + self.about_dialog.retranslateUi(self.about_dialog) + self.shortcut_dialog.retranslateUi(self.shortcut_dialog) + self.convert_dialog.retranslateUi(self.convert_dialog) + + def translate_to_chinese(self): + self.translate('zh') + self.cfg['language'] = 'zh' + + def translate_to_english(self): + self.translate('en') + self.cfg['language'] = 'en' + + def reload_cfg(self): + self.cfg = load_config(self.config_file) + label_dict_list = self.cfg.get('label', []) + d = {} + for label_dict in label_dict_list: + category = label_dict.get('name', 'unknow') + color = label_dict.get('color', '#000000') + d[category] = color + self.category_color_dict = d + + if self.current_index is not None: + self.show_image(self.current_index) + + language = self.cfg.get('language', 'en') + self.translate(language) + + def set_saved_state(self, is_saved:bool): + self.saved = is_saved + if self.files_list is not None and self.current_index is not None: + + if is_saved: + self.setWindowTitle(self.current_label.label_path) + else: + self.setWindowTitle('*{}'.format(self.current_label.label_path)) + + def open_dir(self): + dir = QtWidgets.QFileDialog.getExistingDirectory(self) + if dir: + self.files_list.clear() + self.files_dock_widget.listWidget.clear() + + files = [] + suffixs = tuple(['{}'.format(fmt.data().decode('ascii').lower()) for fmt in QtGui.QImageReader.supportedImageFormats()]) + for f in os.listdir(dir): + if f.lower().endswith(suffixs): + # f = os.path.join(dir, f) + files.append(f) + files = sorted(files) + self.files_list = files + + self.files_dock_widget.update_widget() + + self.current_index = 0 + + self.image_root = dir + self.actionOpen_dir.setStatusTip("Image root: {}".format(self.image_root)) + if self.label_root is None: + self.label_root = dir + self.actionSave_dir.setStatusTip("Label root: {}".format(self.label_root)) + + self.show_image(self.current_index) + + def save_dir(self): + dir = QtWidgets.QFileDialog.getExistingDirectory(self) + if dir: + self.label_root = dir + self.actionSave_dir.setStatusTip("Label root: {}".format(self.label_root)) + + # 刷新图片 + if self.current_index is not None: + self.show_image(self.current_index) + + def save(self): + if self.current_label is None: + return + self.current_label.objects.clear() + for polygon in self.polygons: + object = polygon.to_object() + self.current_label.objects.append(object) + + self.current_label.note = self.info_dock_widget.lineEdit_note.text() + self.current_label.save_annotation() + self.set_saved_state(True) + + def show_image(self, index:int): + self.reset_action() + self.current_label = None + self.load_finished = False + self.saved = True + if not -1 < index < len(self.files_list): + self.scene.clear() + self.scene.setSceneRect(QtCore.QRectF()) + return + try: + self.polygons.clear() + self.labels_dock_widget.listWidget.clear() + self.scene.cancel_draw() + file_path = os.path.join(self.image_root, self.files_list[index]) + image_data = Image.open(file_path) + + self.png_palette = image_data.getpalette() + if self.png_palette is not None: + self.statusbar.showMessage('This is a label file.') + self.actionSegment_anything.setEnabled(False) + self.actionPolygon.setEnabled(False) + self.actionSave.setEnabled(False) + self.actionBit_map.setEnabled(False) + else: + self.actionSegment_anything.setEnabled(self.use_segment_anything) + self.actionPolygon.setEnabled(True) + self.actionSave.setEnabled(True) + self.actionBit_map.setEnabled(True) + self.scene.load_image(file_path) + self.view.zoomfit() + + # load label + if self.png_palette is None: + _, name = os.path.split(file_path) + label_path = os.path.join(self.label_root, '.'.join(name.split('.')[:-1]) + '.json') + self.current_label = Annotation(file_path, label_path) + # 载入数据 + self.current_label.load_annotation() + + for object in self.current_label.objects: + polygon = Polygon() + self.scene.addItem(polygon) + polygon.load_object(object) + self.polygons.append(polygon) + + if self.current_label is not None: + self.setWindowTitle('{}'.format(self.current_label.label_path)) + else: + self.setWindowTitle('{}'.format(file_path)) + + self.labels_dock_widget.update_listwidget() + self.info_dock_widget.update_widget() + self.files_dock_widget.set_select(index) + self.current_index = index + self.files_dock_widget.label_current.setText('{}'.format(self.current_index+1)) + self.load_finished = True + + except Exception as e: + print(e) + finally: + if self.current_index > 0: + self.actionPrev.setEnabled(True) + else: + self.actionPrev.setEnabled(False) + + if self.current_index < len(self.files_list) - 1: + self.actionNext.setEnabled(True) + else: + self.actionNext.setEnabled(False) + + def prev_image(self): + if self.scene.mode != STATUSMode.VIEW: + return + if self.current_index is None: + return + if not self.saved: + result = QtWidgets.QMessageBox.question(self, 'Warning', 'Proceed without saved?', QtWidgets.QMessageBox.StandardButton.Yes|QtWidgets.QMessageBox.StandardButton.No, QtWidgets.QMessageBox.StandardButton.No) + if result == QtWidgets.QMessageBox.StandardButton.No: + return + self.current_index = self.current_index - 1 + if self.current_index < 0: + self.current_index = 0 + QtWidgets.QMessageBox.warning(self, 'Warning', 'This is the first picture.') + else: + self.show_image(self.current_index) + + def next_image(self): + if self.scene.mode != STATUSMode.VIEW: + return + if self.current_index is None: + return + if not self.saved: + result = QtWidgets.QMessageBox.question(self, 'Warning', 'Proceed without saved?', QtWidgets.QMessageBox.StandardButton.Yes|QtWidgets.QMessageBox.StandardButton.No, QtWidgets.QMessageBox.StandardButton.No) + if result == QtWidgets.QMessageBox.StandardButton.No: + return + self.current_index = self.current_index + 1 + if self.current_index > len(self.files_list)-1: + self.current_index = len(self.files_list)-1 + QtWidgets.QMessageBox.warning(self, 'Warning', 'This is the last picture.') + else: + self.show_image(self.current_index) + + def jump_to(self): + index = self.files_dock_widget.lineEdit_jump.text() + if index: + if not index.isdigit(): + if index in self.files_list: + index = self.files_list.index(index)+1 + else: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Don`t exist image named: {}'.format(index)) + self.files_dock_widget.lineEdit_jump.clear() + return + index = int(index)-1 + if 0 <= index < len(self.files_list): + self.show_image(index) + self.files_dock_widget.lineEdit_jump.clear() + else: + QtWidgets.QMessageBox.warning(self, 'Warning', 'Index must be in [1, {}].'.format(len(self.files_list))) + self.files_dock_widget.lineEdit_jump.clear() + self.files_dock_widget.lineEdit_jump.clearFocus() + return + + def cancel_draw(self): + self.scene.cancel_draw() + + def setting(self): + self.setting_dialog.load_cfg() + self.setting_dialog.show() + + def add_new_object(self, category, group, segmentation, area, layer, bbox): + if self.current_label is None: + return + object = Object(category=category, group=group, segmentation=segmentation, area=area, layer=layer, bbox=bbox) + self.current_label.objects.append(object) + + def delete_object(self, index:int): + if 0 <= index < len(self.current_label.objects): + del self.current_label.objects[index] + + def change_bit_map(self): + if self.scene.mode == STATUSMode.CREATE: + self.scene.cancel_draw() + if self.map_mode == MAPMode.LABEL: + # to semantic + for polygon in self.polygons: + polygon.setEnabled(False) + for vertex in polygon.vertexs: + vertex.setVisible(False) + polygon.change_color(QtGui.QColor(self.category_color_dict.get(polygon.category, '#000000'))) + polygon.color.setAlpha(255) + polygon.setBrush(polygon.color) + self.labels_dock_widget.listWidget.setEnabled(False) + self.actionSegment_anything.setEnabled(False) + self.actionPolygon.setEnabled(False) + self.map_mode = MAPMode.SEMANTIC + semantic_icon = QtGui.QIcon() + semantic_icon.addPixmap(QtGui.QPixmap(":/icon/icons/semantic.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionBit_map.setIcon(semantic_icon) + + elif self.map_mode == MAPMode.SEMANTIC: + # to instance + for polygon in self.polygons: + polygon.setEnabled(False) + for vertex in polygon.vertexs: + vertex.setVisible(False) + if polygon.group != '': + rgb = self.instance_cmap[int(polygon.group)] + else: + rgb = self.instance_cmap[0] + polygon.change_color(QtGui.QColor(rgb[0], rgb[1], rgb[2], 255)) + polygon.color.setAlpha(255) + polygon.setBrush(polygon.color) + self.labels_dock_widget.listWidget.setEnabled(False) + self.actionSegment_anything.setEnabled(False) + self.actionPolygon.setEnabled(False) + self.map_mode = MAPMode.INSTANCE + instance_icon = QtGui.QIcon() + instance_icon.addPixmap(QtGui.QPixmap(":/icon/icons/instance.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionBit_map.setIcon(instance_icon) + + elif self.map_mode == MAPMode.INSTANCE: + # to label + for polygon in self.polygons: + polygon.setEnabled(True) + for vertex in polygon.vertexs: + # vertex.setEnabled(True) + vertex.setVisible(polygon.isVisible()) + polygon.change_color(QtGui.QColor(self.category_color_dict.get(polygon.category, '#000000'))) + polygon.color.setAlpha(polygon.nohover_alpha) + polygon.setBrush(polygon.color) + self.labels_dock_widget.listWidget.setEnabled(True) + self.actionSegment_anything.setEnabled(self.use_segment_anything) + self.actionPolygon.setEnabled(True) + self.map_mode = MAPMode.LABEL + label_icon = QtGui.QIcon() + label_icon.addPixmap(QtGui.QPixmap(":/icon/icons/照片_pic.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionBit_map.setIcon(label_icon) + else: + pass + + def label_converter(self): + self.convert_dialog.reset_gui() + self.convert_dialog.show() + + def help(self): + self.shortcut_dialog.show() + + def about(self): + self.about_dialog.show() + + def save_cfg(self, config_file): + save_config(self.cfg, config_file) + + def exit(self): + self.save_cfg(self.config_file) + self.close() + + def closeEvent(self, a0: QtGui.QCloseEvent): + self.exit() + + def init_connect(self): + self.actionOpen_dir.triggered.connect(self.open_dir) + self.actionSave_dir.triggered.connect(self.save_dir) + self.actionPrev.triggered.connect(self.prev_image) + self.actionNext.triggered.connect(self.next_image) + self.actionSetting.triggered.connect(self.setting) + self.actionExit.triggered.connect(self.exit) + + self.actionSegment_anything.triggered.connect(self.scene.start_segment_anything) + self.actionPolygon.triggered.connect(self.scene.start_draw_polygon) + self.actionCancel.triggered.connect(self.scene.cancel_draw) + self.actionBackspace.triggered.connect(self.scene.backspace) + self.actionFinish.triggered.connect(self.scene.finish_draw) + self.actionEdit.triggered.connect(self.scene.edit_polygon) + self.actionDelete.triggered.connect(self.scene.delete_selected_graph) + self.actionSave.triggered.connect(self.save) + self.actionTo_top.triggered.connect(self.scene.move_polygon_to_top) + self.actionTo_bottom.triggered.connect(self.scene.move_polygon_to_bottom) + + self.actionZoom_in.triggered.connect(self.view.zoom_in) + self.actionZoom_out.triggered.connect(self.view.zoom_out) + self.actionFit_wiondow.triggered.connect(self.view.zoomfit) + self.actionBit_map.triggered.connect(self.change_bit_map) + + self.actionConverter.triggered.connect(self.label_converter) + + self.actionShortcut.triggered.connect(self.help) + self.actionAbout.triggered.connect(self.about) + + self.actionChinese.triggered.connect(self.translate_to_chinese) + self.actionEnglish.triggered.connect(self.translate_to_english) + + self.labels_dock_widget.listWidget.doubleClicked.connect(self.scene.edit_polygon) + + def reset_action(self): + self.actionPrev.setEnabled(False) + self.actionNext.setEnabled(False) + self.actionSegment_anything.setEnabled(False) + self.actionPolygon.setEnabled(False) + self.actionEdit.setEnabled(False) + self.actionDelete.setEnabled(False) + self.actionSave.setEnabled(False) + self.actionTo_top.setEnabled(False) + self.actionTo_bottom.setEnabled(False) + self.actionBit_map.setChecked(False) + self.actionBit_map.setEnabled(False) diff --git a/widgets/polygon.py b/widgets/polygon.py new file mode 100644 index 0000000..ce52041 --- /dev/null +++ b/widgets/polygon.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtCore, QtWidgets, QtGui +from annotation import Object +import typing + +class Vertex(QtWidgets.QGraphicsPathItem): + def __init__(self, polygon, index, color): + super(Vertex, self).__init__() + self.polygon = polygon + self.index = index + self.color = color + + self.hover_size = 3 + self.nohover_size = 2 + self.line_width = 0 + + self.nohover = QtGui.QPainterPath() + self.nohover.addEllipse(QtCore.QRectF(-self.nohover_size//2, -self.nohover_size//2, self.nohover_size, self.nohover_size)) + self.hover = QtGui.QPainterPath() + self.hover.addEllipse(QtCore.QRectF(-self.hover_size//2, -self.hover_size//2, self.hover_size, self.hover_size)) + + self.setPath(self.nohover) + self.setBrush(self.color) + self.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.PointingHandCursor)) + self.setPen(QtGui.QPen(self.color, self.line_width)) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges, True) + self.setAcceptHoverEvents(True) + self.setZValue(1e5) + + def itemChange(self, change: 'QtWidgets.QGraphicsItem.GraphicsItemChange', value: typing.Any): + + if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemPositionChange and self.isEnabled(): + # 限制顶点移动到图外 + if value.x() < 0: + value.setX(0) + if value.x() > self.scene().width(): + value.setX(self.scene().width()) + if value.y() < 0: + value.setY(0) + if value.y() > self.scene().height(): + value.setY(self.scene().height()) + + self.polygon.movePoint(self.index, value) + + return super(Vertex, self).itemChange(change, value) + + def hoverEnterEvent(self, event: 'QGraphicsSceneHoverEvent'): + self.setPath(self.hover) + super(Vertex, self).hoverEnterEvent(event) + + def hoverLeaveEvent(self, event: 'QGraphicsSceneHoverEvent'): + self.setPath(self.nohover) + super(Vertex, self).hoverLeaveEvent(event) + + +class Polygon(QtWidgets.QGraphicsPolygonItem): + def __init__(self): + super(Polygon, self).__init__(parent=None) + self.line_width = 0 + self.hover_alpha = 150 + self.nohover_alpha = 80 + self.points = [] + self.vertexs = [] + self.category = '' + self.group = 0 + self.iscrowd = 0 + self.note = '' + + self.rxmin, self.rxmax, self.rymin, self.rymax = 0, 0, 0, 0 # 用于绘画完成后,记录多边形的各边界,此处与points对应 + self.color = QtGui.QColor('#ff0000') + self.is_drawing = True + + self.setPen(QtGui.QPen(self.color, self.line_width)) + self.setBrush(QtGui.QBrush(self.color, QtCore.Qt.BrushStyle.FDiagPattern)) + + self.setAcceptHoverEvents(True) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True) + self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges, True) + self.setZValue(1e5) + + def addPoint(self, point): + self.points.append(point) + vertex = Vertex(self, len(self.points)-1, self.color) + # 添加路径点 + self.scene().addItem(vertex) + self.vertexs.append(vertex) + vertex.setPos(point) + + def movePoint(self, index, point): + if not 0 <= index < len(self.points): + return + self.points[index] = self.mapFromScene(point) + + self.redraw() + if self.scene().mainwindow.load_finished and not self.is_drawing: + self.scene().mainwindow.set_saved_state(False) + + def removePoint(self, index): + if not self.points: + return + self.points.pop(index) + vertex = self.vertexs.pop(index) + self.scene().removeItem(vertex) + del vertex + self.redraw() + + def delete(self): + self.points.clear() + while self.vertexs: + vertex = self.vertexs.pop() + self.scene().removeItem(vertex) + del vertex + + def moveVertex(self, index, point): + if not 0 <= index < len(self.vertexs): + return + vertex = self.vertexs[index] + vertex.setEnabled(False) + vertex.setPos(point) + vertex.setEnabled(True) + + def itemChange(self, change: 'QGraphicsItem.GraphicsItemChange', value: typing.Any): + if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemSelectedHasChanged and not self.is_drawing: # 选中改变 + if self.isSelected(): + color = QtGui.QColor('#00A0FF') + color.setAlpha(self.hover_alpha) + self.setBrush(color) + else: + self.color.setAlpha(self.nohover_alpha) + self.setBrush(self.color) + self.scene().mainwindow.labels_dock_widget.set_selected(self) # 更新label面板 + + if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemPositionChange: # ItemPositionHasChanged + bias = value + l, t, b, r = self.boundingRect().left(), self.boundingRect().top(), self.boundingRect().bottom(), self.boundingRect().right() + if l + bias.x() < 0: bias.setX(-l) + if r + bias.x() > self.scene().width(): bias.setX(self.scene().width()-r) + if t + bias.y() < 0: bias.setY(-t) + if b + bias.y() > self.scene().height(): bias.setY(self.scene().height()-b) + + for index, point in enumerate(self.points): + self.moveVertex(index, point+bias) + + if self.scene().mainwindow.load_finished and not self.is_drawing: + self.scene().mainwindow.set_saved_state(False) + + return super(Polygon, self).itemChange(change, value) + + def hoverEnterEvent(self, event: 'QGraphicsSceneHoverEvent'): + if not self.is_drawing: + self.color.setAlpha(self.hover_alpha) + self.setBrush(self.color) + super(Polygon, self).hoverEnterEvent(event) + + def hoverLeaveEvent(self, event: 'QGraphicsSceneHoverEvent'): + if not self.is_drawing: + self.color.setAlpha(self.nohover_alpha) + self.setBrush(self.color) + super(Polygon, self).hoverEnterEvent(event) + + def mouseDoubleClickEvent(self, event: 'QGraphicsSceneMouseEvent'): + if event.button() == QtCore.Qt.MouseButton.LeftButton: + self.scene().mainwindow.category_edit_widget.polygon = self + self.scene().mainwindow.category_edit_widget.load_cfg() + self.scene().mainwindow.category_edit_widget.show() + + def redraw(self): + if len(self.points) < 1: + return + xs = [p.x() for p in self.points] + ys = [p.y() for p in self.points] + self.rxmin, self.rymin, self.rxmax, self.rymax = min(xs), min(ys), max(xs), max(ys) + self.setPolygon(QtGui.QPolygonF(self.points)) + + def change_color(self, color): + self.color = color + self.color.setAlpha(self.nohover_alpha) + self.setPen(QtGui.QPen(self.color, self.line_width)) + self.setBrush(self.color) + for vertex in self.vertexs: + vertex_color = self.color + vertex_color.setAlpha(255) + vertex.setPen(QtGui.QPen(vertex_color, self.line_width)) + vertex.setBrush(vertex_color) + + def set_drawed(self, category, group, iscrowd, note, color:QtGui.QColor, layer=None): + self.is_drawing = False + self.category = category + self.group = group + self.iscrowd = iscrowd + self.note = note + + self.color = color + self.color.setAlpha(self.nohover_alpha) + self.setPen(QtGui.QPen(self.color, self.line_width)) + self.setBrush(self.color) + if layer is not None: + self.setZValue(layer) + for vertex in self.vertexs: + vertex_color = self.color + vertex_color.setAlpha(255) + vertex.setPen(QtGui.QPen(vertex_color, self.line_width)) + vertex.setBrush(vertex_color) + if layer is not None: + vertex.setZValue(layer) + + def calculate_area(self): + area = 0 + num_points = len(self.points) + for i in range(num_points): + p1 = self.points[i] + p2 = self.points[(i + 1) % num_points] + d = p1.x() * p2.y() - p2.x() * p1.y() + area += d + return abs(area) / 2 + + def load_object(self, object): + segmentation = object.segmentation + for x, y in segmentation: + point = QtCore.QPointF(x, y) + self.addPoint(point) + color = self.scene().mainwindow.category_color_dict.get(object.category, '#000000') + self.set_drawed(object.category, object.group, object.iscrowd, object.note, QtGui.QColor(color), object.layer) # ... + + def to_object(self): + if self.is_drawing: + return None + segmentation = [] + for point in self.points: + point = point + self.pos() + segmentation.append((round(point.x()), round(point.y()))) + xmin = self.boundingRect().x() + self.pos().x() + ymin = self.boundingRect().y() + self.pos().y() + xmax = xmin + self.boundingRect().width() + ymax = ymin + self.boundingRect().height() + + object = Object(self.category, group=self.group, segmentation=segmentation, + area=self.calculate_area(), layer=self.zValue(), bbox=(xmin, ymin, xmax, ymax), iscrowd=self.iscrowd, note=self.note) + return object diff --git a/widgets/process_dialog.py b/widgets/process_dialog.py new file mode 100644 index 0000000..91fdd19 --- /dev/null +++ b/widgets/process_dialog.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from ui.process_dialog import Ui_Dialog +from PyQt5 import QtGui, QtWidgets, QtCore + +class PorcessDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent): + super(PorcessDialog, self).__init__(parent) + self.setupUi(self) + diff --git a/widgets/right_button_menu.py b/widgets/right_button_menu.py new file mode 100644 index 0000000..3fed170 --- /dev/null +++ b/widgets/right_button_menu.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets + +class RightButtonMenu(QtWidgets.QMenu): + def __init__(self, mainwindow): + super(RightButtonMenu, self).__init__() + self.mainwindow = mainwindow + diff --git a/widgets/setting_dialog.py b/widgets/setting_dialog.py new file mode 100644 index 0000000..c27adfd --- /dev/null +++ b/widgets/setting_dialog.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from PyQt5 import QtWidgets, QtCore, QtGui +from ui.setting_dialog import Ui_Dialog +from configs import * +import os + + +class SettingDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent, mainwindow): + super(SettingDialog, self).__init__(parent) + self.mainwindow = mainwindow + self.setupUi(self) + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) + + self.init_connect() + + def get_item_and_widget(self, category, color: str): + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(200, 40)) + + widget = QtWidgets.QWidget() + layout = QtWidgets.QHBoxLayout() + category_label = QtWidgets.QLabel() + category_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + category_label.setText(category) + category_label.setObjectName('category') + # 颜色 + color_button = QtWidgets.QPushButton() + color_button.setStyleSheet('QWidget {background-color: %s}' % color) + color_button.setFixedWidth(50) + color_button.clicked.connect(self.edit_category_item_color) + color_button.setObjectName('color') + # 删除 + delete_button = QtWidgets.QPushButton() + delete_button.setText('delete') + delete_button.setFixedWidth(80) + delete_button.clicked.connect(self.remove_category_item) + + if category == '__background__': + color_button.setEnabled(False) + delete_button.setEnabled(False) + + layout.addWidget(category_label) + layout.addWidget(color_button) + layout.addWidget(delete_button) + widget.setLayout(layout) + return item, widget + + def edit_category_item_color(self): + button = self.sender() + color = QtWidgets.QColorDialog.getColor() + if color.isValid(): + button.setStyleSheet('QWidget {background-color: %s}' % (color.name())) + + def remove_category_item(self): + button = self.sender() + row = self.category_list_widget.indexAt(button.parent().pos()).row() + self.category_list_widget.takeItem(row) + + def load_cfg(self): + cfg = load_config(self.mainwindow.config_file) + self.category_list_widget.clear() + labels = cfg.get('label', []) + labels_key = [l.get('name') for l in labels] + + if '__background__' not in labels_key: + print(labels) + labels.insert(0, {'name': '__background__', 'color': '#000000'}) + + if labels is not None: + for label in labels: + item, item_widget = self.get_item_and_widget(label.get('name', ''), color=label.get('color', '#00ff00')) + self.category_list_widget.addItem(item) + self.category_list_widget.setItemWidget(item, item_widget) + + def add_new_category(self): + category = self.category_input.text() + color = self.color_button.palette().button().color().name() + if category: + item, item_widget = self.get_item_and_widget(category, color) + self.category_list_widget.addItem(item) + self.category_list_widget.setItemWidget(item, item_widget) + self.category_input.clear() + + def choice_color(self): + color = QtWidgets.QColorDialog.getColor() + if color.isValid(): + self.color_button.setStyleSheet('QWidget {background-color: %s}' % color.name()) + + def import_cfg(self): + file, _ = QtWidgets.QFileDialog.getOpenFileName(self, filter='Yaml File(*.yaml)') + if file: + self.mainwindow.config_file = file + self.mainwindow.actionSetting.setStatusTip("Config yaml: {}".format(file)) + self.mainwindow.reload_cfg() + self.load_cfg() + + def export_cfg(self): + file, _ = QtWidgets.QFileDialog.getSaveFileName(self, filter='Yaml File(*.yaml)') + if not file.endswith('.yaml'): + file += '.yaml' + if file: + self.mainwindow.save_cfg(file) + self.load_cfg() + + def apply(self): + cfg = {} + cfg['label'] = [] + for index in range(self.category_list_widget.count()): + item = self.category_list_widget.item(index) + widget = self.category_list_widget.itemWidget(item) + category_label = widget.findChild(QtWidgets.QLabel, 'category') + color_button = widget.findChild(QtWidgets.QPushButton, 'color') + cfg['label'].append( + {'name': category_label.text(), 'color': color_button.palette().button().color().name()}) + + save_config(cfg, self.mainwindow.config_file) + self.mainwindow.reload_cfg() + self.close() + + def cache(self): + self.close() + + def init_connect(self): + self.add_button.clicked.connect(self.add_new_category) + self.apply_button.clicked.connect(self.apply) + self.cache_button.clicked.connect(self.cache) + self.color_button.clicked.connect(self.choice_color) + self.pushButton_import.clicked.connect(self.import_cfg) + self.pushButton_export.clicked.connect(self.export_cfg) \ No newline at end of file diff --git a/widgets/shortcut_dialog.py b/widgets/shortcut_dialog.py new file mode 100644 index 0000000..78d0065 --- /dev/null +++ b/widgets/shortcut_dialog.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# @Author : LG + +from ui.shortcut_dialog import Ui_Dialog +from PyQt5 import QtGui, QtCore, QtWidgets + +class ShortcutDialog(QtWidgets.QDialog, Ui_Dialog): + def __init__(self, parent): + super(ShortcutDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowModality(QtCore.Qt.WindowModality.WindowModal) \ No newline at end of file