diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dcf18d2 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/data/images/train/1.jpg b/data/images/train/1.jpg new file mode 100644 index 0000000..8d4a196 Binary files /dev/null and b/data/images/train/1.jpg differ diff --git a/data/images/train/2.jpg b/data/images/train/2.jpg new file mode 100644 index 0000000..7e30450 Binary files /dev/null and b/data/images/train/2.jpg differ diff --git a/data/images/train/3.jpg b/data/images/train/3.jpg new file mode 100644 index 0000000..b08ad0e Binary files /dev/null and b/data/images/train/3.jpg differ diff --git a/data/images/train/4.jpg b/data/images/train/4.jpg new file mode 100644 index 0000000..119469c Binary files /dev/null and b/data/images/train/4.jpg differ diff --git a/data/images/train/5.jpg b/data/images/train/5.jpg new file mode 100644 index 0000000..cc3a01b Binary files /dev/null and b/data/images/train/5.jpg differ diff --git a/data/images/train/6.jpg b/data/images/train/6.jpg new file mode 100644 index 0000000..fbdc989 Binary files /dev/null and b/data/images/train/6.jpg differ diff --git a/data/images/train/7.jpg b/data/images/train/7.jpg new file mode 100644 index 0000000..25f094c Binary files /dev/null and b/data/images/train/7.jpg differ diff --git a/data/images/train/8.jpg b/data/images/train/8.jpg new file mode 100644 index 0000000..8719f96 Binary files /dev/null and b/data/images/train/8.jpg differ diff --git a/data/images/val/1.jpg b/data/images/val/1.jpg new file mode 100644 index 0000000..8d4a196 Binary files /dev/null and b/data/images/val/1.jpg differ diff --git a/data/images/val/2.jpg b/data/images/val/2.jpg new file mode 100644 index 0000000..7e30450 Binary files /dev/null and b/data/images/val/2.jpg differ diff --git a/data/images/val/3.jpg b/data/images/val/3.jpg new file mode 100644 index 0000000..b08ad0e Binary files /dev/null and b/data/images/val/3.jpg differ diff --git a/data/images/val/4.jpg b/data/images/val/4.jpg new file mode 100644 index 0000000..119469c Binary files /dev/null and b/data/images/val/4.jpg differ diff --git a/data/images/val/5.jpg b/data/images/val/5.jpg new file mode 100644 index 0000000..cc3a01b Binary files /dev/null and b/data/images/val/5.jpg differ diff --git a/data/images/val/6.jpg b/data/images/val/6.jpg new file mode 100644 index 0000000..fbdc989 Binary files /dev/null and b/data/images/val/6.jpg differ diff --git a/data/images/val/7.jpg b/data/images/val/7.jpg new file mode 100644 index 0000000..25f094c Binary files /dev/null and b/data/images/val/7.jpg differ diff --git a/data/images/val/8.jpg b/data/images/val/8.jpg new file mode 100644 index 0000000..8719f96 Binary files /dev/null and b/data/images/val/8.jpg differ diff --git a/data/labels/train.cache b/data/labels/train.cache new file mode 100644 index 0000000..b90f4ee Binary files /dev/null and b/data/labels/train.cache differ diff --git a/data/labels/train/1.txt b/data/labels/train/1.txt new file mode 100644 index 0000000..4cddff4 --- /dev/null +++ b/data/labels/train/1.txt @@ -0,0 +1 @@ +0 0.4796854521625161 0.36631716906946254 0.19134993446920037 0.33944954128440374 diff --git a/data/labels/train/2.txt b/data/labels/train/2.txt new file mode 100644 index 0000000..b418b12 --- /dev/null +++ b/data/labels/train/2.txt @@ -0,0 +1 @@ +0 0.5137614678899075 0.3695937090432503 0.17562254259501947 0.39580602883355154 diff --git a/data/labels/train/3.txt b/data/labels/train/3.txt new file mode 100644 index 0000000..6d7b971 --- /dev/null +++ b/data/labels/train/3.txt @@ -0,0 +1 @@ +0 0.4639580602883355 0.4272608125819135 0.1834862385321101 0.31716906946264745 diff --git a/data/labels/train/4.txt b/data/labels/train/4.txt new file mode 100644 index 0000000..485349b --- /dev/null +++ b/data/labels/train/4.txt @@ -0,0 +1,2 @@ +0 0.4501965923984272 0.4757536041939713 0.17169069462647432 0.3093053735255571 +0 0.37418086500655307 0.4750982961992136 0.027522935779816536 0.0013106159895150426 diff --git a/data/labels/train/5.txt b/data/labels/train/5.txt new file mode 100644 index 0000000..f35316d --- /dev/null +++ b/data/labels/train/5.txt @@ -0,0 +1 @@ +0 0.515727391874181 0.3912188728702489 0.15596330275229378 0.34207077326343355 diff --git a/data/labels/train/6.txt b/data/labels/train/6.txt new file mode 100644 index 0000000..c8b0336 --- /dev/null +++ b/data/labels/train/6.txt @@ -0,0 +1 @@ +0 0.4882044560943644 0.4646133682830928 0.17169069462647438 0.40235910878112674 diff --git a/data/labels/train/7.txt b/data/labels/train/7.txt new file mode 100644 index 0000000..e9696cb --- /dev/null +++ b/data/labels/train/7.txt @@ -0,0 +1 @@ +0 0.48361730013106086 0.496723460026212 0.2568807339449536 0.4325032765399734 diff --git a/data/labels/train/8.txt b/data/labels/train/8.txt new file mode 100644 index 0000000..5d24bee --- /dev/null +++ b/data/labels/train/8.txt @@ -0,0 +1 @@ +0 0.6159895150720839 0.5498034076015726 0.16251638269986907 0.41546526867627775 diff --git a/data/labels/val.cache b/data/labels/val.cache new file mode 100644 index 0000000..1949bf4 Binary files /dev/null and b/data/labels/val.cache differ diff --git a/data/labels/val/1.txt b/data/labels/val/1.txt new file mode 100644 index 0000000..4cddff4 --- /dev/null +++ b/data/labels/val/1.txt @@ -0,0 +1 @@ +0 0.4796854521625161 0.36631716906946254 0.19134993446920037 0.33944954128440374 diff --git a/data/labels/val/2.txt b/data/labels/val/2.txt new file mode 100644 index 0000000..b418b12 --- /dev/null +++ b/data/labels/val/2.txt @@ -0,0 +1 @@ +0 0.5137614678899075 0.3695937090432503 0.17562254259501947 0.39580602883355154 diff --git a/data/labels/val/3.txt b/data/labels/val/3.txt new file mode 100644 index 0000000..6d7b971 --- /dev/null +++ b/data/labels/val/3.txt @@ -0,0 +1 @@ +0 0.4639580602883355 0.4272608125819135 0.1834862385321101 0.31716906946264745 diff --git a/data/labels/val/4.txt b/data/labels/val/4.txt new file mode 100644 index 0000000..485349b --- /dev/null +++ b/data/labels/val/4.txt @@ -0,0 +1,2 @@ +0 0.4501965923984272 0.4757536041939713 0.17169069462647432 0.3093053735255571 +0 0.37418086500655307 0.4750982961992136 0.027522935779816536 0.0013106159895150426 diff --git a/data/labels/val/5.txt b/data/labels/val/5.txt new file mode 100644 index 0000000..f35316d --- /dev/null +++ b/data/labels/val/5.txt @@ -0,0 +1 @@ +0 0.515727391874181 0.3912188728702489 0.15596330275229378 0.34207077326343355 diff --git a/data/labels/val/6.txt b/data/labels/val/6.txt new file mode 100644 index 0000000..c8b0336 --- /dev/null +++ b/data/labels/val/6.txt @@ -0,0 +1 @@ +0 0.4882044560943644 0.4646133682830928 0.17169069462647438 0.40235910878112674 diff --git a/data/labels/val/7.txt b/data/labels/val/7.txt new file mode 100644 index 0000000..e9696cb --- /dev/null +++ b/data/labels/val/7.txt @@ -0,0 +1 @@ +0 0.48361730013106086 0.496723460026212 0.2568807339449536 0.4325032765399734 diff --git a/data/labels/val/8.txt b/data/labels/val/8.txt new file mode 100644 index 0000000..5d24bee --- /dev/null +++ b/data/labels/val/8.txt @@ -0,0 +1 @@ +0 0.6159895150720839 0.5498034076015726 0.16251638269986907 0.41546526867627775 diff --git a/labelImg-master/.gitignore b/labelImg-master/.gitignore new file mode 100644 index 0000000..b13f325 --- /dev/null +++ b/labelImg-master/.gitignore @@ -0,0 +1,19 @@ +resources/icons/.DS_Store + +resources.py + +.idea* +labelImg.egg-info* + +*.pyc +.*.swp + +build/ +dist/ + +tags +cscope* +.ycm_extra_conf.py +.subvimrc +.vscode +*.pkl diff --git a/labelImg-master/.travis.yml b/labelImg-master/.travis.yml new file mode 100644 index 0000000..2f6c540 --- /dev/null +++ b/labelImg-master/.travis.yml @@ -0,0 +1,86 @@ +# vim: set ts=2 et: + +# run xvfb with 32-bit color +# xvfb-run -s '-screen 0 1600x1200x24+32' command_goes_here + +matrix: + include: + + + # Python 2.7 + QT4 + - os: linux + dist: trusty + sudo: required + language: generic + python: "2.7" + env: + - QT=4 + - CONDA=4.2.0 + addons: + apt: + packages: + - cmake + #- python-qt4 + #- pyqt4-dev-tools + - xvfb + before_install: + # ref: https://www.continuum.io/downloads + - curl -O https://repo.continuum.io/archive/Anaconda2-4.2.0-Linux-x86_64.sh + # ref: http://conda.pydata.org/docs/help/silent.html + - /bin/bash Anaconda2-4.2.0-Linux-x86_64.sh -b -p $HOME/anaconda2 + - export PATH="$HOME/anaconda2/bin:$PATH" + # ref: http://stackoverflow.com/questions/21637922/how-to-install-pyqt4-in-anaconda + - conda create -y -n labelImg-py2qt4 python=2.7 + - source activate labelImg-py2qt4 + - conda install -y pyqt=4 + - conda install -y lxml + - make qt4py2 + - xvfb-run make testpy2 + + + # Python 3 + QT5 + - os: linux + dist: trusty + sudo: required + language: generic + python: "3.5" + env: + - QT=5 + - CONDA=4.2.0 + addons: + apt: + packages: + - cmake + - xvfb + before_install: + # ref: https://www.continuum.io/downloads + - curl -O https://repo.continuum.io/archive/Anaconda3-4.2.0-Linux-x86_64.sh + # ref: http://conda.pydata.org/docs/help/silent.html + - /bin/bash Anaconda3-4.2.0-Linux-x86_64.sh -b -p $HOME/anaconda3 + - export PATH="$HOME/anaconda3/bin:$PATH" + # ref: http://stackoverflow.com/questions/21637922/how-to-install-pyqt4-in-anaconda + - conda create -y -n labelImg-py3qt5 python=3.5 + - source activate labelImg-py3qt5 + - conda install -y pyqt=5 + - conda install -y lxml + - make qt5py3 + - xvfb-run make testpy3 + + # Pipenv Python 3 + QT5 - Build .app + - os: osx + language: generic + python: "3.7" + env: + - PIPENV_VENV_IN_PROJECT=1 + - PIPENV_IGNORE_VIRTUALENVS=1 + install: + - pip3 install pipenv + - pipenv install pyqt5 lxml + - pipenv run pip install pyqt5==5.13.2 lxml + - pipenv run make qt5py3 + - rm -rf build dist + - pipenv run python setup.py py2app + - open dist/labelImg.app + +script: + - exit 0 diff --git a/labelImg-master/CONTRIBUTING.rst b/labelImg-master/CONTRIBUTING.rst new file mode 100644 index 0000000..4e05247 --- /dev/null +++ b/labelImg-master/CONTRIBUTING.rst @@ -0,0 +1,3 @@ +TzuTa Lin +[LabelMe](http://labelme2.csail.mit.edu/Release3.0/index.php) +Ryan Flynn diff --git a/labelImg-master/HISTORY.rst b/labelImg-master/HISTORY.rst new file mode 100644 index 0000000..2f89e81 --- /dev/null +++ b/labelImg-master/HISTORY.rst @@ -0,0 +1,110 @@ +History +======= + +1.8.2 (2018-12-02) +------------------ + +* Fix pip depolyment issue + + +1.8.1 (2018-12-02) +------------------ + +* Fix issues +* Support zh-Tw strings + + +1.8.0 (2018-10-21) +------------------ + +* Support drawing sqaure rect +* Add item single click slot +* Fix issues + +1.7.0 (2018-05-18) +------------------ + +* Support YOLO +* Fix minor issues + + +1.6.1 (2018-04-17) +------------------ + +* Fix issue + +1.6.0 (2018-01-29) +------------------ + +* Add more pre-defined labels +* Show cursor pose in status bar +* Fix minor issues + +1.5.2 (2017-10-24) +------------------ + +* Assign different colors to different lablels + +1.5.1 (2017-9-27) +------------------ + +* Show a autosaving dialog + +1.5.0 (2017-9-14) +------------------ + +* Fix the issues +* Add feature: Draw a box easier + + +1.4.3 (2017-08-09) +------------------ + +* Refactor setting +* Fix the issues + + +1.4.0 (2017-07-07) +------------------ + +* Add feature: auto saving +* Add feature: single class mode +* Fix the issues + +1.3.4 (2017-07-07) +------------------ + +* Fix issues and improve zoom-in + +1.3.3 (2017-05-31) +------------------ + +* Fix issues + +1.3.2 (2017-05-18) +------------------ + +* Fix issues + + +1.3.1 (2017-05-11) +------------------ + +* Fix issues + +1.3.0 (2017-04-22) +------------------ + +* Fix issues +* Add difficult tag +* Create new files for pypi + +1.2.3 (2017-04-22) +------------------ + +* Fix issues + +1.2.2 (2017-01-09) +------------------ + +* Fix issues diff --git a/labelImg-master/LICENSE b/labelImg-master/LICENSE new file mode 100644 index 0000000..0ffc8fe --- /dev/null +++ b/labelImg-master/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) <2015-Present> Tzutalin + +Copyright (C) 2013 MIT, Computer Science and Artificial Intelligence Laboratory. Bryan Russell, Antonio Torralba, William T. Freeman + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/labelImg-master/MANIFEST.in b/labelImg-master/MANIFEST.in new file mode 100644 index 0000000..f47f84f --- /dev/null +++ b/labelImg-master/MANIFEST.in @@ -0,0 +1,15 @@ +include CONTRIBUTING.rst +include HISTORY.rst +include LICENSE +include README.rst + +include resources.qrc + +recursive-include data * +recursive-include icons * +recursive-include libs * + +recursive-exclude build-tools * +recursive-exclude tests * +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] diff --git a/labelImg-master/Makefile b/labelImg-master/Makefile new file mode 100644 index 0000000..7d72a89 --- /dev/null +++ b/labelImg-master/Makefile @@ -0,0 +1,35 @@ +# ex: set ts=8 noet: + +all: qt5 test + +test: testpy3 + +testpy2: + python -m unittest discover tests + +testpy3: + python3 -m unittest discover tests + +qt4: qt4py2 + +qt5: qt5py3 + +qt4py2: + pyrcc4 -py2 -o libs/resources.py resources.qrc + +qt4py3: + pyrcc4 -py3 -o libs/resources.py resources.qrc + +qt5py3: + pyrcc5 -o libs/resources.py resources.qrc + +clean: + rm -rf ~/.labelImgSettings.pkl *.pyc dist labelImg.egg-info __pycache__ build + +pip_upload: + python3 setup.py upload + +long_description: + restview --long-description + +.PHONY: all diff --git a/labelImg-master/README.rst b/labelImg-master/README.rst new file mode 100644 index 0000000..a61eb08 --- /dev/null +++ b/labelImg-master/README.rst @@ -0,0 +1,275 @@ +LabelImg +======== + +.. image:: https://img.shields.io/pypi/v/labelimg.svg + :target: https://pypi.python.org/pypi/labelimg + +.. image:: https://img.shields.io/travis/tzutalin/labelImg.svg + :target: https://travis-ci.org/tzutalin/labelImg + +.. image:: /resources/icons/app.png + :width: 200px + :align: center + +LabelImg is a graphical image annotation tool. + +It is written in Python and uses Qt for its graphical interface. + +Annotations are saved as XML files in PASCAL VOC format, the format used +by `ImageNet `__. Besides, it also supports YOLO format + +.. image:: https://raw.githubusercontent.com/tzutalin/labelImg/master/demo/demo3.jpg + :alt: Demo Image + +.. image:: https://raw.githubusercontent.com/tzutalin/labelImg/master/demo/demo.jpg + :alt: Demo Image + +`Watch a demo video `__ + +Installation +------------------ + + +Build from source +~~~~~~~~~~~~~~~~~ + +Linux/Ubuntu/Mac requires at least `Python +2.6 `__ and has been tested with `PyQt +4.8 `__. However, `Python +3 or above `__ and `PyQt5 `__ are strongly recommended. + + +Ubuntu Linux +^^^^^^^^^^^^ +Python 2 + Qt4 + +.. code:: shell + + sudo apt-get install pyqt4-dev-tools + sudo pip install lxml + make qt4py2 + python labelImg.py + python labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + +Python 3 + Qt5 (Recommended) + +.. code:: shell + + sudo apt-get install pyqt5-dev-tools + sudo pip3 install -r requirements/requirements-linux-python3.txt + make qt5py3 + python3 labelImg.py + python3 labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + +macOS +^^^^^ +Python 2 + Qt4 + +.. code:: shell + + brew install qt qt4 + brew install libxml2 + make qt4py2 + python labelImg.py + python labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + +Python 3 + Qt5 (Recommended) + +.. code:: shell + + brew install qt # Install qt-5.x.x by Homebrew + brew install libxml2 + + or using pip + + pip3 install pyqt5 lxml # Install qt and lxml by pip + + make qt5py3 + python3 labelImg.py + python3 labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + + +Python 3 Virtualenv (Recommended) + +Virtualenv can avoid a lot of the QT / Python version issues + +.. code:: shell + + brew install python3 + pip3 install pipenv + pipenv run pip install pyqt5==5.13.2 lxml + pipenv run make qt5py3 + python3 labelImg.py + [Optional] rm -rf build dist; python setup.py py2app -A;mv "dist/labelImg.app" /Applications + +Note: The Last command gives you a nice .app file with a new SVG Icon in your /Applications folder. You can consider using the script: build-tools/build-for-macos.sh + + +Windows +^^^^^^^ + +Install `Python `__, +`PyQt5 `__ +and `install lxml `__. + +Open cmd and go to the `labelImg <#labelimg>`__ directory + +.. code:: shell + + pyrcc4 -o line/resources.py resources.qrc + For pyqt5, pyrcc5 -o libs/resources.py resources.qrc + + python labelImg.py + python labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + +Windows + Anaconda +^^^^^^^^^^^^^^^^^^ + +Download and install `Anaconda `__ (Python 3+) + +Open the Anaconda Prompt and go to the `labelImg <#labelimg>`__ directory + +.. code:: shell + + conda install pyqt=5 + pyrcc5 -o libs/resources.py resources.qrc + python labelImg.py + python labelImg.py [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + +Get from PyPI but only python3.0 or above +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. code:: shell + + pip3 install labelImg + labelImg + labelImg [IMAGE_PATH] [PRE-DEFINED CLASS FILE] + + +Use Docker +~~~~~~~~~~~~~~~~~ +.. code:: shell + + docker run -it \ + --user $(id -u) \ + -e DISPLAY=unix$DISPLAY \ + --workdir=$(pwd) \ + --volume="/home/$USER:/home/$USER" \ + --volume="/etc/group:/etc/group:ro" \ + --volume="/etc/passwd:/etc/passwd:ro" \ + --volume="/etc/shadow:/etc/shadow:ro" \ + --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + tzutalin/py2qt4 + + make qt4py2;./labelImg.py + +You can pull the image which has all of the installed and required dependencies. `Watch a demo video `__ + + +Usage +----- + +Steps (PascalVOC) +~~~~~~~~~~~~~~~~~ + +1. Build and launch using the instructions above. +2. Click 'Change default saved annotation folder' in Menu/File +3. Click 'Open Dir' +4. Click 'Create RectBox' +5. Click and release left mouse to select a region to annotate the rect + box +6. You can use right mouse to drag the rect box to copy or move it + +The annotation will be saved to the folder you specify. + +You can refer to the below hotkeys to speed up your workflow. + +Steps (YOLO) +~~~~~~~~~~~~ + +1. In ``data/predefined_classes.txt`` define the list of classes that will be used for your training. + +2. Build and launch using the instructions above. + +3. Right below "Save" button in the toolbar, click "PascalVOC" button to switch to YOLO format. + +4. You may use Open/OpenDIR to process single or multiple images. When finished with a single image, click save. + +A txt file of YOLO format will be saved in the same folder as your image with same name. A file named "classes.txt" is saved to that folder too. "classes.txt" defines the list of class names that your YOLO label refers to. + +Note: + +- Your label list shall not change in the middle of processing a list of images. When you save an image, classes.txt will also get updated, while previous annotations will not be updated. + +- You shouldn't use "default class" function when saving to YOLO format, it will not be referred. + +- When saving as YOLO format, "difficult" flag is discarded. + +Create pre-defined classes +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can edit the +`data/predefined\_classes.txt `__ +to load pre-defined classes + +Hotkeys +~~~~~~~ + ++------------+--------------------------------------------+ +| Ctrl + u | Load all of the images from a directory | ++------------+--------------------------------------------+ +| Ctrl + r | Change the default annotation target dir | ++------------+--------------------------------------------+ +| Ctrl + s | Save | ++------------+--------------------------------------------+ +| Ctrl + d | Copy the current label and rect box | ++------------+--------------------------------------------+ +| Space | Flag the current image as verified | ++------------+--------------------------------------------+ +| w | Create a rect box | ++------------+--------------------------------------------+ +| d | Next image | ++------------+--------------------------------------------+ +| a | Previous image | ++------------+--------------------------------------------+ +| del | Delete the selected rect box | ++------------+--------------------------------------------+ +| Ctrl++ | Zoom in | ++------------+--------------------------------------------+ +| Ctrl-- | Zoom out | ++------------+--------------------------------------------+ +| ↑→↓← | Keyboard arrows to move selected rect box | ++------------+--------------------------------------------+ + +**Verify Image:** + +When pressing space, the user can flag the image as verified, a green background will appear. +This is used when creating a dataset automatically, the user can then through all the pictures and flag them instead of annotate them. + +**Difficult:** + +The difficult field is set to 1 indicates that the object has been annotated as "difficult", for example, an object which is clearly visible but difficult to recognize without substantial use of context. +According to your deep neural network implementation, you can include or exclude difficult objects during training. + +How to contribute +~~~~~~~~~~~~~~~~~ + +Send a pull request + +License +~~~~~~~ +`Free software: MIT license `_ + +Citation: Tzutalin. LabelImg. Git code (2015). https://github.com/tzutalin/labelImg + +Related +~~~~~~~ + +1. `ImageNet Utils `__ to + download image, create a label text for machine learning, etc +2. `Use Docker to run labelImg `__ +3. `Generating the PASCAL VOC TFRecord files `__ +4. `App Icon based on Icon by Nick Roach (GPL) `__ +5. `Setup python development in vscode `__ +6. `The link of this project on iHub platform `__ + diff --git a/labelImg-master/__init__.py b/labelImg-master/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/labelImg-master/build-tools/.gitignore b/labelImg-master/build-tools/.gitignore new file mode 100644 index 0000000..e05bf6b --- /dev/null +++ b/labelImg-master/build-tools/.gitignore @@ -0,0 +1,12 @@ +*.spec +build +dist +pyinstaller +python-2.* +pywin32* +virtual-wine +venv_wine +PyQt4-* +lxml-* +windows_v* +linux_v* diff --git a/labelImg-master/build-tools/README.md b/labelImg-master/build-tools/README.md new file mode 100644 index 0000000..8e4cc5d --- /dev/null +++ b/labelImg-master/build-tools/README.md @@ -0,0 +1,35 @@ +### Deploy to PyPI + +``` +cd [ROOT] +sh build-tools/build-for-pypi.sh +``` + +### Build for Ubuntu + +``` +cd build-tools +sh run-in-container.sh +sh envsetup.sh +sh build-ubuntu-binary.sh +``` + +### Build for Windows + +``` +cd build-tools +sh run-in-container.sh +sh envsetup.sh +sh build-windows-binary.sh +``` + +### Build for macOS High Sierra +``` +cd build-tools +./build-for-macos.sh +``` + +Note: If there are some problems, try to +``` +sudo rm -rf virtual-wne venv_wine +``` diff --git a/labelImg-master/build-tools/build-for-macos.sh b/labelImg-master/build-tools/build-for-macos.sh new file mode 100644 index 0000000..dfe926b --- /dev/null +++ b/labelImg-master/build-tools/build-for-macos.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +brew install python@2 +pip install --upgrade virtualenv + +# clone labelimg source +rm -rf /tmp/labelImgSetup +mkdir /tmp/labelImgSetup +cd /tmp/labelImgSetup +curl https://codeload.github.com/tzutalin/labelImg/zip/master --output labelImg.zip +unzip labelImg.zip +rm labelImg.zip + +# setup python3 space +virtualenv --system-site-packages -p python3 /tmp/labelImgSetup/labelImg-py3 +source /tmp/labelImgSetup/labelImg-py3/bin/activate +cd labelImg-master + +# build labelImg app +pip install py2app +pip install PyQt5 lxml +make qt5py3 +rm -rf build dist +python setup.py py2app -A +mv "/tmp/labelImgSetup/labelImg-master/dist/labelImg.app" /Applications +# deactivate python3 +deactivate +cd ../ +rm -rf /tmp/labelImgSetup +echo 'DONE' diff --git a/labelImg-master/build-tools/build-for-pypi.sh b/labelImg-master/build-tools/build-for-pypi.sh new file mode 100644 index 0000000..d5ad5c7 --- /dev/null +++ b/labelImg-master/build-tools/build-for-pypi.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Packaging and Release +docker run --workdir=$(pwd)/ --volume="/home/$USER:/home/$USER" tzutalin/py2qt4 /bin/sh -c 'make qt4py2; make test;sudo python setup.py sdist;sudo python setup.py install' + +while true; do + read -p "Do you wish to deploy this to PyPI(twine upload dist/* or pip install dist/*)?" yn + case $yn in + [Yy]* ) docker run -it --rm --workdir=$(pwd)/ --volume="/home/$USER:/home/$USER" tzutalin/py2qt4; break;; + [Nn]* ) exit;; + * ) echo "Please answer yes or no.";; + esac +done +# python setup.py register +# python setup.py sdist upload +# Net pypi: twine upload dist/* + +# Test before upladoing: pip install dist/labelImg.tar.gz diff --git a/labelImg-master/build-tools/build-ubuntu-binary.sh b/labelImg-master/build-tools/build-ubuntu-binary.sh new file mode 100644 index 0000000..dbe5302 --- /dev/null +++ b/labelImg-master/build-tools/build-ubuntu-binary.sh @@ -0,0 +1,24 @@ +#!/bin/bash +### Ubuntu use pyinstall v3.0 +THIS_SCRIPT_PATH=`readlink -f $0` +THIS_SCRIPT_DIR=`dirname ${THIS_SCRIPT_PATH}` +cd pyinstaller +git checkout v3.2 +cd ${THIS_SCRIPT_DIR} + +rm -r build +rm -r dist +rm labelImg.spec +python pyinstaller/pyinstaller.py --hidden-import=xml \ + --hidden-import=xml.etree \ + --hidden-import=xml.etree.ElementTree \ + --hidden-import=lxml.etree \ + -D -F -n labelImg -c "../labelImg.py" -p ../libs -p ../ + +FOLDER=$(git describe --abbrev=0 --tags) +FOLDER="linux_"$FOLDER +rm -rf "$FOLDER" +mkdir "$FOLDER" +cp dist/labelImg $FOLDER +cp -rf ../data $FOLDER/data +zip "$FOLDER.zip" -r $FOLDER diff --git a/labelImg-master/build-tools/build-windows-binary.sh b/labelImg-master/build-tools/build-windows-binary.sh new file mode 100644 index 0000000..566e88f --- /dev/null +++ b/labelImg-master/build-tools/build-windows-binary.sh @@ -0,0 +1,32 @@ +#!/bin/bash +### Window requires pyinstall v2.1 +wine msiexec -i python-2.7.8.msi +wine pywin32-218.win32-py2.7.exe +wine PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe +wine lxml-3.7.3.win32-py2.7.exe + +THIS_SCRIPT_PATH=`readlink -f $0` +THIS_SCRIPT_DIR=`dirname ${THIS_SCRIPT_PATH}` +cd pyinstaller +git checkout v2.1 +cd ${THIS_SCRIPT_DIR} +echo ${THIS_SCRIPT_DIR} + +#. venv_wine/bin/activate +rm -r build +rm -r dist +rm labelImg.spec + +wine c:/Python27/python.exe pyinstaller/pyinstaller.py --hidden-import=xml \ + --hidden-import=xml.etree \ + --hidden-import=xml.etree.ElementTree \ + --hidden-import=lxml.etree \ + -D -F -n labelImg -c "../labelImg.py" -p ../libs -p ../ + +FOLDER=$(git describe --abbrev=0 --tags) +FOLDER="windows_"$FOLDER +rm -rf "$FOLDER" +mkdir "$FOLDER" +cp dist/labelImg.exe $FOLDER +cp -rf ../data $FOLDER/data +zip "$FOLDER.zip" -r $FOLDER diff --git a/labelImg-master/build-tools/envsetup.sh b/labelImg-master/build-tools/envsetup.sh new file mode 100644 index 0000000..242b0c5 --- /dev/null +++ b/labelImg-master/build-tools/envsetup.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +THIS_SCRIPT_PATH=`readlink -f $0` +THIS_SCRIPT_DIR=`dirname ${THIS_SCRIPT_PATH}` +#OS Ubuntu 14.04 +### Common packages for linux/windows +if [ ! -e "pyinstaller" ]; then + git clone https://github.com/pyinstaller/pyinstaller + cd pyinstaller + git checkout v2.1 -b v2.1 + cd ${THIS_SCRIPT_DIR} +fi + +echo "Going to clone and download packages for building windows" +#Pacakges +#> pyinstaller (2.1) +#> wine (1.6.2) +#> virtual-wine (0.1) +#> python-2.7.8.msi +#> pywin32-218.win32-py2.7.exe + +## tool to install on Ubuntu +#$ sudo apt-get install wine + +### Clone a repo to create virtual wine env +if [ ! -e "virtual-wine" ]; then + git clone https://github.com/htgoebel/virtual-wine.git +fi + +apt-get install scons +### Create virtual env +rm -rf venv_wine +./virtual-wine/vwine-setup venv_wine +#### Active virutal env +. venv_wine/bin/activate + +### Use wine to install packages to virtual env +if [ ! -e "python-2.7.8.msi" ]; then + wget "https://www.python.org/ftp/python/2.7.8/python-2.7.8.msi" +fi + +if [ ! -e "pywin32-218.win32-py2.7.exe" ]; then + wget "http://nchc.dl.sourceforge.net/project/pywin32/pywin32/Build%20218/pywin32-218.win32-py2.7.exe" +fi + +if [ ! -e "PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe" ]; then + wget "http://nchc.dl.sourceforge.net/project/pyqt/PyQt4/PyQt-4.11.4/PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe" +fi + +if [ ! -e "lxml-3.7.3.win32-py2.7.exe" ]; then + wget "https://pypi.python.org/packages/a3/f6/a28c5cf63873f6c55a3eb7857b736379229b85ba918261d2e88cf886905e/lxml-3.7.3.win32-py2.7.exe#md5=a0f746355876aca4ca5371cb0f1d13ce" +fi + diff --git a/labelImg-master/build-tools/run-in-container.sh b/labelImg-master/build-tools/run-in-container.sh new file mode 100644 index 0000000..980699d --- /dev/null +++ b/labelImg-master/build-tools/run-in-container.sh @@ -0,0 +1,13 @@ +#!/bin/sh +docker run -it \ + --user $(id -u) \ + -e DISPLAY=unix$DISPLAY \ + --workdir=$(pwd) \ + --volume="/home/$USER:/home/$USER" \ + --volume="/etc/group:/etc/group:ro" \ + --volume="/etc/passwd:/etc/passwd:ro" \ + --volume="/etc/shadow:/etc/shadow:ro" \ + --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + tzutalin/py2qt4 + diff --git a/labelImg-master/data/predefined_classes.txt b/labelImg-master/data/predefined_classes.txt new file mode 100644 index 0000000..bc2eef1 --- /dev/null +++ b/labelImg-master/data/predefined_classes.txt @@ -0,0 +1,15 @@ +dog +person +cat +tv +car +meatballs +marinara sauce +tomato soup +chicken noodle soup +french onion soup +chicken breast +ribs +pulled pork +hamburger +cavity \ No newline at end of file diff --git a/labelImg-master/demo/demo.jpg b/labelImg-master/demo/demo.jpg new file mode 100644 index 0000000..c339af4 Binary files /dev/null and b/labelImg-master/demo/demo.jpg differ diff --git a/labelImg-master/demo/demo3.jpg b/labelImg-master/demo/demo3.jpg new file mode 100644 index 0000000..8d58a44 Binary files /dev/null and b/labelImg-master/demo/demo3.jpg differ diff --git a/labelImg-master/demo/demo4.png b/labelImg-master/demo/demo4.png new file mode 100644 index 0000000..dc21998 Binary files /dev/null and b/labelImg-master/demo/demo4.png differ diff --git a/labelImg-master/demo/demo5.png b/labelImg-master/demo/demo5.png new file mode 100644 index 0000000..0a857a0 Binary files /dev/null and b/labelImg-master/demo/demo5.png differ diff --git a/labelImg-master/issue_template.md b/labelImg-master/issue_template.md new file mode 100644 index 0000000..5222ada --- /dev/null +++ b/labelImg-master/issue_template.md @@ -0,0 +1,7 @@ + + +- **OS:** +- **PyQt version:** diff --git a/labelImg-master/labelImg.py b/labelImg-master/labelImg.py new file mode 100644 index 0000000..15630f3 --- /dev/null +++ b/labelImg-master/labelImg.py @@ -0,0 +1,1482 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import codecs +# import distutils.spawn +import os.path +import platform +import re +import sys +import subprocess + +from functools import partial +from collections import defaultdict + +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + # needed for py3+qt4 + # Ref: + # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html + # http://stackoverflow.com/questions/21217399/pyqt4-qtcore-qvariant-object-instead-of-a-string + if sys.version_info.major >= 3: + import sip + sip.setapi('QVariant', 2) + from PyQt5.QtGui import * + from PyQt5.QtCore import * + +from libs.resources import * +from libs.constants import * +from libs.utils import * +from libs.settings import Settings +from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR +from libs.stringBundle import StringBundle +from libs.canvas import Canvas +from libs.zoomWidget import ZoomWidget +from libs.labelDialog import LabelDialog +from libs.colorDialog import ColorDialog +from libs.labelFile import LabelFile, LabelFileError +from libs.toolBar import ToolBar +from libs.pascal_voc_io import PascalVocReader +from libs.pascal_voc_io import XML_EXT +from libs.yolo_io import YoloReader +from libs.yolo_io import TXT_EXT +from libs.ustr import ustr +from libs.hashableQListWidgetItem import HashableQListWidgetItem + +__appname__ = 'labelImg' + +class WindowMixin(object): + + def menu(self, title, actions=None): + menu = self.menuBar().addMenu(title) + if actions: + addActions(menu, actions) + return menu + + def toolbar(self, title, actions=None): + toolbar = ToolBar(title) + toolbar.setObjectName(u'%sToolBar' % title) + # toolbar.setOrientation(Qt.Vertical) + toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) + if actions: + addActions(toolbar, actions) + self.addToolBar(Qt.LeftToolBarArea, toolbar) + return toolbar + + +class MainWindow(QMainWindow, WindowMixin): + FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = list(range(3)) + + def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSaveDir=None): + super(MainWindow, self).__init__() + self.setWindowTitle(__appname__) + + # Load setting in the main thread + self.settings = Settings() + self.settings.load() + settings = self.settings + + # Load string bundle for i18n + self.stringBundle = StringBundle.getBundle() + getStr = lambda strId: self.stringBundle.getString(strId) + + # Save as Pascal voc xml + self.defaultSaveDir = defaultSaveDir + self.usingPascalVocFormat = True + self.usingYoloFormat = False + + # For loading all image under a directory + self.mImgList = [] + self.dirname = None + self.labelHist = [] + self.lastOpenDir = None + + # Whether we need to save or not. + self.dirty = False + + self._noSelectionSlot = False + self._beginner = True + self.screencastViewer = self.getAvailableScreencastViewer() + self.screencast = "https://youtu.be/p0nR2YsCY_U" + + # Load predefined classes to the list + self.loadPredefinedClasses(defaultPrefdefClassFile) + + # Main widgets and related state. + self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) + + self.itemsToShapes = {} + self.shapesToItems = {} + self.prevLabelText = '' + + listLayout = QVBoxLayout() + listLayout.setContentsMargins(0, 0, 0, 0) + + # Create a widget for using default label + self.useDefaultLabelCheckbox = QCheckBox(getStr('useDefaultLabel')) + self.useDefaultLabelCheckbox.setChecked(False) + self.defaultLabelTextLine = QLineEdit() + useDefaultLabelQHBoxLayout = QHBoxLayout() + useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLabelCheckbox) + useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine) + useDefaultLabelContainer = QWidget() + useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout) + + # Create a widget for edit and diffc button + self.diffcButton = QCheckBox(getStr('useDifficult')) + self.diffcButton.setChecked(False) + self.diffcButton.stateChanged.connect(self.btnstate) + self.editButton = QToolButton() + self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + + # Add some of widgets to listLayout + listLayout.addWidget(self.editButton) + listLayout.addWidget(self.diffcButton) + listLayout.addWidget(useDefaultLabelContainer) + + # Create and add a widget for showing current label items + self.labelList = QListWidget() + labelListContainer = QWidget() + labelListContainer.setLayout(listLayout) + self.labelList.itemActivated.connect(self.labelSelectionChanged) + self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) + self.labelList.itemDoubleClicked.connect(self.editLabel) + # Connect to itemChanged to detect checkbox changes. + self.labelList.itemChanged.connect(self.labelItemChanged) + listLayout.addWidget(self.labelList) + + self.dock = QDockWidget(getStr('boxLabelText'), self) + self.dock.setObjectName(getStr('labels')) + self.dock.setWidget(labelListContainer) + + self.fileListWidget = QListWidget() + self.fileListWidget.itemDoubleClicked.connect(self.fileitemDoubleClicked) + filelistLayout = QVBoxLayout() + filelistLayout.setContentsMargins(0, 0, 0, 0) + filelistLayout.addWidget(self.fileListWidget) + fileListContainer = QWidget() + fileListContainer.setLayout(filelistLayout) + self.filedock = QDockWidget(getStr('fileList'), self) + self.filedock.setObjectName(getStr('files')) + self.filedock.setWidget(fileListContainer) + + self.zoomWidget = ZoomWidget() + self.colorDialog = ColorDialog(parent=self) + + self.canvas = Canvas(parent=self) + self.canvas.zoomRequest.connect(self.zoomRequest) + self.canvas.setDrawingShapeToSquare(settings.get(SETTING_DRAW_SQUARE, False)) + + scroll = QScrollArea() + scroll.setWidget(self.canvas) + scroll.setWidgetResizable(True) + self.scrollBars = { + Qt.Vertical: scroll.verticalScrollBar(), + Qt.Horizontal: scroll.horizontalScrollBar() + } + self.scrollArea = scroll + self.canvas.scrollRequest.connect(self.scrollRequest) + + self.canvas.newShape.connect(self.newShape) + self.canvas.shapeMoved.connect(self.setDirty) + self.canvas.selectionChanged.connect(self.shapeSelectionChanged) + self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) + + self.setCentralWidget(scroll) + self.addDockWidget(Qt.RightDockWidgetArea, self.dock) + self.addDockWidget(Qt.RightDockWidgetArea, self.filedock) + self.filedock.setFeatures(QDockWidget.DockWidgetFloatable) + + self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable + self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) + + # Actions + action = partial(newAction, self) + quit = action(getStr('quit'), self.close, + 'Ctrl+Q', 'quit', getStr('quitApp')) + + open = action(getStr('openFile'), self.openFile, + 'Ctrl+O', 'open', getStr('openFileDetail')) + + opendir = action(getStr('openDir'), self.openDirDialog, + 'Ctrl+u', 'open', getStr('openDir')) + + changeSavedir = action(getStr('changeSaveDir'), self.changeSavedirDialog, + 'Ctrl+r', 'open', getStr('changeSavedAnnotationDir')) + + openAnnotation = action(getStr('openAnnotation'), self.openAnnotationDialog, + 'Ctrl+Shift+O', 'open', getStr('openAnnotationDetail')) + + openNextImg = action(getStr('nextImg'), self.openNextImg, + 'd', 'next', getStr('nextImgDetail')) + + openPrevImg = action(getStr('prevImg'), self.openPrevImg, + 'a', 'prev', getStr('prevImgDetail')) + + verify = action(getStr('verifyImg'), self.verifyImg, + 'space', 'verify', getStr('verifyImgDetail')) + + save = action(getStr('save'), self.saveFile, + 'Ctrl+S', 'save', getStr('saveDetail'), enabled=False) + + save_format = action('&PascalVOC', self.change_format, + 'Ctrl+', 'format_voc', getStr('changeSaveFormat'), enabled=True) + + saveAs = action(getStr('saveAs'), self.saveFileAs, + 'Ctrl+Shift+S', 'save-as', getStr('saveAsDetail'), enabled=False) + + close = action(getStr('closeCur'), self.closeFile, 'Ctrl+W', 'close', getStr('closeCurDetail')) + + resetAll = action(getStr('resetAll'), self.resetAll, None, 'resetall', getStr('resetAllDetail')) + + color1 = action(getStr('boxLineColor'), self.chooseColor1, + 'Ctrl+L', 'color_line', getStr('boxLineColorDetail')) + + createMode = action(getStr('crtBox'), self.setCreateMode, + 'w', 'new', getStr('crtBoxDetail'), enabled=False) + editMode = action('&Edit\nRectBox', self.setEditMode, + 'Ctrl+J', 'edit', u'Move and edit Boxs', enabled=False) + + create = action(getStr('crtBox'), self.createShape, + 'w', 'new', getStr('crtBoxDetail'), enabled=False) + delete = action(getStr('delBox'), self.deleteSelectedShape, + 'Delete', 'delete', getStr('delBoxDetail'), enabled=False) + copy = action(getStr('dupBox'), self.copySelectedShape, + 'Ctrl+D', 'copy', getStr('dupBoxDetail'), + enabled=False) + + advancedMode = action(getStr('advancedMode'), self.toggleAdvancedMode, + 'Ctrl+Shift+A', 'expert', getStr('advancedModeDetail'), + checkable=True) + + hideAll = action('&Hide\nRectBox', partial(self.togglePolygons, False), + 'Ctrl+H', 'hide', getStr('hideAllBoxDetail'), + enabled=False) + showAll = action('&Show\nRectBox', partial(self.togglePolygons, True), + 'Ctrl+A', 'hide', getStr('showAllBoxDetail'), + enabled=False) + + help = action(getStr('tutorial'), self.showTutorialDialog, None, 'help', getStr('tutorialDetail')) + showInfo = action(getStr('info'), self.showInfoDialog, None, 'help', getStr('info')) + + zoom = QWidgetAction(self) + zoom.setDefaultWidget(self.zoomWidget) + self.zoomWidget.setWhatsThis( + u"Zoom in or out of the image. Also accessible with" + " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), + fmtShortcut("Ctrl+Wheel"))) + self.zoomWidget.setEnabled(False) + + zoomIn = action(getStr('zoomin'), partial(self.addZoom, 10), + 'Ctrl++', 'zoom-in', getStr('zoominDetail'), enabled=False) + zoomOut = action(getStr('zoomout'), partial(self.addZoom, -10), + 'Ctrl+-', 'zoom-out', getStr('zoomoutDetail'), enabled=False) + zoomOrg = action(getStr('originalsize'), partial(self.setZoom, 100), + 'Ctrl+=', 'zoom', getStr('originalsizeDetail'), enabled=False) + fitWindow = action(getStr('fitWin'), self.setFitWindow, + 'Ctrl+F', 'fit-window', getStr('fitWinDetail'), + checkable=True, enabled=False) + fitWidth = action(getStr('fitWidth'), self.setFitWidth, + 'Ctrl+Shift+F', 'fit-width', getStr('fitWidthDetail'), + checkable=True, enabled=False) + # Group zoom controls into a list for easier toggling. + zoomActions = (self.zoomWidget, zoomIn, zoomOut, + zoomOrg, fitWindow, fitWidth) + self.zoomMode = self.MANUAL_ZOOM + self.scalers = { + self.FIT_WINDOW: self.scaleFitWindow, + self.FIT_WIDTH: self.scaleFitWidth, + # Set to one to scale to 100% when loading files. + self.MANUAL_ZOOM: lambda: 1, + } + + edit = action(getStr('editLabel'), self.editLabel, + 'Ctrl+E', 'edit', getStr('editLabelDetail'), + enabled=False) + self.editButton.setDefaultAction(edit) + + shapeLineColor = action(getStr('shapeLineColor'), self.chshapeLineColor, + icon='color_line', tip=getStr('shapeLineColorDetail'), + enabled=False) + shapeFillColor = action(getStr('shapeFillColor'), self.chshapeFillColor, + icon='color', tip=getStr('shapeFillColorDetail'), + enabled=False) + + labels = self.dock.toggleViewAction() + labels.setText(getStr('showHide')) + labels.setShortcut('Ctrl+Shift+L') + + # Label list context menu. + labelMenu = QMenu() + addActions(labelMenu, (edit, delete)) + self.labelList.setContextMenuPolicy(Qt.CustomContextMenu) + self.labelList.customContextMenuRequested.connect( + self.popLabelListMenu) + + # Draw squares/rectangles + self.drawSquaresOption = QAction('Draw Squares', self) + self.drawSquaresOption.setShortcut('Ctrl+Shift+R') + self.drawSquaresOption.setCheckable(True) + self.drawSquaresOption.setChecked(settings.get(SETTING_DRAW_SQUARE, False)) + self.drawSquaresOption.triggered.connect(self.toogleDrawSquare) + + # Store actions for further handling. + self.actions = struct(save=save, save_format=save_format, saveAs=saveAs, open=open, close=close, resetAll = resetAll, + lineColor=color1, create=create, delete=delete, edit=edit, copy=copy, + createMode=createMode, editMode=editMode, advancedMode=advancedMode, + shapeLineColor=shapeLineColor, shapeFillColor=shapeFillColor, + zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, + fitWindow=fitWindow, fitWidth=fitWidth, + zoomActions=zoomActions, + fileMenuActions=( + open, opendir, save, saveAs, close, resetAll, quit), + beginner=(), advanced=(), + editMenu=(edit, copy, delete, + None, color1, self.drawSquaresOption), + beginnerContext=(create, edit, copy, delete), + advancedContext=(createMode, editMode, edit, copy, + delete, shapeLineColor, shapeFillColor), + onLoadActive=( + close, create, createMode, editMode), + onShapesPresent=(saveAs, hideAll, showAll)) + + self.menus = struct( + file=self.menu('&File'), + edit=self.menu('&Edit'), + view=self.menu('&View'), + help=self.menu('&Help'), + recentFiles=QMenu('Open &Recent'), + labelList=labelMenu) + + # Auto saving : Enable auto saving if pressing next + self.autoSaving = QAction(getStr('autoSaveMode'), self) + self.autoSaving.setCheckable(True) + self.autoSaving.setChecked(settings.get(SETTING_AUTO_SAVE, False)) + # Sync single class mode from PR#106 + self.singleClassMode = QAction(getStr('singleClsMode'), self) + self.singleClassMode.setShortcut("Ctrl+Shift+S") + self.singleClassMode.setCheckable(True) + self.singleClassMode.setChecked(settings.get(SETTING_SINGLE_CLASS, False)) + self.lastLabel = None + # Add option to enable/disable labels being displayed at the top of bounding boxes + self.displayLabelOption = QAction(getStr('displayLabel'), self) + self.displayLabelOption.setShortcut("Ctrl+Shift+P") + self.displayLabelOption.setCheckable(True) + self.displayLabelOption.setChecked(settings.get(SETTING_PAINT_LABEL, False)) + self.displayLabelOption.triggered.connect(self.togglePaintLabelsOption) + + addActions(self.menus.file, + (open, opendir, changeSavedir, openAnnotation, self.menus.recentFiles, save, save_format, saveAs, close, resetAll, quit)) + addActions(self.menus.help, (help, showInfo)) + addActions(self.menus.view, ( + self.autoSaving, + self.singleClassMode, + self.displayLabelOption, + labels, advancedMode, None, + hideAll, showAll, None, + zoomIn, zoomOut, zoomOrg, None, + fitWindow, fitWidth)) + + self.menus.file.aboutToShow.connect(self.updateFileMenu) + + # Custom context menu for the canvas widget: + addActions(self.canvas.menus[0], self.actions.beginnerContext) + addActions(self.canvas.menus[1], ( + action('&Copy here', self.copyShape), + action('&Move here', self.moveShape))) + + self.tools = self.toolbar('Tools') + self.actions.beginner = ( + open, opendir, changeSavedir, openNextImg, openPrevImg, verify, save, save_format, None, create, copy, delete, None, + zoomIn, zoom, zoomOut, fitWindow, fitWidth) + + self.actions.advanced = ( + open, opendir, changeSavedir, openNextImg, openPrevImg, save, save_format, None, + createMode, editMode, None, + hideAll, showAll) + + self.statusBar().showMessage('%s started.' % __appname__) + self.statusBar().show() + + # Application state. + self.image = QImage() + self.filePath = ustr(defaultFilename) + self.recentFiles = [] + self.maxRecent = 7 + self.lineColor = None + self.fillColor = None + self.zoom_level = 100 + self.fit_window = False + # Add Chris + self.difficult = False + + ## Fix the compatible issue for qt4 and qt5. Convert the QStringList to python list + if settings.get(SETTING_RECENT_FILES): + if have_qstring(): + recentFileQStringList = settings.get(SETTING_RECENT_FILES) + self.recentFiles = [ustr(i) for i in recentFileQStringList] + else: + self.recentFiles = recentFileQStringList = settings.get(SETTING_RECENT_FILES) + + size = settings.get(SETTING_WIN_SIZE, QSize(600, 500)) + position = QPoint(0, 0) + saved_position = settings.get(SETTING_WIN_POSE, position) + # Fix the multiple monitors issue + for i in range(QApplication.desktop().screenCount()): + if QApplication.desktop().availableGeometry(i).contains(saved_position): + position = saved_position + break + self.resize(size) + self.move(position) + saveDir = ustr(settings.get(SETTING_SAVE_DIR, None)) + self.lastOpenDir = ustr(settings.get(SETTING_LAST_OPEN_DIR, None)) + if self.defaultSaveDir is None and saveDir is not None and os.path.exists(saveDir): + self.defaultSaveDir = saveDir + self.statusBar().showMessage('%s started. Annotation will be saved to %s' % + (__appname__, self.defaultSaveDir)) + self.statusBar().show() + + self.restoreState(settings.get(SETTING_WIN_STATE, QByteArray())) + Shape.line_color = self.lineColor = QColor(settings.get(SETTING_LINE_COLOR, DEFAULT_LINE_COLOR)) + Shape.fill_color = self.fillColor = QColor(settings.get(SETTING_FILL_COLOR, DEFAULT_FILL_COLOR)) + self.canvas.setDrawingColor(self.lineColor) + # Add chris + Shape.difficult = self.difficult + + def xbool(x): + if isinstance(x, QVariant): + return x.toBool() + return bool(x) + + if xbool(settings.get(SETTING_ADVANCE_MODE, False)): + self.actions.advancedMode.setChecked(True) + self.toggleAdvancedMode() + + # Populate the File menu dynamically. + self.updateFileMenu() + + # Since loading the file may take some time, make sure it runs in the background. + if self.filePath and os.path.isdir(self.filePath): + self.queueEvent(partial(self.importDirImages, self.filePath or "")) + elif self.filePath: + self.queueEvent(partial(self.loadFile, self.filePath or "")) + + # Callbacks: + self.zoomWidget.valueChanged.connect(self.paintCanvas) + + self.populateModeActions() + + # Display cursor coordinates at the right of status bar + self.labelCoordinates = QLabel('') + self.statusBar().addPermanentWidget(self.labelCoordinates) + + # Open Dir if deafult file + if self.filePath and os.path.isdir(self.filePath): + self.openDirDialog(dirpath=self.filePath, silent=True) + + def keyReleaseEvent(self, event): + if event.key() == Qt.Key_Control: + self.canvas.setDrawingShapeToSquare(False) + + def keyPressEvent(self, event): + if event.key() == Qt.Key_Control: + # Draw rectangle if Ctrl is pressed + self.canvas.setDrawingShapeToSquare(True) + + ## Support Functions ## + def set_format(self, save_format): + if save_format == FORMAT_PASCALVOC: + self.actions.save_format.setText(FORMAT_PASCALVOC) + self.actions.save_format.setIcon(newIcon("format_voc")) + self.usingPascalVocFormat = True + self.usingYoloFormat = False + LabelFile.suffix = XML_EXT + + elif save_format == FORMAT_YOLO: + self.actions.save_format.setText(FORMAT_YOLO) + self.actions.save_format.setIcon(newIcon("format_yolo")) + self.usingPascalVocFormat = False + self.usingYoloFormat = True + LabelFile.suffix = TXT_EXT + + def change_format(self): + if self.usingPascalVocFormat: self.set_format(FORMAT_YOLO) + elif self.usingYoloFormat: self.set_format(FORMAT_PASCALVOC) + + def noShapes(self): + return not self.itemsToShapes + + def toggleAdvancedMode(self, value=True): + self._beginner = not value + self.canvas.setEditing(True) + self.populateModeActions() + self.editButton.setVisible(not value) + if value: + self.actions.createMode.setEnabled(True) + self.actions.editMode.setEnabled(False) + self.dock.setFeatures(self.dock.features() | self.dockFeatures) + else: + self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) + + def populateModeActions(self): + if self.beginner(): + tool, menu = self.actions.beginner, self.actions.beginnerContext + else: + tool, menu = self.actions.advanced, self.actions.advancedContext + self.tools.clear() + addActions(self.tools, tool) + self.canvas.menus[0].clear() + addActions(self.canvas.menus[0], menu) + self.menus.edit.clear() + actions = (self.actions.create,) if self.beginner()\ + else (self.actions.createMode, self.actions.editMode) + addActions(self.menus.edit, actions + self.actions.editMenu) + + def setBeginner(self): + self.tools.clear() + addActions(self.tools, self.actions.beginner) + + def setAdvanced(self): + self.tools.clear() + addActions(self.tools, self.actions.advanced) + + def setDirty(self): + self.dirty = True + self.actions.save.setEnabled(True) + + def setClean(self): + self.dirty = False + self.actions.save.setEnabled(False) + self.actions.create.setEnabled(True) + + def toggleActions(self, value=True): + """Enable/Disable widgets which depend on an opened image.""" + for z in self.actions.zoomActions: + z.setEnabled(value) + for action in self.actions.onLoadActive: + action.setEnabled(value) + + def queueEvent(self, function): + QTimer.singleShot(0, function) + + def status(self, message, delay=5000): + self.statusBar().showMessage(message, delay) + + def resetState(self): + self.itemsToShapes.clear() + self.shapesToItems.clear() + self.labelList.clear() + self.filePath = None + self.imageData = None + self.labelFile = None + self.canvas.resetState() + self.labelCoordinates.clear() + + def currentItem(self): + items = self.labelList.selectedItems() + if items: + return items[0] + return None + + def addRecentFile(self, filePath): + if filePath in self.recentFiles: + self.recentFiles.remove(filePath) + elif len(self.recentFiles) >= self.maxRecent: + self.recentFiles.pop() + self.recentFiles.insert(0, filePath) + + def beginner(self): + return self._beginner + + def advanced(self): + return not self.beginner() + + def getAvailableScreencastViewer(self): + osName = platform.system() + + if osName == 'Windows': + return ['C:\\Program Files\\Internet Explorer\\iexplore.exe'] + elif osName == 'Linux': + return ['xdg-open'] + elif osName == 'Darwin': + return ['open'] + + ## Callbacks ## + def showTutorialDialog(self): + subprocess.Popen(self.screencastViewer + [self.screencast]) + + def showInfoDialog(self): + msg = u'Name:{0} \nApp Version:{1} \n{2} '.format(__appname__, __version__, sys.version_info) + QMessageBox.information(self, u'Information', msg) + + def createShape(self): + assert self.beginner() + self.canvas.setEditing(False) + self.actions.create.setEnabled(False) + + def toggleDrawingSensitive(self, drawing=True): + """In the middle of drawing, toggling between modes should be disabled.""" + self.actions.editMode.setEnabled(not drawing) + if not drawing and self.beginner(): + # Cancel creation. + print('Cancel creation.') + self.canvas.setEditing(True) + self.canvas.restoreCursor() + self.actions.create.setEnabled(True) + + def toggleDrawMode(self, edit=True): + self.canvas.setEditing(edit) + self.actions.createMode.setEnabled(edit) + self.actions.editMode.setEnabled(not edit) + + def setCreateMode(self): + assert self.advanced() + self.toggleDrawMode(False) + + def setEditMode(self): + assert self.advanced() + self.toggleDrawMode(True) + self.labelSelectionChanged() + + def updateFileMenu(self): + currFilePath = self.filePath + + def exists(filename): + return os.path.exists(filename) + menu = self.menus.recentFiles + menu.clear() + files = [f for f in self.recentFiles if f != + currFilePath and exists(f)] + for i, f in enumerate(files): + icon = newIcon('labels') + action = QAction( + icon, '&%d %s' % (i + 1, QFileInfo(f).fileName()), self) + action.triggered.connect(partial(self.loadRecent, f)) + menu.addAction(action) + + def popLabelListMenu(self, point): + self.menus.labelList.exec_(self.labelList.mapToGlobal(point)) + + def editLabel(self): + if not self.canvas.editing(): + return + item = self.currentItem() + if not item: + return + text = self.labelDialog.popUp(item.text()) + if text is not None: + item.setText(text) + item.setBackground(generateColorByText(text)) + self.setDirty() + + # Tzutalin 20160906 : Add file list and dock to move faster + def fileitemDoubleClicked(self, item=None): + currIndex = self.mImgList.index(ustr(item.text())) + if currIndex < len(self.mImgList): + filename = self.mImgList[currIndex] + if filename: + self.loadFile(filename) + + # Add chris + def btnstate(self, item= None): + """ Function to handle difficult examples + Update on each object """ + if not self.canvas.editing(): + return + + item = self.currentItem() + if not item: # If not selected Item, take the first one + item = self.labelList.item(self.labelList.count()-1) + + difficult = self.diffcButton.isChecked() + + try: + shape = self.itemsToShapes[item] + except: + pass + # Checked and Update + try: + if difficult != shape.difficult: + shape.difficult = difficult + self.setDirty() + else: # User probably changed item visibility + self.canvas.setShapeVisible(shape, item.checkState() == Qt.Checked) + except: + pass + + # React to canvas signals. + def shapeSelectionChanged(self, selected=False): + if self._noSelectionSlot: + self._noSelectionSlot = False + else: + shape = self.canvas.selectedShape + if shape: + self.shapesToItems[shape].setSelected(True) + else: + self.labelList.clearSelection() + self.actions.delete.setEnabled(selected) + self.actions.copy.setEnabled(selected) + self.actions.edit.setEnabled(selected) + self.actions.shapeLineColor.setEnabled(selected) + self.actions.shapeFillColor.setEnabled(selected) + + def addLabel(self, shape): + shape.paintLabel = self.displayLabelOption.isChecked() + item = HashableQListWidgetItem(shape.label) + item.setFlags(item.flags() | Qt.ItemIsUserCheckable) + item.setCheckState(Qt.Checked) + item.setBackground(generateColorByText(shape.label)) + self.itemsToShapes[item] = shape + self.shapesToItems[shape] = item + self.labelList.addItem(item) + for action in self.actions.onShapesPresent: + action.setEnabled(True) + + def remLabel(self, shape): + if shape is None: + # print('rm empty label') + return + item = self.shapesToItems[shape] + self.labelList.takeItem(self.labelList.row(item)) + del self.shapesToItems[shape] + del self.itemsToShapes[item] + + def loadLabels(self, shapes): + s = [] + for label, points, line_color, fill_color, difficult in shapes: + shape = Shape(label=label) + for x, y in points: + + # Ensure the labels are within the bounds of the image. If not, fix them. + x, y, snapped = self.canvas.snapPointToCanvas(x, y) + if snapped: + self.setDirty() + + shape.addPoint(QPointF(x, y)) + shape.difficult = difficult + shape.close() + s.append(shape) + + if line_color: + shape.line_color = QColor(*line_color) + else: + shape.line_color = generateColorByText(label) + + if fill_color: + shape.fill_color = QColor(*fill_color) + else: + shape.fill_color = generateColorByText(label) + + self.addLabel(shape) + + self.canvas.loadShapes(s) + + def saveLabels(self, annotationFilePath): + annotationFilePath = ustr(annotationFilePath) + if self.labelFile is None: + self.labelFile = LabelFile() + self.labelFile.verified = self.canvas.verified + + def format_shape(s): + return dict(label=s.label, + line_color=s.line_color.getRgb(), + fill_color=s.fill_color.getRgb(), + points=[(p.x(), p.y()) for p in s.points], + # add chris + difficult = s.difficult) + + shapes = [format_shape(shape) for shape in self.canvas.shapes] + # Can add differrent annotation formats here + try: + if self.usingPascalVocFormat is True: + if annotationFilePath[-4:].lower() != ".xml": + annotationFilePath += XML_EXT + self.labelFile.savePascalVocFormat(annotationFilePath, shapes, self.filePath, self.imageData, + self.lineColor.getRgb(), self.fillColor.getRgb()) + elif self.usingYoloFormat is True: + if annotationFilePath[-4:].lower() != ".txt": + annotationFilePath += TXT_EXT + self.labelFile.saveYoloFormat(annotationFilePath, shapes, self.filePath, self.imageData, self.labelHist, + self.lineColor.getRgb(), self.fillColor.getRgb()) + else: + self.labelFile.save(annotationFilePath, shapes, self.filePath, self.imageData, + self.lineColor.getRgb(), self.fillColor.getRgb()) + print('Image:{0} -> Annotation:{1}'.format(self.filePath, annotationFilePath)) + return True + except LabelFileError as e: + self.errorMessage(u'Error saving label data', u'%s' % e) + return False + + def copySelectedShape(self): + self.addLabel(self.canvas.copySelectedShape()) + # fix copy and delete + self.shapeSelectionChanged(True) + + def labelSelectionChanged(self): + item = self.currentItem() + if item and self.canvas.editing(): + self._noSelectionSlot = True + self.canvas.selectShape(self.itemsToShapes[item]) + shape = self.itemsToShapes[item] + # Add Chris + self.diffcButton.setChecked(shape.difficult) + + def labelItemChanged(self, item): + shape = self.itemsToShapes[item] + label = item.text() + if label != shape.label: + shape.label = item.text() + shape.line_color = generateColorByText(shape.label) + self.setDirty() + else: # User probably changed item visibility + self.canvas.setShapeVisible(shape, item.checkState() == Qt.Checked) + + # Callback functions: + def newShape(self): + """Pop-up and give focus to the label editor. + + position MUST be in global coordinates. + """ + if not self.useDefaultLabelCheckbox.isChecked() or not self.defaultLabelTextLine.text(): + if len(self.labelHist) > 0: + self.labelDialog = LabelDialog( + parent=self, listItem=self.labelHist) + + # Sync single class mode from PR#106 + if self.singleClassMode.isChecked() and self.lastLabel: + text = self.lastLabel + else: + text = self.labelDialog.popUp(text=self.prevLabelText) + self.lastLabel = text + else: + text = self.defaultLabelTextLine.text() + + # Add Chris + self.diffcButton.setChecked(False) + if text is not None: + self.prevLabelText = text + generate_color = generateColorByText(text) + shape = self.canvas.setLastLabel(text, generate_color, generate_color) + self.addLabel(shape) + if self.beginner(): # Switch to edit mode. + self.canvas.setEditing(True) + self.actions.create.setEnabled(True) + else: + self.actions.editMode.setEnabled(True) + self.setDirty() + + if text not in self.labelHist: + self.labelHist.append(text) + else: + # self.canvas.undoLastLine() + self.canvas.resetAllLines() + + def scrollRequest(self, delta, orientation): + units = - delta / (8 * 15) + bar = self.scrollBars[orientation] + bar.setValue(bar.value() + bar.singleStep() * units) + + def setZoom(self, value): + self.actions.fitWidth.setChecked(False) + self.actions.fitWindow.setChecked(False) + self.zoomMode = self.MANUAL_ZOOM + self.zoomWidget.setValue(value) + + def addZoom(self, increment=10): + self.setZoom(self.zoomWidget.value() + increment) + + def zoomRequest(self, delta): + # get the current scrollbar positions + # calculate the percentages ~ coordinates + h_bar = self.scrollBars[Qt.Horizontal] + v_bar = self.scrollBars[Qt.Vertical] + + # get the current maximum, to know the difference after zooming + h_bar_max = h_bar.maximum() + v_bar_max = v_bar.maximum() + + # get the cursor position and canvas size + # calculate the desired movement from 0 to 1 + # where 0 = move left + # 1 = move right + # up and down analogous + cursor = QCursor() + pos = cursor.pos() + relative_pos = QWidget.mapFromGlobal(self, pos) + + cursor_x = relative_pos.x() + cursor_y = relative_pos.y() + + w = self.scrollArea.width() + h = self.scrollArea.height() + + # the scaling from 0 to 1 has some padding + # you don't have to hit the very leftmost pixel for a maximum-left movement + margin = 0.1 + move_x = (cursor_x - margin * w) / (w - 2 * margin * w) + move_y = (cursor_y - margin * h) / (h - 2 * margin * h) + + # clamp the values from 0 to 1 + move_x = min(max(move_x, 0), 1) + move_y = min(max(move_y, 0), 1) + + # zoom in + units = delta / (8 * 15) + scale = 10 + self.addZoom(scale * units) + + # get the difference in scrollbar values + # this is how far we can move + d_h_bar_max = h_bar.maximum() - h_bar_max + d_v_bar_max = v_bar.maximum() - v_bar_max + + # get the new scrollbar values + new_h_bar_value = h_bar.value() + move_x * d_h_bar_max + new_v_bar_value = v_bar.value() + move_y * d_v_bar_max + + h_bar.setValue(new_h_bar_value) + v_bar.setValue(new_v_bar_value) + + def setFitWindow(self, value=True): + if value: + self.actions.fitWidth.setChecked(False) + self.zoomMode = self.FIT_WINDOW if value else self.MANUAL_ZOOM + self.adjustScale() + + def setFitWidth(self, value=True): + if value: + self.actions.fitWindow.setChecked(False) + self.zoomMode = self.FIT_WIDTH if value else self.MANUAL_ZOOM + self.adjustScale() + + def togglePolygons(self, value): + for item, shape in self.itemsToShapes.items(): + item.setCheckState(Qt.Checked if value else Qt.Unchecked) + + def loadFile(self, filePath=None): + """Load the specified file, or the last opened file if None.""" + self.resetState() + self.canvas.setEnabled(False) + if filePath is None: + filePath = self.settings.get(SETTING_FILENAME) + + # Make sure that filePath is a regular python string, rather than QString + filePath = ustr(filePath) + + # Fix bug: An index error after select a directory when open a new file. + unicodeFilePath = ustr(filePath) + unicodeFilePath = os.path.abspath(unicodeFilePath) + # Tzutalin 20160906 : Add file list and dock to move faster + # Highlight the file item + if unicodeFilePath and self.fileListWidget.count() > 0: + if unicodeFilePath in self.mImgList: + index = self.mImgList.index(unicodeFilePath) + fileWidgetItem = self.fileListWidget.item(index) + fileWidgetItem.setSelected(True) + else: + self.fileListWidget.clear() + self.mImgList.clear() + + if unicodeFilePath and os.path.exists(unicodeFilePath): + if LabelFile.isLabelFile(unicodeFilePath): + try: + self.labelFile = LabelFile(unicodeFilePath) + except LabelFileError as e: + self.errorMessage(u'Error opening file', + (u"

%s

" + u"

Make sure %s is a valid label file.") + % (e, unicodeFilePath)) + self.status("Error reading %s" % unicodeFilePath) + return False + self.imageData = self.labelFile.imageData + self.lineColor = QColor(*self.labelFile.lineColor) + self.fillColor = QColor(*self.labelFile.fillColor) + self.canvas.verified = self.labelFile.verified + else: + # Load image: + # read data first and store for saving into label file. + self.imageData = read(unicodeFilePath, None) + self.labelFile = None + self.canvas.verified = False + + image = QImage.fromData(self.imageData) + if image.isNull(): + self.errorMessage(u'Error opening file', + u"

Make sure %s is a valid image file." % unicodeFilePath) + self.status("Error reading %s" % unicodeFilePath) + return False + self.status("Loaded %s" % os.path.basename(unicodeFilePath)) + self.image = image + self.filePath = unicodeFilePath + self.canvas.loadPixmap(QPixmap.fromImage(image)) + if self.labelFile: + self.loadLabels(self.labelFile.shapes) + self.setClean() + self.canvas.setEnabled(True) + self.adjustScale(initial=True) + self.paintCanvas() + self.addRecentFile(self.filePath) + self.toggleActions(True) + + # Label xml file and show bound box according to its filename + # if self.usingPascalVocFormat is True: + if self.defaultSaveDir is not None: + basename = os.path.basename( + os.path.splitext(self.filePath)[0]) + xmlPath = os.path.join(self.defaultSaveDir, basename + XML_EXT) + txtPath = os.path.join(self.defaultSaveDir, basename + TXT_EXT) + + """Annotation file priority: + PascalXML > YOLO + """ + if os.path.isfile(xmlPath): + self.loadPascalXMLByFilename(xmlPath) + elif os.path.isfile(txtPath): + self.loadYOLOTXTByFilename(txtPath) + else: + xmlPath = os.path.splitext(filePath)[0] + XML_EXT + txtPath = os.path.splitext(filePath)[0] + TXT_EXT + if os.path.isfile(xmlPath): + self.loadPascalXMLByFilename(xmlPath) + elif os.path.isfile(txtPath): + self.loadYOLOTXTByFilename(txtPath) + + self.setWindowTitle(__appname__ + ' ' + filePath) + + # Default : select last item if there is at least one item + if self.labelList.count(): + self.labelList.setCurrentItem(self.labelList.item(self.labelList.count()-1)) + self.labelList.item(self.labelList.count()-1).setSelected(True) + + self.canvas.setFocus(True) + return True + return False + + def resizeEvent(self, event): + if self.canvas and not self.image.isNull()\ + and self.zoomMode != self.MANUAL_ZOOM: + self.adjustScale() + super(MainWindow, self).resizeEvent(event) + + def paintCanvas(self): + assert not self.image.isNull(), "cannot paint null image" + self.canvas.scale = 0.01 * self.zoomWidget.value() + self.canvas.adjustSize() + self.canvas.update() + + def adjustScale(self, initial=False): + value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]() + self.zoomWidget.setValue(int(100 * value)) + + def scaleFitWindow(self): + """Figure out the size of the pixmap in order to fit the main widget.""" + e = 2.0 # So that no scrollbars are generated. + w1 = self.centralWidget().width() - e + h1 = self.centralWidget().height() - e + a1 = w1 / h1 + # Calculate a new scale value based on the pixmap's aspect ratio. + w2 = self.canvas.pixmap.width() - 0.0 + h2 = self.canvas.pixmap.height() - 0.0 + a2 = w2 / h2 + return w1 / w2 if a2 >= a1 else h1 / h2 + + def scaleFitWidth(self): + # The epsilon does not seem to work too well here. + w = self.centralWidget().width() - 2.0 + return w / self.canvas.pixmap.width() + + def closeEvent(self, event): + if not self.mayContinue(): + event.ignore() + settings = self.settings + # If it loads images from dir, don't load it at the begining + if self.dirname is None: + settings[SETTING_FILENAME] = self.filePath if self.filePath else '' + else: + settings[SETTING_FILENAME] = '' + + settings[SETTING_WIN_SIZE] = self.size() + settings[SETTING_WIN_POSE] = self.pos() + settings[SETTING_WIN_STATE] = self.saveState() + settings[SETTING_LINE_COLOR] = self.lineColor + settings[SETTING_FILL_COLOR] = self.fillColor + settings[SETTING_RECENT_FILES] = self.recentFiles + settings[SETTING_ADVANCE_MODE] = not self._beginner + if self.defaultSaveDir and os.path.exists(self.defaultSaveDir): + settings[SETTING_SAVE_DIR] = ustr(self.defaultSaveDir) + else: + settings[SETTING_SAVE_DIR] = '' + + if self.lastOpenDir and os.path.exists(self.lastOpenDir): + settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir + else: + settings[SETTING_LAST_OPEN_DIR] = '' + + settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked() + settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked() + settings[SETTING_PAINT_LABEL] = self.displayLabelOption.isChecked() + settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked() + settings.save() + + def loadRecent(self, filename): + if self.mayContinue(): + self.loadFile(filename) + + def scanAllImages(self, folderPath): + extensions = ['.%s' % fmt.data().decode("ascii").lower() for fmt in QImageReader.supportedImageFormats()] + images = [] + + for root, dirs, files in os.walk(folderPath): + for file in files: + if file.lower().endswith(tuple(extensions)): + relativePath = os.path.join(root, file) + path = ustr(os.path.abspath(relativePath)) + images.append(path) + natural_sort(images, key=lambda x: x.lower()) + return images + + def changeSavedirDialog(self, _value=False): + if self.defaultSaveDir is not None: + path = ustr(self.defaultSaveDir) + else: + path = '.' + + dirpath = ustr(QFileDialog.getExistingDirectory(self, + '%s - Save annotations to the directory' % __appname__, path, QFileDialog.ShowDirsOnly + | QFileDialog.DontResolveSymlinks)) + + if dirpath is not None and len(dirpath) > 1: + self.defaultSaveDir = dirpath + + self.statusBar().showMessage('%s . Annotation will be saved to %s' % + ('Change saved folder', self.defaultSaveDir)) + self.statusBar().show() + + def openAnnotationDialog(self, _value=False): + if self.filePath is None: + self.statusBar().showMessage('Please select image first') + self.statusBar().show() + return + + path = os.path.dirname(ustr(self.filePath))\ + if self.filePath else '.' + if self.usingPascalVocFormat: + filters = "Open Annotation XML file (%s)" % ' '.join(['*.xml']) + filename = ustr(QFileDialog.getOpenFileName(self,'%s - Choose a xml file' % __appname__, path, filters)) + if filename: + if isinstance(filename, (tuple, list)): + filename = filename[0] + self.loadPascalXMLByFilename(filename) + + def openDirDialog(self, _value=False, dirpath=None, silent=False): + if not self.mayContinue(): + return + + defaultOpenDirPath = dirpath if dirpath else '.' + if self.lastOpenDir and os.path.exists(self.lastOpenDir): + defaultOpenDirPath = self.lastOpenDir + else: + defaultOpenDirPath = os.path.dirname(self.filePath) if self.filePath else '.' + if silent!=True : + targetDirPath = ustr(QFileDialog.getExistingDirectory(self, + '%s - Open Directory' % __appname__, defaultOpenDirPath, + QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)) + else: + targetDirPath = ustr(defaultOpenDirPath) + + self.importDirImages(targetDirPath) + + def importDirImages(self, dirpath): + if not self.mayContinue() or not dirpath: + return + + self.lastOpenDir = dirpath + self.dirname = dirpath + self.filePath = None + self.fileListWidget.clear() + self.mImgList = self.scanAllImages(dirpath) + self.openNextImg() + for imgPath in self.mImgList: + item = QListWidgetItem(imgPath) + self.fileListWidget.addItem(item) + + def verifyImg(self, _value=False): + # Proceding next image without dialog if having any label + if self.filePath is not None: + try: + self.labelFile.toggleVerify() + except AttributeError: + # If the labelling file does not exist yet, create if and + # re-save it with the verified attribute. + self.saveFile() + if self.labelFile != None: + self.labelFile.toggleVerify() + else: + return + + self.canvas.verified = self.labelFile.verified + self.paintCanvas() + self.saveFile() + + def openPrevImg(self, _value=False): + # Proceding prev image without dialog if having any label + if self.autoSaving.isChecked(): + if self.defaultSaveDir is not None: + if self.dirty is True: + self.saveFile() + else: + self.changeSavedirDialog() + return + + if not self.mayContinue(): + return + + if len(self.mImgList) <= 0: + return + + if self.filePath is None: + return + + currIndex = self.mImgList.index(self.filePath) + if currIndex - 1 >= 0: + filename = self.mImgList[currIndex - 1] + if filename: + self.loadFile(filename) + + def openNextImg(self, _value=False): + # Proceding prev image without dialog if having any label + if self.autoSaving.isChecked(): + if self.defaultSaveDir is not None: + if self.dirty is True: + self.saveFile() + else: + self.changeSavedirDialog() + return + + if not self.mayContinue(): + return + + if len(self.mImgList) <= 0: + return + + filename = None + if self.filePath is None: + filename = self.mImgList[0] + else: + currIndex = self.mImgList.index(self.filePath) + if currIndex + 1 < len(self.mImgList): + filename = self.mImgList[currIndex + 1] + + if filename: + self.loadFile(filename) + + def openFile(self, _value=False): + if not self.mayContinue(): + return + path = os.path.dirname(ustr(self.filePath)) if self.filePath else '.' + formats = ['*.%s' % fmt.data().decode("ascii").lower() for fmt in QImageReader.supportedImageFormats()] + filters = "Image & Label files (%s)" % ' '.join(formats + ['*%s' % LabelFile.suffix]) + filename = QFileDialog.getOpenFileName(self, '%s - Choose Image or Label file' % __appname__, path, filters) + if filename: + if isinstance(filename, (tuple, list)): + filename = filename[0] + self.loadFile(filename) + + def saveFile(self, _value=False): + if self.defaultSaveDir is not None and len(ustr(self.defaultSaveDir)): + if self.filePath: + imgFileName = os.path.basename(self.filePath) + savedFileName = os.path.splitext(imgFileName)[0] + savedPath = os.path.join(ustr(self.defaultSaveDir), savedFileName) + self._saveFile(savedPath) + else: + imgFileDir = os.path.dirname(self.filePath) + imgFileName = os.path.basename(self.filePath) + savedFileName = os.path.splitext(imgFileName)[0] + savedPath = os.path.join(imgFileDir, savedFileName) + self._saveFile(savedPath if self.labelFile + else self.saveFileDialog(removeExt=False)) + + def saveFileAs(self, _value=False): + assert not self.image.isNull(), "cannot save empty image" + self._saveFile(self.saveFileDialog()) + + def saveFileDialog(self, removeExt=True): + caption = '%s - Choose File' % __appname__ + filters = 'File (*%s)' % LabelFile.suffix + openDialogPath = self.currentPath() + dlg = QFileDialog(self, caption, openDialogPath, filters) + dlg.setDefaultSuffix(LabelFile.suffix[1:]) + dlg.setAcceptMode(QFileDialog.AcceptSave) + filenameWithoutExtension = os.path.splitext(self.filePath)[0] + dlg.selectFile(filenameWithoutExtension) + dlg.setOption(QFileDialog.DontUseNativeDialog, False) + if dlg.exec_(): + fullFilePath = ustr(dlg.selectedFiles()[0]) + if removeExt: + return os.path.splitext(fullFilePath)[0] # Return file path without the extension. + else: + return fullFilePath + return '' + + def _saveFile(self, annotationFilePath): + if annotationFilePath and self.saveLabels(annotationFilePath): + self.setClean() + self.statusBar().showMessage('Saved to %s' % annotationFilePath) + self.statusBar().show() + + def closeFile(self, _value=False): + if not self.mayContinue(): + return + self.resetState() + self.setClean() + self.toggleActions(False) + self.canvas.setEnabled(False) + self.actions.saveAs.setEnabled(False) + + def resetAll(self): + self.settings.reset() + self.close() + proc = QProcess() + proc.startDetached(os.path.abspath(__file__)) + + def mayContinue(self): + return not (self.dirty and not self.discardChangesDialog()) + + def discardChangesDialog(self): + yes, no = QMessageBox.Yes, QMessageBox.No + msg = u'You have unsaved changes, proceed anyway?' + return yes == QMessageBox.warning(self, u'Attention', msg, yes | no) + + def errorMessage(self, title, message): + return QMessageBox.critical(self, title, + '

%s

%s' % (title, message)) + + def currentPath(self): + return os.path.dirname(self.filePath) if self.filePath else '.' + + def chooseColor1(self): + color = self.colorDialog.getColor(self.lineColor, u'Choose line color', + default=DEFAULT_LINE_COLOR) + if color: + self.lineColor = color + Shape.line_color = color + self.canvas.setDrawingColor(color) + self.canvas.update() + self.setDirty() + + def deleteSelectedShape(self): + self.remLabel(self.canvas.deleteSelected()) + self.setDirty() + if self.noShapes(): + for action in self.actions.onShapesPresent: + action.setEnabled(False) + + def chshapeLineColor(self): + color = self.colorDialog.getColor(self.lineColor, u'Choose line color', + default=DEFAULT_LINE_COLOR) + if color: + self.canvas.selectedShape.line_color = color + self.canvas.update() + self.setDirty() + + def chshapeFillColor(self): + color = self.colorDialog.getColor(self.fillColor, u'Choose fill color', + default=DEFAULT_FILL_COLOR) + if color: + self.canvas.selectedShape.fill_color = color + self.canvas.update() + self.setDirty() + + def copyShape(self): + self.canvas.endMove(copy=True) + self.addLabel(self.canvas.selectedShape) + self.setDirty() + + def moveShape(self): + self.canvas.endMove(copy=False) + self.setDirty() + + def loadPredefinedClasses(self, predefClassesFile): + if os.path.exists(predefClassesFile) is True: + with codecs.open(predefClassesFile, 'r', 'utf8') as f: + for line in f: + line = line.strip() + if self.labelHist is None: + self.labelHist = [line] + else: + self.labelHist.append(line) + + def loadPascalXMLByFilename(self, xmlPath): + if self.filePath is None: + return + if os.path.isfile(xmlPath) is False: + return + + self.set_format(FORMAT_PASCALVOC) + + tVocParseReader = PascalVocReader(xmlPath) + shapes = tVocParseReader.getShapes() + self.loadLabels(shapes) + self.canvas.verified = tVocParseReader.verified + + def loadYOLOTXTByFilename(self, txtPath): + if self.filePath is None: + return + if os.path.isfile(txtPath) is False: + return + + self.set_format(FORMAT_YOLO) + tYoloParseReader = YoloReader(txtPath, self.image) + shapes = tYoloParseReader.getShapes() + print (shapes) + self.loadLabels(shapes) + self.canvas.verified = tYoloParseReader.verified + + def togglePaintLabelsOption(self): + for shape in self.canvas.shapes: + shape.paintLabel = self.displayLabelOption.isChecked() + + def toogleDrawSquare(self): + self.canvas.setDrawingShapeToSquare(self.drawSquaresOption.isChecked()) + +def inverted(color): + return QColor(*[255 - v for v in color.getRgb()]) + + +def read(filename, default=None): + try: + with open(filename, 'rb') as f: + return f.read() + except: + return default + + +def get_main_app(argv=[]): + """ + Standard boilerplate Qt application code. + Do everything but app.exec_() -- so that we can test the application in one thread + """ + app = QApplication(argv) + app.setApplicationName(__appname__) + app.setWindowIcon(newIcon("app")) + # Tzutalin 201705+: Accept extra agruments to change predefined class file + # Usage : labelImg.py image predefClassFile saveDir + win = MainWindow(argv[1] if len(argv) >= 2 else None, + argv[2] if len(argv) >= 3 else os.path.join( + os.path.dirname(sys.argv[0]), + 'data', 'predefined_classes.txt'), + argv[3] if len(argv) >= 4 else None) + win.show() + return app, win + + +def main(): + '''construct main app and run it''' + app, _win = get_main_app(sys.argv) + return app.exec_() + +if __name__ == '__main__': + sys.exit(main()) diff --git a/labelImg-master/libs/__init__.py b/labelImg-master/libs/__init__.py new file mode 100644 index 0000000..d4e244b --- /dev/null +++ b/labelImg-master/libs/__init__.py @@ -0,0 +1,2 @@ +__version_info__ = ('1', '8', '2') +__version__ = '.'.join(__version_info__) diff --git a/labelImg-master/libs/canvas.py b/labelImg-master/libs/canvas.py new file mode 100644 index 0000000..211c390 --- /dev/null +++ b/labelImg-master/libs/canvas.py @@ -0,0 +1,724 @@ + +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + +#from PyQt4.QtOpenGL import * + +from libs.shape import Shape +from libs.utils import distance + +CURSOR_DEFAULT = Qt.ArrowCursor +CURSOR_POINT = Qt.PointingHandCursor +CURSOR_DRAW = Qt.CrossCursor +CURSOR_MOVE = Qt.ClosedHandCursor +CURSOR_GRAB = Qt.OpenHandCursor + +# class Canvas(QGLWidget): + + +class Canvas(QWidget): + zoomRequest = pyqtSignal(int) + scrollRequest = pyqtSignal(int, int) + newShape = pyqtSignal() + selectionChanged = pyqtSignal(bool) + shapeMoved = pyqtSignal() + drawingPolygon = pyqtSignal(bool) + + CREATE, EDIT = list(range(2)) + + epsilon = 11.0 + + def __init__(self, *args, **kwargs): + super(Canvas, self).__init__(*args, **kwargs) + # Initialise local state. + self.mode = self.EDIT + self.shapes = [] + self.current = None + self.selectedShape = None # save the selected shape here + self.selectedShapeCopy = None + self.drawingLineColor = QColor(0, 0, 255) + self.drawingRectColor = QColor(0, 0, 255) + self.line = Shape(line_color=self.drawingLineColor) + self.prevPoint = QPointF() + self.offsets = QPointF(), QPointF() + self.scale = 1.0 + self.pixmap = QPixmap() + self.visible = {} + self._hideBackround = False + self.hideBackround = False + self.hShape = None + self.hVertex = None + self._painter = QPainter() + self._cursor = CURSOR_DEFAULT + # Menus: + self.menus = (QMenu(), QMenu()) + # Set widget options. + self.setMouseTracking(True) + self.setFocusPolicy(Qt.WheelFocus) + self.verified = False + self.drawSquare = False + + def setDrawingColor(self, qColor): + self.drawingLineColor = qColor + self.drawingRectColor = qColor + + def enterEvent(self, ev): + self.overrideCursor(self._cursor) + + def leaveEvent(self, ev): + self.restoreCursor() + + def focusOutEvent(self, ev): + self.restoreCursor() + + def isVisible(self, shape): + return self.visible.get(shape, True) + + def drawing(self): + return self.mode == self.CREATE + + def editing(self): + return self.mode == self.EDIT + + def setEditing(self, value=True): + self.mode = self.EDIT if value else self.CREATE + if not value: # Create + self.unHighlight() + self.deSelectShape() + self.prevPoint = QPointF() + self.repaint() + + def unHighlight(self): + if self.hShape: + self.hShape.highlightClear() + self.hVertex = self.hShape = None + + def selectedVertex(self): + return self.hVertex is not None + + def mouseMoveEvent(self, ev): + """Update line with last point and current coordinates.""" + pos = self.transformPos(ev.pos()) + + # Update coordinates in status bar if image is opened + window = self.parent().window() + if window.filePath is not None: + self.parent().window().labelCoordinates.setText( + 'X: %d; Y: %d' % (pos.x(), pos.y())) + + # Polygon drawing. + if self.drawing(): + self.overrideCursor(CURSOR_DRAW) + if self.current: + color = self.drawingLineColor + if self.outOfPixmap(pos): + # Don't allow the user to draw outside the pixmap. + # Project the point to the pixmap's edges. + pos = self.intersectionPoint(self.current[-1], pos) + elif len(self.current) > 1 and self.closeEnough(pos, self.current[0]): + # Attract line to starting point and colorise to alert the + # user: + pos = self.current[0] + color = self.current.line_color + self.overrideCursor(CURSOR_POINT) + self.current.highlightVertex(0, Shape.NEAR_VERTEX) + + if self.drawSquare: + initPos = self.current[0] + minX = initPos.x() + minY = initPos.y() + min_size = min(abs(pos.x() - minX), abs(pos.y() - minY)) + directionX = -1 if pos.x() - minX < 0 else 1 + directionY = -1 if pos.y() - minY < 0 else 1 + self.line[1] = QPointF(minX + directionX * min_size, minY + directionY * min_size) + else: + self.line[1] = pos + + self.line.line_color = color + self.prevPoint = QPointF() + self.current.highlightClear() + else: + self.prevPoint = pos + self.repaint() + return + + # Polygon copy moving. + if Qt.RightButton & ev.buttons(): + if self.selectedShapeCopy and self.prevPoint: + self.overrideCursor(CURSOR_MOVE) + self.boundedMoveShape(self.selectedShapeCopy, pos) + self.repaint() + elif self.selectedShape: + self.selectedShapeCopy = self.selectedShape.copy() + self.repaint() + return + + # Polygon/Vertex moving. + if Qt.LeftButton & ev.buttons(): + if self.selectedVertex(): + self.boundedMoveVertex(pos) + self.shapeMoved.emit() + self.repaint() + elif self.selectedShape and self.prevPoint: + self.overrideCursor(CURSOR_MOVE) + self.boundedMoveShape(self.selectedShape, pos) + self.shapeMoved.emit() + self.repaint() + return + + # Just hovering over the canvas, 2 posibilities: + # - Highlight shapes + # - Highlight vertex + # Update shape/vertex fill and tooltip value accordingly. + self.setToolTip("Image") + for shape in reversed([s for s in self.shapes if self.isVisible(s)]): + # Look for a nearby vertex to highlight. If that fails, + # check if we happen to be inside a shape. + index = shape.nearestVertex(pos, self.epsilon) + if index is not None: + if self.selectedVertex(): + self.hShape.highlightClear() + self.hVertex, self.hShape = index, shape + shape.highlightVertex(index, shape.MOVE_VERTEX) + self.overrideCursor(CURSOR_POINT) + self.setToolTip("Click & drag to move point") + self.setStatusTip(self.toolTip()) + self.update() + break + elif shape.containsPoint(pos): + if self.selectedVertex(): + self.hShape.highlightClear() + self.hVertex, self.hShape = None, shape + self.setToolTip( + "Click & drag to move shape '%s'" % shape.label) + self.setStatusTip(self.toolTip()) + self.overrideCursor(CURSOR_GRAB) + self.update() + break + else: # Nothing found, clear highlights, reset state. + if self.hShape: + self.hShape.highlightClear() + self.update() + self.hVertex, self.hShape = None, None + self.overrideCursor(CURSOR_DEFAULT) + + def mousePressEvent(self, ev): + pos = self.transformPos(ev.pos()) + + if ev.button() == Qt.LeftButton: + if self.drawing(): + self.handleDrawing(pos) + else: + self.selectShapePoint(pos) + self.prevPoint = pos + self.repaint() + elif ev.button() == Qt.RightButton and self.editing(): + self.selectShapePoint(pos) + self.prevPoint = pos + self.repaint() + + def mouseReleaseEvent(self, ev): + if ev.button() == Qt.RightButton: + menu = self.menus[bool(self.selectedShapeCopy)] + self.restoreCursor() + if not menu.exec_(self.mapToGlobal(ev.pos()))\ + and self.selectedShapeCopy: + # Cancel the move by deleting the shadow copy. + self.selectedShapeCopy = None + self.repaint() + elif ev.button() == Qt.LeftButton and self.selectedShape: + if self.selectedVertex(): + self.overrideCursor(CURSOR_POINT) + else: + self.overrideCursor(CURSOR_GRAB) + elif ev.button() == Qt.LeftButton: + pos = self.transformPos(ev.pos()) + if self.drawing(): + self.handleDrawing(pos) + + def endMove(self, copy=False): + assert self.selectedShape and self.selectedShapeCopy + shape = self.selectedShapeCopy + #del shape.fill_color + #del shape.line_color + if copy: + self.shapes.append(shape) + self.selectedShape.selected = False + self.selectedShape = shape + self.repaint() + else: + self.selectedShape.points = [p for p in shape.points] + self.selectedShapeCopy = None + + def hideBackroundShapes(self, value): + self.hideBackround = value + if self.selectedShape: + # Only hide other shapes if there is a current selection. + # Otherwise the user will not be able to select a shape. + self.setHiding(True) + self.repaint() + + def handleDrawing(self, pos): + if self.current and self.current.reachMaxPoints() is False: + initPos = self.current[0] + minX = initPos.x() + minY = initPos.y() + targetPos = self.line[1] + maxX = targetPos.x() + maxY = targetPos.y() + self.current.addPoint(QPointF(maxX, minY)) + self.current.addPoint(targetPos) + self.current.addPoint(QPointF(minX, maxY)) + self.finalise() + elif not self.outOfPixmap(pos): + self.current = Shape() + self.current.addPoint(pos) + self.line.points = [pos, pos] + self.setHiding() + self.drawingPolygon.emit(True) + self.update() + + def setHiding(self, enable=True): + self._hideBackround = self.hideBackround if enable else False + + def canCloseShape(self): + return self.drawing() and self.current and len(self.current) > 2 + + def mouseDoubleClickEvent(self, ev): + # We need at least 4 points here, since the mousePress handler + # adds an extra one before this handler is called. + if self.canCloseShape() and len(self.current) > 3: + self.current.popPoint() + self.finalise() + + def selectShape(self, shape): + self.deSelectShape() + shape.selected = True + self.selectedShape = shape + self.setHiding() + self.selectionChanged.emit(True) + self.update() + + def selectShapePoint(self, point): + """Select the first shape created which contains this point.""" + self.deSelectShape() + if self.selectedVertex(): # A vertex is marked for selection. + index, shape = self.hVertex, self.hShape + shape.highlightVertex(index, shape.MOVE_VERTEX) + self.selectShape(shape) + return + for shape in reversed(self.shapes): + if self.isVisible(shape) and shape.containsPoint(point): + self.selectShape(shape) + self.calculateOffsets(shape, point) + return + + def calculateOffsets(self, shape, point): + rect = shape.boundingRect() + x1 = rect.x() - point.x() + y1 = rect.y() - point.y() + x2 = (rect.x() + rect.width()) - point.x() + y2 = (rect.y() + rect.height()) - point.y() + self.offsets = QPointF(x1, y1), QPointF(x2, y2) + + def snapPointToCanvas(self, x, y): + """ + Moves a point x,y to within the boundaries of the canvas. + :return: (x,y,snapped) where snapped is True if x or y were changed, False if not. + """ + if x < 0 or x > self.pixmap.width() or y < 0 or y > self.pixmap.height(): + x = max(x, 0) + y = max(y, 0) + x = min(x, self.pixmap.width()) + y = min(y, self.pixmap.height()) + return x, y, True + + return x, y, False + + def boundedMoveVertex(self, pos): + index, shape = self.hVertex, self.hShape + point = shape[index] + if self.outOfPixmap(pos): + pos = self.intersectionPoint(point, pos) + + if self.drawSquare: + opposite_point_index = (index + 2) % 4 + opposite_point = shape[opposite_point_index] + + min_size = min(abs(pos.x() - opposite_point.x()), abs(pos.y() - opposite_point.y())) + directionX = -1 if pos.x() - opposite_point.x() < 0 else 1 + directionY = -1 if pos.y() - opposite_point.y() < 0 else 1 + shiftPos = QPointF(opposite_point.x() + directionX * min_size - point.x(), + opposite_point.y() + directionY * min_size - point.y()) + else: + shiftPos = pos - point + + shape.moveVertexBy(index, shiftPos) + + lindex = (index + 1) % 4 + rindex = (index + 3) % 4 + lshift = None + rshift = None + if index % 2 == 0: + rshift = QPointF(shiftPos.x(), 0) + lshift = QPointF(0, shiftPos.y()) + else: + lshift = QPointF(shiftPos.x(), 0) + rshift = QPointF(0, shiftPos.y()) + shape.moveVertexBy(rindex, rshift) + shape.moveVertexBy(lindex, lshift) + + def boundedMoveShape(self, shape, pos): + if self.outOfPixmap(pos): + return False # No need to move + o1 = pos + self.offsets[0] + if self.outOfPixmap(o1): + pos -= QPointF(min(0, o1.x()), min(0, o1.y())) + o2 = pos + self.offsets[1] + if self.outOfPixmap(o2): + pos += QPointF(min(0, self.pixmap.width() - o2.x()), + min(0, self.pixmap.height() - o2.y())) + # The next line tracks the new position of the cursor + # relative to the shape, but also results in making it + # a bit "shaky" when nearing the border and allows it to + # go outside of the shape's area for some reason. XXX + #self.calculateOffsets(self.selectedShape, pos) + dp = pos - self.prevPoint + if dp: + shape.moveBy(dp) + self.prevPoint = pos + return True + return False + + def deSelectShape(self): + if self.selectedShape: + self.selectedShape.selected = False + self.selectedShape = None + self.setHiding(False) + self.selectionChanged.emit(False) + self.update() + + def deleteSelected(self): + if self.selectedShape: + shape = self.selectedShape + self.shapes.remove(self.selectedShape) + self.selectedShape = None + self.update() + return shape + + def copySelectedShape(self): + if self.selectedShape: + shape = self.selectedShape.copy() + self.deSelectShape() + self.shapes.append(shape) + shape.selected = True + self.selectedShape = shape + self.boundedShiftShape(shape) + return shape + + def boundedShiftShape(self, shape): + # Try to move in one direction, and if it fails in another. + # Give up if both fail. + point = shape[0] + offset = QPointF(2.0, 2.0) + self.calculateOffsets(shape, point) + self.prevPoint = point + if not self.boundedMoveShape(shape, point - offset): + self.boundedMoveShape(shape, point + offset) + + def paintEvent(self, event): + if not self.pixmap: + return super(Canvas, self).paintEvent(event) + + p = self._painter + p.begin(self) + p.setRenderHint(QPainter.Antialiasing) + p.setRenderHint(QPainter.HighQualityAntialiasing) + p.setRenderHint(QPainter.SmoothPixmapTransform) + + p.scale(self.scale, self.scale) + p.translate(self.offsetToCenter()) + + p.drawPixmap(0, 0, self.pixmap) + Shape.scale = self.scale + for shape in self.shapes: + if (shape.selected or not self._hideBackround) and self.isVisible(shape): + shape.fill = shape.selected or shape == self.hShape + shape.paint(p) + if self.current: + self.current.paint(p) + self.line.paint(p) + if self.selectedShapeCopy: + self.selectedShapeCopy.paint(p) + + # Paint rect + if self.current is not None and len(self.line) == 2: + leftTop = self.line[0] + rightBottom = self.line[1] + rectWidth = rightBottom.x() - leftTop.x() + rectHeight = rightBottom.y() - leftTop.y() + p.setPen(self.drawingRectColor) + brush = QBrush(Qt.BDiagPattern) + p.setBrush(brush) + p.drawRect(leftTop.x(), leftTop.y(), rectWidth, rectHeight) + + if self.drawing() and not self.prevPoint.isNull() and not self.outOfPixmap(self.prevPoint): + p.setPen(QColor(0, 0, 0)) + p.drawLine(self.prevPoint.x(), 0, self.prevPoint.x(), self.pixmap.height()) + p.drawLine(0, self.prevPoint.y(), self.pixmap.width(), self.prevPoint.y()) + + self.setAutoFillBackground(True) + if self.verified: + pal = self.palette() + pal.setColor(self.backgroundRole(), QColor(184, 239, 38, 128)) + self.setPalette(pal) + else: + pal = self.palette() + pal.setColor(self.backgroundRole(), QColor(232, 232, 232, 255)) + self.setPalette(pal) + + p.end() + + def transformPos(self, point): + """Convert from widget-logical coordinates to painter-logical coordinates.""" + return point / self.scale - self.offsetToCenter() + + def offsetToCenter(self): + s = self.scale + area = super(Canvas, self).size() + w, h = self.pixmap.width() * s, self.pixmap.height() * s + aw, ah = area.width(), area.height() + x = (aw - w) / (2 * s) if aw > w else 0 + y = (ah - h) / (2 * s) if ah > h else 0 + return QPointF(x, y) + + def outOfPixmap(self, p): + w, h = self.pixmap.width(), self.pixmap.height() + return not (0 <= p.x() <= w and 0 <= p.y() <= h) + + def finalise(self): + assert self.current + if self.current.points[0] == self.current.points[-1]: + self.current = None + self.drawingPolygon.emit(False) + self.update() + return + + self.current.close() + self.shapes.append(self.current) + self.current = None + self.setHiding(False) + self.newShape.emit() + self.update() + + def closeEnough(self, p1, p2): + #d = distance(p1 - p2) + #m = (p1-p2).manhattanLength() + # print "d %.2f, m %d, %.2f" % (d, m, d - m) + return distance(p1 - p2) < self.epsilon + + def intersectionPoint(self, p1, p2): + # Cycle through each image edge in clockwise fashion, + # and find the one intersecting the current line segment. + # http://paulbourke.net/geometry/lineline2d/ + size = self.pixmap.size() + points = [(0, 0), + (size.width(), 0), + (size.width(), size.height()), + (0, size.height())] + x1, y1 = p1.x(), p1.y() + x2, y2 = p2.x(), p2.y() + d, i, (x, y) = min(self.intersectingEdges((x1, y1), (x2, y2), points)) + x3, y3 = points[i] + x4, y4 = points[(i + 1) % 4] + if (x, y) == (x1, y1): + # Handle cases where previous point is on one of the edges. + if x3 == x4: + return QPointF(x3, min(max(0, y2), max(y3, y4))) + else: # y3 == y4 + return QPointF(min(max(0, x2), max(x3, x4)), y3) + + # Ensure the labels are within the bounds of the image. If not, fix them. + x, y, _ = self.snapPointToCanvas(x, y) + + return QPointF(x, y) + + def intersectingEdges(self, x1y1, x2y2, points): + """For each edge formed by `points', yield the intersection + with the line segment `(x1,y1) - (x2,y2)`, if it exists. + Also return the distance of `(x2,y2)' to the middle of the + edge along with its index, so that the one closest can be chosen.""" + x1, y1 = x1y1 + x2, y2 = x2y2 + for i in range(4): + x3, y3 = points[i] + x4, y4 = points[(i + 1) % 4] + denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1) + nua = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3) + nub = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3) + if denom == 0: + # This covers two cases: + # nua == nub == 0: Coincident + # otherwise: Parallel + continue + ua, ub = nua / denom, nub / denom + if 0 <= ua <= 1 and 0 <= ub <= 1: + x = x1 + ua * (x2 - x1) + y = y1 + ua * (y2 - y1) + m = QPointF((x3 + x4) / 2, (y3 + y4) / 2) + d = distance(m - QPointF(x2, y2)) + yield d, i, (x, y) + + # These two, along with a call to adjustSize are required for the + # scroll area. + def sizeHint(self): + return self.minimumSizeHint() + + def minimumSizeHint(self): + if self.pixmap: + return self.scale * self.pixmap.size() + return super(Canvas, self).minimumSizeHint() + + def wheelEvent(self, ev): + qt_version = 4 if hasattr(ev, "delta") else 5 + if qt_version == 4: + if ev.orientation() == Qt.Vertical: + v_delta = ev.delta() + h_delta = 0 + else: + h_delta = ev.delta() + v_delta = 0 + else: + delta = ev.angleDelta() + h_delta = delta.x() + v_delta = delta.y() + + mods = ev.modifiers() + if Qt.ControlModifier == int(mods) and v_delta: + self.zoomRequest.emit(v_delta) + else: + v_delta and self.scrollRequest.emit(v_delta, Qt.Vertical) + h_delta and self.scrollRequest.emit(h_delta, Qt.Horizontal) + ev.accept() + + def keyPressEvent(self, ev): + key = ev.key() + if key == Qt.Key_Escape and self.current: + print('ESC press') + self.current = None + self.drawingPolygon.emit(False) + self.update() + elif key == Qt.Key_Return and self.canCloseShape(): + self.finalise() + elif key == Qt.Key_Left and self.selectedShape: + self.moveOnePixel('Left') + elif key == Qt.Key_Right and self.selectedShape: + self.moveOnePixel('Right') + elif key == Qt.Key_Up and self.selectedShape: + self.moveOnePixel('Up') + elif key == Qt.Key_Down and self.selectedShape: + self.moveOnePixel('Down') + + def moveOnePixel(self, direction): + # print(self.selectedShape.points) + if direction == 'Left' and not self.moveOutOfBound(QPointF(-1.0, 0)): + # print("move Left one pixel") + self.selectedShape.points[0] += QPointF(-1.0, 0) + self.selectedShape.points[1] += QPointF(-1.0, 0) + self.selectedShape.points[2] += QPointF(-1.0, 0) + self.selectedShape.points[3] += QPointF(-1.0, 0) + elif direction == 'Right' and not self.moveOutOfBound(QPointF(1.0, 0)): + # print("move Right one pixel") + self.selectedShape.points[0] += QPointF(1.0, 0) + self.selectedShape.points[1] += QPointF(1.0, 0) + self.selectedShape.points[2] += QPointF(1.0, 0) + self.selectedShape.points[3] += QPointF(1.0, 0) + elif direction == 'Up' and not self.moveOutOfBound(QPointF(0, -1.0)): + # print("move Up one pixel") + self.selectedShape.points[0] += QPointF(0, -1.0) + self.selectedShape.points[1] += QPointF(0, -1.0) + self.selectedShape.points[2] += QPointF(0, -1.0) + self.selectedShape.points[3] += QPointF(0, -1.0) + elif direction == 'Down' and not self.moveOutOfBound(QPointF(0, 1.0)): + # print("move Down one pixel") + self.selectedShape.points[0] += QPointF(0, 1.0) + self.selectedShape.points[1] += QPointF(0, 1.0) + self.selectedShape.points[2] += QPointF(0, 1.0) + self.selectedShape.points[3] += QPointF(0, 1.0) + self.shapeMoved.emit() + self.repaint() + + def moveOutOfBound(self, step): + points = [p1+p2 for p1, p2 in zip(self.selectedShape.points, [step]*4)] + return True in map(self.outOfPixmap, points) + + def setLastLabel(self, text, line_color = None, fill_color = None): + assert text + self.shapes[-1].label = text + if line_color: + self.shapes[-1].line_color = line_color + + if fill_color: + self.shapes[-1].fill_color = fill_color + + return self.shapes[-1] + + def undoLastLine(self): + assert self.shapes + self.current = self.shapes.pop() + self.current.setOpen() + self.line.points = [self.current[-1], self.current[0]] + self.drawingPolygon.emit(True) + + def resetAllLines(self): + assert self.shapes + self.current = self.shapes.pop() + self.current.setOpen() + self.line.points = [self.current[-1], self.current[0]] + self.drawingPolygon.emit(True) + self.current = None + self.drawingPolygon.emit(False) + self.update() + + def loadPixmap(self, pixmap): + self.pixmap = pixmap + self.shapes = [] + self.repaint() + + def loadShapes(self, shapes): + self.shapes = list(shapes) + self.current = None + self.repaint() + + def setShapeVisible(self, shape, value): + self.visible[shape] = value + self.repaint() + + def currentCursor(self): + cursor = QApplication.overrideCursor() + if cursor is not None: + cursor = cursor.shape() + return cursor + + def overrideCursor(self, cursor): + self._cursor = cursor + if self.currentCursor() is None: + QApplication.setOverrideCursor(cursor) + else: + QApplication.changeOverrideCursor(cursor) + + def restoreCursor(self): + QApplication.restoreOverrideCursor() + + def resetState(self): + self.restoreCursor() + self.pixmap = None + self.update() + + def setDrawingShapeToSquare(self, status): + self.drawSquare = status diff --git a/labelImg-master/libs/colorDialog.py b/labelImg-master/libs/colorDialog.py new file mode 100644 index 0000000..d5d9475 --- /dev/null +++ b/labelImg-master/libs/colorDialog.py @@ -0,0 +1,37 @@ +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import QColorDialog, QDialogButtonBox +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + +BB = QDialogButtonBox + + +class ColorDialog(QColorDialog): + + def __init__(self, parent=None): + super(ColorDialog, self).__init__(parent) + self.setOption(QColorDialog.ShowAlphaChannel) + # The Mac native dialog does not support our restore button. + self.setOption(QColorDialog.DontUseNativeDialog) + # Add a restore defaults button. + # The default is set at invocation time, so that it + # works across dialogs for different elements. + self.default = None + self.bb = self.layout().itemAt(1).widget() + self.bb.addButton(BB.RestoreDefaults) + self.bb.clicked.connect(self.checkRestore) + + def getColor(self, value=None, title=None, default=None): + self.default = default + if title: + self.setWindowTitle(title) + if value: + self.setCurrentColor(value) + return self.currentColor() if self.exec_() else None + + def checkRestore(self, button): + if self.bb.buttonRole(button) & BB.ResetRole and self.default: + self.setCurrentColor(self.default) diff --git a/labelImg-master/libs/constants.py b/labelImg-master/libs/constants.py new file mode 100644 index 0000000..f231ec8 --- /dev/null +++ b/labelImg-master/libs/constants.py @@ -0,0 +1,18 @@ +SETTING_FILENAME = 'filename' +SETTING_RECENT_FILES = 'recentFiles' +SETTING_WIN_SIZE = 'window/size' +SETTING_WIN_POSE = 'window/position' +SETTING_WIN_GEOMETRY = 'window/geometry' +SETTING_LINE_COLOR = 'line/color' +SETTING_FILL_COLOR = 'fill/color' +SETTING_ADVANCE_MODE = 'advanced' +SETTING_WIN_STATE = 'window/state' +SETTING_SAVE_DIR = 'savedir' +SETTING_PAINT_LABEL = 'paintlabel' +SETTING_LAST_OPEN_DIR = 'lastOpenDir' +SETTING_AUTO_SAVE = 'autosave' +SETTING_SINGLE_CLASS = 'singleclass' +FORMAT_PASCALVOC='PascalVOC' +FORMAT_YOLO='YOLO' +SETTING_DRAW_SQUARE = 'draw/square' +DEFAULT_ENCODING = 'utf-8' diff --git a/labelImg-master/libs/hashableQListWidgetItem.py b/labelImg-master/libs/hashableQListWidgetItem.py new file mode 100644 index 0000000..ac7818a --- /dev/null +++ b/labelImg-master/libs/hashableQListWidgetItem.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import sys +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + # needed for py3+qt4 + # Ref: + # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html + # http://stackoverflow.com/questions/21217399/pyqt4-qtcore-qvariant-object-instead-of-a-string + if sys.version_info.major >= 3: + import sip + sip.setapi('QVariant', 2) + from PyQt4.QtGui import * + from PyQt4.QtCore import * + +# PyQt5: TypeError: unhashable type: 'QListWidgetItem' + + +class HashableQListWidgetItem(QListWidgetItem): + + def __init__(self, *args): + super(HashableQListWidgetItem, self).__init__(*args) + + def __hash__(self): + return hash(id(self)) diff --git a/labelImg-master/libs/labelDialog.py b/labelImg-master/libs/labelDialog.py new file mode 100644 index 0000000..b59de08 --- /dev/null +++ b/labelImg-master/libs/labelDialog.py @@ -0,0 +1,83 @@ +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + +from libs.utils import newIcon, labelValidator + +BB = QDialogButtonBox + + +class LabelDialog(QDialog): + + def __init__(self, text="Enter object label", parent=None, listItem=None): + super(LabelDialog, self).__init__(parent) + + self.edit = QLineEdit() + self.edit.setText(text) + self.edit.setValidator(labelValidator()) + self.edit.editingFinished.connect(self.postProcess) + + model = QStringListModel() + model.setStringList(listItem) + completer = QCompleter() + completer.setModel(model) + self.edit.setCompleter(completer) + + layout = QVBoxLayout() + layout.addWidget(self.edit) + self.buttonBox = bb = BB(BB.Ok | BB.Cancel, Qt.Horizontal, self) + bb.button(BB.Ok).setIcon(newIcon('done')) + bb.button(BB.Cancel).setIcon(newIcon('undo')) + bb.accepted.connect(self.validate) + bb.rejected.connect(self.reject) + layout.addWidget(bb) + + if listItem is not None and len(listItem) > 0: + self.listWidget = QListWidget(self) + for item in listItem: + self.listWidget.addItem(item) + self.listWidget.itemClicked.connect(self.listItemClick) + self.listWidget.itemDoubleClicked.connect(self.listItemDoubleClick) + layout.addWidget(self.listWidget) + + self.setLayout(layout) + + def validate(self): + try: + if self.edit.text().trimmed(): + self.accept() + except AttributeError: + # PyQt5: AttributeError: 'str' object has no attribute 'trimmed' + if self.edit.text().strip(): + self.accept() + + def postProcess(self): + try: + self.edit.setText(self.edit.text().trimmed()) + except AttributeError: + # PyQt5: AttributeError: 'str' object has no attribute 'trimmed' + self.edit.setText(self.edit.text()) + + def popUp(self, text='', move=True): + self.edit.setText(text) + self.edit.setSelection(0, len(text)) + self.edit.setFocus(Qt.PopupFocusReason) + if move: + self.move(QCursor.pos()) + return self.edit.text() if self.exec_() else None + + def listItemClick(self, tQListWidgetItem): + try: + text = tQListWidgetItem.text().trimmed() + except AttributeError: + # PyQt5: AttributeError: 'str' object has no attribute 'trimmed' + text = tQListWidgetItem.text().strip() + self.edit.setText(text) + + def listItemDoubleClick(self, tQListWidgetItem): + self.listItemClick(tQListWidgetItem) + self.validate() diff --git a/labelImg-master/libs/labelFile.py b/labelImg-master/libs/labelFile.py new file mode 100644 index 0000000..9a3c54e --- /dev/null +++ b/labelImg-master/libs/labelFile.py @@ -0,0 +1,146 @@ +# Copyright (c) 2016 Tzutalin +# Create by TzuTaLin + +try: + from PyQt5.QtGui import QImage +except ImportError: + from PyQt4.QtGui import QImage + +from base64 import b64encode, b64decode +from libs.pascal_voc_io import PascalVocWriter +from libs.yolo_io import YOLOWriter +from libs.pascal_voc_io import XML_EXT +import os.path +import sys + + +class LabelFileError(Exception): + pass + + +class LabelFile(object): + # It might be changed as window creates. By default, using XML ext + # suffix = '.lif' + suffix = XML_EXT + + def __init__(self, filename=None): + self.shapes = () + self.imagePath = None + self.imageData = None + self.verified = False + + def savePascalVocFormat(self, filename, shapes, imagePath, imageData, + lineColor=None, fillColor=None, databaseSrc=None): + imgFolderPath = os.path.dirname(imagePath) + imgFolderName = os.path.split(imgFolderPath)[-1] + imgFileName = os.path.basename(imagePath) + #imgFileNameWithoutExt = os.path.splitext(imgFileName)[0] + # Read from file path because self.imageData might be empty if saving to + # Pascal format + image = QImage() + image.load(imagePath) + imageShape = [image.height(), image.width(), + 1 if image.isGrayscale() else 3] + writer = PascalVocWriter(imgFolderName, imgFileName, + imageShape, localImgPath=imagePath) + writer.verified = self.verified + + for shape in shapes: + points = shape['points'] + label = shape['label'] + # Add Chris + difficult = int(shape['difficult']) + bndbox = LabelFile.convertPoints2BndBox(points) + writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label, difficult) + + writer.save(targetFile=filename) + return + + def saveYoloFormat(self, filename, shapes, imagePath, imageData, classList, + lineColor=None, fillColor=None, databaseSrc=None): + imgFolderPath = os.path.dirname(imagePath) + imgFolderName = os.path.split(imgFolderPath)[-1] + imgFileName = os.path.basename(imagePath) + #imgFileNameWithoutExt = os.path.splitext(imgFileName)[0] + # Read from file path because self.imageData might be empty if saving to + # Pascal format + image = QImage() + image.load(imagePath) + imageShape = [image.height(), image.width(), + 1 if image.isGrayscale() else 3] + writer = YOLOWriter(imgFolderName, imgFileName, + imageShape, localImgPath=imagePath) + writer.verified = self.verified + + for shape in shapes: + points = shape['points'] + label = shape['label'] + # Add Chris + difficult = int(shape['difficult']) + bndbox = LabelFile.convertPoints2BndBox(points) + writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label, difficult) + + writer.save(targetFile=filename, classList=classList) + return + + def toggleVerify(self): + self.verified = not self.verified + + ''' ttf is disable + def load(self, filename): + import json + with open(filename, 'rb') as f: + data = json.load(f) + imagePath = data['imagePath'] + imageData = b64decode(data['imageData']) + lineColor = data['lineColor'] + fillColor = data['fillColor'] + shapes = ((s['label'], s['points'], s['line_color'], s['fill_color'])\ + for s in data['shapes']) + # Only replace data after everything is loaded. + self.shapes = shapes + self.imagePath = imagePath + self.imageData = imageData + self.lineColor = lineColor + self.fillColor = fillColor + + def save(self, filename, shapes, imagePath, imageData, lineColor=None, fillColor=None): + import json + with open(filename, 'wb') as f: + json.dump(dict( + shapes=shapes, + lineColor=lineColor, fillColor=fillColor, + imagePath=imagePath, + imageData=b64encode(imageData)), + f, ensure_ascii=True, indent=2) + ''' + + @staticmethod + def isLabelFile(filename): + fileSuffix = os.path.splitext(filename)[1].lower() + return fileSuffix == LabelFile.suffix + + @staticmethod + def convertPoints2BndBox(points): + xmin = float('inf') + ymin = float('inf') + xmax = float('-inf') + ymax = float('-inf') + for p in points: + x = p[0] + y = p[1] + xmin = min(x, xmin) + ymin = min(y, ymin) + xmax = max(x, xmax) + ymax = max(y, ymax) + + # Martin Kersner, 2015/11/12 + # 0-valued coordinates of BB caused an error while + # training faster-rcnn object detector. + if xmin < 1: + xmin = 1 + + if ymin < 1: + ymin = 1 + + return (int(xmin), int(ymin), int(xmax), int(ymax)) diff --git a/labelImg-master/libs/pascal_voc_io.py b/labelImg-master/libs/pascal_voc_io.py new file mode 100644 index 0000000..627e315 --- /dev/null +++ b/labelImg-master/libs/pascal_voc_io.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +import sys +from xml.etree import ElementTree +from xml.etree.ElementTree import Element, SubElement +from lxml import etree +import codecs +from libs.constants import DEFAULT_ENCODING +from libs.ustr import ustr + + +XML_EXT = '.xml' +ENCODE_METHOD = DEFAULT_ENCODING + +class PascalVocWriter: + + def __init__(self, foldername, filename, imgSize,databaseSrc='Unknown', localImgPath=None): + self.foldername = foldername + self.filename = filename + self.databaseSrc = databaseSrc + self.imgSize = imgSize + self.boxlist = [] + self.localImgPath = localImgPath + self.verified = False + + def prettify(self, elem): + """ + Return a pretty-printed XML string for the Element. + """ + rough_string = ElementTree.tostring(elem, 'utf8') + root = etree.fromstring(rough_string) + return etree.tostring(root, pretty_print=True, encoding=ENCODE_METHOD).replace(" ".encode(), "\t".encode()) + # minidom does not support UTF-8 + '''reparsed = minidom.parseString(rough_string) + return reparsed.toprettyxml(indent="\t", encoding=ENCODE_METHOD)''' + + def genXML(self): + """ + Return XML root + """ + # Check conditions + if self.filename is None or \ + self.foldername is None or \ + self.imgSize is None: + return None + + top = Element('annotation') + if self.verified: + top.set('verified', 'yes') + + folder = SubElement(top, 'folder') + folder.text = self.foldername + + filename = SubElement(top, 'filename') + filename.text = self.filename + + if self.localImgPath is not None: + localImgPath = SubElement(top, 'path') + localImgPath.text = self.localImgPath + + source = SubElement(top, 'source') + database = SubElement(source, 'database') + database.text = self.databaseSrc + + size_part = SubElement(top, 'size') + width = SubElement(size_part, 'width') + height = SubElement(size_part, 'height') + depth = SubElement(size_part, 'depth') + width.text = str(self.imgSize[1]) + height.text = str(self.imgSize[0]) + if len(self.imgSize) == 3: + depth.text = str(self.imgSize[2]) + else: + depth.text = '1' + + segmented = SubElement(top, 'segmented') + segmented.text = '0' + return top + + def addBndBox(self, xmin, ymin, xmax, ymax, name, difficult): + bndbox = {'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax} + bndbox['name'] = name + bndbox['difficult'] = difficult + self.boxlist.append(bndbox) + + def appendObjects(self, top): + for each_object in self.boxlist: + object_item = SubElement(top, 'object') + name = SubElement(object_item, 'name') + name.text = ustr(each_object['name']) + pose = SubElement(object_item, 'pose') + pose.text = "Unspecified" + truncated = SubElement(object_item, 'truncated') + if int(float(each_object['ymax'])) == int(float(self.imgSize[0])) or (int(float(each_object['ymin']))== 1): + truncated.text = "1" # max == height or min + elif (int(float(each_object['xmax']))==int(float(self.imgSize[1]))) or (int(float(each_object['xmin']))== 1): + truncated.text = "1" # max == width or min + else: + truncated.text = "0" + difficult = SubElement(object_item, 'difficult') + difficult.text = str( bool(each_object['difficult']) & 1 ) + bndbox = SubElement(object_item, 'bndbox') + xmin = SubElement(bndbox, 'xmin') + xmin.text = str(each_object['xmin']) + ymin = SubElement(bndbox, 'ymin') + ymin.text = str(each_object['ymin']) + xmax = SubElement(bndbox, 'xmax') + xmax.text = str(each_object['xmax']) + ymax = SubElement(bndbox, 'ymax') + ymax.text = str(each_object['ymax']) + + def save(self, targetFile=None): + root = self.genXML() + self.appendObjects(root) + out_file = None + if targetFile is None: + out_file = codecs.open( + self.filename + XML_EXT, 'w', encoding=ENCODE_METHOD) + else: + out_file = codecs.open(targetFile, 'w', encoding=ENCODE_METHOD) + + prettifyResult = self.prettify(root) + out_file.write(prettifyResult.decode('utf8')) + out_file.close() + + +class PascalVocReader: + + def __init__(self, filepath): + # shapes type: + # [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color, difficult] + self.shapes = [] + self.filepath = filepath + self.verified = False + try: + self.parseXML() + except: + pass + + def getShapes(self): + return self.shapes + + def addShape(self, label, bndbox, difficult): + xmin = int(float(bndbox.find('xmin').text)) + ymin = int(float(bndbox.find('ymin').text)) + xmax = int(float(bndbox.find('xmax').text)) + ymax = int(float(bndbox.find('ymax').text)) + points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)] + self.shapes.append((label, points, None, None, difficult)) + + def parseXML(self): + assert self.filepath.endswith(XML_EXT), "Unsupport file format" + parser = etree.XMLParser(encoding=ENCODE_METHOD) + xmltree = ElementTree.parse(self.filepath, parser=parser).getroot() + filename = xmltree.find('filename').text + try: + verified = xmltree.attrib['verified'] + if verified == 'yes': + self.verified = True + except KeyError: + self.verified = False + + for object_iter in xmltree.findall('object'): + bndbox = object_iter.find("bndbox") + label = object_iter.find('name').text + # Add chris + difficult = False + if object_iter.find('difficult') is not None: + difficult = bool(int(object_iter.find('difficult').text)) + self.addShape(label, bndbox, difficult) + return True diff --git a/labelImg-master/libs/resources.qrc b/labelImg-master/libs/resources.qrc new file mode 100644 index 0000000..37d2f2d --- /dev/null +++ b/labelImg-master/libs/resources.qrc @@ -0,0 +1,38 @@ + + + +resources/icons/help.png +resources/icons/app.png +resources/icons/expert2.png +resources/icons/done.png +resources/icons/file.png +resources/icons/labels.png +resources/icons/objects.png +resources/icons/close.png +resources/icons/fit-width.png +resources/icons/fit-window.png +resources/icons/undo.png +resources/icons/eye.png +resources/icons/quit.png +resources/icons/copy.png +resources/icons/edit.png +resources/icons/open.png +resources/icons/save.png +resources/icons/format_voc.png +resources/icons/format_yolo.png +resources/icons/save-as.png +resources/icons/color.png +resources/icons/color_line.png +resources/icons/zoom.png +resources/icons/zoom-in.png +resources/icons/zoom-out.png +resources/icons/cancel.png +resources/icons/next.png +resources/icons/prev.png +resources/icons/resetall.png +resources/icons/verify.png +resources/strings/strings.properties +resources/strings/strings-zh-TW.properties +resources/strings/strings-zh-CN.properties + + diff --git a/labelImg-master/libs/settings.py b/labelImg-master/libs/settings.py new file mode 100644 index 0000000..e3eea73 --- /dev/null +++ b/labelImg-master/libs/settings.py @@ -0,0 +1,46 @@ +import pickle +import os +import sys + + +class Settings(object): + def __init__(self): + # Be default, the home will be in the same folder as labelImg + home = os.path.expanduser("~") + self.data = {} + self.path = os.path.join(home, '.labelImgSettings.pkl') + + def __setitem__(self, key, value): + self.data[key] = value + + def __getitem__(self, key): + return self.data[key] + + def get(self, key, default=None): + if key in self.data: + return self.data[key] + return default + + def save(self): + if self.path: + with open(self.path, 'wb') as f: + pickle.dump(self.data, f, pickle.HIGHEST_PROTOCOL) + return True + return False + + def load(self): + try: + if os.path.exists(self.path): + with open(self.path, 'rb') as f: + self.data = pickle.load(f) + return True + except: + print('Loading setting failed') + return False + + def reset(self): + if os.path.exists(self.path): + os.remove(self.path) + print('Remove setting pkl file ${0}'.format(self.path)) + self.data = {} + self.path = None diff --git a/labelImg-master/libs/shape.py b/labelImg-master/libs/shape.py new file mode 100644 index 0000000..c72a68f --- /dev/null +++ b/labelImg-master/libs/shape.py @@ -0,0 +1,205 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + +from libs.utils import distance +import sys + +DEFAULT_LINE_COLOR = QColor(0, 255, 0, 128) +DEFAULT_FILL_COLOR = QColor(255, 0, 0, 128) +DEFAULT_SELECT_LINE_COLOR = QColor(255, 255, 255) +DEFAULT_SELECT_FILL_COLOR = QColor(0, 128, 255, 155) +DEFAULT_VERTEX_FILL_COLOR = QColor(0, 255, 0, 255) +DEFAULT_HVERTEX_FILL_COLOR = QColor(255, 0, 0) +MIN_Y_LABEL = 10 + + +class Shape(object): + P_SQUARE, P_ROUND = range(2) + + MOVE_VERTEX, NEAR_VERTEX = range(2) + + # The following class variables influence the drawing + # of _all_ shape objects. + line_color = DEFAULT_LINE_COLOR + fill_color = DEFAULT_FILL_COLOR + select_line_color = DEFAULT_SELECT_LINE_COLOR + select_fill_color = DEFAULT_SELECT_FILL_COLOR + vertex_fill_color = DEFAULT_VERTEX_FILL_COLOR + hvertex_fill_color = DEFAULT_HVERTEX_FILL_COLOR + point_type = P_ROUND + point_size = 8 + scale = 1.0 + + def __init__(self, label=None, line_color=None, difficult=False, paintLabel=False): + self.label = label + self.points = [] + self.fill = False + self.selected = False + self.difficult = difficult + self.paintLabel = paintLabel + + self._highlightIndex = None + self._highlightMode = self.NEAR_VERTEX + self._highlightSettings = { + self.NEAR_VERTEX: (4, self.P_ROUND), + self.MOVE_VERTEX: (1.5, self.P_SQUARE), + } + + self._closed = False + + if line_color is not None: + # Override the class line_color attribute + # with an object attribute. Currently this + # is used for drawing the pending line a different color. + self.line_color = line_color + + def close(self): + self._closed = True + + def reachMaxPoints(self): + if len(self.points) >= 4: + return True + return False + + def addPoint(self, point): + if not self.reachMaxPoints(): + self.points.append(point) + + def popPoint(self): + if self.points: + return self.points.pop() + return None + + def isClosed(self): + return self._closed + + def setOpen(self): + self._closed = False + + def paint(self, painter): + if self.points: + color = self.select_line_color if self.selected else self.line_color + pen = QPen(color) + # Try using integer sizes for smoother drawing(?) + pen.setWidth(max(1, int(round(2.0 / self.scale)))) + painter.setPen(pen) + + line_path = QPainterPath() + vrtx_path = QPainterPath() + + line_path.moveTo(self.points[0]) + # Uncommenting the following line will draw 2 paths + # for the 1st vertex, and make it non-filled, which + # may be desirable. + #self.drawVertex(vrtx_path, 0) + + for i, p in enumerate(self.points): + line_path.lineTo(p) + self.drawVertex(vrtx_path, i) + if self.isClosed(): + line_path.lineTo(self.points[0]) + + painter.drawPath(line_path) + painter.drawPath(vrtx_path) + painter.fillPath(vrtx_path, self.vertex_fill_color) + + # Draw text at the top-left + if self.paintLabel: + min_x = sys.maxsize + min_y = sys.maxsize + for point in self.points: + min_x = min(min_x, point.x()) + min_y = min(min_y, point.y()) + if min_x != sys.maxsize and min_y != sys.maxsize: + font = QFont() + font.setPointSize(8) + font.setBold(True) + painter.setFont(font) + if(self.label == None): + self.label = "" + if(min_y < MIN_Y_LABEL): + min_y += MIN_Y_LABEL + painter.drawText(min_x, min_y, self.label) + + if self.fill: + color = self.select_fill_color if self.selected else self.fill_color + painter.fillPath(line_path, color) + + def drawVertex(self, path, i): + d = self.point_size / self.scale + shape = self.point_type + point = self.points[i] + if i == self._highlightIndex: + size, shape = self._highlightSettings[self._highlightMode] + d *= size + if self._highlightIndex is not None: + self.vertex_fill_color = self.hvertex_fill_color + else: + self.vertex_fill_color = Shape.vertex_fill_color + if shape == self.P_SQUARE: + path.addRect(point.x() - d / 2, point.y() - d / 2, d, d) + elif shape == self.P_ROUND: + path.addEllipse(point, d / 2.0, d / 2.0) + else: + assert False, "unsupported vertex shape" + + def nearestVertex(self, point, epsilon): + for i, p in enumerate(self.points): + if distance(p - point) <= epsilon: + return i + return None + + def containsPoint(self, point): + return self.makePath().contains(point) + + def makePath(self): + path = QPainterPath(self.points[0]) + for p in self.points[1:]: + path.lineTo(p) + return path + + def boundingRect(self): + return self.makePath().boundingRect() + + def moveBy(self, offset): + self.points = [p + offset for p in self.points] + + def moveVertexBy(self, i, offset): + self.points[i] = self.points[i] + offset + + def highlightVertex(self, i, action): + self._highlightIndex = i + self._highlightMode = action + + def highlightClear(self): + self._highlightIndex = None + + def copy(self): + shape = Shape("%s" % self.label) + shape.points = [p for p in self.points] + shape.fill = self.fill + shape.selected = self.selected + shape._closed = self._closed + if self.line_color != Shape.line_color: + shape.line_color = self.line_color + if self.fill_color != Shape.fill_color: + shape.fill_color = self.fill_color + shape.difficult = self.difficult + return shape + + def __len__(self): + return len(self.points) + + def __getitem__(self, key): + return self.points[key] + + def __setitem__(self, key, value): + self.points[key] = value diff --git a/labelImg-master/libs/stringBundle.py b/labelImg-master/libs/stringBundle.py new file mode 100644 index 0000000..a84f169 --- /dev/null +++ b/labelImg-master/libs/stringBundle.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import re +import os +import sys +import locale +from libs.ustr import ustr + +try: + from PyQt5.QtCore import * +except ImportError: + if sys.version_info.major >= 3: + import sip + sip.setapi('QVariant', 2) + from PyQt4.QtCore import * + + +class StringBundle: + + __create_key = object() + + def __init__(self, create_key, localeStr): + assert(create_key == StringBundle.__create_key), "StringBundle must be created using StringBundle.getBundle" + self.idToMessage = {} + paths = self.__createLookupFallbackList(localeStr) + for path in paths: + self.__loadBundle(path) + + @classmethod + def getBundle(cls, localeStr=None): + if localeStr is None: + try: + localeStr = locale.getlocale()[0] if locale.getlocale() and len( + locale.getlocale()) > 0 else os.getenv('LANG') + except: + print('Invalid locale') + localeStr = 'en' + + return StringBundle(cls.__create_key, localeStr) + + def getString(self, stringId): + assert(stringId in self.idToMessage), "Missing string id : " + stringId + return self.idToMessage[stringId] + + def __createLookupFallbackList(self, localeStr): + resultPaths = [] + basePath = ":/strings" + resultPaths.append(basePath) + if localeStr is not None: + # Don't follow standard BCP47. Simple fallback + tags = re.split('[^a-zA-Z]', localeStr) + for tag in tags: + lastPath = resultPaths[-1] + resultPaths.append(lastPath + '-' + tag) + + return resultPaths + + def __loadBundle(self, path): + PROP_SEPERATOR = '=' + f = QFile(path) + if f.exists(): + if f.open(QIODevice.ReadOnly | QFile.Text): + text = QTextStream(f) + text.setCodec("UTF-8") + + while not text.atEnd(): + line = ustr(text.readLine()) + key_value = line.split(PROP_SEPERATOR) + key = key_value[0].strip() + value = PROP_SEPERATOR.join(key_value[1:]).strip().strip('"') + self.idToMessage[key] = value + + f.close() diff --git a/labelImg-master/libs/toolBar.py b/labelImg-master/libs/toolBar.py new file mode 100644 index 0000000..b11887e --- /dev/null +++ b/labelImg-master/libs/toolBar.py @@ -0,0 +1,39 @@ +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + + +class ToolBar(QToolBar): + + def __init__(self, title): + super(ToolBar, self).__init__(title) + layout = self.layout() + m = (0, 0, 0, 0) + layout.setSpacing(0) + layout.setContentsMargins(*m) + self.setContentsMargins(*m) + self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint) + + def addAction(self, action): + if isinstance(action, QWidgetAction): + return super(ToolBar, self).addAction(action) + btn = ToolButton() + btn.setDefaultAction(action) + btn.setToolButtonStyle(self.toolButtonStyle()) + self.addWidget(btn) + + +class ToolButton(QToolButton): + """ToolBar companion class which ensures all buttons have the same size.""" + minSize = (60, 60) + + def minimumSizeHint(self): + ms = super(ToolButton, self).minimumSizeHint() + w1, h1 = ms.width(), ms.height() + w2, h2 = self.minSize + ToolButton.minSize = max(w1, w2), max(h1, h2) + return QSize(*ToolButton.minSize) diff --git a/labelImg-master/libs/ustr.py b/labelImg-master/libs/ustr.py new file mode 100644 index 0000000..511e68b --- /dev/null +++ b/labelImg-master/libs/ustr.py @@ -0,0 +1,17 @@ +import sys +from libs.constants import DEFAULT_ENCODING + +def ustr(x): + '''py2/py3 unicode helper''' + + if sys.version_info < (3, 0, 0): + from PyQt4.QtCore import QString + if type(x) == str: + return x.decode(DEFAULT_ENCODING) + if type(x) == QString: + #https://blog.csdn.net/friendan/article/details/51088476 + #https://blog.csdn.net/xxm524/article/details/74937308 + return unicode(x.toUtf8(), DEFAULT_ENCODING, 'ignore') + return x + else: + return x diff --git a/labelImg-master/libs/utils.py b/labelImg-master/libs/utils.py new file mode 100644 index 0000000..dacf682 --- /dev/null +++ b/labelImg-master/libs/utils.py @@ -0,0 +1,103 @@ +from math import sqrt +from libs.ustr import ustr +import hashlib +import re +import sys + +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + + +def newIcon(icon): + return QIcon(':/' + icon) + + +def newButton(text, icon=None, slot=None): + b = QPushButton(text) + if icon is not None: + b.setIcon(newIcon(icon)) + if slot is not None: + b.clicked.connect(slot) + return b + + +def newAction(parent, text, slot=None, shortcut=None, icon=None, + tip=None, checkable=False, enabled=True): + """Create a new action and assign callbacks, shortcuts, etc.""" + a = QAction(text, parent) + if icon is not None: + a.setIcon(newIcon(icon)) + if shortcut is not None: + if isinstance(shortcut, (list, tuple)): + a.setShortcuts(shortcut) + else: + a.setShortcut(shortcut) + if tip is not None: + a.setToolTip(tip) + a.setStatusTip(tip) + if slot is not None: + a.triggered.connect(slot) + if checkable: + a.setCheckable(True) + a.setEnabled(enabled) + return a + + +def addActions(widget, actions): + for action in actions: + if action is None: + widget.addSeparator() + elif isinstance(action, QMenu): + widget.addMenu(action) + else: + widget.addAction(action) + + +def labelValidator(): + return QRegExpValidator(QRegExp(r'^[^ \t].+'), None) + + +class struct(object): + + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +def distance(p): + return sqrt(p.x() * p.x() + p.y() * p.y()) + + +def fmtShortcut(text): + mod, key = text.split('+', 1) + return '%s+%s' % (mod, key) + + +def generateColorByText(text): + s = ustr(text) + hashCode = int(hashlib.sha256(s.encode('utf-8')).hexdigest(), 16) + r = int((hashCode / 255) % 255) + g = int((hashCode / 65025) % 255) + b = int((hashCode / 16581375) % 255) + return QColor(r, g, b, 100) + +def have_qstring(): + '''p3/qt5 get rid of QString wrapper as py3 has native unicode str type''' + return not (sys.version_info.major >= 3 or QT_VERSION_STR.startswith('5.')) + +def util_qt_strlistclass(): + return QStringList if have_qstring() else list + +def natural_sort(list, key=lambda s:s): + """ + Sort the list into natural alphanumeric order. + """ + def get_alphanum_key_func(key): + convert = lambda text: int(text) if text.isdigit() else text + return lambda s: [convert(c) for c in re.split('([0-9]+)', key(s))] + sort_key = get_alphanum_key_func(key) + list.sort(key=sort_key) diff --git a/labelImg-master/libs/yolo_io.py b/labelImg-master/libs/yolo_io.py new file mode 100644 index 0000000..d494485 --- /dev/null +++ b/labelImg-master/libs/yolo_io.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +import sys +import os +from xml.etree import ElementTree +from xml.etree.ElementTree import Element, SubElement +from lxml import etree +import codecs +from libs.constants import DEFAULT_ENCODING + +TXT_EXT = '.txt' +ENCODE_METHOD = DEFAULT_ENCODING + +class YOLOWriter: + + def __init__(self, foldername, filename, imgSize, databaseSrc='Unknown', localImgPath=None): + self.foldername = foldername + self.filename = filename + self.databaseSrc = databaseSrc + self.imgSize = imgSize + self.boxlist = [] + self.localImgPath = localImgPath + self.verified = False + + def addBndBox(self, xmin, ymin, xmax, ymax, name, difficult): + bndbox = {'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax} + bndbox['name'] = name + bndbox['difficult'] = difficult + self.boxlist.append(bndbox) + + def BndBox2YoloLine(self, box, classList=[]): + xmin = box['xmin'] + xmax = box['xmax'] + ymin = box['ymin'] + ymax = box['ymax'] + + xcen = float((xmin + xmax)) / 2 / self.imgSize[1] + ycen = float((ymin + ymax)) / 2 / self.imgSize[0] + + w = float((xmax - xmin)) / self.imgSize[1] + h = float((ymax - ymin)) / self.imgSize[0] + + # PR387 + boxName = box['name'] + if boxName not in classList: + classList.append(boxName) + + classIndex = classList.index(boxName) + + return classIndex, xcen, ycen, w, h + + def save(self, classList=[], targetFile=None): + + out_file = None #Update yolo .txt + out_class_file = None #Update class list .txt + + if targetFile is None: + out_file = open( + self.filename + TXT_EXT, 'w', encoding=ENCODE_METHOD) + classesFile = os.path.join(os.path.dirname(os.path.abspath(self.filename)), "classes.txt") + out_class_file = open(classesFile, 'w') + + else: + out_file = codecs.open(targetFile, 'w', encoding=ENCODE_METHOD) + classesFile = os.path.join(os.path.dirname(os.path.abspath(targetFile)), "classes.txt") + out_class_file = open(classesFile, 'w') + + + for box in self.boxlist: + classIndex, xcen, ycen, w, h = self.BndBox2YoloLine(box, classList) + # print (classIndex, xcen, ycen, w, h) + out_file.write("%d %.6f %.6f %.6f %.6f\n" % (classIndex, xcen, ycen, w, h)) + + # print (classList) + # print (out_class_file) + for c in classList: + out_class_file.write(c+'\n') + + out_class_file.close() + out_file.close() + + + +class YoloReader: + + def __init__(self, filepath, image, classListPath=None): + # shapes type: + # [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color, difficult] + self.shapes = [] + self.filepath = filepath + + if classListPath is None: + dir_path = os.path.dirname(os.path.realpath(self.filepath)) + self.classListPath = os.path.join(dir_path, "classes.txt") + else: + self.classListPath = classListPath + + # print (filepath, self.classListPath) + + classesFile = open(self.classListPath, 'r') + self.classes = classesFile.read().strip('\n').split('\n') + + # print (self.classes) + + imgSize = [image.height(), image.width(), + 1 if image.isGrayscale() else 3] + + self.imgSize = imgSize + + self.verified = False + # try: + self.parseYoloFormat() + # except: + # pass + + def getShapes(self): + return self.shapes + + def addShape(self, label, xmin, ymin, xmax, ymax, difficult): + + points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)] + self.shapes.append((label, points, None, None, difficult)) + + def yoloLine2Shape(self, classIndex, xcen, ycen, w, h): + label = self.classes[int(classIndex)] + + xmin = max(float(xcen) - float(w) / 2, 0) + xmax = min(float(xcen) + float(w) / 2, 1) + ymin = max(float(ycen) - float(h) / 2, 0) + ymax = min(float(ycen) + float(h) / 2, 1) + + xmin = int(self.imgSize[1] * xmin) + xmax = int(self.imgSize[1] * xmax) + ymin = int(self.imgSize[0] * ymin) + ymax = int(self.imgSize[0] * ymax) + + return label, xmin, ymin, xmax, ymax + + def parseYoloFormat(self): + bndBoxFile = open(self.filepath, 'r') + for bndBox in bndBoxFile: + classIndex, xcen, ycen, w, h = bndBox.split(' ') + label, xmin, ymin, xmax, ymax = self.yoloLine2Shape(classIndex, xcen, ycen, w, h) + + # Caveat: difficult flag is discarded when saved as yolo format. + self.addShape(label, xmin, ymin, xmax, ymax, False) diff --git a/labelImg-master/libs/zoomWidget.py b/labelImg-master/libs/zoomWidget.py new file mode 100644 index 0000000..d33de0d --- /dev/null +++ b/labelImg-master/libs/zoomWidget.py @@ -0,0 +1,26 @@ +try: + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + from PyQt4.QtGui import * + from PyQt4.QtCore import * + + +class ZoomWidget(QSpinBox): + + def __init__(self, value=100): + super(ZoomWidget, self).__init__() + self.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.setRange(1, 500) + self.setSuffix(' %') + self.setValue(value) + self.setToolTip(u'Zoom Level') + self.setStatusTip(self.toolTip()) + self.setAlignment(Qt.AlignCenter) + + def minimumSizeHint(self): + height = super(ZoomWidget, self).minimumSizeHint().height() + fm = QFontMetrics(self.font()) + width = fm.width(str(self.maximum())) + return QSize(width, height) diff --git a/labelImg-master/requirements/requirements-linux-python3.txt b/labelImg-master/requirements/requirements-linux-python3.txt new file mode 100644 index 0000000..787a7fd --- /dev/null +++ b/labelImg-master/requirements/requirements-linux-python3.txt @@ -0,0 +1,2 @@ +pyqt5==5.10.1 +lxml==4.2.4 diff --git a/labelImg-master/resources.qrc b/labelImg-master/resources.qrc new file mode 100644 index 0000000..37d2f2d --- /dev/null +++ b/labelImg-master/resources.qrc @@ -0,0 +1,38 @@ + + + +resources/icons/help.png +resources/icons/app.png +resources/icons/expert2.png +resources/icons/done.png +resources/icons/file.png +resources/icons/labels.png +resources/icons/objects.png +resources/icons/close.png +resources/icons/fit-width.png +resources/icons/fit-window.png +resources/icons/undo.png +resources/icons/eye.png +resources/icons/quit.png +resources/icons/copy.png +resources/icons/edit.png +resources/icons/open.png +resources/icons/save.png +resources/icons/format_voc.png +resources/icons/format_yolo.png +resources/icons/save-as.png +resources/icons/color.png +resources/icons/color_line.png +resources/icons/zoom.png +resources/icons/zoom-in.png +resources/icons/zoom-out.png +resources/icons/cancel.png +resources/icons/next.png +resources/icons/prev.png +resources/icons/resetall.png +resources/icons/verify.png +resources/strings/strings.properties +resources/strings/strings-zh-TW.properties +resources/strings/strings-zh-CN.properties + + diff --git a/labelImg-master/resources/icons/app.icns b/labelImg-master/resources/icons/app.icns new file mode 100644 index 0000000..9409991 Binary files /dev/null and b/labelImg-master/resources/icons/app.icns differ diff --git a/labelImg-master/resources/icons/app.png b/labelImg-master/resources/icons/app.png new file mode 100644 index 0000000..f2dc33e Binary files /dev/null and b/labelImg-master/resources/icons/app.png differ diff --git a/labelImg-master/resources/icons/app.svg b/labelImg-master/resources/icons/app.svg new file mode 100644 index 0000000..b691a2e --- /dev/null +++ b/labelImg-master/resources/icons/app.svg @@ -0,0 +1,30 @@ + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + + + + diff --git a/labelImg-master/resources/icons/cancel.png b/labelImg-master/resources/icons/cancel.png new file mode 100644 index 0000000..8fbfab8 Binary files /dev/null and b/labelImg-master/resources/icons/cancel.png differ diff --git a/labelImg-master/resources/icons/close.png b/labelImg-master/resources/icons/close.png new file mode 100644 index 0000000..aa52a8d Binary files /dev/null and b/labelImg-master/resources/icons/close.png differ diff --git a/labelImg-master/resources/icons/color.png b/labelImg-master/resources/icons/color.png new file mode 100644 index 0000000..1a1e1ad Binary files /dev/null and b/labelImg-master/resources/icons/color.png differ diff --git a/labelImg-master/resources/icons/color_line.png b/labelImg-master/resources/icons/color_line.png new file mode 100644 index 0000000..6ef10bf Binary files /dev/null and b/labelImg-master/resources/icons/color_line.png differ diff --git a/labelImg-master/resources/icons/copy.png b/labelImg-master/resources/icons/copy.png new file mode 100644 index 0000000..a4c9bdd Binary files /dev/null and b/labelImg-master/resources/icons/copy.png differ diff --git a/labelImg-master/resources/icons/delete.png b/labelImg-master/resources/icons/delete.png new file mode 100644 index 0000000..a1a4074 Binary files /dev/null and b/labelImg-master/resources/icons/delete.png differ diff --git a/labelImg-master/resources/icons/done.png b/labelImg-master/resources/icons/done.png new file mode 100644 index 0000000..d8a03f4 Binary files /dev/null and b/labelImg-master/resources/icons/done.png differ diff --git a/labelImg-master/resources/icons/done.svg b/labelImg-master/resources/icons/done.svg new file mode 100644 index 0000000..aa8fd28 --- /dev/null +++ b/labelImg-master/resources/icons/done.svg @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + begin='' id='W5M0MpCehiHzreSzNTczkc9d' + + + + +Adobe PDF library 5.00 + + + + + +2003-12-22T22:34:35+02:00 + +2004-04-17T21:25:50Z + +Adobe Illustrator 10.0 + +2004-01-19T17:51:02+01:00 + + + + +JPEG + +256 + +256 + +/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA +AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK +DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f +Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER +AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA +AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB +UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE +1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ +qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy +obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp +0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo ++DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 +FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F +XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX +Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY +q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq +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 + + + + + + +uuid:4b4d592f-95b8-4bcd-a892-74a536c5e52f + + + +image/svg+xml + + + +test.ai + + + + + + end='w' + + + + + + + + + + diff --git a/labelImg-master/resources/icons/edit.png b/labelImg-master/resources/icons/edit.png new file mode 100644 index 0000000..3677539 Binary files /dev/null and b/labelImg-master/resources/icons/edit.png differ diff --git a/labelImg-master/resources/icons/expert1.png b/labelImg-master/resources/icons/expert1.png new file mode 100644 index 0000000..2813645 Binary files /dev/null and b/labelImg-master/resources/icons/expert1.png differ diff --git a/labelImg-master/resources/icons/expert2.png b/labelImg-master/resources/icons/expert2.png new file mode 100644 index 0000000..7c470b6 Binary files /dev/null and b/labelImg-master/resources/icons/expert2.png differ diff --git a/labelImg-master/resources/icons/eye.png b/labelImg-master/resources/icons/eye.png new file mode 100644 index 0000000..c4b6550 Binary files /dev/null and b/labelImg-master/resources/icons/eye.png differ diff --git a/labelImg-master/resources/icons/feBlend-icon.png b/labelImg-master/resources/icons/feBlend-icon.png new file mode 100644 index 0000000..1c1aca8 Binary files /dev/null and b/labelImg-master/resources/icons/feBlend-icon.png differ diff --git a/labelImg-master/resources/icons/file.png b/labelImg-master/resources/icons/file.png new file mode 100644 index 0000000..1ec0515 Binary files /dev/null and b/labelImg-master/resources/icons/file.png differ diff --git a/labelImg-master/resources/icons/fit-width.png b/labelImg-master/resources/icons/fit-width.png new file mode 100644 index 0000000..0a54907 Binary files /dev/null and b/labelImg-master/resources/icons/fit-width.png differ diff --git a/labelImg-master/resources/icons/fit-window.png b/labelImg-master/resources/icons/fit-window.png new file mode 100644 index 0000000..585e970 Binary files /dev/null and b/labelImg-master/resources/icons/fit-window.png differ diff --git a/labelImg-master/resources/icons/fit.png b/labelImg-master/resources/icons/fit.png new file mode 100644 index 0000000..9e0e817 Binary files /dev/null and b/labelImg-master/resources/icons/fit.png differ diff --git a/labelImg-master/resources/icons/format_voc.png b/labelImg-master/resources/icons/format_voc.png new file mode 100644 index 0000000..cb15e43 Binary files /dev/null and b/labelImg-master/resources/icons/format_voc.png differ diff --git a/labelImg-master/resources/icons/format_yolo.png b/labelImg-master/resources/icons/format_yolo.png new file mode 100644 index 0000000..ca9acc7 Binary files /dev/null and b/labelImg-master/resources/icons/format_yolo.png differ diff --git a/labelImg-master/resources/icons/help.png b/labelImg-master/resources/icons/help.png new file mode 100644 index 0000000..93bf094 Binary files /dev/null and b/labelImg-master/resources/icons/help.png differ diff --git a/labelImg-master/resources/icons/labels.png b/labelImg-master/resources/icons/labels.png new file mode 100644 index 0000000..c82ffb7 Binary files /dev/null and b/labelImg-master/resources/icons/labels.png differ diff --git a/labelImg-master/resources/icons/labels.svg b/labelImg-master/resources/icons/labels.svg new file mode 100644 index 0000000..652cef3 --- /dev/null +++ b/labelImg-master/resources/icons/labels.svg @@ -0,0 +1,819 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + begin='' id='W5M0MpCehiHzreSzNTczkc9d' + + + + + +Adobe PDF library 5.00 + + + + + +2004-01-26T11:58:28+02:00 + +2004-03-28T20:41:40Z + +Adobe Illustrator 10.0 + +2004-02-16T23:58:32+01:00 + + + + +JPEG + +256 + +256 + +/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA +AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK +DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f +Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER +AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA +AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB +UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE +1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ +qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy +obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp +0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo ++DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 +FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqlvmDzFo +3l7TJdT1e5W1tItuTbszHoiKN2Y+AxV4j5g/5ydvTcMnl/SYlgU0Se/LOzDxMcTIF/4M4qk//QzP +nv8A5YNL/wCRVx/2UYq7/oZnz3/ywaX/AMirj/soxV3/AEMz57/5YNL/AORVx/2UYq7/AKGZ89/8 +sGl/8irj/soxV3/QzPnv/lg0v/kVcf8AZRirv+hmfPf/ACwaX/yKuP8AsoxV3/QzPnv/AJYNL/5F +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 +f//Z + + + + + + +uuid:4ee3f24b-6ed2-4a2e-8f7a-50b762c8da8b + + + +image/svg+xml + + + +mime.ai + + + + image/svg+xml + end='w' + + +Labels + \ No newline at end of file diff --git a/labelImg-master/resources/icons/new.png b/labelImg-master/resources/icons/new.png new file mode 100644 index 0000000..dd795cf Binary files /dev/null and b/labelImg-master/resources/icons/new.png differ diff --git a/labelImg-master/resources/icons/next.png b/labelImg-master/resources/icons/next.png new file mode 100644 index 0000000..163a343 Binary files /dev/null and b/labelImg-master/resources/icons/next.png differ diff --git a/labelImg-master/resources/icons/objects.png b/labelImg-master/resources/icons/objects.png new file mode 100644 index 0000000..593bb6d Binary files /dev/null and b/labelImg-master/resources/icons/objects.png differ diff --git a/labelImg-master/resources/icons/open.png b/labelImg-master/resources/icons/open.png new file mode 100644 index 0000000..45fa288 Binary files /dev/null and b/labelImg-master/resources/icons/open.png differ diff --git a/labelImg-master/resources/icons/open.svg b/labelImg-master/resources/icons/open.svg new file mode 100644 index 0000000..48e7a34 --- /dev/null +++ b/labelImg-master/resources/icons/open.svg @@ -0,0 +1,577 @@ + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/labelImg-master/resources/icons/prev.png b/labelImg-master/resources/icons/prev.png new file mode 100644 index 0000000..31b4545 Binary files /dev/null and b/labelImg-master/resources/icons/prev.png differ diff --git a/labelImg-master/resources/icons/quit.png b/labelImg-master/resources/icons/quit.png new file mode 100644 index 0000000..7445887 Binary files /dev/null and b/labelImg-master/resources/icons/quit.png differ diff --git a/labelImg-master/resources/icons/resetall.png b/labelImg-master/resources/icons/resetall.png new file mode 100644 index 0000000..acc12c3 Binary files /dev/null and b/labelImg-master/resources/icons/resetall.png differ diff --git a/labelImg-master/resources/icons/save-as.png b/labelImg-master/resources/icons/save-as.png new file mode 100644 index 0000000..1b5d900 Binary files /dev/null and b/labelImg-master/resources/icons/save-as.png differ diff --git a/labelImg-master/resources/icons/save-as.svg b/labelImg-master/resources/icons/save-as.svg new file mode 100644 index 0000000..c8441a1 --- /dev/null +++ b/labelImg-master/resources/icons/save-as.svg @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + +begin='' id='W5M0MpCehiHzreSzNTczkc9d' + + + + +Adobe PDF library 5.00 + + + + + +2004-01-26T11:58:28+02:00 + +2004-03-28T20:41:40Z + +Adobe Illustrator 10.0 + +2004-02-16T23:58:32+01:00 + + + + +JPEG + +256 + +256 + +/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA +AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK +DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f +Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER +AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA +AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB +UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE +1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ +qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy +obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp +0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo ++DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 +FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqlvmDzFo +3l7TJdT1e5W1tItuTbszHoiKN2Y+AxV4j5g/5ydvTcMnl/SYlgU0Se/LOzDxMcTIF/4M4qk//QzP +nv8A5YNL/wCRVx/2UYq7/oZnz3/ywaX/AMirj/soxV3/AEMz57/5YNL/AORVx/2UYq7/AKGZ89/8 +sGl/8irj/soxV3/QzPnv/lg0v/kVcf8AZRirv+hmfPf/ACwaX/yKuP8AsoxV3/QzPnv/AJYNL/5F +XH/ZRirv+hmfPf8AywaX/wAirj/soxV3/QzPnv8A5YNL/wCRVx/2UYq7/oZnz3/ywaX/AMirj/so +xV3/AEMz57/5YNL/AORVx/2UYq7/AKGZ89/8sGl/8irj/soxV3/QzPnv/lg0v/kVcf8AZRirv+hm +fPf/ACwaX/yKuP8AsoxV3/QzPnv/AJYNL/5FXH/ZRirv+hmfPf8AywaX/wAirj/soxV3/QzPnv8A +5YNL/wCRVx/2UYq7/oZnz3/ywaX/AMirj/soxV3/AEMz57/5YNL/AORVx/2UYq7/AKGZ89/8sGl/ +8irj/soxV3/QzPnv/lg0v/kVcf8AZRirv+hmfPf/ACwaX/yKuP8AsoxVFad/zk75oS4B1HSbG4t+ +6W/qwP8A8E7zj/hcVeyeRfzJ8tec7Vn0yUx3kQBuLCaizJ25AAkMlf2l+mmKsqxV2KuxV2KuxV2K +vm/XDqf5ufmk+j287Q+XtJLqJF3VIY2CSzAHYvM9AvtTwOKvePLfk/y35bs0tdHsYrZVFGlCgyuf +GSQ/Ex+ZxVOK4q6oxVrkMVdyGKu5jFWvUGKu9RffFWvVX3xV3rL74q71l8DirXrp4HFXfWE8DirX +1hPA4q76yngcVd9Zj8D+GKtfWo/A/hirvrcfgfw/rirvrcfgfw/rirX1yLwb8P64q765F4N+H9cV +d9di8G/D+uKtfXovBvw/riqVa/5X8r+abR7TV7GO55CiyMoWZP8AKjkHxKR7HFXzB5n0XXfys8/R +NZXBJgIudOujsJYGJUpIB8ijj+oxV9VeWtfs/MGhWWsWf9xexLKErUoxHxI3up2OKplirsVdirsV +Q+oMy2Fyy/aWJyvzCnFXhP8AziwqvL5nmYcpQLIBz1oxuC2/uVGKvficVaxVrFWicVaJxVrFWsVa +JxVonFWsVaxVrFWicVaxVrFWicVaJxVrFWsVaJxVonFWsVaxVdCSJkp/MP14q8V/5ypRBJ5ZkCjm +wvVZu5CmAgfRyOKsn/5x3vJX8lwWzElQZmSvbjMR/wAbYq9XxV2KuxV2KofUv+Oddf8AGGT/AIic +VeE/84pn/lKP+jD/ALGcVe+nFWsVaJxVonFWsVaxVonFWicVaxVrFWsVaJxVrFWsVaJxVonFWsVa +xVonFWicVaxVrFWicVXQ/wB9H/rD9eKvFv8AnKw/8ov/ANH/AP2LYqn/APzjn/yisHyuP+T4xV6/ +irsVdirsVQ+pf8c66/4wyf8AETirwf8A5xRNf8U/9GH/AGM4q9+PXFWicVaJxVrFWsVaJxVonFWs +VaxVrFWicVaxVrFWicVaJxVrFWsVaJxVonFWsVaxVonFWicVXQ/30f8ArD9eKvFf+crjT/C3/R// +ANi2Ksg/5xy/5RS3+Vx/yfGKvYMVdirsVdiqH1L/AI511/xhk/4icVeDf84nmv8Ain/ow/7GcVe/ +HrirROKtYq1irROKtE4q1irWKtYq0TirWKtYq0TirROKtYq1irROKtE4q1irWKtE4q0TirWKroP7 ++P8A1h+vFXiv/OWBp/hb/o//AOxbFWQf844f8onb/K4/5PjFXsOKuxV2KuxVD6l/xzrr/jDJ/wAR +OKvBP+cTD/ylX/Rh/wBjOKvf2O5xVrFWsVaJxVonFXln5ofnxoPk9pNM05V1XX1qrwK1IYD/AMXO +v7X+Qu/iRmNm1IhsNy7vs7sWef1S9MPtPu/W+fdS81/mp5+uWaS6urm3ZivoQH6vZoaV4mhSKtP5 +zXNXn1dbzlT1uDQ6fAPTEX8z+tX8r+Z/Pf5Xa5azXMUo0+evrac8oe3njGz8GQugkWoNRuNq7GhO +m1Q5xNhhrNHh1cDH+Ideo/Y+q/KfnXRfM+nw3umyVinXkgPXbZlPgynqM3UJiQsPAajTzwzMJiiE ++yTS1irROKtE4q1irWKtE4q0TirWKtYq0TirROKtYq1iq6A/v4/9Zf14q8U/5yzP/KK/9H//AGLY +qyH/AJxv/wCUSt/lcf8AJ/FXsWKuxV2KuxVD6l/xzrr/AIwyf8ROKvAv+cSj/wApV/0Yf9jOKvoB +upxVrFWicVaJxV4h+fH50yaCJPK/l2amsSLTUL1DvbI4qET/AItYGtf2R79MPU6jh9I5vSdi9keL ++9yD0dB3/s+95B5J/L5tQC6rrQZ4JgJLe2JPKXlv6krdeJ6qK1br0+1zGu7S8P0w3l937Xryeg5P +W7GwRESONFSNAFjjQBVVR0CqKAD2GaCUpTNyNlxpzA5Jlr3ky01XQTYapDytrj4gw2kikH2HQkfC +wH8QdiRncdk9ncOmqW0pG/c8jqe1JQ1PHjO0dvIvF/L+u6/+Vvm19PvuUmnyMryqlaPGTRLiCtPi +FKHxoVPTaeHMcciO40XoNTpsfaGATjtLp+o/jzfVXlnzJY67psN3bSrKJUEiOvR1P7Q/iOxzbRkC +LDw2XHKEjGQqQTgnCwaJxVrFWsVaJxVonFWsVaxVonFWicVaxVrFWicVXwf38f8ArL+vFXiX/OWp +/wCUV/6P/wDsWxVkX/ONv/KI23yuf+T+KvY8VdirsVdiqH1L/jnXX/GGT/iJxV4D/wA4kGv+K/8A +t3/9jOKvoFvtH54qtJxVonFWMfmT5vXyj5M1LWwA1xDGEs4z0aeUhI6juAzcm9gcryz4YkuZ2fpf +HzRh0PP3PkvyBob+ZPMFzqWpt9aS3YT3Pq0czTzMSvME7glWZutaUPXOY7R1RxQ2+qX4t9GkBECI +2H6HtlraEmp3J3JOcsBbjZMjItDtrU3a+oQWT4lQ9GI7Z1HY/YxmRlyD0dB3/s+/3PM9p9p1cIHf +qe5mUsMV5CSAC1KMh751s5iIsvOAW87/ADA8gadr+mtY3i8WXk1hegVkglI/FTQc16MPAgEeXajX +ZtNq5ZpbwyHcfo946PXdn5/DiBHp073j/kXzlrX5ceZZNB1rktgJfiZakRM2wnjJA5RuPtDw361B +7fQ62MoiUTcJOX2n2fHVw8SH94Pt8i+qNH1i11SzS4gdW5KGPA8lIYVDKR1U9jm5BeHlEg0eaOxQ +1irROKtE4q1irWKtE4q0TirWKtYq0TirROKr4P7+P/XX9eKvEv8AnLc0/wAKf9vD/sWxVkf/ADjX +/wAofbfK5/5P4q9jxV2KuxV2KofUv+Oddf8AGGT/AIicVfP/APziMa/4r/7d/wD2M4q+gm+0fniq +0nFWsVedfn15Y1LzF+Xlzb6chlurOaO8WAbtIsQZWVffi5I+WUamBlDZ2vYupjh1AMuRFPn78qPM +lrYm40e4iIuJpDNCxNAxChWjpTZhxqPHfw35/P2fHUyAMuCvK/1PXdpZp4o+JEcUevf7/c9Xt9Qk +moFURr4Dc/fm30Xs/gwnil65efL5frt43Vdq5cuw9I8v1ptbB6rwryG4I7ZstXq8WngZ5JCMR3/j +d1+PHKZqIssu0fUGZQrn9+o+LwYZwp9pBq8hEPTGPIHr5/s6O1/I+HHfcpndWsN3CSBWv2l/z75b +qtNDUQJq+8fjqxx5DAvKfzN/LO08x2fAkQapbqTp98QeJHUxTUqSh+9TuO6tzej1U+z8vBPfDL8X +7+96HR6wjccuoed/lX+Y+p+TtZPlrzCWtoIpDHE02wt3O5R/GJ67GtB16bj0PSaoUN7ieRYdr9mD +PHxsX1df6X7Q+oLC/hvbdZoj7MvcHwzaPGognFWicVaxVrFWicVaJxVrFWsVaJxVonFWsVX2/wDv +RF/rr+vFXiP/ADlyaf4U/wC3h/2LYqyT/nGr/lDrb5XP/URir2TFXYq7FXYqh9S/4511/wAYZP8A +iJxV8+/84hn/AJSz/t3/APYzir6Dc/Efniq3FWsVWnf5Yq+d/wA+PydeGWTzf5ahKnl6mpWkIPIP +Wvrx07/zU+fXrg6nT/xB6rsTtblhynb+E/o/V8kF+VXnTStfC6bqf7rW0X4BXilyqipZAOjgCrL9 +K7VC6HtjtPXYcXFhIqPPaz79/wBSdb2Ljxz4gPQfs8vd3fLuvqaRJGKIoUe2ebavX5tRLiyzMz5/ +o7lx44wFRFLlLIwZTRhuCMx4TMSCNiGZF7FP9M1H1BXpIPtr4+4zs+yu0+Mf0hzH6XW6jBXuRd9Z +Q3UJIFVO5p1B8R75s9do4ajGSOR/FtGHKYF41+bP5W/p+3N3Yqkeu2y/umPwrcxiv7pmNArfyMfk +djVdJ2br5aLJ4OX+7PI937O/uei0WsEf6v3Md/Jr81b3S75PLGvM0c0bfV7V56q3JW4/VpeW6sDs +len2fDPQ9LqOh+Dhds9lgjxsXvIH3j9PzfSFtdQ3MCzRGqt94Pgcz3lVTFWsVaJxVonFWsVaxVon +FWicVaxVrFV9uf8ASIv9df14q8Q/5y8P/KJ/9vD/ALFsVZL/AM40f8oba/K5/wCojFXsuKuxV2Ku +xVD6l/xzrr/jDJ/xE4q+fP8AnEE/8pZ/27/+xnFX0G/2j8ziq3FWsVaJxVZIiOjI6hkYEMp3BB6g +4q+Yvzr/ACku/K+of4r8sq8enGQSzRw1DWsla81p+wT93yzXanT16hyex7H7UGWPg5dz0vr5Hz+9 +l35Z/mFaeatMEM7LHrVqg+t2/Tmo29aPxUnr/Kdj1Unzbt3sbwScuMfuzzHd+z7vcy1OnOGVfwnk +f0Hz+/5s0IzmGm243eNw6GjL0OW4ssschKPMLIAiiyDTtQWReQ6/7sTw9xnb9l9piYsfEOrz4KVd +R0+K5hLDodwR2PjmV2l2fDPCxy+78dWGDMYF4X+cX5Wzamr61pMBOs261ubeMfFdRrQBkp1kQDYd +WGw3AB13ZHaUsE/y+fl/Cf0e7u7uT0mi1YGx+k/Yu/JL83pLgx6Hq8pa+ReMMjH/AHoRR3J/3ao/ +4Ie+eg6fPfpPN0/bPZXhk5cY9HUd37Pue+xTRzRrLGwZGFVYZlvOricVaJxVrFWsVaJxVonFWsVa +xVonFV9v/vRF/rr+vFXiH/OXx/5RP/t4f9i2Ksl/5xn/AOUMtflc/wDURir2bFXYq7FXYqh9S/45 +11/xhk/4icVfPX/OH5r/AIt/7d//AGNYq+hH+23zOKrcVaJxVrFWsVUbq2t7u3ktrmNZYJlKSxuK +qynqCMUgkGw+VPzW/LbV/wAvNfj8xeXnkj0ppfUt7iPrbSMT+6bqCjVoK7EfCffVarTAXtcS9r2X +2jHVQ8LL9f8AuvP3/wBoeofl/wCeLHzboy3KFY9QgAS/tQd0c9CK78XpVfu6g55j232OdNLjh/dH +7PL3d32+dObFLFPhPwPf+3vZORmga7XQyyQyB0NCPxHgcvwZ5YpCUeaJREhRZDYXySIGH2T9te4O +d32b2jGcbHLqO51ebCQWtT02OePkvzVvD+zB2r2ZHLGx8D3fsTp85iXz3+cn5aTQyzea9EjMN3A3 +ranBF8P2fiN0lKUYUq9Ov2v5iYdi9rSEvy+baY+k9/l+rvek0epBHAd4nl+r8e5lP5L/AJuLrFuN +M1RwupQj96NgJVH+7Y18R+2o+Y8B3eDPxCjzed7W7MOCXHD+7P2fjo9oV1ZQykFWFQR0IOZLpXYq +1irROKtE4q1irWKtE4q1iq+2/wB6Iv8AXX9eKvD/APnMA0/wl/28P+xXFWTf84y/8oXafK5/6iMV +ez4q7FXYq7FUPqX/ABzrr/jDJ/xE4q+eP+cPTX/Fv/bu/wCxrFX0K/22+ZxVaTirWKtYq0TirROK +oPVdLsNV0+fT7+Fbi0uFKSxOAQQfngIvYsoTMSJRNEPlHzr5S8yflN5ui1TSJGbTJWItJ2+JHQ7t +bzgEV6fxBBFc0+r0kSDGQuEnuNFrIa3Fwz+sc/8Aih+PseyeTvOOneaNFi1K0+BvsXNsTVopQAWQ +mgqN9jTcfdnmHa/ZEtLOxvjPI/oP43+biZMRhLhlz+8d/wCOSfBlOaWmFK1vO8EgdOn7Q7EZk6XV +Swz4o/HzYTgJCiyGyvI5Iwa1jbqD2Pvne9n6+M4f0D9jq8uIg+ahqmmCQB02cfYb+BzF7W7L4xxR ++ocj+j9TZp9RWxfNv5qfl1deWb//ABb5YBtIYZBJd28VB9WlJp6kQ6ekxNCnRe3wmi5XYnbByfus +m2aP21+nv+b0mnzxyx8Oe4P2/j8bvTfyh/Naz8xaeLe6ZYb+EAXNvX7J6eqlf91sf+BP3ntsOYTH +m8r2n2dLTz23geR/Q9TrXfLnWNE4q0TirWKtYq0TirWKtYqvtv8AemL/AF1/Xirw7/nMI0/wl/28 +f+xXFWUf84x/8oVafK5/6iMVez4q7FXYq7FUPqX/ABzrr/jDJ/xE4q+d/wDnDo/8pd/27v8AsaxV +9CyH42+ZxVbirWKtE4q0TirWKtYqlXmXy5pXmPR7jSdThE1rcLxNeqnsynsR45GURIUW3DmlimJx +NEPlbU9P80flB5zPEG4024+yGNI7q3B6EgfDInZqbHxBIOk1uijOJhMXEvb6fPj12K+U4/Yf1F7Z +5e8yabrulQ6np0hktph0YUdHH2o5F3oy9/vFQQc8x7T7MnpcnCd4nke/9rimBBMZfUPx8k2SfNWY +sTBF2d8YJOQ3U/aXxzK0erlgnY5dQ0ZcPEGSWl1HLGBXlG3Q+Htne6LWRyQA5wLqcuMg+aB1nSI5 +43BRXDqVZGAKupFCrA7GozWdrdmSvxMe0xyP469zkabUVsXzJ598j6r+XutxeZfLbOulep9glmNs +7HeCWpq8T9FY7/stvRm2/YnbH5gVL05o8x3+f63ooThqIHHk3v7fP3vbPyu/MnT/ADPpMZDenMlE +mgY7xSU+yT3U/sN/mOwxZRMW8frtFLTz4Ty6HvegE5Y4TWKtYq0TirWKtYq1iq+2P+kxf66/rxV4 +d/zmKf8AlEf+3j/2K4qyj/nGL/lCbT5XX/URir2jFXYq7FXYqh9S/wCOddf8YZP+InFXzr/zhwf+ +Uv8A+3d/2NYq+hpPtt8ziq3FWicVaJxVrFWsVaJxVonFWP8AnbyZpHm7QptK1JNm+KCcfbikH2WU +5CcBIUXI0upngmJw5vmCxuvMX5T+b59M1SJptOmI+sInSWIfZnhJ25rXpX2PY5oNfoI5YnHMbfjc +PbRnDV4xOG0x9nkfL+17fp2q2V/Zw31jOtxZ3C84Jk6MvTvuCCKEHcHY755rrtDPT5DCXwPeGiO/ +MURzCNSf3zBMUGCP0/U2t3od4m+0v8RmZodYcEv6B5/rcXNp+IebKbW6jmjCkhkYfA2d1pdRHJHh +O4PIumyYzE2lXmLQLW+tZ7e4hWaC4Ro54W6SIwoRt3pmk7T7PniyDNi2nHf3/j7XK02or8cnzF5l +8va/+VvmmPVtKLTaJcMVgkapVlO7W1xTo4pVT+0ByG4YL0fY3a8dRDiG0x9Q/HR38hDVYzCfP8bh +9C/l9580zzPpENxby8uXw0enNXHWOQfzD8RvnUwmJCw8ZqtLPBMwl/ay7JuM0TirWKtYq1irROKq +lt/vTF/rr+vFXhn/ADmOf+UQ/wC3j/2K4qyn/nGD/lB7P5XX/UTir2nFXYq7FXYqh9S/4511/wAY +ZP8AiJxV85/84bGv+L/+3d/2NYq+iJP7xvmcVWE4q0TirWKtYq0TirROKtYq1irEPzJ/LzS/Ouhv +Z3AEV9EC1jd03jkp38VPcZXlxiYouZodbPTz4o8uo73zh5W17Vvy68y3Pl7zDG8envJ/pCgEiNzR +VuYtqspAo1Oo9xTOd7R7OjngYT59D3PZkxzwGXFz+/8Aon8be57ZFco6JJG6yRSKHilQhkdGFVZW +GxBG4Oec6nSzwzMJjcMIESFhXSf3zFMUGCaaXqxt34SGsLf8KfHNhoNacJ4ZfQfscPUabiFjmy23 +uUnjEbmtRVG8c7fDljljwy+BdJPGYmwx7zZ5asdU0+5sr2AT2lyvG4hP7QrUMpHRlIrUdDnPa3SZ +NNl8fD9Q5+Y/HP8AW52l1HL7HzS6+Yfym83ru1zpF38SOPhS4hU9uoWaLluO1f5WFet7K7TjngJw ++I7vx0dxqMENXjo7SH2fsL6X8n+btO8xaXBdWswlWVOSOOrAdQR2dejDOhjISFh4rNhlikYyFEMg +yTU1irWKtE4q1iqpa/70xf66/rxV4X/zmSaf4Q/7eP8A2K4qyr/nF/8A5Qaz+V1/1E4q9qxV2Kux +V2KofUv+Oddf8YZP+InFXzl/zhoa/wCMP+3d/wBjWKvoiT+8b5n9eKrCcVaxVrFWicVaJxVrFWsV +aJxVonFWAfm1+V1j510gtEFh1u1UmzuSOvcxvTs2U5sQmPN2PZ3aEtPO+cDzDwbyD5vv/K2qyeVv +MnK2s1kKIZtvqkxJJ3/31ITv2B+IftV5rtPs2OojR2mOR/HR6+dSAy4975+Y/WP2e7sPqMjFW2Iz +gM2CWORjIVIMokSFjkqpP75QYoME40fWfQYQzN+6J+Fv5T/TNp2drvDPBL6fucDVaXi3HNmEMyXM +fpuaOPsnxzsYSGaPDLm6KUDA2OTCfzD8nWes6Df2VzErRtG8kZYf3M6IxjmSm/wnw6io6EjNHDSZ +NNqRPH9Mj6h5d7tdFqLIHX8bPA/yY8z3eh+Y59HuGeOK4LERmtY7mHqQOx4g8vGgzuNLOjXe2du6 +cTxDIOcfuL6k0fU0v7USbeotA9Ohr0I+ebB5FHYq0TirWKtYqqWv+9UP+uv68VeF/wDOZZp/g/8A +7eP/AGK4qyr/AJxd/wCUFs/ldf8AUTir2vFXYq7FXYqh9S/4511/xhk/4icVfOH/ADhia/4w/wC3 +b/2NYq+iZT+8b5n9eKrMVaxVonFWicVaxVrFWicVaJxVrFWsVeWfnR+Ulv5ssG1XTI1j1+1QlSBT +6wij+7b3/lOY+fDxCxzdt2X2kcEuGX92fs83kv5c+e7m1nTyr5hYxGFvQ0+5m2eJwaC2lr+xXZCf +s9Ps048x2p2YM8bG2SP2+RerkBH95DeJ5/8AFD9Pf7+fT+boxVgQymhB6gjOGnjMSQRRDkCpCxyK +qk+VmLEwT/Q9c9Nlt5noP91SE9D4H2zb9na4xIhI+4us1mkv1D4ppqdy+tXUGiwL3EmoTDokSmvH +5tnWwHjECveXCwQGnic0vdEd5/Y+b/zp0N/J/wCa0moWqFLW9dNTtlGwJdv3yV95Fb6DmzPplYc7 +QZBqNNwy84l7d+Xmrxy8FR+UMyj02HQq45Ic2gNi3jJwMZGJ5hn5OFi1irWKtYqqWp/0qH/XX9Yx +V4V/zmcaf4P/AO3l/wBiuKsr/wCcXP8AlBLL5XX/AFE4q9sxV2KuxV2KofUv+Oddf8YZP+InFXzf +/wA4Xmv+Mf8At2/9jWKvomX+8f5n9eKrMVaJxVonFWsVaxVonFWicVaxVrFWicVaJxV4t+eP5PLr +UMnmPQYQNWiWt5bIAPrCj9r/AFwPvzFz4OLcc3edk9p+EfDmfQfs/Ywv8tvzA/SSxeXtaYrq0Q9O +xu3/AN3hf90yk9JV/ZY/a6H4qcuU7W7L8YccP7wfb+3u+Xc9IR4J4h/dnn/R8x5d/dz72frG7EhQ +aru3sPE+GcfHHKRoCy5RkEdpunXd7MI7YBiDR5m/uk+n9o/575vdB2OSbn8unxcXU6mGIXL5dT+p +6JoOmWmmWxiiq8kh5Tzt9uRvE/wzstPjjAUHkdZqp5pWeQ5DueX/APOT3lb9I+TbbXYUrcaNMPVY +Df6vcEI3Twk4H78syDZzexM/DkMDyl94Yb+TmvPLpFoC/wC9tHNsxP8Ak0eL8CBmVppXH3ON21g4 +M5PSW76DhmWaFJV+y6hh9IzIdSuxVrFWicVVLX/eqH/XX9YxV4V/zmgaf4O/7eX/AGK4qyz/AJxa +/wCUDsvldf8AUScVe2Yq7FXYq7FUPqX/ABzrr/jDJ/xE4q+bf+cLTX/GP/bt/wCxrFX0VL/ev/rH +9eKrCcVaJxVrFWsVaJxVonFWsVaxVonFWicVaxVo74q8F/Or8k5by5fzF5ZhUTSVa/sRRQTSvqJ2 +BP7Vdu+YmfT3vF6DsvtcYxwZPp6Hu/Y8z078w/O3lu9S31pJNQiiP+8uoF2ald/Tlrypttuy+2az +Jpo3uKL0UTHJD93Kr6int3kj85vJmuCO09UaTemgW0ueKKT4RyD4G9gaE+GARMXn9XoMsSZH1eb0 +yC498thN1UosQ/OLz35a0DyZfWWrD61catby21rpyMBJJzUqXrvwVK15U69N8zcOM5Nujjz1XgET +/iB2fOf5VambLX7jTy443KcomFfikhPJSvzQscGnPDMxL0na4GbTxyx8j8JfgPqjytei50xd907e +zbj8a5nPLJvirROKtYqqWv8AvVD/AK6/rGKvCf8AnNI0/wAHf9vL/sVxVlv/ADix/wAoFY/K6/6i +Tir23FXYq7FXYqh9S/4511/xhk/4icVfNf8AzhWf+Uy/7dv/AGN4q+i5T+9f/WP68VWE4q1irWKt +E4q0TirWKtYq0TirROKtYq1irROKtHFWGeavy30fW0k9S3jkVqt6bAAhj3Unb78jKIPNtw554zcC +QXiHm38h720keTSXIpU/Vpq9P8k7n/iWYs9L/Nd/pe3jyyj4j9SRaL+Yv5leRD9RmZ3tACkdregy +xrtt6T1qvH+UNTxGYksfCdw7GeDBqomUCL7x+kMO1rVNX1/UpdS1C8e/vpz8bSbP2oqoPhCitFVP +uGbXBqMdUPS8V2j2JqcRMj+8j3j9I6fc1peoyWGoWGpLXnbSKJAD8TCMio9gYzx+/MbVR4MgkOrv +/Z/MM+klhPOO3wPL7bfV/wCX+pKzCIMGRxRSOhDfEp/XmWC6GUSDRZ2TihrFWsVVLT/euH/jIv6x +irwj/nNQ/wDKG/8Aby/7FMVZd/ziv/ygNj8rr/qKOKvbsVdirsVdiqH1L/jnXX/GGT/iJxV80/8A +OFBr/jL/ALdv/Y3ir6MmP71/9Y/rxVZirWKtE4q0TirWKtYq0TirROKtYq1irROKtYq1irWKqc0M +MyGOVA6HsRXFWMa/5B0jVIXR4kdXFDHKKinhy6/fXAQDzZwySgbiaLxjzh+QZiZ5tKZrdzUiB94y +dzsf6H6Mxp6UHk7vS9uTjtkHEO/q8r1vy75k0ovb39rII0IZpgvJaLVVJelQKdA2Y8xMCjydxpZ6 +aczkx0Jy59D8R+l7H+T2vNNo9i3KsttW2fsAYqGP/hOOZmnlcXnO18PBnPdLf8fF73HIskayL9lw +GX5EVy51jeKtYqqWh/0uH/jIv6xirwf/AJzXNP8ABv8A28v+xTFWX/8AOKv/AJL+x+V3/wBRRxV7 +firsVdirsVQ+pf8AHOuv+MMn/ETir5o/5wmNf8Z/9u3/ALG8VfRs396/+sf14qp4q0TirROKtYq1 +irROKtE4q1irWKtE4q1irWKtYq0TirWKtYqskRJFKuoZT1UioxVI9V8o6ZfIQEUH+VxyX6O6/Rir +EW8gNpk0k1lEYjI4kbiOalhtUkfF274AAGc8kpVZJpnukpLHYRLIQSBVSO6ncdfnhYIvFWicVVbT +/euD/jIv/Ehirwb/AJzZNP8ABn/by/7FMVZf/wA4qf8AkvrD5Xf/AFFHFXuGKuxV2KuxVD6l/wAc +66/4wyf8ROKvmb/nCQ/8pn/27P8AsbxV9HTf3z/6x/XiqmTirROKtYq1irROKtE4q1irWKtE4q1i +rWKtYq0TirWKtYq1irROKtYq1irWKtE4q1iqrZ/71wf8ZF/4kMVeC/8AObZ/5Qz/ALef/YpirMP+ +cUv/ACXth8rv/qKOKvccVdirsVdiqH1L/jnXX/GGT/iJxV8y/wDOER/5TT/t2f8AY3ir6OnP75/9 +Y/rxVTJxVrFWsVaJxVonFWsVaxVonFWsVaxVrFWicVaxVrFWsVaJxVrFWsVaxVonFWsVaxVVs/8A +eyD/AIyL/wASGKvBf+c3T/yhf/bz/wCxTFWY/wDOKH/kvLD5Xf8A1FHFXuOKuxV2KuxVD6l/xzrr +/jDJ/wAROKvmP/nB81/xp/27P+xvFX0fOf30n+sf14qp4q1irROKtE4q1irWKtE4q1irWKtYq0Ti +rWKtYq1irROKtYq1irWKtE4q1irWKtYqq2Z/0yD/AIyJ/wASGKvBP+c4DT/Bf/bz/wCxTFWZf84n +/wDku9P+V3/1FHFXuWKuxV2KuxVD6l/xzrr/AIwyf8ROKvmD/nCCRUn86W7njORpzCM7NRDdBtvY +sK4q+kbiomkr/Mf14qp4q0TirROKtYq1irROKtYq1irWKtE4q1irWKtYq0TirWKtYq1irROKtYq1 +irWKtE4qrWIJvIABU81P3GuKvAP+c4ZozL5MiDAyIupOydwrG1Cn6eJxVm3/ADieGH5dafUEHjdn +fwN0SMVe5Yq7FXYq7FVskayRtG32XBVvkRTFXxjrN7rf5Efnjca1FbNP5e1ZpDLAtFWW2mcPLGld +g8MlGT2p2JxV9U+U/PHknzvp8d/5f1SG8DrV4UcLcRnussJ+NCPcfLbFU8/R0X8zfhirv0bF/M34 +Yq1+jIv52/DFXfoyL+dvwxV36Lh/nb8MVa/RUP8AO34Yq79FQ/zt+H9MVa/RMP8AO34Yq79Ew/zt ++GKu/REH87fh/TFWv0PB/O34f0xV36Hg/nb8P6Yq79DQfzt+H9MVa/QsH87fh/TFXfoWD/fj/h/T +FWv0Jb/78f8AD+mKu/Qdv/vx/wAP6Yq1+g7f/fj/AIf0xV36Ct/9+P8Ah/TFXfoK3/34/wCH9MVa +/QNv/vx/w/pirv0Bbf78f8P6Yqk3mfzh5E8iWEuoa9qcNpxUlIpHDXEngsUK/G5PsPntir4i/MXz +tr35wfmQtxa27Rxy8bTSbImvo2yEtykI2qas7n6OgGKvsf8AJ7y5HoWhW1jAP3NpbpEGIoWJp8R9 +24VPzxV6FirsVdirsVdirE/zG/Lfy/560OTTNViUvSsE9KsjjoR3+7FXyP5v/wCcW/Nuk3rpYTLL +ASfTMwYrx9pIw1fpQYqx3/oXzz942v8AwU//AFSxV3/Qvnn7xtf+Cn/6pYq7/oXzz942v/BT/wDV +LFXf9C+efvG1/wCCn/6pYq7/AKF88/eNr/wU/wD1SxV3/Qvnn7xtf+Cn/wCqWKu/6F88/eNr/wAF +P/1SxV3/AEL55+8bX/gp/wDqlirv+hfPP3ja/wDBT/8AVLFXf9C+efvG1/4Kf/qlirv+hfPP3ja/ +8FP/ANUsVd/0L55+8bX/AIKf/qlirv8AoXzz942v/BT/APVLFXf9C+efvG1/4Kf/AKpYq7/oXzz9 +42v/AAU//VLFXf8AQvnn7xtf+Cn/AOqWKu/6F88/eNr/AMFP/wBUsVd/0L55+8bX/gp/+qWKu/6F +88/eNr/wU/8A1SxV3/Qvnn7xtf8Agp/+qWKu/wChfPP3ja/8FP8A9UsVd/0L55+8bX/gp/8Aqliq +L0z/AJxz85XFwEu54IIu7xiWRv8AgWWP9eKvevys/JPTPLg/0WEz3sgHr3UtC5HWjECiJ/kjr3xV +7vpthHY2qwpuert4se+KorFXYq7FXYq7FXYqtkijlUpIgdD1VgCPxxVCnRtLJ/3mT7sVd+htL/5Z +k/HFXfobS/8AlmT8cVd+htL/AOWZPxxV36G0v/lmT8cVd+htL/5Zk/HFXfobS/8AlmT8cVd+htL/ +AOWZPxxV36G0v/lmT8cVd+htL/5Zk/HFXfobS/8AlmT8cVd+htL/AOWZPxxV36G0v/lmT8cVd+ht +L/5Zk/HFXfobS/8AlmT8cVd+htL/AOWZPxxV36G0v/lmT8cVd+htL/5Zk/HFXfobS/8AlmT8cVd+ +htL/AOWZPxxV36G0v/lmT8cVd+htL/5Zk/HFXDRtLB/3mT7sVRUcUcShI0CIOiqAB+GKrsVdirsV +f//Z + + + + + + +uuid:4ee3f24b-6ed2-4a2e-8f7a-50b762c8da8b + + + +image/svg+xml + + + +mime.ai + + + + + + +end='w' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +begin='' id='W5M0MpCehiHzreSzNTczkc9d' + + + + +Adobe PDF library 5.00 + + + + + +2004-02-04T02:08:51+02:00 + +2004-03-29T09:20:16Z + +Adobe Illustrator 10.0 + +2004-02-29T14:54:28+01:00 + + + + +JPEG + +256 + +256 + +/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA +AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK +DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f +Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER +AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA +AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB +UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE +1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ +qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy +obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp +0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo ++DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 +FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F +XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX +Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY +q7FXzd+b/wDzlWum3k+h+QxFc3EJMdzrkoEkKuNiLZPsyU/nb4fAEb50vZ/YXEBPLsP5v62meXue +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 + + + + + + +uuid:f3c53255-be8a-4b04-817b-695bf2c54c8b + + + +image/svg+xml + + + +filesave.ai + + + + + + +end='w' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labelImg-master/resources/icons/save.png b/labelImg-master/resources/icons/save.png new file mode 100644 index 0000000..daba865 Binary files /dev/null and b/labelImg-master/resources/icons/save.png differ diff --git a/labelImg-master/resources/icons/save.svg b/labelImg-master/resources/icons/save.svg new file mode 100644 index 0000000..5533e48 --- /dev/null +++ b/labelImg-master/resources/icons/save.svg @@ -0,0 +1,679 @@ + + + + + + + + begin='' id='W5M0MpCehiHzreSzNTczkc9d' + + + + +Adobe PDF library 5.00 + + + + + +2004-02-04T02:08:51+02:00 + +2004-03-29T09:20:16Z + +Adobe Illustrator 10.0 + +2004-02-29T14:54:28+01:00 + + + + +JPEG + +256 + +256 + +/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA +AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK +DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f +Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAEAAwER +AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA +AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB +UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE +1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ +qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy +obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp +0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo ++DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 +FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F +XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX +Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY +q7FXzd+b/wDzlWum3k+h+QxFc3EJMdzrkoEkKuNiLZPsyU/nb4fAEb50vZ/YXEBPLsP5v62meXue +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 + + + + + + +uuid:f3c53255-be8a-4b04-817b-695bf2c54c8b + + + +image/svg+xml + + + +filesave.ai + + + + + + end='w' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labelImg-master/resources/icons/undo-cross.png b/labelImg-master/resources/icons/undo-cross.png new file mode 100644 index 0000000..7d57dcb Binary files /dev/null and b/labelImg-master/resources/icons/undo-cross.png differ diff --git a/labelImg-master/resources/icons/undo.png b/labelImg-master/resources/icons/undo.png new file mode 100644 index 0000000..b2ac62b Binary files /dev/null and b/labelImg-master/resources/icons/undo.png differ diff --git a/labelImg-master/resources/icons/verify.png b/labelImg-master/resources/icons/verify.png new file mode 100644 index 0000000..3f4a3b5 Binary files /dev/null and b/labelImg-master/resources/icons/verify.png differ diff --git a/labelImg-master/resources/icons/zoom-in.png b/labelImg-master/resources/icons/zoom-in.png new file mode 100644 index 0000000..1ac4864 Binary files /dev/null and b/labelImg-master/resources/icons/zoom-in.png differ diff --git a/labelImg-master/resources/icons/zoom-out.png b/labelImg-master/resources/icons/zoom-out.png new file mode 100644 index 0000000..d67a87d Binary files /dev/null and b/labelImg-master/resources/icons/zoom-out.png differ diff --git a/labelImg-master/resources/icons/zoom.png b/labelImg-master/resources/icons/zoom.png new file mode 100644 index 0000000..8265f27 Binary files /dev/null and b/labelImg-master/resources/icons/zoom.png differ diff --git a/labelImg-master/resources/strings/strings-zh-CN.properties b/labelImg-master/resources/strings/strings-zh-CN.properties new file mode 100644 index 0000000..5459a0e --- /dev/null +++ b/labelImg-master/resources/strings/strings-zh-CN.properties @@ -0,0 +1,65 @@ +saveAsDetail=將标签保存到其他文件 +changeSaveDir=改变存放目录 +openFile=打开文件 +shapeLineColorDetail=更改线条颜色 +resetAll=全部重置 +crtBox=创建区块 +crtBoxDetail=创建一个新的区块 +dupBoxDetail=复制区块 +verifyImg=验证图像 +zoominDetail=放大 +verifyImgDetail=验证图像 +saveDetail=保存标签文件 +openFileDetail=打开图像文件 +fitWidthDetail=调整宽度适应到窗口宽度 +tutorial=YouTube教学 +editLabel=编辑标签 +openAnnotationDetail=打开标签文件 +quit=退出 +shapeFillColorDetail=更改填充颜色 +closeCurDetail=关闭当前文件 +closeCur=关闭文件 +fitWin=调整到窗口大小 +delBox=删除选择的区块 +boxLineColorDetail=选择线框颜色 +originalsize=原始大小 +resetAllDetail=重置所有设定 +zoomoutDetail=放大画面 +save=保存 +saveAs=另存为 +fitWinDetail=缩放到当前窗口大小 +openDir=打开目录 +showHide=显示/隐藏标签 +changeSaveFormat=更改存储格式 +shapeFillColor=填充颜色 +quitApp=退出程序 +dupBox=复制区块 +delBoxDetail=删除区块 +zoomin=放大画面 +info=信息 +openAnnotation=开启标签 +prevImgDetail=上一个图像 +fitWidth=缩放到跟当前画面一样宽 +zoomout=缩小画面 +changeSavedAnnotationDir=更改保存标签文件的预设目录 +nextImgDetail=下一个图像 +originalsizeDetail=放大到原始大小 +prevImg=上一个图像 +tutorialDetail=显示示范内容 +shapeLineColor=形状线条颜色 +boxLineColor=区块线条颜色 +editLabelDetail=修改当前所选的区块颜色 +nextImg=下一个图片 +useDefaultLabel=使用预设标签 +useDifficult=有难度的 +boxLabelText=区块的标签 +labels=标签 +autoSaveMode=自动保存模式 +singleClsMode=单一类别模式 +displayLabel=显示类别 +fileList=文件列表 +files=文件 +advancedMode=专家模式 +advancedModeDetail=切换到专家模式 +showAllBoxDetail=显示所有区块 +hideAllBoxDetail=隐藏所有区块 diff --git a/labelImg-master/resources/strings/strings-zh-TW.properties b/labelImg-master/resources/strings/strings-zh-TW.properties new file mode 100644 index 0000000..c09f369 --- /dev/null +++ b/labelImg-master/resources/strings/strings-zh-TW.properties @@ -0,0 +1,65 @@ +saveAsDetail=將標籤保存到其他文件 +changeSaveDir=改變存放目錄 +openFile=開啟檔案 +shapeLineColorDetail=更改線條顏色 +resetAll=重置 +crtBox=創建區塊 +crtBoxDetail=畫一個區塊 +dupBoxDetail=複製區塊 +verifyImg=驗證圖像 +zoominDetail=放大 +verifyImgDetail=驗證圖像 +saveDetail=將標籤存到 +openFileDetail=打開圖像 +fitWidthDetail=調整到窗口寬度 +tutorial=YouTube教學 +editLabel=編輯標籤 +openAnnotationDetail=打開標籤文件 +quit=結束 +shapeFillColorDetail=更改填充顏色 +closeCurDetail=關閉目前檔案 +closeCur=關閉 +fitWin=調整到跟窗口一樣大小 +delBox=刪除選取區塊 +boxLineColorDetail=選擇框線顏色 +originalsize=原始大小 +resetAllDetail=重設所有設定 +zoomoutDetail=畫面放大 +save=儲存 +saveAs=另存為 +fitWinDetail=縮放到窗口一樣 +openDir=開啟目錄 +showHide=顯示/隱藏標籤 +changeSaveFormat=更改儲存格式 +shapeFillColor=填充顏色 +quitApp=離開本程式 +dupBox=複製區塊 +delBoxDetail=刪除區塊 +zoomin=放大畫面 +info=資訊 +openAnnotation=開啟標籤 +prevImgDetail=上一個圖像 +fitWidth=縮放到跟畫面一樣寬 +zoomout=縮小畫面 +changeSavedAnnotationDir=更改預設標籤存的目錄 +nextImgDetail=下一個圖像 +originalsizeDetail=放大到原始大小 +prevImg=上一個圖像 +tutorialDetail=顯示示範內容 +shapeLineColor=形狀線條顏色 +boxLineColor=日期分隔線顏色 +editLabelDetail=修改所選區塊的標籤 +nextImg=下一張圖片 +useDefaultLabel=使用預設標籤 +useDifficult=有難度的 +boxLabelText=區塊的標籤 +labels=標籤 +autoSaveMode=自動儲存模式 +singleClsMode=單一類別模式 +displayLabel=顯示類別 +fileList=檔案清單 +files=檔案 +advancedMode=進階模式 +advancedModeDetail=切到進階模式 +showAllBoxDetail=顯示所有區塊 +hideAllBoxDetail=隱藏所有區塊 \ No newline at end of file diff --git a/labelImg-master/resources/strings/strings.properties b/labelImg-master/resources/strings/strings.properties new file mode 100644 index 0000000..94525fe --- /dev/null +++ b/labelImg-master/resources/strings/strings.properties @@ -0,0 +1,65 @@ +openFile=Open +openFileDetail=Open image or label file +quit=Quit +quitApp=Quit application +openDir=Open Dir +changeSavedAnnotationDir=Change default saved Annotation dir +openAnnotation=Open Annotation +openAnnotationDetail=Open an annotation file +changeSaveDir=Change Save Dir +nextImg=Next Image +nextImgDetail=Open the next Image +prevImg=Prev Image +prevImgDetail=Open the previous Image +verifyImg=Verify Image +verifyImgDetail=Verify Image +save=Save +saveDetail=Save the labels to a file +changeSaveFormat=Change save format +saveAs=Save As +saveAsDetail=Save the labels to a different file +closeCur=Close +closeCurDetail=Close the current file +resetAll=Reset All +resetAllDetail=Reset All +boxLineColor=Box Line Color +boxLineColorDetail=Choose Box line color +crtBox=Create\nRectBox +crtBoxDetail=Draw a new box +delBox=Delete\nRectBox +delBoxDetail=Remove the box +dupBox=Duplicate\nRectBox +dupBoxDetail=Create a duplicate of the selected box +tutorial=Tutorial +tutorialDetail=Show demo +info=Information +zoomin=Zoom In +zoominDetail=Increase zoom level +zoomout=Zoom Out +zoomoutDetail=Decrease zoom level +originalsize=Original size +originalsizeDetail=Zoom to original size +fitWin=Fit Window +fitWinDetail=Zoom follows window size +fitWidth=Fit Width +fitWidthDetail=Zoom follows window width +editLabel=Edit Label +editLabelDetail=Modify the label of the selected Box +shapeLineColor=Shape Line Color +shapeLineColorDetail=Change the line color for this specific shape +shapeFillColor=Shape Fill Color +shapeFillColorDetail=Change the fill color for this specific shape +showHide=Show/Hide Label Panel +useDefaultLabel=Use default label +useDifficult=difficult +boxLabelText=Box Labels +labels=Labels +autoSaveMode=Auto Save mode +singleClsMode=Single Class Mode +displayLabel=Display Labels +fileList=File List +files=Files +advancedMode=Advanced Mode +advancedModeDetail=Swtich to advanced mode +showAllBoxDetail=Show all bounding boxes +hideAllBoxDetail=Hide all bounding boxes diff --git a/labelImg-master/setup.cfg b/labelImg-master/setup.cfg new file mode 100644 index 0000000..3b273b6 --- /dev/null +++ b/labelImg-master/setup.cfg @@ -0,0 +1,8 @@ +[bumpversion] +commit = True +tag = True + +[bumpversion:file:setup.py] + +[bdist_wheel] +universal = 1 diff --git a/labelImg-master/setup.py b/labelImg-master/setup.py new file mode 100644 index 0000000..a765bf6 --- /dev/null +++ b/labelImg-master/setup.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from setuptools import setup, find_packages, Command +from sys import platform as _platform +from shutil import rmtree +import sys +import os + +here = os.path.abspath(os.path.dirname(__file__)) +NAME = 'labelImg' +REQUIRES_PYTHON = '>=3.0.0' +REQUIRED_DEP = ['pyqt5', 'lxml'] +about = {} + +with open(os.path.join(here, 'libs', '__init__.py')) as f: + exec(f.read(), about) + +with open('README.rst') as readme_file: + readme = readme_file.read() + +with open('HISTORY.rst') as history_file: + history = history_file.read() + + +# OS specific settings +SET_REQUIRES = [] +if _platform == "linux" or _platform == "linux2": + # linux + print('linux') +elif _platform == "darwin": + # MAC OS X + SET_REQUIRES.append('py2app') + +required_packages = find_packages() +required_packages.append('labelImg') + +APP = [NAME + '.py'] +OPTIONS = { + 'argv_emulation': True, + 'iconfile': 'resources/icons/app.icns' +} + +class UploadCommand(Command): + """Support setup.py upload.""" + + description=readme + '\n\n' + history, + + user_options = [] + + @staticmethod + def status(s): + """Prints things in bold.""" + print('\033[1m{0}\033[0m'.format(s)) + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + try: + self.status('Removing previous builds…') + rmtree(os.path.join(here, 'dist')) + except OSError: + self.status('Fail to remove previous builds..') + pass + + self.status('Building Source and Wheel (universal) distribution…') + os.system( + '{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) + + self.status('Uploading the package to PyPI via Twine…') + os.system('twine upload dist/*') + + self.status('Pushing git tags…') + os.system('git tag -d v{0}'.format(about['__version__'])) + os.system('git tag v{0}'.format(about['__version__'])) + # os.system('git push --tags') + + sys.exit() + + +setup( + app=APP, + name=NAME, + version=about['__version__'], + description="LabelImg is a graphical image annotation tool and label object bounding boxes in images", + long_description=readme + '\n\n' + history, + author="TzuTa Lin", + author_email='tzu.ta.lin@gmail.com', + url='https://github.com/tzutalin/labelImg', + python_requires=REQUIRES_PYTHON, + package_dir={'labelImg': '.'}, + packages=required_packages, + entry_points={ + 'console_scripts': [ + 'labelImg=labelImg.labelImg:main' + ] + }, + include_package_data=True, + install_requires=REQUIRED_DEP, + license="MIT license", + zip_safe=False, + keywords='labelImg labelTool development annotation deeplearning', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Natural Language :: English', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + ], + package_data={'data/predefined_classes.txt': ['data/predefined_classes.txt']}, + options={'py2app': OPTIONS}, + setup_requires=SET_REQUIRES, + # $ setup.py publish support. + cmdclass={ + 'upload': UploadCommand, + } +) diff --git a/labelImg-master/tests/.gitignore b/labelImg-master/tests/.gitignore new file mode 100644 index 0000000..a6535f3 --- /dev/null +++ b/labelImg-master/tests/.gitignore @@ -0,0 +1 @@ +test.xml diff --git a/labelImg-master/tests/test.512.512.bmp b/labelImg-master/tests/test.512.512.bmp new file mode 100644 index 0000000..fe7415d Binary files /dev/null and b/labelImg-master/tests/test.512.512.bmp differ diff --git a/labelImg-master/tests/test_io.py b/labelImg-master/tests/test_io.py new file mode 100644 index 0000000..7067b40 --- /dev/null +++ b/labelImg-master/tests/test_io.py @@ -0,0 +1,32 @@ +import os +import sys +import unittest + +class TestPascalVocRW(unittest.TestCase): + + def test_upper(self): + dir_name = os.path.abspath(os.path.dirname(__file__)) + libs_path = os.path.join(dir_name, '..', 'libs') + sys.path.insert(0, libs_path) + from pascal_voc_io import PascalVocWriter + from pascal_voc_io import PascalVocReader + + # Test Write/Read + writer = PascalVocWriter('tests', 'test', (512, 512, 1), localImgPath='tests/test.512.512.bmp') + difficult = 1 + writer.addBndBox(60, 40, 430, 504, 'person', difficult) + writer.addBndBox(113, 40, 450, 403, 'face', difficult) + writer.save('tests/test.xml') + + reader = PascalVocReader('tests/test.xml') + shapes = reader.getShapes() + + personBndBox = shapes[0] + face = shapes[1] + self.assertEqual(personBndBox[0], 'person') + self.assertEqual(personBndBox[1], [(60, 40), (430, 40), (430, 504), (60, 504)]) + self.assertEqual(face[0], 'face') + self.assertEqual(face[1], [(113, 40), (450, 40), (450, 403), (113, 403)]) + +if __name__ == '__main__': + unittest.main() diff --git a/labelImg-master/tests/test_qt.py b/labelImg-master/tests/test_qt.py new file mode 100644 index 0000000..869094d --- /dev/null +++ b/labelImg-master/tests/test_qt.py @@ -0,0 +1,20 @@ + +from unittest import TestCase + +from labelImg import get_main_app + + +class TestMainWindow(TestCase): + + app = None + win = None + + def setUp(self): + self.app, self.win = get_main_app() + + def tearDown(self): + self.win.close() + self.app.quit() + + def test_noop(self): + pass diff --git a/labelImg-master/tests/test_settings.py b/labelImg-master/tests/test_settings.py new file mode 100644 index 0000000..4df06d5 --- /dev/null +++ b/labelImg-master/tests/test_settings.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +import os +import sys +import time +import unittest + +__author__ = 'TzuTaLin' + +dir_name = os.path.abspath(os.path.dirname(__file__)) +libs_path = os.path.join(dir_name, '..', 'libs') +sys.path.insert(0, libs_path) +from settings import Settings + +class TestSettings(unittest.TestCase): + + def test_basic(self): + settings = Settings() + settings['test0'] = 'hello' + settings['test1'] = 10 + settings['test2'] = [0, 2, 3] + self.assertEqual(settings.get('test3', 3), 3) + self.assertEqual(settings.save(), True) + + settings.load() + self.assertEqual(settings.get('test0'), 'hello') + self.assertEqual(settings.get('test1'), 10) + + settings.reset() + + + +if __name__ == '__main__': + unittest.main() diff --git a/labelImg-master/tests/test_stringBundle.py b/labelImg-master/tests/test_stringBundle.py new file mode 100644 index 0000000..d4eb7f2 --- /dev/null +++ b/labelImg-master/tests/test_stringBundle.py @@ -0,0 +1,29 @@ +import os +import sys +import unittest +import resources +from stringBundle import StringBundle + +class TestStringBundle(unittest.TestCase): + + def test_loadDefaultBundle_withoutError(self): + strBundle = StringBundle.getBundle('en') + self.assertEqual(strBundle.getString("openDir"), 'Open Dir', 'Fail to load the default bundle') + + def test_fallback_withoutError(self): + strBundle = StringBundle.getBundle('zh-TW') + self.assertEqual(strBundle.getString("openDir"), u'\u958B\u555F\u76EE\u9304', 'Fail to load the zh-TW bundle') + + def test_setInvaleLocaleToEnv_printErrorMsg(self): + prev_lc = os.environ['LC_ALL'] + prev_lang = os.environ['LANG'] + os.environ['LC_ALL'] = 'UTF-8' + os.environ['LANG'] = 'UTF-8' + strBundle = StringBundle.getBundle() + self.assertEqual(strBundle.getString("openDir"), 'Open Dir', 'Fail to load the default bundle') + os.environ['LC_ALL'] = prev_lc + os.environ['LANG'] = prev_lang + + +if __name__ == '__main__': + unittest.main() diff --git a/labelImg-master/tests/test_utils.py b/labelImg-master/tests/test_utils.py new file mode 100644 index 0000000..1b0a6c4 --- /dev/null +++ b/labelImg-master/tests/test_utils.py @@ -0,0 +1,22 @@ +import os +import sys +import unittest +from libs.utils import struct, newAction, newIcon, addActions, fmtShortcut, generateColorByText, natural_sort + +class TestUtils(unittest.TestCase): + + def test_generateColorByGivingUniceText_noError(self): + res = generateColorByText(u'\u958B\u555F\u76EE\u9304') + self.assertTrue(res.green() >= 0) + self.assertTrue(res.red() >= 0) + self.assertTrue(res.blue() >= 0) + + def test_nautalSort_noError(self): + l1 = ['f1', 'f11', 'f3' ] + exptected_l1 = ['f1', 'f3', 'f11'] + natural_sort(l1) + for idx, val in enumerate(l1): + self.assertTrue(val == exptected_l1[idx]) + +if __name__ == '__main__': + unittest.main() diff --git a/labelImg-master/tests/臉書.jpg b/labelImg-master/tests/臉書.jpg new file mode 100644 index 0000000..f600309 Binary files /dev/null and b/labelImg-master/tests/臉書.jpg differ diff --git a/res/1.mp4 b/res/1.mp4 new file mode 100644 index 0000000..b2722ad Binary files /dev/null and b/res/1.mp4 differ diff --git a/res/2.mp4 b/res/2.mp4 new file mode 100644 index 0000000..966620a Binary files /dev/null and b/res/2.mp4 differ diff --git a/res/video.mp4 b/res/video.mp4 new file mode 100644 index 0000000..82e80ee Binary files /dev/null and b/res/video.mp4 differ diff --git a/runs/detect/predict/test.avi b/runs/detect/predict/test.avi new file mode 100644 index 0000000..ad5eb76 Binary files /dev/null and b/runs/detect/predict/test.avi differ diff --git a/runs/detect/predict10/1.avi b/runs/detect/predict10/1.avi new file mode 100644 index 0000000..091a27d Binary files /dev/null and b/runs/detect/predict10/1.avi differ diff --git a/runs/detect/predict11/2.avi b/runs/detect/predict11/2.avi new file mode 100644 index 0000000..453115f Binary files /dev/null and b/runs/detect/predict11/2.avi differ diff --git a/runs/detect/predict12/2.avi b/runs/detect/predict12/2.avi new file mode 100644 index 0000000..453115f Binary files /dev/null and b/runs/detect/predict12/2.avi differ diff --git a/runs/detect/predict13/2.avi b/runs/detect/predict13/2.avi new file mode 100644 index 0000000..453115f Binary files /dev/null and b/runs/detect/predict13/2.avi differ diff --git a/runs/detect/predict14/2.avi b/runs/detect/predict14/2.avi new file mode 100644 index 0000000..05d0392 Binary files /dev/null and b/runs/detect/predict14/2.avi differ diff --git a/runs/detect/predict15/2.avi b/runs/detect/predict15/2.avi new file mode 100644 index 0000000..453115f Binary files /dev/null and b/runs/detect/predict15/2.avi differ diff --git a/runs/detect/predict16/2.avi b/runs/detect/predict16/2.avi new file mode 100644 index 0000000..453115f Binary files /dev/null and b/runs/detect/predict16/2.avi differ diff --git a/runs/detect/predict2/test.avi b/runs/detect/predict2/test.avi new file mode 100644 index 0000000..ad5eb76 Binary files /dev/null and b/runs/detect/predict2/test.avi differ diff --git a/runs/detect/predict3/test.avi b/runs/detect/predict3/test.avi new file mode 100644 index 0000000..04db8ad Binary files /dev/null and b/runs/detect/predict3/test.avi differ diff --git a/runs/detect/predict4/video.avi b/runs/detect/predict4/video.avi new file mode 100644 index 0000000..75ed7ac Binary files /dev/null and b/runs/detect/predict4/video.avi differ diff --git a/runs/detect/predict5/video.avi b/runs/detect/predict5/video.avi new file mode 100644 index 0000000..75ed7ac Binary files /dev/null and b/runs/detect/predict5/video.avi differ diff --git a/runs/detect/predict6/video.avi b/runs/detect/predict6/video.avi new file mode 100644 index 0000000..13d65db Binary files /dev/null and b/runs/detect/predict6/video.avi differ diff --git a/runs/detect/predict7/video.avi b/runs/detect/predict7/video.avi new file mode 100644 index 0000000..72d4342 Binary files /dev/null and b/runs/detect/predict7/video.avi differ diff --git a/runs/detect/predict8/video.avi b/runs/detect/predict8/video.avi new file mode 100644 index 0000000..2e4264e Binary files /dev/null and b/runs/detect/predict8/video.avi differ diff --git a/runs/detect/predict9/1.avi b/runs/detect/predict9/1.avi new file mode 100644 index 0000000..091a27d Binary files /dev/null and b/runs/detect/predict9/1.avi differ diff --git a/runs/detect/train/args.yaml b/runs/detect/train/args.yaml new file mode 100644 index 0000000..6eb5cb3 --- /dev/null +++ b/runs/detect/train/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: yolov8n.pt +data: data.yaml +epochs: 50 +time: null +patience: 100 +batch: 8 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train diff --git a/runs/detect/train2/args.yaml b/runs/detect/train2/args.yaml new file mode 100644 index 0000000..f914118 --- /dev/null +++ b/runs/detect/train2/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: yolov8n.pt +data: data.yaml +epochs: 50 +time: null +patience: 100 +batch: 8 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train2 +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train2 diff --git a/runs/detect/train3/F1_curve.png b/runs/detect/train3/F1_curve.png new file mode 100644 index 0000000..74dcb96 Binary files /dev/null and b/runs/detect/train3/F1_curve.png differ diff --git a/runs/detect/train3/PR_curve.png b/runs/detect/train3/PR_curve.png new file mode 100644 index 0000000..025142d Binary files /dev/null and b/runs/detect/train3/PR_curve.png differ diff --git a/runs/detect/train3/P_curve.png b/runs/detect/train3/P_curve.png new file mode 100644 index 0000000..fa09717 Binary files /dev/null and b/runs/detect/train3/P_curve.png differ diff --git a/runs/detect/train3/R_curve.png b/runs/detect/train3/R_curve.png new file mode 100644 index 0000000..5904085 Binary files /dev/null and b/runs/detect/train3/R_curve.png differ diff --git a/runs/detect/train3/args.yaml b/runs/detect/train3/args.yaml new file mode 100644 index 0000000..edd8e4f --- /dev/null +++ b/runs/detect/train3/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: yolov8n.pt +data: data.yaml +epochs: 50 +time: null +patience: 100 +batch: 8 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train3 +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train3 diff --git a/runs/detect/train3/confusion_matrix.png b/runs/detect/train3/confusion_matrix.png new file mode 100644 index 0000000..fbc20c5 Binary files /dev/null and b/runs/detect/train3/confusion_matrix.png differ diff --git a/runs/detect/train3/confusion_matrix_normalized.png b/runs/detect/train3/confusion_matrix_normalized.png new file mode 100644 index 0000000..0d37ba0 Binary files /dev/null and b/runs/detect/train3/confusion_matrix_normalized.png differ diff --git a/runs/detect/train3/labels.jpg b/runs/detect/train3/labels.jpg new file mode 100644 index 0000000..e572540 Binary files /dev/null and b/runs/detect/train3/labels.jpg differ diff --git a/runs/detect/train3/results.csv b/runs/detect/train3/results.csv new file mode 100644 index 0000000..4d3283f --- /dev/null +++ b/runs/detect/train3/results.csv @@ -0,0 +1,51 @@ +epoch,time,train/box_loss,train/cls_loss,train/dfl_loss,metrics/precision(B),metrics/recall(B),metrics/mAP50(B),metrics/mAP50-95(B),val/box_loss,val/cls_loss,val/dfl_loss,lr/pg0,lr/pg1,lr/pg2 +1,3.15281,1.10022,3.14022,1.2255,0.00333,0.88889,0.32571,0.29217,0.34034,3.11736,0.87949,0,0,0 +2,5.68083,1.05538,3.31638,1.20438,0.00333,0.88889,0.37584,0.34515,0.32069,3.10227,0.87873,1.9604e-05,1.9604e-05,1.9604e-05 +3,8.15579,0.94798,3.16007,1.04138,0.00333,0.88889,0.63964,0.58705,0.30532,3.09222,0.87571,3.8416e-05,3.8416e-05,3.8416e-05 +4,10.715,0.62586,3.14025,1.02961,0.00333,0.88889,0.72823,0.65649,0.30679,3.0871,0.86894,5.6436e-05,5.6436e-05,5.6436e-05 +5,13.1396,0.86929,2.84358,1.05884,0.00333,0.88889,0.8302,0.75392,0.29772,3.107,0.86258,7.3664e-05,7.3664e-05,7.3664e-05 +6,15.5778,0.76563,2.79469,1.06727,0.00333,0.88889,0.8632,0.7838,0.32053,3.06857,0.86553,9.01e-05,9.01e-05,9.01e-05 +7,17.9613,0.64827,2.61013,1.00925,0.00333,0.88889,0.8852,0.81237,0.34311,3.04094,0.86747,0.000105744,0.000105744,0.000105744 +8,20.3928,0.72143,2.1563,0.96856,0.00333,0.88889,0.8852,0.79883,0.36531,3.0106,0.86746,0.000120596,0.000120596,0.000120596 +9,22.7815,0.57035,1.99286,0.90814,0.00333,0.88889,0.8852,0.79883,0.36531,3.0106,0.86746,0.000134656,0.000134656,0.000134656 +10,25.2309,0.69121,1.91028,1.01505,0.00333,0.88889,0.8852,0.79883,0.3861,2.97352,0.87094,0.000147924,0.000147924,0.000147924 +11,27.6395,0.88369,1.77167,1.19643,0.00333,0.88889,0.8852,0.79883,0.3861,2.97352,0.87094,0.0001604,0.0001604,0.0001604 +12,30.1606,0.60341,1.56535,0.93827,0.00333,0.88889,0.8852,0.78783,0.40306,2.94302,0.86504,0.000172084,0.000172084,0.000172084 +13,32.6564,0.67771,1.58706,0.9812,0.00333,0.88889,0.8852,0.78783,0.40306,2.94302,0.86504,0.000182976,0.000182976,0.000182976 +14,35.1385,0.95266,1.55727,1.14234,0.00333,0.88889,0.8852,0.7808,0.42724,2.8288,0.86476,0.000193076,0.000193076,0.000193076 +15,37.5563,0.59165,1.64354,0.83242,0.00333,0.88889,0.8852,0.7808,0.42724,2.8288,0.86476,0.000202384,0.000202384,0.000202384 +16,40.0186,0.88703,1.38812,1.05784,0.93683,0.88889,0.8852,0.77212,0.42412,2.73737,0.86377,0.0002109,0.0002109,0.0002109 +17,42.4647,0.59867,1.32607,1.00033,0.93683,0.88889,0.8852,0.77212,0.42412,2.73737,0.86377,0.000218624,0.000218624,0.000218624 +18,44.9617,0.76615,1.33177,1.07213,1,0.83494,0.8852,0.74988,0.43705,2.65651,0.86286,0.000225556,0.000225556,0.000225556 +19,47.3372,0.52303,1.70157,0.8597,1,0.83494,0.8852,0.74988,0.43705,2.65651,0.86286,0.000231696,0.000231696,0.000231696 +20,49.8584,0.67289,2.50893,0.92172,1,0.81512,0.8852,0.79322,0.45192,2.58511,0.86661,0.000237044,0.000237044,0.000237044 +21,52.3133,0.72742,1.44767,1.03485,1,0.81512,0.8852,0.79322,0.45192,2.58511,0.86661,0.0002416,0.0002416,0.0002416 +22,54.8088,0.68092,1.43855,0.91056,1,0.81606,0.8852,0.76464,0.45326,2.61417,0.87402,0.000245364,0.000245364,0.000245364 +23,57.2028,0.52225,1.19582,0.86461,1,0.81606,0.8852,0.76464,0.45326,2.61417,0.87402,0.000248336,0.000248336,0.000248336 +24,59.6553,0.67045,1.53593,0.99181,1,0.81606,0.8852,0.76464,0.45326,2.61417,0.87402,0.000250516,0.000250516,0.000250516 +25,62.237,0.64146,1.52373,1.03151,1,0.78759,0.8852,0.79185,0.48735,2.70008,0.8891,0.000251904,0.000251904,0.000251904 +26,64.7911,0.91542,1.33012,1.04646,1,0.78759,0.8852,0.79185,0.48735,2.70008,0.8891,0.0002525,0.0002525,0.0002525 +27,67.3228,0.88468,1.28592,1.09112,1,0.78759,0.8852,0.79185,0.48735,2.70008,0.8891,0.000252304,0.000252304,0.000252304 +28,69.8307,0.76852,1.27101,0.95144,1,0.63539,0.8852,0.78625,0.48011,2.75817,0.89035,0.000251316,0.000251316,0.000251316 +29,72.4024,0.87868,1.35438,1.03544,1,0.63539,0.8852,0.78625,0.48011,2.75817,0.89035,0.000249536,0.000249536,0.000249536 +30,74.8523,0.70824,1.13341,0.91661,1,0.63539,0.8852,0.78625,0.48011,2.75817,0.89035,0.000246964,0.000246964,0.000246964 +31,77.3209,0.72848,1.43246,1.02215,1,0.48756,0.8852,0.8292,0.42791,2.78051,0.88405,0.0002436,0.0002436,0.0002436 +32,79.9742,0.9278,1.75649,1.28212,1,0.48756,0.8852,0.8292,0.42791,2.78051,0.88405,0.000239444,0.000239444,0.000239444 +33,82.3529,0.57168,1.12277,0.86624,1,0.48756,0.8852,0.8292,0.42791,2.78051,0.88405,0.000234496,0.000234496,0.000234496 +34,85.0071,0.48654,1.12103,0.87536,1,0.49647,0.8852,0.82658,0.37727,2.78461,0.87961,0.000228756,0.000228756,0.000228756 +35,87.3931,0.64266,1.23656,1.04788,1,0.49647,0.8852,0.82658,0.37727,2.78461,0.87961,0.000222224,0.000222224,0.000222224 +36,89.7618,0.6237,1.33377,0.97587,1,0.49647,0.8852,0.82658,0.37727,2.78461,0.87961,0.0002149,0.0002149,0.0002149 +37,92.2967,0.76488,1.68602,0.96816,1,0.49647,0.8852,0.82658,0.37727,2.78461,0.87961,0.000206784,0.000206784,0.000206784 +38,94.8909,0.80571,1.48616,1.12267,1,0.66807,0.8852,0.86322,0.33862,2.77101,0.87143,0.000197876,0.000197876,0.000197876 +39,97.3842,0.54691,1.20211,0.91226,1,0.66807,0.8852,0.86322,0.33862,2.77101,0.87143,0.000188176,0.000188176,0.000188176 +40,100.002,0.67186,1.2534,0.87116,1,0.66807,0.8852,0.86322,0.33862,2.77101,0.87143,0.000177684,0.000177684,0.000177684 +41,102.416,0.43224,1.31894,0.78367,1,0.66807,0.8852,0.86322,0.33862,2.77101,0.87143,0.0001664,0.0001664,0.0001664 +42,104.939,0.3859,1.4498,0.84241,0.99496,0.88889,0.8852,0.86322,0.36192,2.6923,0.86417,0.000154324,0.000154324,0.000154324 +43,107.366,0.43439,1.36382,0.83218,0.99496,0.88889,0.8852,0.86322,0.36192,2.6923,0.86417,0.000141456,0.000141456,0.000141456 +44,109.79,0.39154,1.27984,0.74676,0.99496,0.88889,0.8852,0.86322,0.36192,2.6923,0.86417,0.000127796,0.000127796,0.000127796 +45,112.242,0.4359,1.38331,0.93381,0.99496,0.88889,0.8852,0.86322,0.36192,2.6923,0.86417,0.000113344,0.000113344,0.000113344 +46,114.805,0.37316,1.30903,0.88283,0.95971,0.88889,0.8852,0.84438,0.35247,2.59497,0.85796,9.81e-05,9.81e-05,9.81e-05 +47,117.219,0.44499,1.36407,0.76849,0.95971,0.88889,0.8852,0.84438,0.35247,2.59497,0.85796,8.2064e-05,8.2064e-05,8.2064e-05 +48,119.642,0.47196,1.32602,0.86557,0.95971,0.88889,0.8852,0.84438,0.35247,2.59497,0.85796,6.5236e-05,6.5236e-05,6.5236e-05 +49,122.033,0.36545,1.31759,0.79923,0.95971,0.88889,0.8852,0.84438,0.35247,2.59497,0.85796,4.7616e-05,4.7616e-05,4.7616e-05 +50,124.471,0.3751,1.37416,0.70301,0.96003,0.88889,0.8852,0.84438,0.34377,2.50209,0.85536,2.9204e-05,2.9204e-05,2.9204e-05 diff --git a/runs/detect/train3/results.png b/runs/detect/train3/results.png new file mode 100644 index 0000000..b224862 Binary files /dev/null and b/runs/detect/train3/results.png differ diff --git a/runs/detect/train3/train_batch0.jpg b/runs/detect/train3/train_batch0.jpg new file mode 100644 index 0000000..a790255 Binary files /dev/null and b/runs/detect/train3/train_batch0.jpg differ diff --git a/runs/detect/train3/train_batch1.jpg b/runs/detect/train3/train_batch1.jpg new file mode 100644 index 0000000..7bccf1d Binary files /dev/null and b/runs/detect/train3/train_batch1.jpg differ diff --git a/runs/detect/train3/train_batch2.jpg b/runs/detect/train3/train_batch2.jpg new file mode 100644 index 0000000..db0de92 Binary files /dev/null and b/runs/detect/train3/train_batch2.jpg differ diff --git a/runs/detect/train3/train_batch40.jpg b/runs/detect/train3/train_batch40.jpg new file mode 100644 index 0000000..6fe7149 Binary files /dev/null and b/runs/detect/train3/train_batch40.jpg differ diff --git a/runs/detect/train3/train_batch41.jpg b/runs/detect/train3/train_batch41.jpg new file mode 100644 index 0000000..c66b8d8 Binary files /dev/null and b/runs/detect/train3/train_batch41.jpg differ diff --git a/runs/detect/train3/train_batch42.jpg b/runs/detect/train3/train_batch42.jpg new file mode 100644 index 0000000..6107a07 Binary files /dev/null and b/runs/detect/train3/train_batch42.jpg differ diff --git a/runs/detect/train3/val_batch0_labels.jpg b/runs/detect/train3/val_batch0_labels.jpg new file mode 100644 index 0000000..5dded87 Binary files /dev/null and b/runs/detect/train3/val_batch0_labels.jpg differ diff --git a/runs/detect/train3/val_batch0_pred.jpg b/runs/detect/train3/val_batch0_pred.jpg new file mode 100644 index 0000000..41f8dd9 Binary files /dev/null and b/runs/detect/train3/val_batch0_pred.jpg differ diff --git a/runs/detect/train3/weights/best.pt b/runs/detect/train3/weights/best.pt new file mode 100644 index 0000000..350a384 Binary files /dev/null and b/runs/detect/train3/weights/best.pt differ diff --git a/runs/detect/train3/weights/last.pt b/runs/detect/train3/weights/last.pt new file mode 100644 index 0000000..dc8be8d Binary files /dev/null and b/runs/detect/train3/weights/last.pt differ diff --git a/runs/detect/train4/args.yaml b/runs/detect/train4/args.yaml new file mode 100644 index 0000000..88ca9f4 --- /dev/null +++ b/runs/detect/train4/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: yolov8n.pt +data: data.yaml +epochs: 200 +time: null +patience: 100 +batch: 8 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train4 +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train4 diff --git a/runs/detect/train4/labels.jpg b/runs/detect/train4/labels.jpg new file mode 100644 index 0000000..e572540 Binary files /dev/null and b/runs/detect/train4/labels.jpg differ diff --git a/runs/detect/train5/F1_curve.png b/runs/detect/train5/F1_curve.png new file mode 100644 index 0000000..344a3eb Binary files /dev/null and b/runs/detect/train5/F1_curve.png differ diff --git a/runs/detect/train5/PR_curve.png b/runs/detect/train5/PR_curve.png new file mode 100644 index 0000000..025142d Binary files /dev/null and b/runs/detect/train5/PR_curve.png differ diff --git a/runs/detect/train5/P_curve.png b/runs/detect/train5/P_curve.png new file mode 100644 index 0000000..a831e9a Binary files /dev/null and b/runs/detect/train5/P_curve.png differ diff --git a/runs/detect/train5/R_curve.png b/runs/detect/train5/R_curve.png new file mode 100644 index 0000000..5e8d4c2 Binary files /dev/null and b/runs/detect/train5/R_curve.png differ diff --git a/runs/detect/train5/args.yaml b/runs/detect/train5/args.yaml new file mode 100644 index 0000000..363ce0f --- /dev/null +++ b/runs/detect/train5/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: C:\workspace\le-yolo\runs\detect\train3\weights\last.pt +data: data.yaml +epochs: 200 +time: null +patience: 100 +batch: 8 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train5 +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train5 diff --git a/runs/detect/train5/confusion_matrix.png b/runs/detect/train5/confusion_matrix.png new file mode 100644 index 0000000..2a6cc84 Binary files /dev/null and b/runs/detect/train5/confusion_matrix.png differ diff --git a/runs/detect/train5/confusion_matrix_normalized.png b/runs/detect/train5/confusion_matrix_normalized.png new file mode 100644 index 0000000..a324049 Binary files /dev/null and b/runs/detect/train5/confusion_matrix_normalized.png differ diff --git a/runs/detect/train5/labels.jpg b/runs/detect/train5/labels.jpg new file mode 100644 index 0000000..e572540 Binary files /dev/null and b/runs/detect/train5/labels.jpg differ diff --git a/runs/detect/train5/results.csv b/runs/detect/train5/results.csv new file mode 100644 index 0000000..0a7d6ee --- /dev/null +++ b/runs/detect/train5/results.csv @@ -0,0 +1,103 @@ +epoch,time,train/box_loss,train/cls_loss,train/dfl_loss,metrics/precision(B),metrics/recall(B),metrics/mAP50(B),metrics/mAP50-95(B),val/box_loss,val/cls_loss,val/dfl_loss,lr/pg0,lr/pg1,lr/pg2 +1,2.67339,0.61832,1.14057,0.96964,0.96233,0.88889,0.8852,0.84438,0.34289,2.48256,0.85487,0,0,0 +2,5.09004,0.45762,1.18623,0.84615,0.96579,0.88889,0.8852,0.86322,0.32791,2.46007,0.85592,1.9901e-05,1.9901e-05,1.9901e-05 +3,7.60049,0.4178,1.17018,0.82961,0.96868,0.88889,0.8852,0.86322,0.32163,2.4327,0.85697,3.9604e-05,3.9604e-05,3.9604e-05 +4,9.98038,0.48083,1.22269,0.89059,0.96965,0.88889,0.8852,0.86047,0.31544,2.3946,0.85823,5.9109e-05,5.9109e-05,5.9109e-05 +5,12.3866,0.6278,1.10782,0.90417,0.97657,0.88889,0.8852,0.86047,0.32674,2.35093,0.86008,7.8416e-05,7.8416e-05,7.8416e-05 +6,14.8973,0.52602,0.91438,0.90707,0.98043,0.88889,0.8852,0.84444,0.34292,2.31656,0.86257,9.7525e-05,9.7525e-05,9.7525e-05 +7,17.2429,0.49335,1.07923,0.87905,0.98309,0.88889,0.8852,0.84628,0.34967,2.25899,0.86559,0.000116436,0.000116436,0.000116436 +8,19.6462,0.61429,0.96989,0.91982,0.98432,0.88889,0.8852,0.82474,0.34933,2.19648,0.8656,0.000135149,0.000135149,0.000135149 +9,21.982,0.50596,1.10315,0.92002,0.98432,0.88889,0.8852,0.82474,0.34933,2.19648,0.8656,0.000153664,0.000153664,0.000153664 +10,24.3517,0.59467,0.94249,0.9794,0.98466,0.88889,0.8852,0.84261,0.34808,2.08523,0.8623,0.000171981,0.000171981,0.000171981 +11,26.6746,0.69522,1.21661,1.09188,0.98466,0.88889,0.8852,0.84261,0.34808,2.08523,0.8623,0.0001901,0.0001901,0.0001901 +12,29.0535,0.48624,0.98387,0.88991,0.98579,0.88889,0.8852,0.83436,0.33667,1.96997,0.85881,0.000208021,0.000208021,0.000208021 +13,31.4143,0.55648,0.92089,0.93619,0.98579,0.88889,0.8852,0.83436,0.33667,1.96997,0.85881,0.000225744,0.000225744,0.000225744 +14,33.8123,0.74386,1.10125,0.97377,0.9828,0.88889,0.8852,0.83711,0.35397,1.97892,0.85376,0.000243269,0.000243269,0.000243269 +15,36.1456,0.55277,1.25464,0.84283,0.9828,0.88889,0.8852,0.83711,0.35397,1.97892,0.85376,0.000260596,0.000260596,0.000260596 +16,38.531,0.54716,0.9451,0.87762,0.97588,0.88889,0.8852,0.83095,0.38255,2.17418,0.85391,0.000277725,0.000277725,0.000277725 +17,40.8926,0.58252,1.02719,0.98344,0.97588,0.88889,0.8852,0.83095,0.38255,2.17418,0.85391,0.000294656,0.000294656,0.000294656 +18,43.3687,0.6243,1.0316,0.94663,0.96132,0.88889,0.8852,0.83095,0.39044,2.38818,0.85494,0.000311389,0.000311389,0.000311389 +19,45.7729,0.50991,1.2308,0.91477,0.96132,0.88889,0.8852,0.83095,0.39044,2.38818,0.85494,0.000327924,0.000327924,0.000327924 +20,48.1666,0.58582,1.58938,0.89876,0.9945,0.88889,0.8852,0.81727,0.41818,2.53039,0.85505,0.000344261,0.000344261,0.000344261 +21,50.5222,0.63541,1.13028,0.97161,0.9945,0.88889,0.8852,0.81727,0.41818,2.53039,0.85505,0.0003604,0.0003604,0.0003604 +22,52.8816,0.56815,1.11015,0.86219,0.97676,0.88889,0.8852,0.82472,0.41382,2.50032,0.8548,0.000376341,0.000376341,0.000376341 +23,55.241,0.4446,1.04105,0.83186,0.97676,0.88889,0.8852,0.82472,0.41382,2.50032,0.8548,0.000392084,0.000392084,0.000392084 +24,57.6428,0.81079,1.48197,1.17129,0.97676,0.88889,0.8852,0.82472,0.41382,2.50032,0.8548,0.000407629,0.000407629,0.000407629 +25,60.0587,0.60764,1.29201,0.94437,0.97093,0.88889,0.8852,0.82336,0.38947,2.26571,0.85077,0.000422976,0.000422976,0.000422976 +26,62.4506,0.74966,1.05885,1.00084,0.97093,0.88889,0.8852,0.82336,0.38947,2.26571,0.85077,0.000438125,0.000438125,0.000438125 +27,64.8378,0.76867,1.13755,1.02766,0.97093,0.88889,0.8852,0.82336,0.38947,2.26571,0.85077,0.000453076,0.000453076,0.000453076 +28,67.2118,0.82856,1.12362,0.95532,0.98111,0.88889,0.8852,0.83095,0.3931,2.00783,0.85204,0.000467829,0.000467829,0.000467829 +29,69.5655,0.84951,1.21617,1.07707,0.98111,0.88889,0.8852,0.83095,0.3931,2.00783,0.85204,0.000482384,0.000482384,0.000482384 +30,71.9275,0.67293,1.02036,0.90876,0.98111,0.88889,0.8852,0.83095,0.3931,2.00783,0.85204,0.000496741,0.000496741,0.000496741 +31,74.3812,0.65062,1.14422,0.94948,0.98933,0.88889,0.8852,0.81668,0.39975,1.78119,0.85198,0.0005109,0.0005109,0.0005109 +32,76.7801,0.97271,1.56493,1.44105,0.98933,0.88889,0.8852,0.81668,0.39975,1.78119,0.85198,0.000524861,0.000524861,0.000524861 +33,79.1052,0.55073,0.92717,0.85531,0.98933,0.88889,0.8852,0.81668,0.39975,1.78119,0.85198,0.000538624,0.000538624,0.000538624 +34,81.4605,0.52801,0.94671,0.90402,0.99072,0.88889,0.8852,0.82311,0.41385,1.60565,0.85071,0.000552189,0.000552189,0.000552189 +35,83.7832,0.73578,1.26274,1.14028,0.99072,0.88889,0.8852,0.82311,0.41385,1.60565,0.85071,0.000565556,0.000565556,0.000565556 +36,86.1307,0.68725,1.08364,1.00251,0.99072,0.88889,0.8852,0.82311,0.41385,1.60565,0.85071,0.000578725,0.000578725,0.000578725 +37,88.5128,0.71518,1.32409,0.96695,0.99072,0.88889,0.8852,0.82311,0.41385,1.60565,0.85071,0.000591696,0.000591696,0.000591696 +38,90.8977,0.85454,1.37877,1.16789,0.99131,0.88889,0.8852,0.80329,0.40134,1.53915,0.85021,0.000604469,0.000604469,0.000604469 +39,93.3448,0.73548,1.07552,0.9398,0.99131,0.88889,0.8852,0.80329,0.40134,1.53915,0.85021,0.000617044,0.000617044,0.000617044 +40,95.7953,0.5952,1.13214,0.83742,0.99131,0.88889,0.8852,0.80329,0.40134,1.53915,0.85021,0.000629421,0.000629421,0.000629421 +41,98.1229,0.79572,1.11991,1.15744,0.99131,0.88889,0.8852,0.80329,0.40134,1.53915,0.85021,0.0006416,0.0006416,0.0006416 +42,100.504,0.66331,1.12817,0.96887,0.9921,0.88889,0.8852,0.75364,0.51466,1.41164,0.87532,0.000653581,0.000653581,0.000653581 +43,102.883,0.88604,1.34558,1.10748,0.9921,0.88889,0.8852,0.75364,0.51466,1.41164,0.87532,0.000665364,0.000665364,0.000665364 +44,105.238,0.66965,1.06127,0.9416,0.9921,0.88889,0.8852,0.75364,0.51466,1.41164,0.87532,0.000676949,0.000676949,0.000676949 +45,107.578,0.6744,1.28697,1.02179,0.9921,0.88889,0.8852,0.75364,0.51466,1.41164,0.87532,0.000688336,0.000688336,0.000688336 +46,109.975,0.89497,1.07277,1.19768,0.99181,0.88889,0.8852,0.73423,0.62066,1.4192,0.90695,0.000699525,0.000699525,0.000699525 +47,112.307,1.21509,1.61059,1.5069,0.99181,0.88889,0.8852,0.73423,0.62066,1.4192,0.90695,0.000710516,0.000710516,0.000710516 +48,114.664,0.7325,1.13365,1.06054,0.99181,0.88889,0.8852,0.73423,0.62066,1.4192,0.90695,0.000721309,0.000721309,0.000721309 +49,117.077,0.87712,1.49915,1.13423,0.99181,0.88889,0.8852,0.73423,0.62066,1.4192,0.90695,0.000731904,0.000731904,0.000731904 +50,119.513,0.7641,1.00751,0.93622,0.99336,0.88889,0.8852,0.76757,0.6285,1.40914,0.91582,0.000742301,0.000742301,0.000742301 +51,121.859,0.80487,1.02137,1.0223,0.99336,0.88889,0.8852,0.76757,0.6285,1.40914,0.91582,0.0007525,0.0007525,0.0007525 +52,124.239,0.8842,1.52877,1.06398,0.99336,0.88889,0.8852,0.76757,0.6285,1.40914,0.91582,0.000762501,0.000762501,0.000762501 +53,126.624,0.67371,1.15463,0.90841,0.99336,0.88889,0.8852,0.76757,0.6285,1.40914,0.91582,0.000772304,0.000772304,0.000772304 +54,129.016,0.7695,1.11711,1.00695,0.99336,0.88889,0.8852,0.76757,0.6285,1.40914,0.91582,0.000781909,0.000781909,0.000781909 +55,131.462,0.97449,1.18503,1.21886,0.99378,0.88889,0.8852,0.78791,0.60719,1.31667,0.91882,0.000791316,0.000791316,0.000791316 +56,133.943,0.73369,1.35327,1.03889,0.99378,0.88889,0.8852,0.78791,0.60719,1.31667,0.91882,0.000800525,0.000800525,0.000800525 +57,136.325,0.63543,1.16751,0.87116,0.99378,0.88889,0.8852,0.78791,0.60719,1.31667,0.91882,0.000809536,0.000809536,0.000809536 +58,138.714,0.89618,1.25217,1.05405,0.99378,0.88889,0.8852,0.78791,0.60719,1.31667,0.91882,0.000818349,0.000818349,0.000818349 +59,141.155,0.65537,1.04452,0.93955,0.99378,0.88889,0.8852,0.78791,0.60719,1.31667,0.91882,0.000826964,0.000826964,0.000826964 +60,143.531,0.69248,1.14361,1.04093,0.99406,0.88889,0.8852,0.77223,0.51287,1.13532,0.88077,0.000835381,0.000835381,0.000835381 +61,145.916,0.72916,0.90805,1.05146,0.99406,0.88889,0.8852,0.77223,0.51287,1.13532,0.88077,0.0008436,0.0008436,0.0008436 +62,148.317,0.84334,1.20647,1.08022,0.99406,0.88889,0.8852,0.77223,0.51287,1.13532,0.88077,0.000851621,0.000851621,0.000851621 +63,150.689,0.53598,0.99282,0.94661,0.99406,0.88889,0.8852,0.77223,0.51287,1.13532,0.88077,0.000859444,0.000859444,0.000859444 +64,153.111,0.66993,1.12479,1.04425,0.99406,0.88889,0.8852,0.77223,0.51287,1.13532,0.88077,0.000867069,0.000867069,0.000867069 +65,155.577,0.68368,1.21123,0.99139,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000874496,0.000874496,0.000874496 +66,157.915,0.68925,0.9485,0.97626,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000881725,0.000881725,0.000881725 +67,160.283,0.59629,0.95086,0.89794,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000888756,0.000888756,0.000888756 +68,162.64,0.62357,0.97354,0.93467,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000895589,0.000895589,0.000895589 +69,164.974,0.53405,1.1027,0.90809,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000902224,0.000902224,0.000902224 +70,167.31,0.6005,1.18297,0.99935,0.99406,0.88889,0.8852,0.76712,0.55903,1.1558,0.89368,0.000908661,0.000908661,0.000908661 +71,169.777,0.61019,0.96051,0.9094,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.0009149,0.0009149,0.0009149 +72,172.154,0.52546,1.30039,0.88774,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.000920941,0.000920941,0.000920941 +73,174.492,0.67895,1.29729,0.96617,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.000926784,0.000926784,0.000926784 +74,176.901,0.69609,1.11204,0.99213,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.000932429,0.000932429,0.000932429 +75,179.293,0.68095,0.90637,0.96327,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.000937876,0.000937876,0.000937876 +76,181.644,0.75062,1.06108,1.00375,0.99388,0.88889,0.8852,0.80761,0.54084,1.20126,0.89822,0.000943125,0.000943125,0.000943125 +77,184.038,0.81906,1.34644,1.04751,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000948176,0.000948176,0.000948176 +78,186.421,0.8321,1.09199,1.11162,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000953029,0.000953029,0.000953029 +79,188.813,0.69429,1.29677,0.94483,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000957684,0.000957684,0.000957684 +80,191.139,0.49987,0.99018,0.93999,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000962141,0.000962141,0.000962141 +81,193.482,0.68197,1.00514,0.96103,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.0009664,0.0009664,0.0009664 +82,195.866,0.77105,1.04411,1.06886,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000970461,0.000970461,0.000970461 +83,198.181,0.82641,1.21712,1.0154,0.99182,0.88889,0.8852,0.81786,0.41751,1.27595,0.87693,0.000974324,0.000974324,0.000974324 +84,200.596,0.91184,1.13117,1.09616,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000977989,0.000977989,0.000977989 +85,202.924,0.59474,1.10096,0.99698,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000981456,0.000981456,0.000981456 +86,205.255,0.70448,1.08273,0.97212,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000984725,0.000984725,0.000984725 +87,207.635,0.60008,0.94615,0.88845,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000987796,0.000987796,0.000987796 +88,209.989,0.7716,1.10441,1.07113,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000990669,0.000990669,0.000990669 +89,212.338,0.54266,1.20955,0.94432,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000993344,0.000993344,0.000993344 +90,214.92,0.78635,1.09836,1.05601,0.991,0.88889,0.8852,0.80668,0.44144,1.35018,0.87153,0.000995821,0.000995821,0.000995821 +91,217.279,0.77563,1.22971,0.93955,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.0009981,0.0009981,0.0009981 +92,219.608,0.62199,0.98525,0.92761,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100018,0.00100018,0.00100018 +93,221.969,0.68844,0.90696,0.99478,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100206,0.00100206,0.00100206 +94,224.335,0.54038,1.2907,0.94759,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100375,0.00100375,0.00100375 +95,226.67,0.62397,1.04703,0.91073,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100524,0.00100524,0.00100524 +96,229.006,0.57449,0.87945,0.85397,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100653,0.00100653,0.00100653 +97,231.402,0.69251,1.29495,1.05802,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100762,0.00100762,0.00100762 +98,233.865,0.87854,1.19071,1.09647,0.99365,0.88889,0.8852,0.75795,0.55018,1.1417,0.88082,0.00100851,0.00100851,0.00100851 +99,236.318,0.87895,1.10823,1.12946,0.99541,0.88889,0.8852,0.78294,0.54804,1.15956,0.8686,0.0010092,0.0010092,0.0010092 +100,238.748,0.88589,1.00296,0.96315,0.99541,0.88889,0.8852,0.78294,0.54804,1.15956,0.8686,0.0010097,0.0010097,0.0010097 +101,241.16,0.8676,1.29074,1.10989,0.99541,0.88889,0.8852,0.78294,0.54804,1.15956,0.8686,0.00101,0.00101,0.00101 +102,243.523,0.75596,1.1178,1.046,0.99541,0.88889,0.8852,0.78294,0.54804,1.15956,0.8686,0.0010001,0.0010001,0.0010001 diff --git a/runs/detect/train5/results.png b/runs/detect/train5/results.png new file mode 100644 index 0000000..251bae6 Binary files /dev/null and b/runs/detect/train5/results.png differ diff --git a/runs/detect/train5/train_batch0.jpg b/runs/detect/train5/train_batch0.jpg new file mode 100644 index 0000000..a790255 Binary files /dev/null and b/runs/detect/train5/train_batch0.jpg differ diff --git a/runs/detect/train5/train_batch1.jpg b/runs/detect/train5/train_batch1.jpg new file mode 100644 index 0000000..7bccf1d Binary files /dev/null and b/runs/detect/train5/train_batch1.jpg differ diff --git a/runs/detect/train5/train_batch2.jpg b/runs/detect/train5/train_batch2.jpg new file mode 100644 index 0000000..db0de92 Binary files /dev/null and b/runs/detect/train5/train_batch2.jpg differ diff --git a/runs/detect/train5/val_batch0_labels.jpg b/runs/detect/train5/val_batch0_labels.jpg new file mode 100644 index 0000000..5dded87 Binary files /dev/null and b/runs/detect/train5/val_batch0_labels.jpg differ diff --git a/runs/detect/train5/val_batch0_pred.jpg b/runs/detect/train5/val_batch0_pred.jpg new file mode 100644 index 0000000..a44bdd6 Binary files /dev/null and b/runs/detect/train5/val_batch0_pred.jpg differ diff --git a/runs/detect/train5/weights/best.pt b/runs/detect/train5/weights/best.pt new file mode 100644 index 0000000..ca48b9b Binary files /dev/null and b/runs/detect/train5/weights/best.pt differ diff --git a/runs/detect/train5/weights/last.pt b/runs/detect/train5/weights/last.pt new file mode 100644 index 0000000..7ec828a Binary files /dev/null and b/runs/detect/train5/weights/last.pt differ diff --git a/runs/detect/train6/F1_curve.png b/runs/detect/train6/F1_curve.png new file mode 100644 index 0000000..c9d0086 Binary files /dev/null and b/runs/detect/train6/F1_curve.png differ diff --git a/runs/detect/train6/PR_curve.png b/runs/detect/train6/PR_curve.png new file mode 100644 index 0000000..724a8ef Binary files /dev/null and b/runs/detect/train6/PR_curve.png differ diff --git a/runs/detect/train6/P_curve.png b/runs/detect/train6/P_curve.png new file mode 100644 index 0000000..2dc6201 Binary files /dev/null and b/runs/detect/train6/P_curve.png differ diff --git a/runs/detect/train6/R_curve.png b/runs/detect/train6/R_curve.png new file mode 100644 index 0000000..824e1b1 Binary files /dev/null and b/runs/detect/train6/R_curve.png differ diff --git a/runs/detect/train6/args.yaml b/runs/detect/train6/args.yaml new file mode 100644 index 0000000..680a29c --- /dev/null +++ b/runs/detect/train6/args.yaml @@ -0,0 +1,105 @@ +task: detect +mode: train +model: yolov8n.pt +data: data.yaml +epochs: 500 +time: null +patience: 100 +batch: 3 +imgsz: 640 +save: true +save_period: -1 +cache: false +device: cpu +workers: 8 +project: null +name: train6 +exist_ok: false +pretrained: true +optimizer: auto +verbose: true +seed: 0 +deterministic: true +single_cls: false +rect: false +cos_lr: false +close_mosaic: 10 +resume: false +amp: true +fraction: 1.0 +profile: false +freeze: null +multi_scale: false +overlap_mask: true +mask_ratio: 4 +dropout: 0.0 +val: true +split: val +save_json: false +conf: null +iou: 0.7 +max_det: 300 +half: false +dnn: false +plots: true +source: null +vid_stride: 1 +stream_buffer: false +visualize: false +augment: false +agnostic_nms: false +classes: null +retina_masks: false +embed: null +show: false +save_frames: false +save_txt: false +save_conf: false +save_crop: false +show_labels: true +show_conf: true +show_boxes: true +line_width: null +format: torchscript +keras: false +optimize: false +int8: false +dynamic: false +simplify: true +opset: null +workspace: null +nms: false +lr0: 0.01 +lrf: 0.01 +momentum: 0.937 +weight_decay: 0.0005 +warmup_epochs: 3.0 +warmup_momentum: 0.8 +warmup_bias_lr: 0.1 +box: 7.5 +cls: 0.5 +dfl: 1.5 +pose: 12.0 +kobj: 1.0 +nbs: 64 +hsv_h: 0.015 +hsv_s: 0.7 +hsv_v: 0.4 +degrees: 0.0 +translate: 0.1 +scale: 0.5 +shear: 0.0 +perspective: 0.0 +flipud: 0.0 +fliplr: 0.5 +bgr: 0.0 +mosaic: 1.0 +mixup: 0.0 +cutmix: 0.0 +copy_paste: 0.0 +copy_paste_mode: flip +auto_augment: randaugment +erasing: 0.4 +cfg: null +tracker: botsort.yaml +save_dir: C:\workspace\le-yolo\runs\detect\train6 diff --git a/runs/detect/train6/confusion_matrix.png b/runs/detect/train6/confusion_matrix.png new file mode 100644 index 0000000..fbc20c5 Binary files /dev/null and b/runs/detect/train6/confusion_matrix.png differ diff --git a/runs/detect/train6/confusion_matrix_normalized.png b/runs/detect/train6/confusion_matrix_normalized.png new file mode 100644 index 0000000..0d37ba0 Binary files /dev/null and b/runs/detect/train6/confusion_matrix_normalized.png differ diff --git a/runs/detect/train6/labels.jpg b/runs/detect/train6/labels.jpg new file mode 100644 index 0000000..e572540 Binary files /dev/null and b/runs/detect/train6/labels.jpg differ diff --git a/runs/detect/train6/results.csv b/runs/detect/train6/results.csv new file mode 100644 index 0000000..bce040d --- /dev/null +++ b/runs/detect/train6/results.csv @@ -0,0 +1,105 @@ +epoch,time,train/box_loss,train/cls_loss,train/dfl_loss,metrics/precision(B),metrics/recall(B),metrics/mAP50(B),metrics/mAP50-95(B),val/box_loss,val/cls_loss,val/dfl_loss,lr/pg0,lr/pg1,lr/pg2 +1,2.67795,1.27905,3.24362,1.30371,0.00333,0.88889,0.40865,0.37899,0.32191,3.10663,0.84784,4e-05,4e-05,4e-05 +2,5.09254,0.98756,3.0412,1.11673,0.00333,0.88889,0.57671,0.52573,0.30795,3.10622,0.83504,9.9802e-05,9.9802e-05,9.9802e-05 +3,7.5974,0.72408,3.03488,0.95692,0.00333,0.88889,0.80252,0.75001,0.35484,3.10151,0.837,0.000159366,0.000159366,0.000159366 +4,9.98193,0.4863,3.05383,0.93557,0.00333,0.88889,0.87298,0.81759,0.39024,3.08366,0.83707,0.000218693,0.000218693,0.000218693 +5,12.2816,0.97693,2.29936,1.05502,0.00333,0.88889,0.8852,0.76467,0.46905,3.03797,0.84486,0.000277782,0.000277782,0.000277782 +6,14.5462,0.62948,2.82315,0.95893,0.00333,0.88889,0.8852,0.76602,0.53693,2.97087,0.85383,0.000336634,0.000336634,0.000336634 +7,16.7704,0.64673,1.78792,0.94692,0.00333,0.88889,0.8852,0.76602,0.53693,2.97087,0.85383,0.000395248,0.000395248,0.000395248 +8,19.1617,0.90428,1.51959,0.97618,0.95687,0.88889,0.8852,0.78745,0.57408,2.80877,0.8614,0.000453624,0.000453624,0.000453624 +9,21.3984,0.73933,1.45439,1.00473,0.95687,0.88889,0.8852,0.78745,0.57408,2.80877,0.8614,0.000511763,0.000511763,0.000511763 +10,23.6597,0.72383,1.48773,1.07725,0.97649,0.88889,0.8852,0.72079,0.76262,2.50584,0.93079,0.000569664,0.000569664,0.000569664 +11,25.9231,0.91272,2.0963,1.24114,0.97649,0.88889,0.8852,0.72079,0.76262,2.50584,0.93079,0.000627328,0.000627328,0.000627328 +12,28.252,0.72902,1.30912,0.95611,1,0.56488,0.87298,0.68585,0.92343,2.8316,1.00301,0.000684754,0.000684754,0.000684754 +13,30.5298,0.77018,1.375,1.01699,1,0.56488,0.87298,0.68585,0.92343,2.8316,1.00301,0.000741942,0.000741942,0.000741942 +14,32.7901,1.08536,1.89609,1.28064,1,0.56488,0.87298,0.68585,0.92343,2.8316,1.00301,0.000798893,0.000798893,0.000798893 +15,35.0072,0.71429,2.20852,0.88781,1,0.56488,0.87298,0.68585,0.92343,2.8316,1.00301,0.000855606,0.000855606,0.000855606 +16,37.2745,1.00485,1.73181,1.11101,1,0.29103,0.78218,0.49263,1.50615,3.56637,1.26244,0.000912082,0.000912082,0.000912082 +17,39.5884,0.98953,1.75123,1.19853,1,0.29103,0.78218,0.49263,1.50615,3.56637,1.26244,0.00096832,0.00096832,0.00096832 +18,41.8368,1.10986,1.98043,1.20789,1,0.29103,0.78218,0.49263,1.50615,3.56637,1.26244,0.00102432,0.00102432,0.00102432 +19,44.0787,0.93739,2.3785,1.20116,1,0.29103,0.78218,0.49263,1.50615,3.56637,1.26244,0.00108008,0.00108008,0.00108008 +20,46.3797,1.16955,2.52993,1.34473,1,0.53034,0.74233,0.57976,1.25833,3.20967,1.25833,0.00113561,0.00113561,0.00113561 +21,48.685,0.96654,1.89043,1.24844,1,0.53034,0.74233,0.57976,1.25833,3.20967,1.25833,0.0011909,0.0011909,0.0011909 +22,50.9478,1.02031,1.68544,0.98893,1,0.53034,0.74233,0.57976,1.25833,3.20967,1.25833,0.00124595,0.00124595,0.00124595 +23,53.21,0.70895,1.87494,0.89338,1,0.53034,0.74233,0.57976,1.25833,3.20967,1.25833,0.00130076,0.00130076,0.00130076 +24,55.5248,0.83497,2.50946,1.22273,1,0.53034,0.74233,0.57976,1.25833,3.20967,1.25833,0.00135533,0.00135533,0.00135533 +25,57.8665,1.0376,2.35996,1.22457,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00140967,0.00140967,0.00140967 +26,60.2004,1.16131,1.77476,1.16964,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00146377,0.00146377,0.00146377 +27,62.5187,0.99319,2.0313,1.11383,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00151763,0.00151763,0.00151763 +28,65.0548,0.96165,1.62008,1.08608,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00157126,0.00157126,0.00157126 +29,67.345,1.27797,2.2427,1.43302,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00162464,0.00162464,0.00162464 +30,69.6022,1.01235,1.92345,1.10763,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.00167779,0.00167779,0.00167779 +31,71.8442,0.97522,1.80498,1.03414,0.97493,0.55556,0.78131,0.53135,1.195,3.78545,1.11106,0.0017307,0.0017307,0.0017307 +32,74.1916,1.3933,2.62316,1.55349,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00178338,0.00178338,0.00178338 +33,76.4383,0.90452,1.41513,0.981,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00183581,0.00183581,0.00183581 +34,78.6722,0.92794,1.73043,1.10102,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00186932,0.00186932,0.00186932 +35,80.9255,1.23513,2.17191,1.31006,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00186536,0.00186536,0.00186536 +36,83.1627,0.97986,2.02621,1.14236,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.0018614,0.0018614,0.0018614 +37,85.4793,0.88313,2.19899,1.0059,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00185744,0.00185744,0.00185744 +38,87.7531,1.48866,2.56755,1.6594,1,0.88116,0.8852,0.66362,0.91472,2.17002,1.42451,0.00185348,0.00185348,0.00185348 +39,90.0454,1.18119,1.69549,1.16404,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00184952,0.00184952,0.00184952 +40,92.2773,1.18817,1.82216,1.30513,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00184556,0.00184556,0.00184556 +41,94.5209,1.1457,1.9247,1.42785,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.0018416,0.0018416,0.0018416 +42,96.7818,0.95592,1.74857,1.1364,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00183764,0.00183764,0.00183764 +43,99.0475,0.92277,2.98682,1.10743,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00183368,0.00183368,0.00183368 +44,101.333,1.04883,2.03719,1.08668,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00182972,0.00182972,0.00182972 +45,103.579,1.20426,2.03691,1.17871,0.85558,0.77778,0.84145,0.58203,0.92895,2.02279,1.27738,0.00182576,0.00182576,0.00182576 +46,105.888,1.16457,1.82163,1.25208,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.0018218,0.0018218,0.0018218 +47,108.158,1.41602,2.29267,1.32991,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.00181784,0.00181784,0.00181784 +48,110.421,1.29142,1.96265,1.22785,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.00181388,0.00181388,0.00181388 +49,112.743,1.16174,2.07302,1.23214,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.00180992,0.00180992,0.00180992 +50,115.044,1.21833,1.81467,1.16257,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.00180596,0.00180596,0.00180596 +51,117.345,1.05494,1.7611,1.16658,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.001802,0.001802,0.001802 +52,119.599,1.18708,2.69756,1.15335,0.63211,0.66667,0.73389,0.51108,1.39313,2.39865,1.7205,0.00179804,0.00179804,0.00179804 +53,121.899,1.18044,1.82261,1.1866,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00179408,0.00179408,0.00179408 +54,124.236,1.03304,1.74743,1.22446,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00179012,0.00179012,0.00179012 +55,126.564,1.14346,1.78663,1.23261,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00178616,0.00178616,0.00178616 +56,129,1.09489,2.11696,1.16755,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.0017822,0.0017822,0.0017822 +57,131.354,0.91336,1.70765,1.15637,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00177824,0.00177824,0.00177824 +58,133.682,1.15293,1.86471,1.26461,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00177428,0.00177428,0.00177428 +59,136.345,1.01331,1.69096,1.09072,0.72636,0.88518,0.75131,0.54765,0.96058,2.20226,1.0733,0.00177032,0.00177032,0.00177032 +60,138.726,0.87277,1.63231,1.06982,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.00176636,0.00176636,0.00176636 +61,141.514,0.94482,1.21048,1.12625,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.0017624,0.0017624,0.0017624 +62,144.088,1.35551,1.9419,1.32975,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.00175844,0.00175844,0.00175844 +63,146.655,0.81021,1.53806,1.12253,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.00175448,0.00175448,0.00175448 +64,149.268,1.04121,1.87248,1.31633,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.00175052,0.00175052,0.00175052 +65,152.09,1.09547,1.80434,1.21025,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.00174656,0.00174656,0.00174656 +66,154.617,0.8121,1.31265,1.04187,0.88175,0.88889,0.8852,0.62629,0.92977,2.26573,0.99996,0.0017426,0.0017426,0.0017426 +67,157.26,0.84264,1.51601,1.02304,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00173864,0.00173864,0.00173864 +68,159.778,0.78871,1.41874,1.02518,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00173468,0.00173468,0.00173468 +69,162.29,0.98977,1.85231,1.24652,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00173072,0.00173072,0.00173072 +70,164.792,0.9729,2.21472,1.12597,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00172676,0.00172676,0.00172676 +71,167.349,0.86683,1.51254,1.02215,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.0017228,0.0017228,0.0017228 +72,170.034,0.94062,1.9615,1.18005,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00171884,0.00171884,0.00171884 +73,172.637,1.1132,2.73009,1.04916,0.98143,0.88889,0.8852,0.63635,0.97678,1.97834,1.15336,0.00171488,0.00171488,0.00171488 +74,175.685,0.80801,1.70499,1.04335,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00171092,0.00171092,0.00171092 +75,178.093,1.11995,1.53155,1.1913,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00170696,0.00170696,0.00170696 +76,180.533,0.89758,1.61335,1.13305,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.001703,0.001703,0.001703 +77,182.926,0.93648,1.71941,1.11532,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00169904,0.00169904,0.00169904 +78,185.231,1.21461,1.56689,1.35139,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00169508,0.00169508,0.00169508 +79,187.507,1.08127,1.77739,1.15528,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00169112,0.00169112,0.00169112 +80,189.784,0.81228,1.4656,1.01938,0.98147,0.88889,0.8852,0.74296,0.73088,2.01762,1.01098,0.00168716,0.00168716,0.00168716 +81,192.085,0.92497,1.42455,1.08237,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.0016832,0.0016832,0.0016832 +82,194.363,0.91327,1.60324,1.18723,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.00167924,0.00167924,0.00167924 +83,196.627,1.09651,1.65158,1.16131,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.00167528,0.00167528,0.00167528 +84,198.925,0.90448,1.88114,1.01694,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.00167132,0.00167132,0.00167132 +85,201.164,0.95253,1.56788,1.18512,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.00166736,0.00166736,0.00166736 +86,203.416,1.01586,1.65221,1.1115,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.0016634,0.0016634,0.0016634 +87,205.679,0.93381,1.33418,1.03337,0.99042,0.88889,0.8852,0.70304,0.71864,1.6568,0.98498,0.00165944,0.00165944,0.00165944 +88,208.054,1.12109,1.65396,1.25144,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00165548,0.00165548,0.00165548 +89,210.317,0.96261,1.41334,1.14778,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00165152,0.00165152,0.00165152 +90,212.571,0.98662,1.35466,1.30028,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00164756,0.00164756,0.00164756 +91,214.821,0.95476,1.37853,1.11952,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.0016436,0.0016436,0.0016436 +92,217.097,0.76714,1.34939,1.0739,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00163964,0.00163964,0.00163964 +93,219.363,1.07072,1.34053,1.16561,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00163568,0.00163568,0.00163568 +94,221.64,0.73114,1.7112,1.0523,0.99149,0.88889,0.8852,0.70619,0.69207,1.7073,0.94201,0.00163172,0.00163172,0.00163172 +95,223.93,0.8394,1.51995,1.02761,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.00162776,0.00162776,0.00162776 +96,226.291,0.69965,1.11519,0.98087,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.0016238,0.0016238,0.0016238 +97,228.564,1.00733,2.0208,1.31328,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.00161984,0.00161984,0.00161984 +98,230.865,0.76349,1.50017,1.05159,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.00161588,0.00161588,0.00161588 +99,233.153,1.09349,1.51612,1.41843,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.00161192,0.00161192,0.00161192 +100,235.443,0.93364,1.19268,1.0842,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.00160796,0.00160796,0.00160796 +101,237.737,1.16238,1.82491,1.23051,0.9914,0.88889,0.8852,0.73166,0.69271,1.40691,0.93966,0.001604,0.001604,0.001604 +102,240.043,1.00923,1.42276,1.13879,0.99335,0.88889,0.8852,0.74276,0.70275,1.55305,0.95414,0.00160004,0.00160004,0.00160004 +103,242.485,0.91573,1.41443,1.07295,0.99335,0.88889,0.8852,0.74276,0.70275,1.55305,0.95414,0.00159608,0.00159608,0.00159608 +104,244.775,0.89041,1.45741,1.08817,0.99335,0.88889,0.8852,0.74276,0.70275,1.55305,0.95414,0.00159212,0.00159212,0.00159212 diff --git a/runs/detect/train6/results.png b/runs/detect/train6/results.png new file mode 100644 index 0000000..cf3c24d Binary files /dev/null and b/runs/detect/train6/results.png differ diff --git a/runs/detect/train6/train_batch0.jpg b/runs/detect/train6/train_batch0.jpg new file mode 100644 index 0000000..fb646bf Binary files /dev/null and b/runs/detect/train6/train_batch0.jpg differ diff --git a/runs/detect/train6/train_batch1.jpg b/runs/detect/train6/train_batch1.jpg new file mode 100644 index 0000000..56b467d Binary files /dev/null and b/runs/detect/train6/train_batch1.jpg differ diff --git a/runs/detect/train6/train_batch2.jpg b/runs/detect/train6/train_batch2.jpg new file mode 100644 index 0000000..375d69c Binary files /dev/null and b/runs/detect/train6/train_batch2.jpg differ diff --git a/runs/detect/train6/val_batch0_labels.jpg b/runs/detect/train6/val_batch0_labels.jpg new file mode 100644 index 0000000..f82cba8 Binary files /dev/null and b/runs/detect/train6/val_batch0_labels.jpg differ diff --git a/runs/detect/train6/val_batch0_pred.jpg b/runs/detect/train6/val_batch0_pred.jpg new file mode 100644 index 0000000..d69a420 Binary files /dev/null and b/runs/detect/train6/val_batch0_pred.jpg differ diff --git a/runs/detect/train6/val_batch1_labels.jpg b/runs/detect/train6/val_batch1_labels.jpg new file mode 100644 index 0000000..6e75b37 Binary files /dev/null and b/runs/detect/train6/val_batch1_labels.jpg differ diff --git a/runs/detect/train6/val_batch1_pred.jpg b/runs/detect/train6/val_batch1_pred.jpg new file mode 100644 index 0000000..1bc164d Binary files /dev/null and b/runs/detect/train6/val_batch1_pred.jpg differ diff --git a/runs/detect/train6/weights/best.pt b/runs/detect/train6/weights/best.pt new file mode 100644 index 0000000..57f6ab3 Binary files /dev/null and b/runs/detect/train6/weights/best.pt differ diff --git a/runs/detect/train6/weights/last.pt b/runs/detect/train6/weights/last.pt new file mode 100644 index 0000000..43dbd92 Binary files /dev/null and b/runs/detect/train6/weights/last.pt differ diff --git a/src/data.yaml b/src/data.yaml new file mode 100644 index 0000000..ee8e68a --- /dev/null +++ b/src/data.yaml @@ -0,0 +1,5 @@ +path: C:\workspace\le-yolo\data +train: images/train +val: images/val +nc: 1 +names: [ 'A' ] \ No newline at end of file diff --git a/src/test.py b/src/test.py new file mode 100644 index 0000000..da51b99 --- /dev/null +++ b/src/test.py @@ -0,0 +1,3 @@ +from ultralytics import YOLO +model = YOLO(r"C:\workspace\le-yolo\runs\detect\train6\weights\best.pt") +results = model.predict("../res/2.mp4", show=True, save=True) \ No newline at end of file diff --git a/src/train.py b/src/train.py new file mode 100644 index 0000000..2a00257 --- /dev/null +++ b/src/train.py @@ -0,0 +1,4 @@ +from ultralytics import YOLO +model = YOLO("yolov8n.pt") +model.train(data="data.yaml", epochs=500, batch=3, device='cpu') +print('训练完成') \ No newline at end of file