├── .devcontainer └── devcontainer.json ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ ├── codeql.yml │ ├── cypress.yml │ ├── doc_to_pages.yml │ ├── issue2project.yml │ ├── publish.yml │ ├── publish_doc.yml │ ├── remove_triage.yml │ ├── rm_action_runs.yml │ ├── rm_cache.yml │ ├── stale.yml │ └── triage.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .vscode ├── extensions.json └── settings.json ├── Dockerfile.dev ├── LICENSE ├── MANIFEST.in ├── README.md ├── doc ├── CN │ ├── ML │ │ ├── auto_inference.md │ │ ├── install_ml.md │ │ ├── interactive_segmentation.md │ │ └── ml.md │ ├── README.md │ ├── _config.yml │ ├── assets │ │ ├── accept_model_label.png │ │ ├── action-1.png │ │ ├── add_label.png │ │ ├── auto_inference.png │ │ ├── classification.png │ │ ├── cn_home.png │ │ ├── create.png │ │ ├── dataset_path.png │ │ ├── dataset_split.png │ │ ├── dont_accept_model_label.png │ │ ├── export.png │ │ ├── export_detail.png │ │ ├── group_qr.png │ │ ├── import_name.png │ │ ├── interact_button.png │ │ ├── interact_mode.png │ │ ├── interact_setting.png │ │ ├── label_page.png │ │ ├── miniconda_cn.png │ │ ├── miniconda_init_cn.png │ │ ├── miniconda_install_type.png │ │ ├── ml_backend_url.png │ │ ├── msvc.png │ │ ├── project_overview.png │ │ ├── project_overview_to_label.png │ │ ├── project_overview_to_split.png │ │ ├── sample_button.png │ │ ├── sample_page.png │ │ ├── sample_structure.png │ │ ├── start_two.png │ │ ├── test_label.png │ │ ├── to_auto_inference.png │ │ ├── to_home.png │ │ └── to_overview.png │ ├── developers_guide.md │ ├── install.md │ ├── manual │ │ ├── classification.md │ │ ├── common.md │ │ ├── detection.md │ │ ├── instance_segmentation.md │ │ ├── manual.md │ │ ├── ocr.md │ │ └── semantic_segmentation.md │ ├── quick_start.md │ ├── release_notes.md │ └── training │ │ ├── PdLabel_PdClas.md │ │ ├── PdLabel_PdDet.md │ │ ├── PdLabel_PdSeg.md │ │ ├── PdLabel_PdX.md │ │ └── training.md ├── EN │ ├── README.md │ ├── _config.yml │ ├── assets │ │ └── group_qr.png │ ├── developers_guide.md │ └── project │ │ └── dataset_file_structure.md ├── Gemfile ├── README.md ├── old │ ├── dataset_file_structure.md │ └── detection_ml.md └── prepare.py ├── docker-compose-dev.yml ├── docstring_format.mustache ├── paddlelabel ├── __init__.py ├── __main__.py ├── alembic.ini ├── api │ ├── __init__.py │ ├── controller │ │ ├── __init__.py │ │ ├── annotation.py │ │ ├── base.py │ │ ├── data.py │ │ ├── label.py │ │ ├── project.py │ │ ├── sample.py │ │ ├── setting.py │ │ ├── tag.py │ │ ├── task.py │ │ └── user.py │ ├── model │ │ ├── __init__.py │ │ ├── annotation.py │ │ ├── base.py │ │ ├── data.py │ │ ├── label.py │ │ ├── project.py │ │ ├── setting.py │ │ ├── tag.py │ │ ├── tag_task.py │ │ ├── task.py │ │ └── user.py │ ├── rpc │ │ ├── __init__.py │ │ ├── cache.py │ │ ├── debug.py │ │ ├── file.py │ │ ├── monitor.py │ │ ├── seg.py │ │ └── util │ │ │ ├── __init__.py │ │ │ └── polygon.py │ ├── schema │ │ ├── __init__.py │ │ ├── annotation.py │ │ ├── base.py │ │ ├── data.py │ │ ├── label.py │ │ ├── project.py │ │ ├── setting.py │ │ ├── tag.py │ │ ├── tag_task.py │ │ ├── task.py │ │ ├── user.py │ │ └── util.py │ └── util.py ├── config.py ├── dbmigration │ ├── README.md │ ├── __init__.py │ ├── env.py │ ├── script.py.mako │ └── versions │ │ ├── 23c1bf9b7f48_v0_1_2.py │ │ ├── 61968cbf48e8_v0_1_3.py │ │ ├── __init__.py │ │ ├── a609821ce310_v0_1_4.py │ │ ├── e660f34b820d_v1_0_1.py │ │ └── f47b7f5b73b9_v1_0_0.py ├── default_setting.json ├── io │ ├── __init__.py │ └── image.py ├── openapi.yml ├── sample │ ├── bear │ │ ├── classification │ │ │ ├── multiClass │ │ │ │ ├── labels.txt │ │ │ │ ├── test_list.txt │ │ │ │ ├── train_list.txt │ │ │ │ └── val_list.txt │ │ │ └── singleClass │ │ │ │ ├── labels.txt │ │ │ │ ├── test_list.txt │ │ │ │ ├── train_list.txt │ │ │ │ └── val_list.txt │ │ ├── detection │ │ │ ├── coco │ │ │ │ ├── test.json │ │ │ │ ├── train.json │ │ │ │ └── val.json │ │ │ ├── voc │ │ │ │ ├── Annotations │ │ │ │ │ ├── 1.xml │ │ │ │ │ ├── 2.xml │ │ │ │ │ └── 3.xml │ │ │ │ ├── labels.txt │ │ │ │ ├── test_list.txt │ │ │ │ ├── train_list.txt │ │ │ │ └── val_list.txt │ │ │ └── yolo │ │ │ │ ├── Annotations │ │ │ │ ├── 1.txt │ │ │ │ ├── 2.txt │ │ │ │ └── 3.txt │ │ │ │ ├── classes.names │ │ │ │ ├── test_list.txt │ │ │ │ ├── train_list.txt │ │ │ │ └── val_list.txt │ │ ├── img │ │ │ ├── 05.jpg │ │ │ ├── 06.jpg │ │ │ ├── 07.jpg │ │ │ ├── 08.jpg │ │ │ ├── 09.jpg │ │ │ ├── 1.jpeg │ │ │ ├── 10.jpg │ │ │ ├── 11.png │ │ │ ├── 2.jpeg │ │ │ ├── 3.jpeg │ │ │ └── 4.jpeg │ │ ├── instanceSegmentation │ │ │ ├── coco │ │ │ │ ├── test.json │ │ │ │ ├── train.json │ │ │ │ └── val.json │ │ │ ├── eiseg │ │ │ │ └── label │ │ │ │ │ ├── 1.json │ │ │ │ │ ├── 2.json │ │ │ │ │ └── 3.json │ │ │ └── mask │ │ │ │ ├── Annotations │ │ │ │ ├── 1.tiff │ │ │ │ ├── 2.tiff │ │ │ │ └── 3.tiff │ │ │ │ ├── labels.txt │ │ │ │ ├── test_list.txt │ │ │ │ ├── train_list.txt │ │ │ │ └── val_list.txt │ │ ├── opticalCharacterRecognition │ │ │ └── txt │ │ │ │ └── Label.txt │ │ ├── placeholder │ │ │ ├── labels.txt │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ ├── point │ │ │ └── labelme │ │ │ │ └── Annotations │ │ │ │ ├── 1.json │ │ │ │ ├── 2.json │ │ │ │ ├── 3.json │ │ │ │ └── 4.json │ │ └── semanticSegmentation │ │ │ ├── coco │ │ │ ├── test.json │ │ │ ├── train.json │ │ │ └── val.json │ │ │ ├── eiseg │ │ │ └── label │ │ │ │ ├── 1.json │ │ │ │ ├── 2.json │ │ │ │ └── 3.json │ │ │ └── mask │ │ │ ├── Annotations │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ └── 3.png │ │ │ ├── labels.txt │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ └── fruit │ │ ├── classification │ │ ├── multiClass │ │ │ ├── labels.txt │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ └── singleClass │ │ │ ├── labels.txt │ │ │ ├── paddlelabel.warning │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ ├── detection │ │ ├── coco │ │ │ ├── test.json │ │ │ ├── train.json │ │ │ └── val.json │ │ ├── voc │ │ │ ├── Annotations │ │ │ │ ├── 1.xml │ │ │ │ ├── 2.xml │ │ │ │ ├── 3.xml │ │ │ │ └── 4.xml │ │ │ ├── labels.txt │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ └── yolo │ │ │ ├── Annotations │ │ │ ├── 1.txt │ │ │ ├── 2.txt │ │ │ ├── 3.txt │ │ │ └── 4.txt │ │ │ ├── classes.names │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ ├── img │ │ ├── 1.jpeg │ │ ├── 2.jpeg │ │ ├── 3.jpeg │ │ ├── 4.jpeg │ │ └── 5.jpeg │ │ ├── instanceSegmentation │ │ ├── coco │ │ │ ├── test.json │ │ │ ├── train.json │ │ │ └── val.json │ │ └── mask │ │ │ ├── Annotations │ │ │ ├── 1.tiff │ │ │ ├── 2.tiff │ │ │ ├── 3.tiff │ │ │ └── 4.tiff │ │ │ ├── labels.txt │ │ │ ├── test_list.txt │ │ │ ├── train_list.txt │ │ │ └── val_list.txt │ │ ├── placeholder │ │ ├── labels.txt │ │ ├── paddlelabel.warning │ │ ├── test_list.txt │ │ ├── train_list.txt │ │ └── val_list.txt │ │ └── semanticSegmentation │ │ ├── coco │ │ ├── test.json │ │ ├── train.json │ │ └── val.json │ │ └── mask │ │ ├── Annotations │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ └── 4.png │ │ ├── labels.txt │ │ ├── test_list.txt │ │ ├── train_list.txt │ │ └── val_list.txt ├── serve.py ├── task │ ├── __init__.py │ ├── base.py │ ├── classification.py │ ├── detection.py │ ├── instance_segmentation.py │ ├── optical_character_recognition.py │ ├── point.py │ ├── semantic_segmentation.py │ └── util │ │ ├── __init__.py │ │ ├── color.py │ │ ├── file.py │ │ ├── labelme.py │ │ └── manager.py ├── tool │ ├── __main__.py │ └── simple_file_format.py ├── util.py └── version ├── pyproject.toml ├── pyproject.toml.temp ├── requirements-dev.txt ├── requirements.txt ├── setup.py ├── thunder-tests ├── thunderActivity.json ├── thunderCollection.json ├── thunderEnvironment.json └── thunderclient.json └── tool ├── build_frontend.sh ├── bumpversion.py ├── file.py ├── gen_sample_dst.py ├── get_frontend.sh ├── old ├── Procfile ├── clas │ ├── __init__.py │ └── mv_image_acc_split.py ├── cypress.sh ├── freeze_env.sh ├── install.sh ├── kill_by_port.py ├── labels │ └── labels_remove_first_value.py ├── pypi.sh ├── rm_workflow_runs.sh └── runtime.txt └── zip_sample.sh /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "dockerComposeFile": [ 3 | "../docker-compose-dev.yml" 4 | ], 5 | "extensions": [ 6 | "dbaeumer.vscode-eslint", 7 | "ms-python.vscode-pylance", 8 | "ms-python.python" 9 | ], 10 | "features": { 11 | "git": "os-provided", 12 | "github-cli": "latest", 13 | "sshd": "latest" 14 | }, 15 | "forwardPorts": [ 16 | 5000 17 | ], 18 | "name": "backend-pp-label-vscode", 19 | "service": "pp-labeling-backend", 20 | "settings": {}, 21 | "workspaceFolder": "/app" 22 | } 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" # See documentation for possible values 9 | directory: "/requirements.txt" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build & E2E Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | pull_request: 8 | branches: 9 | - v* 10 | workflow_dispatch: 11 | inputs: 12 | force_regen_doc: 13 | description: "Force regenerate doc site" 14 | required: false 15 | default: true 16 | type: boolean 17 | schedule: 18 | - cron: "0 12 * * *" 19 | 20 | jobs: 21 | update_doc_build: 22 | # uses: PaddleCV-SIG/PaddleLabel/.github/workflows/doc_to_pages.yml@develop 23 | uses: ./.github/workflows/doc_to_pages.yml 24 | with: 25 | baseurl: "/static/doc/" 26 | deploy: false 27 | # force_regen: ${{ inputs.force_regen_doc }} 28 | force_regen: true 29 | 30 | build: 31 | runs-on: ubuntu-latest 32 | strategy: 33 | matrix: 34 | python-version: ["3.11"] 35 | 36 | needs: update_doc_build 37 | steps: 38 | - name: Checkout backend code 39 | uses: actions/checkout@v3 40 | 41 | - name: Download built frontend 42 | uses: dawidd6/action-download-artifact@v2 43 | with: 44 | workflow: build.yml 45 | workflow_conclusion: success 46 | repo: PaddleCV-SIG/PaddleLabel-Frontend 47 | name: PaddleLabel_built_frontend 48 | path: ./paddlelabel/static/ 49 | search_artifacts: true 50 | 51 | - name: Download built doc static site 52 | uses: actions/download-artifact@v3 53 | # uses: dawidd6/action-download-artifact@v2 54 | with: 55 | # workflow_conclusion: "" 56 | # branch: develop 57 | name: github-pages 58 | # search_artifacts: true 59 | # check_artifacts: true 60 | path: ./paddlelabel/static/doc/ 61 | 62 | - name: Unarchive doc site 63 | run: | 64 | cd ./paddlelabel/static/doc/ 65 | ls 66 | tar -xvf artifact.tar 67 | rm artifact.tar 68 | tree . 69 | cd - 70 | 71 | - name: Set up Python ${{ matrix.python-version }} 72 | uses: actions/setup-python@v4 73 | with: 74 | python-version: ${{ matrix.python-version }} 75 | cache: "pip" 76 | 77 | - name: Install dependencies 78 | run: | 79 | python -m pip install --upgrade pip 80 | pip install --upgrade twine wheel 81 | 82 | - name: Write backend commit hash to package 83 | run: | 84 | echo backend $(git rev-parse --short HEAD) >> ./paddlelabel/static/git_versions.html 85 | 86 | - name: Generate package 87 | run: | 88 | python setup.py sdist bdist_wheel 89 | 90 | - name: Set action summary 91 | run: | 92 | echo " 93 | # Build Summary 94 | branch: $(git branch --show-current) 95 | version: $(cat paddlelabel/version) 96 | " >> $GITHUB_STEP_SUMMARY 97 | 98 | - name: Save built package 99 | uses: actions/upload-artifact@v3 100 | with: 101 | name: PaddleLabel_built_package 102 | path: | 103 | dist 104 | 105 | cypress_e2e_test: 106 | needs: build 107 | # uses: PaddleCV-SIG/PaddleLabel/.github/workflows/cypress.yml@develop 108 | uses: ./.github/workflows/cypress.yml 109 | 110 | bump_version: 111 | if: github.event_name == 'push' 112 | runs-on: ubuntu-latest 113 | strategy: 114 | matrix: 115 | python-version: ["3.11"] 116 | needs: cypress_e2e_test 117 | steps: 118 | - name: Checkout backend code 119 | uses: actions/checkout@v3 120 | 121 | - name: Bump version 122 | id: bump_version 123 | # if: github.event_name == 'push' 124 | run: | 125 | python tool/bumpversion.py 126 | git config --global user.email "bot@github.com" && git config --global user.name "Action Bot" 127 | git add paddlelabel/version; git commit -m "bump version"; git push 128 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [v*] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [v*] 20 | schedule: 21 | - cron: "31 15 * * 5" 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: ["python"] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Use only 'java' to analyze code written in Java, Kotlin or both 38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 40 | 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v3 44 | 45 | # Initializes the CodeQL tools for scanning. 46 | - name: Initialize CodeQL 47 | uses: github/codeql-action/init@v2 48 | with: 49 | languages: ${{ matrix.language }} 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | 54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 55 | # queries: security-extended,security-and-quality 56 | 57 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 58 | # If this step fails, then you should remove it and run the build manually (see below) 59 | - name: Autobuild 60 | uses: github/codeql-action/autobuild@v2 61 | 62 | # ℹ️ Command-line programs to run using the OS shell. 63 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 64 | 65 | # If the Autobuild fails above, remove it and uncomment the following three lines. 66 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 67 | 68 | # - run: | 69 | # echo "Run, Build Application using script" 70 | # ./location_of_script_within_repo/buildscript.sh 71 | 72 | - name: Perform CodeQL Analysis 73 | uses: github/codeql-action/analyze@v2 74 | with: 75 | category: "/language:${{matrix.language}}" 76 | -------------------------------------------------------------------------------- /.github/workflows/issue2project.yml: -------------------------------------------------------------------------------- 1 | name: Add issues to project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@v0.3.0 14 | with: 15 | project-url: https://github.com/orgs/PaddleCV-SIG/projects/2 16 | github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} 17 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publishing latest built package to pypi 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | dry_run: 7 | description: "Skip last publish step" 8 | required: false 9 | default: true 10 | type: boolean 11 | jobs: 12 | publish: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Download artifact 17 | id: download-artifact 18 | uses: dawidd6/action-download-artifact@v2 19 | with: 20 | workflow: build.yml 21 | workflow_conclusion: success 22 | branch: develop 23 | name: PaddleLabel_built_package 24 | path: | 25 | dist 26 | 27 | - run: | 28 | pwd 29 | ls 30 | tree . 31 | 32 | - name: Publish to PyPI 33 | if: ${{ inputs.dry_run != true }} 34 | uses: pypa/gh-action-pypi-publish@release/v1 35 | with: 36 | user: __token__ 37 | password: ${{ secrets.PADDLELABEL_PUBLISH_API_TOKEN }} 38 | verbose: true 39 | -------------------------------------------------------------------------------- /.github/workflows/publish_doc.yml: -------------------------------------------------------------------------------- 1 | name: Publish doc to pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | - doc 8 | workflow_dispatch: 9 | inputs: 10 | force_regen: 11 | description: "Force the jekyll generation step" 12 | required: false 13 | default: true 14 | type: boolean 15 | 16 | 17 | jobs: 18 | publish_doc: 19 | uses: PaddleCV-SIG/PaddleLabel/.github/workflows/doc_to_pages.yml@develop 20 | with: 21 | baseurl: "/PaddleLabel/" 22 | deploy: true 23 | force_regen: ${{ inputs.force_regen }} 24 | -------------------------------------------------------------------------------- /.github/workflows/remove_triage.yml: -------------------------------------------------------------------------------- 1 | name: Remove triage label 2 | on: 3 | issues: 4 | types: 5 | - assigned 6 | jobs: 7 | remove_label: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | steps: 12 | - uses: actions/github-script@v6 13 | with: 14 | script: | 15 | github.rest.issues.removeLabel({ 16 | issue_number: context.issue.number, 17 | owner: context.repo.owner, 18 | repo: context.repo.repo, 19 | name: ["triage"] 20 | }) 21 | -------------------------------------------------------------------------------- /.github/workflows/rm_action_runs.yml: -------------------------------------------------------------------------------- 1 | name: Delete old workflow runs 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | days: 6 | description: 'Number of days.' 7 | required: true 8 | default: 30 9 | minimum_runs: 10 | description: 'The minimum runs to keep for each workflow.' 11 | required: true 12 | default: 6 13 | delete_workflow_pattern: 14 | description: 'The name or filename of the workflow. if not set then it will target all workflows.' 15 | required: false 16 | delete_workflow_by_state_pattern: 17 | description: 'Remove workflow by state: active, deleted, disabled_fork, disabled_inactivity, disabled_manually' 18 | required: true 19 | default: "All" 20 | type: choice 21 | options: 22 | - "All" 23 | - active 24 | - deleted 25 | - disabled_inactivity 26 | - disabled_manually 27 | delete_run_by_conclusion_pattern: 28 | description: 'Remove workflow by conclusion: action_required, cancelled, failure, skipped, success' 29 | required: true 30 | default: "All" 31 | type: choice 32 | options: 33 | - "All" 34 | - action_required 35 | - cancelled 36 | - failure 37 | - skipped 38 | - success 39 | dry_run: 40 | description: 'Only log actions, do not perform any delete operations.' 41 | required: false 42 | 43 | jobs: 44 | del_runs: 45 | runs-on: ubuntu-latest 46 | steps: 47 | - name: Delete workflow runs 48 | uses: Mattraks/delete-workflow-runs@v2 49 | with: 50 | token: ${{ github.token }} 51 | repository: ${{ github.repository }} 52 | retain_days: ${{ github.event.inputs.days }} 53 | keep_minimum_runs: ${{ github.event.inputs.minimum_runs }} 54 | delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }} 55 | delete_workflow_by_state_pattern: ${{ github.event.inputs.delete_workflow_by_state_pattern }} 56 | delete_run_by_conclusion_pattern: ${{ github.event.inputs.delete_run_by_conclusion_pattern }} 57 | dry_run: ${{ github.event.inputs.dry_run }} 58 | -------------------------------------------------------------------------------- /.github/workflows/rm_cache.yml: -------------------------------------------------------------------------------- 1 | name: Delete All Caches 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 0 * * SUN" 7 | 8 | jobs: 9 | delete: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: snnaplab/delete-branch-cache-action@v1 13 | # with: 14 | # # Specify explicitly because the ref at the time of merging will be a branch name such as 'main', 'develop' 15 | # ref: refs/pull/${{ github.event.number }}/merge 16 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Mark stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | - cron: '0 17 * * *' 11 | 12 | jobs: 13 | stale: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | issues: write 18 | pull-requests: none 19 | 20 | steps: 21 | - uses: actions/stale@v5 22 | with: 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.' 25 | stale-issue-label: 'stale' 26 | close-issue-reason: 'completed' 27 | exempt-issue-labels: 'bug, enhancement, Feature Request, WIP, TobeReviewed' 28 | operations-per-run: 900 29 | days-before-pr-stale: -1 30 | days-before-pr-close: -1 31 | ascending: true 32 | -------------------------------------------------------------------------------- /.github/workflows/triage.yml: -------------------------------------------------------------------------------- 1 | name: Label issues 2 | on: 3 | issues: 4 | types: 5 | - reopened 6 | - opened 7 | jobs: 8 | label_issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | steps: 13 | - uses: actions/github-script@v6 14 | with: 15 | script: | 16 | github.rest.issues.addLabels({ 17 | issue_number: context.issue.number, 18 | owner: context.repo.owner, 19 | repo: context.repo.repo, 20 | labels: ["triage"] 21 | }) 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project Specific 2 | pplabel.db 3 | paddlelabel.db 4 | static/ 5 | temp/ 6 | temp 7 | test.py 8 | *.log 9 | *.test 10 | 11 | paddlelabel.warning 12 | 13 | _site 14 | .jekyll-cache 15 | Gemfile.lock 16 | 17 | # Byte-compiled / optimized / DLL files 18 | __pycache__/ 19 | *.py[cod] 20 | *$py.class 21 | *.db 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | lib/ 35 | lib64/ 36 | parts/ 37 | sdist/ 38 | var/ 39 | wheels/ 40 | pip-wheel-metadata/ 41 | share/python-wheels/ 42 | *.egg-info/ 43 | .installed.cfg 44 | *.egg 45 | MANIFEST 46 | 47 | # PyInstaller 48 | # Usually these files are written by a python script from a template 49 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 50 | *.manifest 51 | *.spec 52 | 53 | # Installer logs 54 | pip-log.txt 55 | pip-delete-this-directory.txt 56 | 57 | # Unit test / coverage reports 58 | htmlcov/ 59 | .tox/ 60 | .nox/ 61 | .coverage 62 | .coverage.* 63 | .cache 64 | nosetests.xml 65 | coverage.xml 66 | *.cover 67 | *.py,cover 68 | .hypothesis/ 69 | .pytest_cache/ 70 | 71 | # Translations 72 | *.mo 73 | *.pot 74 | 75 | # Django stuff: 76 | *.log 77 | local_settings.py 78 | db.sqlite3 79 | db.sqlite3-journal 80 | 81 | # Flask stuff: 82 | instance/ 83 | .webassets-cache 84 | 85 | # Scrapy stuff: 86 | .scrapy 87 | 88 | # Sphinx documentation 89 | docs/_build/ 90 | 91 | # PyBuilder 92 | target/ 93 | 94 | # Jupyter Notebook 95 | .ipynb_checkpoints 96 | 97 | # IPython 98 | profile_default/ 99 | ipython_config.py 100 | 101 | # pyenv 102 | .python-version 103 | 104 | # pipenv 105 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 106 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 107 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 108 | # install all needed dependencies. 109 | #Pipfile.lock 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.3.0 4 | hooks: 5 | - id: no-commit-to-branch 6 | args: [--pattern, ^v] 7 | # - id: check-added-large-files 8 | # args: [--maxkb=16] 9 | - id: check-case-conflict 10 | - id: check-yaml 11 | - id: check-xml 12 | - id: check-toml 13 | - id: check-merge-conflict 14 | - id: check-symlinks 15 | - id: destroyed-symlinks 16 | - id: mixed-line-ending 17 | args: [--fix=lf] 18 | - id: end-of-file-fixer 19 | - id: trailing-whitespace 20 | - id: check-json 21 | - id: pretty-format-json 22 | args: [--autofix, --indent=4, --no-ensure-ascii] 23 | # - id: detect-aws-credentials 24 | - id: detect-private-key 25 | - id: fix-encoding-pragma 26 | 27 | # - repo: https://github.com/pre-commit/mirrors-mypy 28 | # rev: v0.991 29 | # hooks: 30 | # - id: mypy 31 | - repo: https://github.com/psf/black 32 | rev: 22.10.0 33 | hooks: 34 | - id: black 35 | 36 | - repo: https://github.com/pre-commit/pygrep-hooks 37 | rev: v1.10.0 # Use the ref you want to point at 38 | hooks: 39 | - id: python-use-type-annotations 40 | 41 | 42 | # - repo: https://github.com/sonatype-nexus-community/jake 43 | # rev: "v3.0.0" 44 | # hooks: 45 | # - id: scan 46 | # - repo: https://github.com/executablebooks/mdformat 47 | # rev: 0.7.16 # Use the ref you want to point at 48 | # hooks: 49 | # - id: mdformat 50 | # exclude: doc/CN/project/detection.md # messes up image['file_name'] 51 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dotjoshjohnson.xml", 4 | "njpwerner.autodocstring", 5 | "pejmannikram.vscode-auto-scroll", 6 | "streetsidesoftware.code-spell-checker", 7 | "fabiospampinato.vscode-highlight", 8 | "redhat.vscode-yaml", 9 | "ms-python.isort", 10 | "yzhang.markdown-all-in-one", 11 | "ms-python.vscode-pylance", 12 | "ms-python.python" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "autoDocstring.customTemplatePath": "docstring_format.mustache", 3 | "cSpell.words": [ 4 | "anns", 5 | "autofix", 6 | "bgid", 7 | "bndbox", 8 | "callouts", 9 | "catg", 10 | "catgs", 11 | "choco", 12 | "Clas", 13 | "conda", 14 | "connexion", 15 | "datas", 16 | "dawidd", 17 | "dbmigration", 18 | "dsts", 19 | "dtype", 20 | "easydata", 21 | "eiseg", 22 | "imread", 23 | "jemoji", 24 | "labelme", 25 | "levelname", 26 | "linhandev", 27 | "micromamba", 28 | "miniconda", 29 | "msvc", 30 | "msys", 31 | "nncol", 32 | "noviz", 33 | "numpy", 34 | "ondelete", 35 | "onupdate", 36 | "outcoco", 37 | "pacman", 38 | "paddlelabel", 39 | "paddlelabl", 40 | "paddlepaddle", 41 | "pdlabel", 42 | "Pico", 43 | "pjid", 44 | "pkgs", 45 | "popleft", 46 | "PPLC", 47 | "pycocotoolse", 48 | "pypi", 49 | "regen", 50 | "rget", 51 | "SQLALCHEMY", 52 | "supercategory", 53 | "vcbuildtools", 54 | "vcredist", 55 | "venv", 56 | "werkzeug", 57 | "xlen", 58 | "xmax", 59 | "xmid", 60 | "xmin", 61 | "ylen", 62 | "ymax", 63 | "ymid", 64 | "ymin", 65 | "yolo" 66 | ], 67 | "python.analysis.diagnosticMode": "workspace", 68 | "python.analysis.typeCheckingMode": "basic", 69 | "python.formatting.provider": "black", 70 | "python.languageServer": "Pylance" 71 | } 72 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | WORKDIR /app 4 | # ADD . . 5 | 6 | # Keeps Python from generating .pyc files in the container 7 | ENV PYTHONDONTWRITEBYTECODE=1 8 | 9 | # Turns off buffering for easier container logging 10 | ENV PYTHONUNBUFFERED=1 11 | 12 | # Important Install For GDAL 13 | RUN apt-get update \ 14 | && apt-get install -y gdal-bin libgdal-dev 15 | 16 | RUN export CPLUS_INCLUDE_PATH=/usr/include/gdal 17 | RUN export C_INCLUDE_PATH=/usr/include/gdal 18 | 19 | # Install requirements 20 | COPY ./requirements.txt . 21 | RUN pip install --upgrade pip 22 | RUN pip install -r requirements.txt 23 | 24 | # Add source code 25 | 26 | # Set environment variables 27 | # ENV FLASK_APP=setup.py 28 | 29 | # Run 30 | ENTRYPOINT [ "python", "-m", "paddlelabel" ] 31 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include paddlelabel/sample/ * 2 | recursive-include paddlelabel/static/ * 3 | 4 | include paddlelabel/alembic.ini 5 | include paddlelabel/dbmigration/script.py.mako 6 | include paddlelabel/version 7 | include paddlelabel/default_setting.json 8 | include paddlelabel/openapi.yml 9 | include requirements.txt 10 | 11 | # exclude test/ 12 | # exclude tool/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | doc/CN/README.md -------------------------------------------------------------------------------- /doc/CN/ML/auto_inference.md: -------------------------------------------------------------------------------- 1 | # 自动预标注使用方法 2 | 3 | 4 | 5 | - [模型列表](#%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8) 6 | - [前置步骤](#%E5%89%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4) 7 | - [进行设置](#%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE) 8 | - [使用自动预标注](#%E4%BD%BF%E7%94%A8%E8%87%AA%E5%8A%A8%E9%A2%84%E6%A0%87%E6%B3%A8) 9 | 10 | 11 | 12 | PaddleLabel 基于 [PaddleClas](https://github.com/PaddlePaddle/PaddleClas),[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection) 和 [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) 中的预训练模型为分类,检测和 OCR 项目提供自动预标注能力。您只需在“自动推理设置”中进行简单配置即可启用这一功能。本文档以分类项目为例介绍自动预标注功能的配置和使用方法,检测和 OCR 项目中的使用流程基本完全相同。 13 | 14 | ![](https://user-images.githubusercontent.com/35907364/204250596-061d8193-b011-44b4-9b25-83efc77fef04.gif) 15 | 16 | 22 | 23 | ## 模型列表 24 | 25 | PaddleLabel 目前支持的模型和使用各模型所需的 PaddleLabel-ML 版本如下 26 | 27 | - 分类 28 | - [PP-LCNetV2](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/models/ImageNet1k/PP-LCNetV2.md) 29 | v0.5.0+ {: .label } 30 | - 检测 31 | - [PP-PicoDet](https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.5/configs/picodet) 32 | v0.5.0+ {: .label } 33 | - OCR 34 | - [PP-OCRv3](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/PP-OCRv3_introduction.md) 35 | v0.5.0+ {: .label } 36 | 37 | ## 前置步骤 38 | 39 | 1. 在使用自动预标注功能前请先参考 [此文档](/doc/CN/ML/install_ml.md) 安装 PaddleLabel-ML 辅助标注后端 40 | 41 | 2. 启动 PaddleLabel 和 PaddleLabel-ML 42 | 43 | 打开两个命令行终端,第一个输入 `paddlelabel` 并回车,第二个输入 `paddlelabel-ml` 并回车,分别启动项目的 web 部分和辅助标注部分 44 | ![](/doc/CN/assets/start_two.png) 45 | 46 | 3. 创建项目 47 | 48 | 您可以参考快速体验文档[创建内置样例项目](/doc/CN/quick_start.md#创建样例项目)或[导入一个数据集](/doc/CN/quick_start.md#导入数据集) 49 | 50 | ## 进行设置 51 | 52 | 1. 点击“项目总览”页面上方“自动推理设置”按钮进入设置页面 53 | ![](/doc/CN/assets/to_auto_inference.png) 54 | 2. 填写机器学习后端网址 55 | 56 | 默认网址为`http://127.0.0.1:1234`。这一网址可以通过观察 paddlelabel-ml 启动时的命令行输出确定 57 | ![](/doc/CN/assets/ml_backend_url.png) 58 | 59 | 3. 点击模型选择下拉菜单选择一个模型 60 | 4. 选择是否使用预标注标签 61 | 62 | - 此处如选择`是` 63 | - 预标注模型的推理结果类别将被原样添加到图像标注中 64 | - 如果模型推理出了一个项目中没有的类别,会自动向项目中添加该类别标签 65 | ![](/doc/CN/assets/accept_model_label.png) 66 | - 此处如选择`否`,则不直接使用预标注模型标签 67 | - 您需要提供预标注模型标签与项目中标签的对应关系。比如指定预标注模型的标签“咖啡杯”对应项目中的标签“杯子”,标注时如果模型对一张图片推理结果为“咖啡杯”,则会向该图片添加“杯子”类别 68 | - 多个预标注模型的标签可以对应同一个项目中的标签,比如使用下图中的配置,“咖啡壶”和“咖啡杯”类别的推理结果都会向图片中添加“咖啡用具”标签 69 | - 一个模型标签只能对应到一个项目中的标签 70 | - 注意在这个模式下,辅助标注流程会忽略所有未提供对应关系的预标注模型标签 71 | ![](/doc/CN/assets/dont_accept_model_label.png) 72 | 73 | 5. 完成设置后,点击`确定`保存,跳转回项目总览页面 74 | 75 | ## 使用自动预标注 76 | 77 | - 预标注模型会在您进入标注页面时自动加载 78 | - 当您翻到一张之前没有进行过预标注的图片时会自动触发推理。您也可以点击右侧工具栏中的“自动推理”按钮手动触发一次推理 79 | - 您可以通过调节右侧工具栏中的“推理阈值”控制预标注结果的数量 80 | -------------------------------------------------------------------------------- /doc/CN/ML/install_ml.md: -------------------------------------------------------------------------------- 1 | # 机器学习后端安装 2 | 3 | 4 | 5 | - [前置步骤](#%E5%89%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4) 6 | - [安装方式](#%E5%AE%89%E8%A3%85%E6%96%B9%E5%BC%8F) 7 | - [通过 pip 安装](#%E9%80%9A%E8%BF%87-pip-%E5%AE%89%E8%A3%85) 8 | - [下载最新开发版](#%E4%B8%8B%E8%BD%BD%E6%9C%80%E6%96%B0%E5%BC%80%E5%8F%91%E7%89%88) 9 | - [通过源码安装](#%E9%80%9A%E8%BF%87%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85) 10 | - [启动](#%E5%90%AF%E5%8A%A8) 11 | - [更多启动选项](#%E6%9B%B4%E5%A4%9A%E5%90%AF%E5%8A%A8%E9%80%89%E9%A1%B9) 12 | - [下一步](#%E4%B8%8B%E4%B8%80%E6%AD%A5) 13 | 14 | 15 | 16 | ## 前置步骤 17 | 18 | 为了避免环境冲突,建议首先创建一个新的虚拟环境。 19 | 20 | ```python 21 | conda create -n paddlelabel-ml python=3.10 22 | conda activate paddlelabel-ml 23 | ``` 24 | 25 | 您可以选择安装 cpu 或 gpu 版本的 PaddlePaddle,cpu 版本安装简便,首次尝试推荐安装这一版本;gpu 版本推理速度更快,重度使用时体验更好。推荐安装不低于 2.2.0 版本的 PaddlePaddle。 26 | 27 | cpu 版本 28 | 29 | ```shell 30 | pip install paddlepaddle 31 | ``` 32 | 33 | gpu 版本 34 | 35 | ```shell 36 | 37 | ``` 38 | 39 | 40 | 41 | ## 安装方式 42 | 43 | 与 PaddleLabel 类似,您可以通过以下三种方式中的**任意一种**安装 PaddleLabel-ML,其中通过 pip 安装最简单。 44 | 45 | ### 通过 pip 安装 46 | 47 | ```shell 48 | pip install --upgrade paddlelabel-ml 49 | ``` 50 | 51 | 看到类似于 `Successfully installed paddlelabel-ml-0.5.0` 的命令行输出即为安装成功,您可以直接继续浏览[启动](#%E5%90%AF%E5%8A%A8)章节。 52 | 53 | {: .note } 54 | **以下两种安装方式主要针对二次开发场景** 55 | 56 | ### 下载最新开发版 57 | 58 |
详细步骤 59 | 每当 PaddleLabel-ML 的代码有更新,项目的 Github Action 脚本都会构建一个反映最新版代码的安装包。这一安装包未经过全面测试,因此很可能存在一些问题,仅推荐为尝试最新版本使用。其中可能修复了一些 pypi 版本中存在的问题,添加了一些新功能或进行了一些性能提升。 60 | 61 | 下载方式为 62 | 63 | 64 | 65 | 1. 访问 [Action 执行记录网页](https://github.com/PaddleCV-SIG/PaddleLabel-ML/actions/workflows/build.yml) 66 | 2. 选择最上面(最新)的一条执行记录,点击进入 67 | ![](/doc/CN/assets/action-1.png) 68 | 3. 滑到页面最下方,点击下载 69 | PaddleLabel-ML_built_package 压缩包 70 | ![1](https://user-images.githubusercontent.com/29757093/201905747-a2b0901c-9331-4a90-b4ae-44c855314810.jpg) 71 | 4. 解压该压缩包,之后执行 72 | 73 | ```shell 74 | pip install [解压出的.whl文件名,如 paddlelabel-ml-0.5.0-py3-none-any.whl ] 75 | ``` 76 | 77 |
78 | 79 | ### 通过源码安装 80 | 81 |
详细步骤 82 | 83 | 84 | 85 |
86 | 87 | ## 启动 88 | 89 | 完成上述的安装操作后,可以直接在终端使用如下指令启动 PaddleLabel-ML 90 | 91 | ```shell 92 | paddlelabel-ml # 启动paddlelabel-ml 93 | ``` 94 | 95 | 看到类似 `PaddleLabel-ML is running at http://localhost:1234` 的输出即为启动成功。您也可以访问[http://localhost:1234/running](http://localhost:1234/running)网页确定 ML 后端是否启动成功。 96 | 97 | {: .note} 98 | PaddleLabel-ML 没有独立的前端网页,您可以继续浏览[机器学习辅助标注](/doc/CN/ML/ml.md)章节了解如何在各个类型项目中配置和使用机器学习辅助标注功能。 99 | 100 | ### 更多启动选项 101 | 102 | PaddleLabel-ML 的默认运行网址为[http://localhost:1234](http://localhost:1234)。如果该端口已被占用,可以通过`--port`或`-p`参数指定其他端口。此外可以通过`--lan`或`-l`参数将服务暴露到局域网。在 docker 中运行 PaddleLabel 时也需要添加`--lan`参数。 103 | 104 | ```shell 105 | paddlelabel --port 6000 --lan # 在6000端口上运行并将服务暴露到局域网 106 | ``` 107 | 108 | 更多启动参数可以使用 `paddlelabel-ml -h` 查看。 109 | 110 | ## 下一步 111 | 112 | 恭喜您成功运行 PaddleLabel 机器学习辅助标注后端!您可以继续浏览[机器学习辅助标注](/doc/CN/ML/ml.md)章节了解如何在各个类型项目中配置和使用辅助标注功能。 113 | -------------------------------------------------------------------------------- /doc/CN/ML/interactive_segmentation.md: -------------------------------------------------------------------------------- 1 | # 交互式分割使用方法 2 | 3 | 4 | 5 | - [前置步骤](#%E5%89%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4) 6 | - [进行设置](#%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE) 7 | - [使用交互式标注](#%E4%BD%BF%E7%94%A8%E4%BA%A4%E4%BA%92%E5%BC%8F%E6%A0%87%E6%B3%A8) 8 | 9 | 10 | 11 | 12 | 13 | PaddleLabel 基于[EdgeFlow](https://arxiv.org/abs/2109.09406)模型在语义和实例分割项目中提供交互式分割支持。 14 | 15 | ## 前置步骤 16 | 17 | 1. 在使用自动预标注功能前请先参考 [此文档](/doc/CN/ML/install_ml.md) 安装 PaddleLabel-ML 辅助标注后端 18 | 19 | 2. 启动 PaddleLabel 和 PaddleLabel-ML 20 | 21 | 打开两个命令行终端,第一个输入 `paddlelabel` 并回车,第二个输入 `paddlelabel-ml` 并回车,分别启动项目的 web 部分和辅助标注部分 22 | ![](/doc/CN/assets/start_two.png) 23 | 24 | 3. 创建项目 25 | 26 | 您可以参考快速体验文档[创建内置样例项目](/doc/CN/quick_start.md#创建样例项目)或[导入一个数据集](/doc/CN/quick_start.md#导入数据集) 27 | 28 | ## 进行设置 29 | 30 | 1. 创建项目后直接进入标注页面,当鼠标悬浮在右侧工具栏“交互式分割”按钮上时,其左侧会出现“交互式分割设置”按钮,点击该按钮将弹出设置面板。 31 | ![](/doc/CN/assets/interact_button.png) 32 | ![](/doc/CN/assets/interact_setting.png) 33 | 2. 交互式分割设置中,机器学习后端网址为必填项,该网址可以通过观察 PaddleLabel-ML 启动时的命令行输出确定 34 | ![](/doc/CN/assets/ml_backend_url.png) 35 | 3. 模型和权重文件路径为选填项,如果留空,默认使用的模型是 HRNet18_OCR64 通用分割场景高精度模型。此外 EdgeFlow 还提供针对人像,遥感,医疗和瑕疵检测的垂类模型,您可以展开下方列表查看和下载。注意两个路径需要使用绝对路径,模型和权重文件要对应。 36 |
点击查看更多模型 37 | 38 | | 模型类型 | 适用场景 | 模型结构 | 模型下载地址 | 39 | | ------------ | -------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | 40 | | 高精度模型 | 通用场景的图像标注 | HRNet18_OCR64 | [static_hrnet18_ocr64_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_cocolvis.zip) | 41 | | 轻量化模型 | 通用场景的图像标注 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_cocolvis.zip) | 42 | | 高精度模型 | 通用图像标注场景 | EdgeFlow | [static_edgeflow_cocolvis](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_edgeflow_cocolvis.zip) | 43 | | 高精度模型 | 人像标注场景 | HRNet18_OCR64 | [static_hrnet18_ocr64_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr64_human.zip) | 44 | | 轻量化模型 | 人像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_human](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_human.zip) | 45 | | 轻量化模型 | 遥感建筑物标注场景 | HRNet18s_OCR48 | [static_hrnet18_ocr48_rsbuilding_instance](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18_ocr48_rsbuilding_instance.zip) | 46 | | 高精度模型\* | x 光胸腔标注场景 | Resnet50_Deeplabv3+ | [static_resnet50_deeplab_chest_xray](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_resnet50_deeplab_chest_xray.zip) | 47 | | 轻量化模型 | 医疗肝脏标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_lits](https://paddleseg.bj.bcebos.com/eiseg/0.4/static_hrnet18s_ocr48_lits.zip) | 48 | | 轻量化模型\* | MRI 椎骨图像标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_MRSpineSeg](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_MRSpineSeg.zip) | 49 | | 轻量化模型\* | 质检铝板瑕疵标注场景 | HRNet18s_OCR48 | [static_hrnet18s_ocr48_aluminium](https://paddleseg.bj.bcebos.com/eiseg/0.5/static_hrnet18s_ocr48_aluminium.zip) | 50 | 51 |
52 | 53 | 4. 完成设置后点击“确定”,模型会在后台加载,通常时间不超过 1 分钟。加载完成后页面顶部会弹出消息`模型加载完成,您可以开始使用智能标注工具了`。 54 | 55 | ## 使用交互式标注 56 | 57 | 1. 点击页面右侧工具栏中“交互式分割”按钮进入交互式分割模式。此时页面上一些工具会被置灰禁用,再次点击“交互式分割”按钮退出后会恢复 58 | ![](/doc/CN/assets/interact_mode.png) 59 | 2. 选中一个标签,之后在图像中前景位置鼠标左键点击添加正样本点;在模型过度分割,掩膜蔓延到背景的位置鼠标右键点击添加负样本点,点击可以进行多轮。此外您可以在此过程中通过调整分割阈值控制整体边缘位置 60 | 3. 无论语义还是实例分割项目,推荐每次只用交互式分割标注一个对象,这样标注精度更高。完成一个对象的标注后,按下鼠标中键保存结果和清空当前控制点 61 | -------------------------------------------------------------------------------- /doc/CN/ML/ml.md: -------------------------------------------------------------------------------- 1 | # 机器学习辅助标注 2 | -------------------------------------------------------------------------------- /doc/CN/_config.yml: -------------------------------------------------------------------------------- 1 | title: PaddleLabel 2 | description: 高效灵活的数据标注工具 3 | theme: just-the-docs 4 | 5 | url: https://paddlecv-sig.github.io/ 6 | baseurl: "/PaddleLabel/CN" 7 | 8 | permalink: pretty 9 | 10 | search_enabled: false 11 | heading_anchors: true 12 | enable_copy_code_button: true 13 | 14 | # footer 15 | last_edit_timestamp: true # show or hide edit time - page must have `last_modified_date` defined in the frontmatter 16 | last_edit_time_format: "%F %I:%M %p" # uses ruby's time format: https://ruby-doc.org/stdlib-2.7.0/libdoc/time/rdoc/Time.html 17 | 18 | # "%b %e %Y at %I:%M %p" Jan 1 2020 at 12:00 AM 19 | # "%Y-%m-%e %I:%M %p" 20 | 21 | gh_edit_link: true 22 | gh_edit_link_text: "在 Github 上编辑此页面" 23 | gh_edit_repository: "https://github.com/PaddleCV-SIG/PaddleLabel" 24 | gh_edit_branch: "develop" 25 | gh_edit_source: "doc/CN" 26 | gh_edit_view_mode: "edit" 27 | footer_content: "PaddleLabel 以 Apache 2.0 协议发行。本网站未引入任何访问统计" 28 | 29 | callouts: 30 | note: 31 | title: "" 32 | color: yellow 33 | 34 | aux_links: # remove if you don't want this link to appear on your pages 35 | 项目 Github: https://github.com/PaddleCV-SIG/PaddleLabel 36 | 37 | kramdown: 38 | parse_block_html: true 39 | # syntax_highlighter_opts: 40 | # block: 41 | # line_numbers: true 42 | 43 | # safe: false 44 | 45 | plugins: 46 | - jemoji 47 | - jekyll-assets 48 | -------------------------------------------------------------------------------- /doc/CN/assets/accept_model_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/accept_model_label.png -------------------------------------------------------------------------------- /doc/CN/assets/action-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/action-1.png -------------------------------------------------------------------------------- /doc/CN/assets/add_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/add_label.png -------------------------------------------------------------------------------- /doc/CN/assets/auto_inference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/auto_inference.png -------------------------------------------------------------------------------- /doc/CN/assets/classification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/classification.png -------------------------------------------------------------------------------- /doc/CN/assets/cn_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/cn_home.png -------------------------------------------------------------------------------- /doc/CN/assets/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/create.png -------------------------------------------------------------------------------- /doc/CN/assets/dataset_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/dataset_path.png -------------------------------------------------------------------------------- /doc/CN/assets/dataset_split.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/dataset_split.png -------------------------------------------------------------------------------- /doc/CN/assets/dont_accept_model_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/dont_accept_model_label.png -------------------------------------------------------------------------------- /doc/CN/assets/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/export.png -------------------------------------------------------------------------------- /doc/CN/assets/export_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/export_detail.png -------------------------------------------------------------------------------- /doc/CN/assets/group_qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/group_qr.png -------------------------------------------------------------------------------- /doc/CN/assets/import_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/import_name.png -------------------------------------------------------------------------------- /doc/CN/assets/interact_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/interact_button.png -------------------------------------------------------------------------------- /doc/CN/assets/interact_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/interact_mode.png -------------------------------------------------------------------------------- /doc/CN/assets/interact_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/interact_setting.png -------------------------------------------------------------------------------- /doc/CN/assets/label_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/label_page.png -------------------------------------------------------------------------------- /doc/CN/assets/miniconda_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/miniconda_cn.png -------------------------------------------------------------------------------- /doc/CN/assets/miniconda_init_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/miniconda_init_cn.png -------------------------------------------------------------------------------- /doc/CN/assets/miniconda_install_type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/miniconda_install_type.png -------------------------------------------------------------------------------- /doc/CN/assets/ml_backend_url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/ml_backend_url.png -------------------------------------------------------------------------------- /doc/CN/assets/msvc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/msvc.png -------------------------------------------------------------------------------- /doc/CN/assets/project_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/project_overview.png -------------------------------------------------------------------------------- /doc/CN/assets/project_overview_to_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/project_overview_to_label.png -------------------------------------------------------------------------------- /doc/CN/assets/project_overview_to_split.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/project_overview_to_split.png -------------------------------------------------------------------------------- /doc/CN/assets/sample_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/sample_button.png -------------------------------------------------------------------------------- /doc/CN/assets/sample_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/sample_page.png -------------------------------------------------------------------------------- /doc/CN/assets/sample_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/sample_structure.png -------------------------------------------------------------------------------- /doc/CN/assets/start_two.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/start_two.png -------------------------------------------------------------------------------- /doc/CN/assets/test_label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/test_label.png -------------------------------------------------------------------------------- /doc/CN/assets/to_auto_inference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/to_auto_inference.png -------------------------------------------------------------------------------- /doc/CN/assets/to_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/to_home.png -------------------------------------------------------------------------------- /doc/CN/assets/to_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/doc/CN/assets/to_overview.png -------------------------------------------------------------------------------- /doc/CN/manual/classification.md: -------------------------------------------------------------------------------- 1 | # 图像分类手动标注 2 | 3 | 4 | 5 | - [单分类数据集格式](#%E5%8D%95%E5%88%86%E7%B1%BB%E6%95%B0%E6%8D%AE%E9%9B%86%E6%A0%BC%E5%BC%8F) 6 | - [ImageNet](#imagenet) 7 | - [ImageNet-txt](#imagenet-txt) 8 | - [多分类数据集格式](#%E5%A4%9A%E5%88%86%E7%B1%BB%E6%95%B0%E6%8D%AE%E9%9B%86%E6%A0%BC%E5%BC%8F) 9 | - [ImageNet-txt](#imagenet-txt) 10 | - [数据标注](#%E6%95%B0%E6%8D%AE%E6%A0%87%E6%B3%A8) 11 | - [下一步](#%E4%B8%8B%E4%B8%80%E6%AD%A5) 12 | 13 | 14 | 15 | {: .note } 16 | 有关数据集[导入](../quick_start.html#导入数据集),[导出](../quick_start.html#导出数据集),[训练/验证/测试集划分](../quick_start.html#数据集划分)步骤请参快速开始文档 17 | 18 | ![image](/doc/CN/assets/classification.png) 19 | 20 | PaddleLabel 支持**单分类**和**多分类**两种图像分类项目。其中单分类项目一张图片只能对应一个类别,多分类项目一张图片可以对应多个类别。 21 | 22 | ## 单分类数据集格式 23 | 24 | ### ImageNet 25 | 26 | v0.1.0+ {: .label } 27 | 28 | ImageNet 格式数据集中,图像所在文件夹名称即为图像类别。 29 | 30 | 样例格式如下,标注 `# 可选` 的文件导入时可以不提供: 31 | 32 | ```shell 33 | 数据集路径 34 | ├── Cat 35 | │ ├── cat-1.jpg 36 | │ ├── cat-2.png 37 | │ ├── cat-3.webp 38 | │ └── ... 39 | ├── Dog 40 | │ ├── dog-1.jpg 41 | │ ├── dog-2.jpg 42 | │ ├── dog-3.jpg 43 | │ └── ... 44 | ├── monkey.jpg 45 | ├── train_list.txt # 可选 46 | ├── val_list.txt # 可选 47 | ├── test_list.txt # 可选 48 | └── labels.txt # 可选 49 | 50 | # labels.txt 51 | Monkey 52 | Mouse 53 | Cat 54 | 55 | # train_list.txt 56 | Cat/cat-1.jpg 2 57 | ``` 58 | 59 | 根据文件夹名表示类别的规则,上述数据集导入后,三张猫和三张狗的图片会有分类,monkey.jpg 没有分类。 60 | 61 | 如果提供了 labels.txt 文件,该文件中的类别会在开始导入图像之前按顺序创建。此后如果文件夹名表示的类别不存在也会自动创建,因此 labels.txt 不需要包含所有文件夹名。 62 | 63 | {: .note} 64 | ImageNet 格式仅以图像所在文件夹判断图像分类,train/val/test_list.txt 文件中的**子集划分信息会被导入**,但是其中的**类别信息不会被导入**。如果您数据集的类别信息保存在三个列表文件中,请使用 ImageNet-txt 格式 65 | 66 | ### ImageNet-txt 67 | 68 | v1.0.0+ {: .label } 69 | 70 | ImageNet-txt 格式的数据集在 train/val/test_list.txt 文件中记录图像的类别。 71 | 72 | 样例格式如下: 73 | 74 | ```shell 75 | 数据集路径 76 | ├── image 77 | │ ├── cat-1.jpg 78 | │ ├── cat-2.png 79 | │ ├── cat-3.webp 80 | │ ├── dog-1.jpg 81 | │ ├── dog-2.jpg 82 | │ ├── dog-3.jpg 83 | │ ├── monkey.jpg 84 | │ └── ... 85 | ├── train_list.txt # 可选 86 | ├── val_list.txt # 可选 87 | ├── test_list.txt # 可选 88 | └── labels.txt # 可选 89 | 90 | # labels.txt 91 | Monkey 92 | Mouse 93 | Cat 94 | 95 | # train_list.txt 96 | image/dog-1.jpg Dog 97 | image/cat-2.png 2 # 对应 labels.txt 中第三行类别 Cat 98 | ``` 99 | 100 | labels.txt 的处理同 ImageNet 格式。在三个列表文件中,每行使用空格分隔,第一部分为到一个图片文件的路径,第二部分为一个字符串或一个数字代表类别。 101 | 102 | - labels.txt 中类别编号从 0 开始,所以数字类别 i 将对应 labels.txt 中第 i+1 行 103 | - 字符串类别的处理同 ImageNet 格式中的文件夹名,如果不存在对应类别将在导入过程中自动创建 104 | 105 | {: .note} 106 | 三个列表文件以空格为分隔符,请不要在文件路径或类别名称中使用空格 107 | 108 | ## 多分类数据集格式 109 | 110 | ### ImageNet-txt 111 | 112 | v0.1.0+ {: .label } 113 | 114 | 多分类的 ImageNet-txt 格式和单分类的基本相同,唯一区别是多分类的三个列表文件中,每行文件名后面可以跟多个空格分隔的表示类别的数字或字符串。 115 | 116 | 样例格式如下: 117 | 118 | ```shell 119 | 数据集路径 120 | ├── image 121 | │ ├── cat.jpg 122 | │ ├── dog.jpg 123 | │ └── monkey.jpg 124 | ├── labels.txt # 可选 125 | ├── test_list.txt # 可选 126 | ├── train_list.txt # 可选 127 | └── val_list.txt # 可选 128 | 129 | # labels.txt 130 | cat 131 | dog 132 | yellow 133 | black 134 | 135 | # train_list.txt 136 | image/cat.jpg 0 2 # 对应第一行和第3行类别,cat,yellow 137 | image/dog.jpg 1 3 138 | image/monkey.jpg monkey yellow black 139 | ``` 140 | 141 | {: .note} 142 | 三个列表文件以空格为分隔符,请不要在文件路径或类别名称中使用空格 143 | 144 | ## 数据标注 145 | 146 | 创建项目后会自动跳转到标注页面 147 | 148 | 1. 您可以点击右侧类别列表下方“添加类别”按钮创建一个新类别 149 | ![](/doc/CN/assets/add_label.png) 150 | ![](/doc/CN/assets/test_label.png) 151 | 2. 您可以点击一个类别右侧的 x 删除该类别。注:如果有图片属于该类别,该类别不能被删除 152 | 3. 点击类别进行标注,单分类项目仅允许选中一个类别,多分类项目可以同时选中多个类别。每次选择后标注结果将自动保存,页面上方将提示“保存成功” 153 | 4. 完成一张图片标注后点击画布左右 < > 按钮切换图片 154 | 155 | 156 | 157 | ## 下一步 158 | 159 | 您可以继续浏览[自动预标注使用方法](/doc/CN/ML/auto_inference.md)了解如何使用 PaddleLabel-ML 提高分类项目标注效率。 160 | -------------------------------------------------------------------------------- /doc/CN/manual/common.md: -------------------------------------------------------------------------------- 1 | ## 无标注数据集 2 | 3 | 如果您的数据集不包含任何标注,只需将所有图像文件放在一个文件夹下。 PaddleLabel 会遍历文件夹(及所有子文件夹)中所有文件,并按照**文件拓展名**判断其类型,导入所有图像文件。所有隐藏文件(文件名以`.`开头)将被忽略。 4 | 5 | ## 基础功能 6 | 7 | 不同类型项目的数据集文件结构有所不同,但大多数类型的项目都支持一些基础功能。 8 | 9 | ### labels.txt 10 | 11 | 所有不使用 COCO 格式保存标注的项目都支持`labels.txt`。PaddleLabel 在导入过程中会在数据集路径下寻找`labels.txt`文件。您可以在这个文件中列出该项目的所有标签(每行一个)。例如下面这样: 12 | 13 | ```text 14 | # labels.txt 15 | Monkey 16 | Mouse 17 | ``` 18 | 19 | PaddleLabel 的标签名称支持任何字符串,但是标签名称可能被用作导出数据集的文件夹名,所以应避免任何您的操作系统不支持的字符串,可以参考[这篇回答](https://stackoverflow.com/a/31976060)。Paddle 生态中的其他工具对标签名可能有进一步限制,如[PaddleX](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/data/format/classification.md)不支持中文字符作为标签名称。 20 | 21 | 在导入过程中,`labels.txt`可以包含标签名以外的信息。目前支持 4 种格式,如下所示。其中`|`表示分隔符,默认为空格。 22 | 23 | 标签长度: 24 | 25 | - 1:标签名 26 | - 2:标签名 | 标签编号 27 | - 3:标签名 | 标签编号 | 十六进制颜色或常用颜色名称或灰度值 28 | - 5:标签名 | 标签编号 | 红色 | 绿色 | 蓝色 29 | 30 | 其他: 31 | 32 | - `//`:`//`后的字符串将被作为标签注释 33 | - `-`:如果需要指定标签颜色,但不想指定标签编号,在标签编号位置写`-` 34 | 35 | 一些例子: 36 | 37 | ```text 38 | dog 39 | monkey 4 40 | mouse - #0000ff // mouse's id will be 5 41 | cat 10 yellow 42 | zibra 11 blue // some common colors are supported 43 | snake 12 255 0 0 // rgb color 44 | ``` 45 | 46 | 所有支持的颜色名称在[这里](https://github.com/PaddleCV-SIG/PaddleLabel/blob/develop/paddlelabel/task/util/color.py#L15)列出。 47 | 48 | 在导入过程中,PaddleLabel 会首先创建`labels.txt`中指定的标签。因此这个文件中的标签的编号将从**0**开始并递增。在导出过程中也将生成此文件。 49 | 50 | ### xx_list.txt 51 | 52 | 所有不使用 COCO 格式保存标注的项目都支持`xx_list.txt`。`xx_list.txt`包括`train_list.txt`,`val_list.txt`和`test_list.txt`。这三个文件需要放在数据集文件夹的根目录中,与`labels.txt`相同。 53 | 54 | 这三个文件指定了数据集的划分以及标签或标注文件与图像文件间的匹配关系(比如 voc 格式下,每一行是图像文件的路径和标签文件的路径)。这三个文件的内容结构相同,每一行都以一条数据的路径开始,其路径为相对数据集根目录的相对路径,后面跟着表示类别的整数/字符串,或者标签文件的路径。例如: 55 | 56 | ```text 57 | # train_list.txt 58 | image/9911.jpg 0 3 59 | image/9932.jpg 4 60 | image/9928.jpg Cat 61 | ``` 62 | 63 | 或 64 | 65 | ```text 66 | # train_list.txt 67 | JPEGImages/1.jpeg Annotations/1.xml 68 | JPEGImages/2.jpeg Annotations/2.xml 69 | JPEGImages/3.jpeg Annotations/3.xml 70 | ``` 71 | 72 | 需要注意的是,**大多数项目都只会用到`xx_list.txt`中的数据集划分信息**。 73 | 74 | 如果标签类别为整数,PaddleLabel 将在`labels.txt`中查找标签,标签 id 从**0**开始。一些数据集中一条数据可以有多个类别,比如图像多分类。如果希望用数字作为标签名称,您可以将数字写在`labels.txt`中,并在`xx_list.txt`中提供标签 id。或者可以给数字标签加一个前缀,例如将`10`表示为`n10`。 75 | 76 | 这三个文件都将在导出过程中生成,即使其中一些文件是空的。注意,为了确保这些文件可以被 Paddle 生态系统中的其他工具读取,没有注释的数据**不会包含在`xx_list.txt`中**。 77 | -------------------------------------------------------------------------------- /doc/CN/manual/instance_segmentation.md: -------------------------------------------------------------------------------- 1 | # 实例分割手动标注 2 | 3 | 4 | 5 | - [数据结构](#%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) 6 | - [掩膜格式](#%E6%8E%A9%E8%86%9C%E6%A0%BC%E5%BC%8F) 7 | - [多边形格式](#%E5%A4%9A%E8%BE%B9%E5%BD%A2%E6%A0%BC%E5%BC%8F) 8 | - [数据标注](#%E6%95%B0%E6%8D%AE%E6%A0%87%E6%B3%A8) 9 | - [多边形标注](#%E5%A4%9A%E8%BE%B9%E5%BD%A2%E6%A0%87%E6%B3%A8) 10 | - [掩膜标注](#%E6%8E%A9%E8%86%9C%E6%A0%87%E6%B3%A8) 11 | - [下一步](#%E4%B8%8B%E4%B8%80%E6%AD%A5) 12 | 13 | 14 | 15 | ![image](https://user-images.githubusercontent.com/35907364/204429739-408e67c3-2748-434c-ba73-258d9602fe91.png) 16 | 17 | {: .note } 18 | 有关数据集[导入](../quick_start.html#导入数据集),[导出](../quick_start.html#导出数据集),[训练/验证/测试集划分](../quick_start.html#数据集划分)步骤请参快速开始文档 19 | 20 | PaddleLabel 将语义分割和实例分割视为两种项目类型,目前二者之间不支持转换。在语义分割项目中,每个像素将有一个分类,表示其为背景或前景中的某一类别。实例分割项目在逐像素分类的基础上给每个像素一个实例 id,即不仅区分像素所属类别,而且区分同一类别下像素属于哪个实例。 21 | 22 | PaddleLabel 支持多种分割数据集格式,各种类型的数据集导入后都可以使用多边形和笔刷两种标注工具。数据集导出时 23 | 24 | - 如果导出掩膜格式,多边形标注会被转换成掩模格式 25 | - 如果导出多边形格式,会跳过所有掩膜格式标注 26 | 27 | ## 数据结构 28 | 29 | ### 掩膜格式 30 | 31 | {: .label } 32 | v0.1.0+ 33 | 34 | 样例格式如下: 35 | 36 | ```shell 37 | 数据集路径 38 | ├── Annotations 39 | │ ├── A0001.tif 40 | │ ├── B0001.tif 41 | │ ├── H0002.tif 42 | │ └── ... 43 | ├── JPEGImages 44 | │ ├── A0001.jpg 45 | │ ├── B0001.png 46 | │ ├── H0002.bmp 47 | │ └── ... 48 | ├── labels.txt 49 | ├── test_list.txt 50 | ├── train_list.txt 51 | └── val_list.txt 52 | 53 | # labels.txt 54 | background - 55 | optic_disk - 128 0 0 // 对于伪彩色掩膜,需要按此结构提供每个类别的颜色。灰度掩膜的id默认为从0开始依次递增 56 | ``` 57 | 58 | ### 多边形格式 59 | 60 | {: .label } 61 | v0.1.0+ 62 | 63 | 样例格式如下: 64 | 65 | ```shell 66 | 数据集路径 67 | ├── image 68 | │ ├── 0001.jpg 69 | │ ├── 0002.jpg 70 | │ ├── 0003.jpg 71 | │ └── ... 72 | ├── train.json 73 | ├── val.json 74 | └── test.json 75 | ``` 76 | 77 | COCO 文件的格式如下: 78 | 79 | ```text 80 | { 81 | "info": info, 82 | "images": [image], 83 | "annotations": [annotation], 84 | "licenses": [license], 85 | "categories": [category], 86 | } 87 | 88 | image{ 89 | "id": int, 90 | "width": int, 91 | "height": int, 92 | "file_name": str, 93 | "license": int, 94 | "flickr_url": str, 95 | "coco_url": str, 96 | "date_captured": datetime, 97 | } 98 | 99 | annotation{ 100 | "id": int, 101 | "image_id": int, 102 | "category_id": int, 103 | "segmentation": RLE or [polygon], 104 | "area": float, 105 | "bbox": [x,y,width,height], 106 | "iscrowd": 0 or 1, 107 | } 108 | 109 | category{ 110 | "id": int, 111 | "name": str, 112 | "supercategory": str, 113 | "color": str // this feature is specific to PP Label. It's not in the coco spec. 114 | } 115 | ``` 116 | 117 | 118 | ## 数据标注 119 | 120 | ### 多边形标注 121 | 122 | 1. 点击右侧“添加标签”,填写信息并创建标签 123 | 2. 选择一个标签,点击左侧工具栏的“多边形”,在图像界面上点击需要标注的物体轮廓,形成多边形包围物体,实例分割可以反复选择同一标签标注不同的实例,需要修改多边形可以点击左侧工具栏的“编辑”进行修改 124 | 3. **标注完成一个实例后,点击右上角"确定轮廓"进行实例确认** 125 | 4. 点击左右按钮切换图像,重复上述操作,直到所有数据标注完毕 126 | 5. 下方进度展示可以查看标注进度 127 | 128 | ### 掩膜标注 129 | 130 | 1. 点击右侧“添加标签”,填写信息并创建标签 131 | 2. 选择一个标签,点击左侧工具栏的“笔刷”(鼠标悬浮可以修改笔刷大小),在图像界面上按住鼠标左键绘制需要标注的物体内部,实例分割可以反复选择同一标签标注不同的实例,,需要删除掩膜可以点击左侧工具栏的“橡皮擦”进行修改 132 | 3. **标注完成一个实例后,点击右上角"确定轮廓"进行实例确认** 133 | 4. 点击左右按钮切换图像,重复上述操作,直到所有数据标注完毕 134 | 5. 下方进度展示可以查看标注进度 135 | 136 | 137 | 138 | ## 下一步 139 | 140 | 您可以继续浏览[交互式分割使用方法](/doc/CN/ML/interactive_segmentation.md)了解如何使用 PaddleLabel-ML 提高语义分割标注效率。 141 | -------------------------------------------------------------------------------- /doc/CN/manual/manual.md: -------------------------------------------------------------------------------- 1 | # 手动标注 2 | 3 | {: toc} 4 | -------------------------------------------------------------------------------- /doc/CN/manual/ocr.md: -------------------------------------------------------------------------------- 1 | # OCR 手动标注 2 | 3 | 4 | 5 | - [数据集格式](#%E6%95%B0%E6%8D%AE%E9%9B%86%E6%A0%BC%E5%BC%8F) 6 | - [PaddleOCR txt](#paddleocr-txt) 7 | - [数据标注](#%E6%95%B0%E6%8D%AE%E6%A0%87%E6%B3%A8) 8 | - [两点矩形](#%E4%B8%A4%E7%82%B9%E7%9F%A9%E5%BD%A2) 9 | - [多边形](#%E5%A4%9A%E8%BE%B9%E5%BD%A2) 10 | - [下一步](#%E4%B8%8B%E4%B8%80%E6%AD%A5) 11 | 12 | 13 | 14 | {: .note } 15 | 有关数据集[导入](../quick_start.html#导入数据集),[导出](../quick_start.html#导出数据集),[训练/验证/测试集划分](../quick_start.html#数据集划分)步骤请参快速开始文档 16 | 17 | PaddleLabel 目前支持 PaddleOCR txt 格式的数据集导入导出。 18 | 19 | ## 数据集格式 20 | 21 | ### PaddleOCR txt 22 | 23 | {: .label } v1.0.0+ 24 | 25 | PaddleOCR txt 格式中,所有标注数据存储在 Label.txt 文件中。 26 | 27 | 样例格式如下: 28 | 29 | ```shell 30 | 数据集路径 31 | ├── image 32 | │ ├── 1.jpg 33 | │ ├── 2.png 34 | │ ├── 3.webp 35 | │ └── ... 36 | └── Label.txt # 可选 37 | 38 | # Label.txt 39 | 05.jpg [{"points": [[x1, y1], [x2, y2], [x3, y3], [x4, y4]], "transcription": "文字内容", "illegibility": true, "language": "ch"}, ...] 40 | ``` 41 | 42 | ## 数据标注 43 | 44 | PaddleLabel 目前支持两顶点矩形和多边形两种文字位置标画工具。完成文字位置标画后,右侧“识别结果”列表中会添加一条记录,文字内容为“待识别”。单击一条识别结果中的文字可以对其进行编辑。 45 | 46 | ### 两点矩形 47 | 48 | 两点矩形的四条边为水平或竖直方向,仅支持对矩形四个顶点中两个的位置进行修改。如果需要四点的自由四边形,请使用多边形工具。创建两点矩形识别记录的过程如下 49 | 50 | 1. 在左侧工具栏中点击激活“矩形”工具 51 | 2. 在画布中按住鼠标左键进行拖拽创建一个矩形。松开左键后标注记录会自动保存 52 | 3. 在右侧识别结果列表中修改识别记录文字内容 53 | 54 | ### 多边形 55 | 56 | 多边形识别记录的所有顶点位置都可以修改,使用过程如下 57 | 58 | 1. 在左侧工具栏中点击激活“多边形”工具 59 | 2. 围绕文字区域,点击鼠标左键添加多边形顶点标画文字位置。完成标画后点击鼠标右键。多边形记录会自动保存 60 | 3. 在右侧识别结果列表中修改识别记录文字内容 61 | 62 | ## 下一步 63 | 64 | 您可以继续浏览[自动预标注使用方法](/doc/CN/ML/auto_inference.md)了解如何使用 PaddleLabel-ML 提高 OCR 项目标注效率。 65 | -------------------------------------------------------------------------------- /doc/CN/manual/semantic_segmentation.md: -------------------------------------------------------------------------------- 1 | # 语义分割手动标注 2 | 3 | 4 | 5 | - [数据结构](#%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84) 6 | - [掩膜格式](#%E6%8E%A9%E8%86%9C%E6%A0%BC%E5%BC%8F) 7 | - [COCO 格式](#coco-%E6%A0%BC%E5%BC%8F) 8 | - [数据标注](#%E6%95%B0%E6%8D%AE%E6%A0%87%E6%B3%A8) 9 | - [多边形标注](#%E5%A4%9A%E8%BE%B9%E5%BD%A2%E6%A0%87%E6%B3%A8) 10 | - [掩膜标注](#%E6%8E%A9%E8%86%9C%E6%A0%87%E6%B3%A8) 11 | - [下一步](#%E4%B8%8B%E4%B8%80%E6%AD%A5) 12 | 13 | 14 | 15 | {: .note } 16 | 有关数据集[导入](../quick_start.html#导入数据集),[导出](../quick_start.html#导出数据集),[训练/验证/测试集划分](../quick_start.html#数据集划分)步骤请参快速开始文档 17 | 18 | ![image](https://user-images.githubusercontent.com/29757093/182841499-85b9df06-f793-4831-b3f5-54c013ce531c.png) 19 | 20 | PaddleLabel 将语义分割和实例分割视为两种项目类型,目前二者之间不支持转换。在语义分割项目中,每个像素有一个分类,表示其为背景或前景中的某一类别。实例分割项目在逐像素分类的基础上给每个像素一个实例 id,即不仅区分像素所属类别,而且区分同一类别下像素属于哪个实例。 21 | 22 | PaddleLabel 支持多种分割数据集格式,各种类型的数据集导入后都可以使用多边形和笔刷两种标注工具。数据集导出时 23 | 24 | - 如果导出掩膜格式,多边形标注会被转换成掩模格式 25 | - 如果导出多边形格式,会跳过所有掩膜格式标注 26 | 27 | ## 数据结构 28 | 29 | ### 掩膜格式 30 | 31 | {: .label } v0.1.0+ 32 | 33 | 掩膜格式数据集中图片和掩膜一般都是图片文件,二者需要通过所在文件夹进行区分。**创建此类型标注项目时,请将待标注图片放在`JPEGImages`文件夹中,将已有标注放在`Annotations`文件夹中,数据集路径请填写二者的上层目录(下方示例中的`数据集路径`)。** 34 | 35 | {: .note} 36 | 此类型项目可以导入 EISeg 保存的灰度和伪彩色掩膜。不过 EISeg 保存伪彩色掩膜时文件名格式为 `图片名_pseudo.png` ,导入前需要去掉伪彩色掩膜文件名中的`_pseudo`部分,重命名为 `图片名.png`。 37 | 38 | 样例格式如下: 39 | 40 | ```shell 41 | 数据集路径 42 | ├── Annotations 43 | │ ├── A0001.png 44 | │ ├── B0001.png 45 | │ ├── H0002.png 46 | │ └── ... 47 | ├── JPEGImages 48 | │ ├── A0001.jpg 49 | │ ├── B0001.png 50 | │ ├── H0002.bmp 51 | │ └── ... 52 | ├── labels.txt 53 | ├── test_list.txt 54 | ├── train_list.txt 55 | └── val_list.txt 56 | 57 | # labels.txt 58 | background 59 | optic_disk - 128 0 0 // 对于伪彩色掩膜,需要按此结构提供每个类别的颜色。灰度掩膜的id默认为从0开始依次递增 60 | ``` 61 | 62 | 63 | 64 | ### COCO 格式 65 | 66 | {: .label } v0.1.0+ 67 | 68 | COCO 格式的图片和标注对应规则可以参考[检测项目](./detection.md#coco)中的描述。 69 | 70 | 样例格式如下: 71 | 72 | ```shell 73 | 数据集路径 74 | ├── image 75 | │ ├── 0001.jpg 76 | │ ├── 0002.jpg 77 | │ ├── 0003.jpg 78 | │ └── ... 79 | ├── train.json 80 | ├── val.json 81 | └── test.json 82 | ``` 83 | 84 | COCO 文件的格式如下: 85 | 86 | ```text 87 | { 88 | "info": info, 89 | "images": [image], 90 | "annotations": [annotation], 91 | "licenses": [license], 92 | "categories": [category], 93 | } 94 | 95 | image{ 96 | "id": int, 97 | "width": int, 98 | "height": int, 99 | "file_name": str, 100 | "license": int, 101 | "flickr_url": str, 102 | "coco_url": str, 103 | "date_captured": datetime, 104 | } 105 | 106 | annotation{ 107 | "id": int, 108 | "image_id": int, 109 | "category_id": int, 110 | "segmentation": RLE or [polygon], 111 | "area": float, 112 | "bbox": [x,y,width,height], 113 | "iscrowd": 0 or 1, 114 | } 115 | 116 | category{ 117 | "id": int, 118 | "name": str, 119 | "supercategory": str, 120 | "color": str // this feature is specific to PP Label. It's not in the coco spec. 121 | } 122 | ``` 123 | 124 | ## 数据标注 125 | 126 | 语义分割项目支持多边形和笔刷/橡皮掩膜标注两种标画工具 127 | 128 | ### 多边形标注 129 | 130 | 1. 在右侧“类别列表”中点击选中一个类别,在左侧工具栏中点击“多边形”按钮激活该工具 131 | 2. 在图像中沿待标注物体的边缘点击,使用多边形包围该物体。完成后`点击鼠标右键结束对该物体的标注`,标注结果将自动保存。这一过程可以重复多次,通常一个多边形只框选一个物体 132 | 3. 如需要修改多边形顶点可以在左侧工具栏中点击“编辑”,之后拖动顶点位置 133 | 4. 完成一张图片标注后点击画布两侧的 < > 按钮切换图片 134 | 135 | ### 掩膜标注 136 | 137 | 1. 在右侧“类别列表”中点击选中一个类别,在左侧工具栏中点击“笔刷”按钮激活该工具 138 | 2. 鼠标悬浮在笔刷工具上方时,可以在弹出的悬浮框中调整笔刷大小 139 | 3. 在图像中使用笔刷标画所有属于该类别的像素。可以使用橡皮擦工具擦除过多的标画。每笔标注会自动保存 140 | 4. 完成一张图片标画后点击画布两侧 < > 按钮切换图片 141 | 142 | ## 下一步 143 | 144 | 您可以继续浏览[交互式分割使用方法](/doc/CN/ML/interactive_segmentation.md)了解如何使用 PaddleLabel-ML 提高语义分割标注效率 145 | -------------------------------------------------------------------------------- /doc/CN/release_notes.md: -------------------------------------------------------------------------------- 1 | # PaddleLabel 版本更新记录 2 | 3 | 4 | 5 | - [v1.0.1 2023-01-27](#v101-2023-01-27) 6 | - [v1.0.0 2023-01-17](#v100-2023-01-17) 7 | - [v0.5.0 2022-11-30](#v050-2022-11-30) 8 | - [v0.1.0 2022-08-18](#v010-2022-08-18) 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | ## v1.0.1 2023-01-27 20 | 21 | - 前端 22 | - 【目标检测】:修复 自动推理添加结果类型为 ocr 矩形的问题 23 | - 【自动推理】:改善 为各个类型项目设置较为合理的默认自动推理阈值 24 | - 后端 25 | - 【更新提示】:改善 在检测到更新时指引用户访问本页面查看更新内容 26 | - 【windows 中文路径】:改善 全面从 cv2.imread 转向 PIL.Image.open,取得更好的中文路径支持 27 | - 【样例数据集】:改善 备份旧版样例数据集并重新创建,去除一些旧版中的文件 28 | - 【目标检测】:修复 coco 格式导出长宽翻转错误 29 | 30 | 31 | 32 | ## v1.0.0 2023-01-17 33 | 34 | - 【OCR】新增 OCR 项目标注能力,支持 [PP-OCRv3](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/PP-OCRv3_introduction.md) 模型预标注 35 | - 【导入/导出】新增 EISeg 格式导入,新增大量[自动化测试](https://github.com/PaddleCV-SIG/PaddleLabel/actions/workflows/cypress.yml),修复诸多导入导出 bug 36 | - 【文档】重新梳理后[文档](https://paddlecv-sig.github.io/PaddleLabel/)内容简洁清晰并和软件一同打包发布,进一步降低上手难度 37 | 38 | 39 | 40 | ## v0.5.0 2022-11-30 41 | 42 | - 【界面】全面升级分类、检测及分割的前端标注界面体验,显著提升标注流畅度 43 | - 【分类】新增 PPLCNet 预训练模型,为分类功能提供预标注能力 44 | - 【检测】新增 PicoDet 预训练模型,为检测功能提供预标注能力 45 | - 【分割】(1)优化语义分割及实例分割关于实例的区分,实例分割通过'确认轮廓'来区分实例; (2)新增根据类别或根据实例选择颜色显示模式; (3)修复交互式分割 localStorage 超限问题 46 | 47 | 48 | 49 | ## v0.1.0 2022-08-18 50 | 51 | - 【分类】支持单分类与多分类标注及标签的导入导出。简单灵活实现自定义数据集分类标注任务并导出供[PaddleClas](https://github.com/PaddlePaddle/PaddleClas)进行训练 52 | - 【检测】支持检测框标注及标签的导入导出。快速上手生成自己的检测数据集并应用到[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection) 53 | - 【分割】支持多边形、笔刷及交互式等多种标注方式,支持标注语义分割与实例分割两种场景。多种分割标注方式可灵活选择,方便将导出数据应用在[PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)获取个性化定制模型 54 | -------------------------------------------------------------------------------- /doc/CN/training/PdLabel_PdDet.md: -------------------------------------------------------------------------------- 1 | # 道路标志检测:从 PaddleLabel 到 PaddleDetection 2 | 3 | PaddleLabel 标注数据+PaddleDetection 训练预测=快速完成一次目标检测的任务 4 | 5 | ______________________________________________________________________ 6 | 7 | ## 1. 数据准备 8 | 9 | - 首先使用`PaddleLabel`对自制的路标数据集进行标注,其次使用`Split Dataset`功能分割数据集,最后导出数据集 10 | - 从`PaddleLabel`导出后的内容全部放到自己的建立的文件夹下,例如`roadsign_det_dataset`,其目录结构如下: 11 | 12 | ``` 13 | ├── roadsign_det_dataset 14 | │ ├── Annotations 15 | │ ├── JPEGImages 16 | │ ├── labels.txt 17 | │ ├── test_list.txt 18 | │ ├── train_list.txt 19 | │ ├── val_list.txt 20 | ``` 21 | 22 | ## 2. 训练 23 | 24 | ### 2.1 安装必备的库 25 | 26 | **2.1.1 安装 paddlepaddle** 27 | 28 | ``` 29 | # 您的机器安装的是 CUDA9 或 CUDA10,请运行以下命令安装 30 | pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple 31 | # 您的机器是CPU,请运行以下命令安装 32 | # pip install paddlepaddle 33 | ``` 34 | 35 | **2.1.2 安装 paddledetection 以及依赖项** 36 | 37 | ``` 38 | git clone https://gitee.com/paddlepaddle/PaddleDetection 39 | cd PaddleDetection 40 | pip install -r requirements.txt 41 | python setup.py install 42 | ``` 43 | 44 | ### 2.2 准备自制的路标数据集 45 | 46 | ``` 47 | cd ./PaddleDection/dataset/ 48 | mkdir roadsign_det_dataset 49 | cd ../../ 50 | cp -r ./roadsign_det_dataset/* ./PaddleDection/dataset/roadsign_det_dataset 51 | ``` 52 | 53 | ### 2.3 修改配置文件 54 | 55 | 该任务主要涉及 6 个配置文件,分别是: 56 | 57 | 1. 主配置文件入口:yolov3_mobilenet_v1_roadsign.yml 58 | 1. 定义训练数据的路径:roadsign_voc.yml 59 | 1. 定义公共参数:runtime.yml 60 | 1. 定义优化器的策略:optimizer_40e.yml 61 | 1. 定义模型和主干网络:yolov3_mobilenet_v1.yml 62 | 1. 定义数据预处理方式:yolov3_reader.yml 63 | 64 | 这里我们只需要改动一个配置文件即定义训练数据的路径的配置文件: 65 | 66 | > PaddleDetection/configs/datasets/roadsign_voc.yml 67 | 68 | ``` 69 | metric: VOC 70 | map_type: integral 71 | num_classes: 4 72 | 73 | TrainDataset: 74 | !VOCDataSet 75 | dataset_dir: dataset/roadsign_det_dataset 76 | anno_path: train_list.txt 77 | label_list: labels.txt 78 | data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult'] 79 | 80 | EvalDataset: 81 | !VOCDataSet 82 | dataset_dir: dataset/roadsign_det_dataset 83 | anno_path: val_list.txt 84 | label_list: labels.txt 85 | data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult'] 86 | 87 | TestDataset: 88 | !ImageFolder 89 | anno_path: dataset/roadsign_det_dataset/labels.txt 90 | ``` 91 | 92 | ### 2.4 开始训练 93 | 94 | ``` 95 | export CUDA_VISIBLE_DEVICES=0 96 | # 开始训练 97 | python PeddleDetection/tools/train.py -c configs/yolov3/yolov3_mobilenet_v1_roadsign.yml --eval -o use_gpu=true 98 | ``` 99 | 100 | ## 3. 模型评估 101 | 102 | ### 3.1 评估 103 | 104 | ``` 105 | python PeddleDetection/tools/eval.py -c PeddleDetection/configs/yolov3/yolov3_mobilenet_v1_roadsign.yml -o use_gpu=true 106 | ``` 107 | 108 | ### 3.2 预测 109 | 110 | ``` 111 | python PeddleDetection/tools/infer.py \ 112 | -c PeddleDetection/configs/yolov3/yolov3_mobilenet_v1_roadsign.yml \ 113 | -o use_gpu=true \ 114 | --infer_img=demo/road554.png 115 | ``` 116 | 117 | 预测的样例图片如下图: 118 | 119 | 120 | 121 | 预测的结果是: 122 | 123 | > speedlimit 0.77 预测正确 ✔ 124 | 125 | ## AI Studio 第三方教程推荐 126 | 127 | [快速体验演示案例](https://aistudio.baidu.com/aistudio/projectdetail/4349280) 128 | -------------------------------------------------------------------------------- /doc/CN/training/training.md: -------------------------------------------------------------------------------- 1 | # 进行训练 2 | -------------------------------------------------------------------------------- /doc/EN/_config.yml: -------------------------------------------------------------------------------- 1 | title: PaddleLabel 2 | description: An effective and flexible tool for data annotation 3 | theme: just-the-docs 4 | 5 | url: https://paddlecv-sig.github.io/ 6 | baseurl: "/PaddleLabel/EN/" 7 | 8 | permalink: pretty 9 | 10 | search_enabled: false 11 | heading_anchors: true 12 | enable_copy_code_button: true 13 | 14 | aux_links: # remove if you don't want this link to appear on your pages 15 | Project Github: https://github.com/PaddleCV-SIG/PaddleLabel/ 16 | 17 | plugins: 18 | - jemoji 19 | 20 | kramdown: 21 | parse_block_html: true 22 | # syntax_highlighter_opts: 23 | # block: 24 | # line_numbers: true 25 | -------------------------------------------------------------------------------- /doc/EN/assets/group_qr.png: -------------------------------------------------------------------------------- 1 | ../../CN/assets/group_qr.png -------------------------------------------------------------------------------- /doc/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem "jekyll", "~> 4.3" # installed by `gem jekyll` 4 | # gem "webrick" # required when using Ruby >= 3 and Jekyll <= 4.2.2 5 | 6 | gem "just-the-docs", "0.4.0.rc4" # currently the latest pre-release 7 | # gem "just-the-docs" # the latest release - currently 0.3.3 8 | 9 | gem "jemoji" 10 | gem "jekyll-assets", group: :jekyll_plugins 11 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | CN/README.md -------------------------------------------------------------------------------- /doc/old/detection_ml.md: -------------------------------------------------------------------------------- 1 | # 目标检测自动标注 2 | 3 | 4 | - [简介](#%E7%AE%80%E4%BB%8B) 5 | - [使用教程](#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B) 6 | - [安装](#%E5%AE%89%E8%A3%85) 7 | - [使用](#%E4%BD%BF%E7%94%A8) 8 | 9 | 10 | 11 | {: note} 12 | 在使用辅助标注功能前请先按照 [此文档](/doc/CN/ML/install_ml.md) 介绍步骤安装并启动 PaddleLabel-ML 后端 13 | ## 简介 14 | 15 | PaddleLabel 提供图像检测自动标注功能,用户只需要在`自动推理设置`中进行简单设置,即可启用自动标注的功能,从而更快的完成对应的图像检测标注任务。 16 | 17 |
18 |

19 | LOGO 20 |

21 |
22 | 23 | ## 使用教程 24 | 25 | ### 安装 26 | 27 | - 创建虚拟环境 28 | 29 | ```shell 30 | # 创建虚拟环境 31 | conda create -n paddlelabel python=3.10 32 | conda activate paddlelabel 33 | ``` 34 | 35 | - 安装 PaddlePaddle 36 | 37 | 版本要求: PaddlePaddle >= 2.2.0 38 | 39 | PaddlePaddle 安装请参考[官网](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/windows-pip.html)。 40 | 41 | - 安装前端和机器学习后端 42 | 43 | ```shell 44 | pip install paddlelabel 45 | pip install paddlelabel_ml 46 | ``` 47 | 48 | ### 使用 49 | 50 | 0. **启动** 51 | 52 | 可以直接打开两个终端,分别使用如下指令启动 PaddleLabel 的前后端。 53 | 54 | ```shell 55 | paddlelabel # 启动paddlelabel,前端 56 | ``` 57 | 58 | ```shell 59 | paddlelabel_ml # 启动paddlelabel_ml,机器学习后端 60 | ``` 61 | 62 | 1. **新项目创建** 63 | 64 | 浏览器打开 PaddleLabel 后,可以通过创建项目下的“图像检测”卡片创建一个新的图像检测标注项目(如果已经创建,可以通过下方“我的项目”找到对应名称的项目,点击“标注”继续标注)。 65 | 66 | 项目创建选项卡有如下选项需要填写: 67 | 68 | - 项目名称(必填):填写该检测标注项目的项目名 69 | - 数据地址(必填):填写本地数据集文件夹的路径,可以直接通过复制路径并粘贴得到。 70 | - 数据集描述(选填):填写该检测标注项目的使用的数据集的描述文字 71 | - 导入标注格式(必选):选择该任务导入标签为 COCO、VOC 或 YOLO 格式 72 | 73 | 对于标签格式的详细说明,请参考[目标检测标注](detection.html)。 74 | 75 | 1. **数据导入** 76 | 77 | 在创建项目时需要填写数据地址,该地址对应的是数据集的文件夹,为了使 PaddleLabel 能够正确的识别和处理数据集,请参考[数据结构](dataset_file_structure.html)组织数据集。同时 PaddleLabel 提供了参考数据集,位于`~/.paddlelabel/sample/det`路径下,也可参考该数据集文件结构组织数据。 78 | 79 | 3. **智能标注** 80 | 81 | 进入标注界面,在检测任务的标注中,除了手动标注外[(数据标注)](detection.html),还可以按照如下步骤进行智能标注,即使用图像检测模型来自动标注。 82 | 83 | 1. 点击右侧“项目总览”,进入项目总览界面 84 | 85 |

86 | 87 |

88 | 89 | 2. 点击“自动推理设置”,进入对应设置页面后,有如下选项需要填写: 90 | 91 |

92 | 93 |

94 | 95 | - 机器学习后端网址(必填):填写在终端中使用`paddlelabel_ml`命令启动后的机器学习后端网址,默认为`http://127.0.0.1:1234`。 96 | 97 | - 模型选择(必选):选择 PaddleLabel 支持的图像检测模型,目前可选模型有 PicoDet。 98 | 99 | - 使用预标注模型标签(必选):选择是否使用预标注模型便签,选择'是'则表示用户接受模型推理出的标签来作为图像检测的标注标签,接受预标注模型标签后,当模型检测到新标签后,会自动在标签列表中增加该标签;选择'否',则用户需要自行建立标签对应关系。 100 | 101 | - 标签对应关系(非必填):如果用户在`使用预标注模型标签`选项栏中选择'是',则`标签对应关系`处可不填,选择'否',此时`标签对应关系`处显示两个选择框,左侧的选择框中的标签为模型推理的标签,支持模糊搜索,右侧的选择框中的标签为标签列表中出现过的标签,用户也可以在此处新增标签,用户可按照自己的偏好建立标签对,这样就实现了模型推理标签和用户自定义标签的一一对应,从而就可以在图像检测智能标注中只展示符合用户自定义标签的结果。 102 | 103 | 最后选择`确定`按钮,即可完成"自动推理设置" 104 | 105 | 3. 点击"去标注",进入标注界面 106 | 107 | 1. 点击"自动推理",模型给出的预测结果即可显示到标签列表中,如果提示"自动推理未发现高置信度结果",则可点击"推理阈值",相应的调低推理阈值后再次点击"自动推理",即可得到预测结果 108 | 109 | 1. 如果对自动推理的结果不满意,用户可点击`清空标注`按钮以及`添加标签`按钮来为当前图像进行手动添加标签进行标注 110 | 111 | 1. 点击左右按钮切换图像,重复上述步骤 4 和步骤 5 操作,直到所有数据标注完毕 112 | 113 | 1. 下方进度展示可以查看标注进度 114 | 115 | 1. **完成标注** 116 | 117 | - 完成数据标注后,PaddleLabel 提供了方便的数据划分功能,以便与 Paddle 其他工具套件(如 PaddleDetection)进行快速衔接。点击右侧工具栏的**项目总览**按钮,来到该项目的总览界面,这里可以看到数据以及标注状态。 118 | 119 | - 点击**划分数据集**按钮弹出划分比例的设置,分别填入对应训练集、验证集和测试集的占比,点击确定即可完成数据集的划分。 120 | 121 | - 点击**导出数据集**,输入需要导出到的文件夹路径,点击确认,即可导出标注完成的数据到指定路径。 122 | -------------------------------------------------------------------------------- /doc/prepare.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from pathlib import Path 3 | import sys 4 | import subprocess 5 | 6 | headers = { 7 | "CN/README.md": """--- 8 | layout: home 9 | title: 项目简介 10 | nav_order: 0 11 | permalink: / 12 | """, 13 | "CN/install.md": """--- 14 | layout: default 15 | title: 安装 16 | nav_order: 1 17 | """, 18 | "CN/quick_start.md": """--- 19 | layout: default 20 | title: 快速体验 21 | nav_order: 2 22 | """, 23 | # 手动标注 24 | "CN/manual/manual.md": """--- 25 | layout: default 26 | title: 手动标注 27 | nav_order: 3 28 | has_children: true 29 | """, 30 | "CN/manual/classification.md": """--- 31 | layout: default 32 | title: 图像分类 33 | parent: 手动标注 34 | nav_order: 1 35 | """, 36 | "CN/manual/detection.md": """--- 37 | layout: default 38 | title: 目标检测 39 | parent: 手动标注 40 | nav_order: 2 41 | """, 42 | "CN/manual/semantic_segmentation.md": """--- 43 | layout: default 44 | title: 语义分割 45 | parent: 手动标注 46 | nav_order: 3 47 | """, 48 | "CN/manual/instance_segmentation.md": """--- 49 | layout: default 50 | title: 实例分割 51 | parent: 手动标注 52 | nav_order: 4 53 | """, 54 | "CN/manual/ocr.md": """--- 55 | layout: default 56 | title: OCR 57 | parent: 手动标注 58 | nav_order: 5 59 | """, 60 | # ML辅助标注 61 | "CN/ML/ml.md": """--- 62 | layout: default 63 | title: 机器学习辅助标注 64 | nav_order: 4 65 | has_children: true 66 | """, 67 | "CN/ML/install_ml.md": """--- 68 | layout: default 69 | title: 机器学习后端安装 70 | parent: 机器学习辅助标注 71 | nav_order: 1 72 | """, 73 | "CN/ML/auto_inference.md": """--- 74 | layout: default 75 | title: 自动预标注使用方法 76 | parent: 机器学习辅助标注 77 | nav_order: 2 78 | """, 79 | "CN/ML/interactive_segmentation.md": """--- 80 | layout: default 81 | title: 交互式分割 82 | parent: 机器学习辅助标注 83 | nav_order: 3 84 | """, 85 | "CN/training/training.md": """--- 86 | layout: default 87 | title: 进行训练 88 | nav_order: 4 89 | has_children: true 90 | permalink: docs/training 91 | """, 92 | # 训练方式 93 | "CN/training/PdLabel_PdX.md": """--- 94 | layout: default 95 | title: PaddleX 分类/检测/分割 96 | parent: 进行训练 97 | nav_order: 5 98 | """, 99 | "CN/training/PdLabel_PdClas.md": """--- 100 | layout: default 101 | title: PaddleClas 花朵分类 102 | parent: 进行训练 103 | nav_order: 1 104 | """, 105 | "CN/training/PdLabel_PdDet.md": """--- 106 | layout: default 107 | title: PaddleDetection 道路标志检测 108 | parent: 进行训练 109 | nav_order: 2 110 | """, 111 | "CN/training/PdLabel_PdSeg.md": """--- 112 | layout: default 113 | title: PaddleSeg 图像分割 114 | parent: 进行训练 115 | nav_order: 3 116 | """, 117 | "CN/release_notes.md": """--- 118 | layout: default 119 | title: 版本历史 120 | nav_order: 6 121 | """, 122 | "EN/README.md": """--- 123 | layout: home 124 | title: Introduction 125 | nav_order: 0 126 | permalink: / 127 | """, 128 | } 129 | 130 | if len(sys.argv) == 1: 131 | base_url = "/PaddleLabel/" 132 | else: 133 | base_url = sys.argv[1] 134 | 135 | HERE = Path(__file__).parent.absolute() 136 | for name, header in headers.items(): 137 | # if name != "CN/install.md": 138 | # continue 139 | path = HERE / name 140 | print("----") 141 | print(path) 142 | content = path.read_text() 143 | content = content.replace(".md", ".html") 144 | content = content.replace("/doc/", base_url) 145 | lines = content.split("\n") 146 | lines = [l for l in lines if not l.endswith(".mp4")] 147 | content = "\n".join(lines) 148 | # cmd = f"git rev-list --count HEAD {name}" 149 | cmd = f"git --no-pager log -1 --pretty='%ad' --date=iso {name}" 150 | # print(cmd) 151 | last_mod = subprocess.run(cmd.split(" "), capture_output=True, encoding="utf8").stdout.strip() 152 | if path.name != "README.md": 153 | header += f"permalink: {str(name).replace('.md', '.html').replace('CN/','').replace('EN/','')}\n" 154 | header += f"last_modified_date: {last_mod}\n---\n\n" 155 | print(header) 156 | 157 | content = header + content 158 | path.write_text(content) 159 | -------------------------------------------------------------------------------- /docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | volumes: 4 | pip: 5 | 6 | services: 7 | pp-labeling-backend: 8 | build: 9 | context: . 10 | dockerfile: Dockerfile.dev 11 | image: pp-label-backend:0.0.1 12 | container_name: "pp-label-backend" 13 | ports: 14 | - "5000:5000" 15 | volumes: 16 | - .:/app 17 | environment: 18 | - FLASK_ENV=development 19 | # command: /bin/sh -c "while sleep 1000; do :; done" 20 | -------------------------------------------------------------------------------- /docstring_format.mustache: -------------------------------------------------------------------------------- 1 | {{! Numpy Docstring Template }} 2 | {{summaryPlaceholder}} 3 | 4 | {{extendedSummaryPlaceholder}} 5 | {{#parametersExist}} 6 | 7 | Parameters 8 | ---------- 9 | {{#args}} 10 | {{var}} : {{typePlaceholder}} 11 | {{descriptionPlaceholder}} 12 | {{/args}} 13 | {{#kwargs}} 14 | {{var}} : {{typePlaceholder}}, optional 15 | {{descriptionPlaceholder}}. Defaults to {{&default}} 16 | {{/kwargs}} 17 | {{/parametersExist}} 18 | {{#returnsExist}} 19 | 20 | Returns 21 | ------- 22 | {{#returns}} 23 | {{typePlaceholder}} 24 | {{descriptionPlaceholder}} 25 | {{/returns}} 26 | {{/returnsExist}} 27 | {{#yieldsExist}} 28 | 29 | Yields 30 | ------ 31 | {{#yields}} 32 | {{typePlaceholder}} 33 | {{descriptionPlaceholder}} 34 | {{/yields}} 35 | {{/yieldsExist}} 36 | {{#exceptionsExist}} 37 | 38 | Raises 39 | ------ 40 | {{#exceptions}} 41 | {{type}} 42 | {{descriptionPlaceholder}} 43 | {{/exceptions}} 44 | {{/exceptionsExist}} 45 | -------------------------------------------------------------------------------- /paddlelabel/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import annotations 3 | import logging 4 | 5 | print("Starting PaddleLabel") 6 | 7 | # 1. get version 8 | from pathlib import Path 9 | 10 | __version__ = open((Path(__file__).parent / "version"), "r").read().strip() 11 | 12 | 13 | from dataclasses import dataclass 14 | 15 | # 2. global configs 16 | @dataclass 17 | class Configs: 18 | host: str = "127.0.0.1" 19 | port: int = 17995 20 | debug: bool = False # if running in debug mode 21 | log_level: int = logging.INFO 22 | 23 | # requests with the same request id arriving less than request_id_timeout s apart will be rejected 24 | request_id_timeout: float = 2 25 | 26 | """ file position settings """ 27 | # _home: Path = Path(str(Path().home().absolute()).strip()) / ".paddlelabel" 28 | _home: Path = Path().home().absolute() / ".paddlelabel" 29 | install_base: Path = Path(__file__).absolute().parent # TODO: a better name? 30 | 31 | @property 32 | def home(self) -> Path: 33 | return self._home 34 | 35 | @home.setter 36 | def home(self, home_path: Path | str): 37 | home_path = Path(home_path) 38 | if not home_path.exists(): 39 | home_path.mkdir(parents=True) # TODO: catch no permission 40 | self._home = home_path 41 | 42 | @property 43 | def sample_dir(self) -> Path: 44 | return self._home / "sample" 45 | 46 | # db settings 47 | db_engine: str = "sqlite" 48 | # db_head_version: str = "f47b7f5b73b9" # latest db version 49 | SQLALCHEMY_ECHO: bool = False 50 | 51 | @property 52 | def db_path(self) -> Path: 53 | return self._home / "paddlelabel.db" 54 | 55 | @property 56 | def db_url(self) -> str: 57 | return f"{self.db_engine}:///{str(self.db_path)}" 58 | 59 | 60 | configs = Configs() 61 | 62 | # 3. enable foreign key constraint for sqlite 63 | # TODO: run this conditionally based on db engine used 64 | from sqlalchemy.engine import Engine 65 | from sqlalchemy import event 66 | 67 | 68 | @event.listens_for(Engine, "connect") 69 | def set_sqlite_pragma(dbapi_connection, connection_record): 70 | cursor = dbapi_connection.cursor() 71 | cursor.execute("PRAGMA foreign_keys=ON") 72 | cursor.close() 73 | -------------------------------------------------------------------------------- /paddlelabel/api/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | 4 | from flask import abort, session, request 5 | 6 | from paddlelabel import configs 7 | from paddlelabel.config import app 8 | 9 | from . import controller 10 | from .model import Project, Label, Task, Data, Annotation, TaskCategory 11 | from .util import decode_token 12 | from . import rpc 13 | 14 | # TODO: is this specific to flask or is connexion function 15 | @app.before_request 16 | def check_request_id(): 17 | request_id = request.headers.get("request_id", None) 18 | if request_id is None or len(request_id) == 0: 19 | return 20 | curr_time = time.time() 21 | if "request_ids" not in session: 22 | session["request_ids"] = [(curr_time, request_id)] 23 | return 24 | session["request_ids"] = list( 25 | filter( 26 | lambda item: curr_time - item[0] < configs.request_id_timeout, 27 | session["request_ids"], 28 | ) 29 | ) 30 | exist = False 31 | for ts, id in session["request_ids"]: 32 | if id == request_id: 33 | exist = True 34 | session["request_ids"].append((curr_time, request_id)) 35 | if exist: 36 | abort(409, f"Duplicate request from {curr_time - ts}s ago") 37 | -------------------------------------------------------------------------------- /paddlelabel/api/controller/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/api/controller/__init__.py -------------------------------------------------------------------------------- /paddlelabel/api/controller/data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | import os 4 | import os.path as osp 5 | import random 6 | 7 | import cv2 8 | import flask 9 | import tempfile 10 | 11 | from .base import crud 12 | from ..model import Data, Project, Task 13 | from ..schema import DataSchema 14 | from paddlelabel.api.util import abort 15 | from paddlelabel.task.instance_segmentation import draw_mask 16 | 17 | get_all, get, post, put, delete = crud(Data, DataSchema) 18 | 19 | 20 | # TODO: dont use flask 21 | def get_image(data_id): 22 | # if random.random()<0.9: 23 | # abort("Mimic package loss", 404) 24 | _, data = Data._exists(data_id) 25 | path = data.path 26 | project_id = data.task.project_id 27 | data_dir = Project._get(project_id=project_id).data_dir 28 | 29 | folder = osp.join(data_dir, osp.dirname(path)) 30 | file_name = osp.basename(path) 31 | # return flask.send_from_directory(data_dir, path) 32 | 33 | return flask.send_from_directory(folder, file_name) 34 | 35 | # data_path = osp.join(data_dir, path) 36 | # image = cv2.imread(data_path) 37 | # image_png = cv2.imencode(".png", image) 38 | # b64_string = base64.b64encode(image_png[1]).decode("utf-8") 39 | # return json.dumps({"image": b64_string}), 200 40 | 41 | 42 | def get_mask(data_id): 43 | _, data = Data._exists(data_id) 44 | mask = draw_mask(data, mask_type="pseudo") 45 | if mask is None: 46 | abort("This data probably doesn't have segmentation mask", 500) 47 | 48 | tempf = tempfile.NamedTemporaryFile(suffix=".png") 49 | cv2.imwrite(tempf.name, mask) 50 | 51 | return flask.send_from_directory(osp.dirname(tempf.name), osp.basename(tempf.name)) 52 | 53 | 54 | def get_by_task(task_id): 55 | Task._exists(task_id) 56 | datas = Data._get(task_id=task_id, many=True) 57 | return DataSchema(many=True).dump(datas), 200 58 | -------------------------------------------------------------------------------- /paddlelabel/api/controller/setting.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | 4 | from ..model import TaskCategory 5 | 6 | from paddlelabel.config import se 7 | 8 | 9 | # TODO: change task_categories to project_category 10 | def init_site_settings(json_path): 11 | settings = json.loads(open(json_path, "r").read()) 12 | task_categories = settings["site"]["task_categories"] 13 | for idx, (cat, handler) in task_categories.items(): 14 | idx = int(idx) 15 | curr_cat = TaskCategory.query.filter(TaskCategory.task_category_id == idx).one_or_none() 16 | if curr_cat is None: 17 | curr_cat = TaskCategory(idx, cat, handler) 18 | se.add(curr_cat) 19 | se.commit() 20 | -------------------------------------------------------------------------------- /paddlelabel/api/controller/tag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import connexion 3 | 4 | from paddlelabel.config import db 5 | from .base import crud 6 | from ..model import Tag, Project, Task, TagTask 7 | from ..schema import TagSchema, TagTaskSchema 8 | from ..util import abort 9 | 10 | 11 | def pre_add(new_tag, se): 12 | curr_tag = Tag._get(project_id=new_tag.project_id, name=new_tag.name) 13 | if curr_tag is not None: 14 | abort( 15 | f"Duplicate tag with tag name {new_tag.name} under project {new_tag.project_id}", 16 | 409, 17 | ) 18 | return new_tag 19 | 20 | 21 | get_all, get, post, put, delete = crud(Tag, TagSchema, [pre_add]) 22 | 23 | 24 | def get_by_project(project_id): 25 | Project._exists(project_id) 26 | tags = Tag._get(project_id=project_id, many=True) 27 | return TagSchema(many=True).dump(tags), 200 28 | 29 | 30 | def get_by_task(task_id): 31 | Task._exists(task_id) 32 | tag_tasks = TagTask._get(task_id=task_id, many=True) 33 | tags = [] 34 | for tag_task in tag_tasks: 35 | tag = Tag._get(tag_id=tag_task.tag_id) 36 | tags.append(tag) 37 | return TagSchema(many=True).dump(tags), 200 38 | 39 | 40 | def add_to_task(task_id): 41 | # 1. check 42 | # 1.1 check task exists 43 | task = Task._get(task_id=task_id) 44 | if task is None: 45 | abort(f"No task with task id {task_id}", 404) 46 | 47 | body = connexion.request.json 48 | tag_id = body["tag_id"] 49 | # 1.2 check tag exist 50 | tag = Tag._get(tag_id=tag_id) 51 | if tag is None: 52 | abort(f"No tag with tag id {tag_id}", 404) 53 | # 1.3 no duplicate records 54 | curr_tag_task = TagTask._get(task_id=task_id, tag_id=tag_id) 55 | if curr_tag_task is not None: 56 | abort(f"Task {task_id} is already tagged {tag_id}", 409) 57 | # 1.4 check tag under task 58 | project_id = Task._get(task_id=task_id).project_id 59 | if tag.project_id != project_id: 60 | abort(f"Tag {tag_id} is not under project {project_id}", 404) 61 | 62 | tag_task = TagTask( 63 | tag_id=tag_id, 64 | task_id=task_id, 65 | project_id=task.project_id, 66 | ) 67 | db.session.add(tag_task) 68 | db.session.commit() 69 | tag_tasks = TagTask._get(task_id=task_id, many=True) 70 | tags = [] 71 | for tag_task in tag_tasks: 72 | tags.append(tag_task.tag) 73 | return TagSchema(many=True).dump(tags), 201 74 | -------------------------------------------------------------------------------- /paddlelabel/api/controller/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import connexion 3 | 4 | from paddlelabel.config import db 5 | from .base import crud 6 | from ..model import Task, Project 7 | from ..schema import TaskSchema 8 | from paddlelabel.api.util import abort, parse_order_by 9 | 10 | # TODO: reject tasks with same datas 11 | get_all, get, post, put, delete = crud(Task, TaskSchema) 12 | 13 | 14 | def get_by_project(project_id, order_by="created asc"): 15 | if connexion.request.method == "HEAD": 16 | return get_stat_by_project(project_id) 17 | Project._exists(project_id) 18 | order = parse_order_by(Task, order_by) 19 | 20 | tasks = Task.query.filter(Task.project_id == project_id).order_by(order).all() 21 | return TaskSchema(many=True).dump(tasks), 200 22 | 23 | 24 | # TODO: dont lazy load annotations in tasks 25 | def get_stat_by_project(project_id): 26 | Project._exists(project_id) 27 | tasks = Task.query.filter(Task.project_id == project_id).all() 28 | ann_count = 0 29 | for task in tasks: 30 | if len(task.annotations) != 0: 31 | ann_count += 1 32 | res = {"finished": ann_count, "total": len(tasks)} 33 | return res, 200, res 34 | 35 | 36 | def set_all_by_project(project_id): 37 | if "data_predicted" in connexion.request.json.keys(): 38 | for task in Task._get(project_id=project_id, many=True): 39 | for data in task.datas: 40 | data.predicted = connexion.request.json["data_predicted"] 41 | db.session.commit() 42 | -------------------------------------------------------------------------------- /paddlelabel/api/controller/user.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import re 3 | 4 | from marshmallow import fields 5 | import uuid 6 | from werkzeug.security import generate_password_hash, check_password_hash 7 | 8 | from ..model import User 9 | from ..schema import UserSchema 10 | from .base import crud 11 | from ..util import abort, generate_token 12 | 13 | 14 | def validata_email(email): 15 | regex = re.compile(r"([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+") 16 | if re.fullmatch(regex, email): 17 | return True 18 | return False 19 | 20 | 21 | def pre_add(user, se): 22 | if not validata_email(user.email): 23 | abort("Email is not valid", 400) 24 | user.password = generate_password_hash(user.password, method="sha256") 25 | user.uuid = str(uuid.uuid4()) 26 | return user 27 | 28 | 29 | def pre_put(curr_user, new_user, se): 30 | if "email" in new_user.keys(): 31 | if not validata_email(new_user["email"]): 32 | abort("Email is not valid", 400) 33 | if "password" in new_user.keys(): 34 | new_user["password"] = generate_password_hash(new_user["password"], method="sha256") 35 | 36 | 37 | get_all, get, post, put, delete = crud(User, UserSchema, [pre_add, pre_put]) 38 | 39 | 40 | def login(): 41 | r = connexion.request.json 42 | username = r.get("username", None) 43 | password = r.get("password", None) 44 | if username is None: 45 | abort("Need username to login", 401) 46 | if password is None: 47 | abort("Need password to login", 401) 48 | user = User._get(username=username) 49 | if user is None: 50 | abort(f"Username or password is wrong", 401) 51 | if check_password_hash(user.password, password): 52 | return generate_token(user.uuid) 53 | else: 54 | abort(f"Username or password is wrong", 401) 55 | -------------------------------------------------------------------------------- /paddlelabel/api/model/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .project import Project 3 | from .label import Label 4 | from .task import Task 5 | from .data import Data 6 | from .annotation import Annotation 7 | from .user import User 8 | from .setting import TaskCategory, AlembicVersion 9 | from .tag import Tag 10 | from .tag_task import TagTask 11 | -------------------------------------------------------------------------------- /paddlelabel/api/model/annotation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.config import db 3 | from paddlelabel.api.util import nncol 4 | from .base import BaseModel 5 | 6 | 7 | class Annotation(BaseModel): 8 | __tablename__ = "annotation" 9 | __table_args__ = {"comment": "Stores all annotations"} 10 | annotation_id = nncol(db.Integer(), primary_key=True) 11 | frontend_id = db.Column(db.Integer()) # unique id within data, start from 1 12 | result = db.Column(db.String()) 13 | type = db.Column(db.String()) 14 | label_id = nncol(db.Integer(), db.ForeignKey("label.label_id", ondelete="CASCADE")) 15 | data_id = db.Column(db.Integer(), db.ForeignKey("data.data_id", ondelete="CASCADE")) 16 | predicted_by = db.Column(db.String()) 17 | 18 | # TODO: remove 19 | task_id = nncol(db.Integer(), db.ForeignKey("task.task_id", ondelete="CASCADE")) 20 | # task = db.relationship("Task") 21 | project_id = nncol(db.Integer(), db.ForeignKey("project.project_id")) 22 | 23 | _immutables = BaseModel._immutables + ["annotation_id", "label_id", "task_id", "slice_id"] 24 | -------------------------------------------------------------------------------- /paddlelabel/api/model/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import annotations 3 | 4 | from datetime import datetime 5 | from typing import List, TypeVar, Type, Tuple, overload 6 | 7 | from paddlelabel.config import db 8 | from paddlelabel.api.util import nncol, abort 9 | from paddlelabel.util import pyVerGt 10 | 11 | T = TypeVar("T") 12 | # TODO: nn string col cant be "" 13 | class BaseModel(db.Model): 14 | __abstract__ = True 15 | __tablename__ = "" 16 | __table_args__ = {"comment": ""} 17 | created = nncol(db.DateTime, default=datetime.utcnow) 18 | modified = nncol(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) 19 | 20 | _immutables = ["created", "modified", "immutables"] 21 | _nested = ["project"] 22 | 23 | @classmethod 24 | @property 25 | def _cols(cls): 26 | return [c.key for c in cls.__table__.columns] 27 | 28 | def __repr__(self): 29 | s = f"Object {self.__tablename__}: " 30 | for att in dir(self): 31 | if ( 32 | att[0] != "_" 33 | and att[-1] != "s" 34 | and att not in ["query", "registry", "metadata", "query_class"] 35 | and att not in self._nested 36 | ): 37 | s += f"{att}: {getattr(self, att)} " 38 | s += "\n" 39 | return s 40 | 41 | @classmethod 42 | def _exists(cls: Type[T], item_id, throw=True) -> Tuple[bool, None | T]: 43 | item = cls.query.filter(getattr(cls, cls.__tablename__ + "_id") == item_id).one_or_none() 44 | if item is None: 45 | if throw: 46 | abort(f"No {cls.__tablename__} with id : {item_id}", 404) 47 | else: 48 | return False, None 49 | return True, item 50 | 51 | @overload 52 | @classmethod 53 | def _get(cls: Type[T], many: bool, **kwargs) -> List[T]: 54 | ... 55 | 56 | @overload 57 | @classmethod 58 | def _get(cls: Type[T], **kwargs) -> T | None: 59 | ... 60 | 61 | @classmethod 62 | def _get(cls, many: bool = False, **kwargs): 63 | if pyVerGt(): # skip check for py < 3.9 64 | for key in kwargs.keys(): 65 | if key not in cls._cols: 66 | raise AttributeError(f"Model {cls.__tablename__} don't have attribute {key}") 67 | 68 | conditions = {} 69 | for k, v in list(kwargs.items()): 70 | conditions[k] = v 71 | if many: 72 | items = cls.query.filter_by(**conditions).all() 73 | return items 74 | 75 | item = cls.query.filter_by(**conditions).one_or_none() 76 | return item 77 | -------------------------------------------------------------------------------- /paddlelabel/api/model/data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.config import db 3 | from ..util import nncol 4 | from .base import BaseModel 5 | 6 | 7 | class Data(BaseModel): 8 | __tablename__ = "data" 9 | __table_args__ = {"comment": "Contains all the data files"} 10 | data_id = nncol(db.Integer(), primary_key=True) 11 | task_id = db.Column(db.Integer(), db.ForeignKey("task.task_id", ondelete="CASCADE")) 12 | # task = db.relationship("Task", lazy="selectin") 13 | annotations = db.relationship("Annotation", lazy="selectin", cascade="all, delete-orphan") 14 | path = nncol(db.String()) 15 | size = db.Column(db.String()) # , separated string. natural image: 1,height,width 16 | predicted = db.Column(db.Boolean()) 17 | 18 | _immutables = BaseModel._immutables + ["data_id", "task_id"] 19 | -------------------------------------------------------------------------------- /paddlelabel/api/model/label.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import datetime 3 | 4 | from paddlelabel.config import db 5 | from ..util import nncol 6 | from .base import BaseModel 7 | 8 | 9 | class Label(BaseModel): 10 | __tablename__ = "label" 11 | __table_args__ = {"comment": "Contains all the label information"} 12 | label_id = nncol(db.Integer(), primary_key=True) 13 | id = nncol(db.Integer()) 14 | project_id = db.Column(db.Integer(), db.ForeignKey("project.project_id")) # TODO: why missing project_id when nncol 15 | name = nncol(db.String()) 16 | color = db.Column(db.String()) 17 | comment = db.Column(db.String()) 18 | annotations = db.relationship("Annotation", lazy="noload", backref="label") # cascade="all, delete-orphan" 19 | super_category_id = db.Column(db.Integer()) # TODO: foreign key 20 | _immutables = BaseModel._immutables + ["label_id", "project_id"] 21 | -------------------------------------------------------------------------------- /paddlelabel/api/model/project.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | 4 | from paddlelabel.config import db 5 | from paddlelabel.api.util import nncol 6 | 7 | # TODO: circular risk 8 | from .base import BaseModel 9 | 10 | 11 | class Project(BaseModel): 12 | __tablename__ = "project" 13 | __table_args__ = {"comment": "Stores information and settings for each project"} 14 | project_id = nncol(db.Integer, primary_key=True) 15 | name = nncol(db.String(), unique=True) 16 | description = db.Column(db.String()) 17 | task_category_id = db.Column(db.Integer(), db.ForeignKey("taskCategory.task_category_id")) 18 | task_category = db.relationship("TaskCategory") 19 | data_dir = nncol(db.String(), unique=True) 20 | label_dir = db.Column(db.String(), unique=True) # TODO: remove 21 | labels = db.relationship( 22 | "Label", 23 | lazy="selectin", 24 | cascade="all, delete-orphan", 25 | ) 26 | tasks = db.relationship("Task", lazy="noload", cascade="all, delete-orphan") 27 | annotations = db.relationship("Annotation", lazy="noload", cascade="all, delete-orphan") 28 | label_format = db.Column(db.String()) 29 | other_settings = db.Column(db.String()) 30 | 31 | _immutables = BaseModel._immutables + ["project_id", "task_category_id"] 32 | 33 | def _get_other_settings(self): 34 | if self.other_settings is None: 35 | return {} 36 | return json.loads(self.other_settings) 37 | -------------------------------------------------------------------------------- /paddlelabel/api/model/setting.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os.path as osp 3 | 4 | from functools import total_ordering 5 | 6 | from paddlelabel.config import db 7 | from paddlelabel.api.util import nncol 8 | from .base import BaseModel 9 | 10 | 11 | class TaskCategory(BaseModel): 12 | __tablename__ = "taskCategory" 13 | task_category_id = nncol( 14 | db.Integer(), 15 | primary_key=True, 16 | autoincrement=False, 17 | ) 18 | name = nncol(db.String(), unique=True) 19 | handler = db.Column(db.String()) 20 | 21 | def __init__(self, task_category_id, name, handler): 22 | super().__init__() 23 | self.task_category_id = task_category_id 24 | self.name = name 25 | if len(handler) == 0: 26 | self.handler = None 27 | else: 28 | self.handler = handler 29 | 30 | 31 | class AlembicVersion(db.Model): 32 | __tablename__ = "alembic_version" 33 | version_num = db.Column(db.String(), primary_key=True) 34 | -------------------------------------------------------------------------------- /paddlelabel/api/model/tag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.config import db 3 | from paddlelabel.api.util import nncol 4 | from .base import BaseModel 5 | 6 | 7 | class Tag(BaseModel): 8 | __tablename__ = "tag" 9 | __table_args__ = {"comment": "Contains all the tags"} 10 | tag_id = nncol(db.Integer(), primary_key=True) 11 | project_id = nncol(db.Integer(), db.ForeignKey("project.project_id")) 12 | name = nncol(db.String()) 13 | color = db.Column(db.String()) 14 | comment = db.Column(db.String()) 15 | 16 | _immutables = BaseModel._immutables + ["tag_id", "project_id"] 17 | -------------------------------------------------------------------------------- /paddlelabel/api/model/tag_task.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.config import db 3 | from paddlelabel.api.util import nncol 4 | from .base import BaseModel 5 | 6 | 7 | class TagTask(BaseModel): 8 | __tablename__ = "tagTask" 9 | __table_args__ = {"comment": "Tag and task intersect"} 10 | tag_task_id = nncol(db.Integer(), primary_key=True) 11 | project_id = nncol(db.Integer(), db.ForeignKey("project.project_id")) 12 | tag_id = nncol(db.Integer(), db.ForeignKey("tag.tag_id")) 13 | task_id = nncol(db.Integer(), db.ForeignKey("task.task_id")) 14 | tag = db.relationship("Tag") 15 | 16 | _immutables = BaseModel._immutables + [ 17 | "tag_task_id", 18 | "project_id", 19 | "tag_id", 20 | "task_id", 21 | ] 22 | -------------------------------------------------------------------------------- /paddlelabel/api/model/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import datetime 3 | 4 | from sqlalchemy.orm import backref 5 | 6 | from paddlelabel.config import db 7 | from ..util import nncol 8 | from .annotation import Annotation 9 | from .project import Project 10 | from .base import BaseModel 11 | 12 | 13 | class Task(BaseModel): 14 | __tablename__ = "task" 15 | __table_args__ = {"comment": "Contains all the tasks"} 16 | task_id = nncol(db.Integer(), primary_key=True) 17 | project_id = nncol( 18 | db.Integer(), 19 | db.ForeignKey("project.project_id", ondelete="CASCADE"), 20 | ) 21 | datas = db.relationship("Data", lazy="selectin", backref="task", cascade="all, delete-orphan") 22 | annotations = db.relationship("Annotation", lazy="selectin", backref="task", cascade="all, delete-orphan") 23 | # TODO: split with tag 24 | set = nncol(db.Integer()) # 0 train, 1 val, 2 test 25 | -------------------------------------------------------------------------------- /paddlelabel/api/model/user.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import datetime 3 | 4 | from paddlelabel.config import db 5 | from paddlelabel.api.util import nncol 6 | 7 | from .base import BaseModel 8 | 9 | 10 | class User(BaseModel): 11 | __tablename__ = "user" 12 | __table_args__ = {"comment": "Stores all user info"} 13 | user_id = nncol(db.Integer, primary_key=True) 14 | uuid = nncol(db.String(), unique=True) 15 | username = nncol(db.String(), unique=True) 16 | email = nncol(db.String()) 17 | password = nncol(db.String()) 18 | role_id = nncol(db.Integer()) 19 | 20 | _immutables = BaseModel._immutables + ["user_id", "uuid"] 21 | -------------------------------------------------------------------------------- /paddlelabel/api/rpc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/api/rpc/__init__.py -------------------------------------------------------------------------------- /paddlelabel/api/rpc/cache.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import connexion 3 | import time 4 | 5 | cache_dict = {} 6 | 7 | 8 | def create_cache(): 9 | content = connexion.request.json["content"] 10 | global cache_dict 11 | cache_id = str(time.time()) 12 | cache_dict[cache_id] = content 13 | # print(cache_id, content) 14 | return {"cache_id": cache_id} 15 | 16 | 17 | def get_cache(cache_id): 18 | # print(cache_id, type(cache_id), cache_dict) 19 | content = cache_dict.get(cache_id, None) 20 | if content is None: 21 | return {"title": f"no cache record with cache_id {cache_id} found"}, 404 22 | return {"content": content} 23 | -------------------------------------------------------------------------------- /paddlelabel/api/rpc/debug.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import logging 3 | 4 | logger = logging.getLogger("paddlelabel") 5 | 6 | 7 | def cmdOutputDebugId(debug_id): 8 | logger.debug(f"Debug ID: {debug_id}") 9 | return "OK", 200 10 | -------------------------------------------------------------------------------- /paddlelabel/api/rpc/file.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | def get_folders(): 3 | raise NotImplementedError() 4 | 5 | # path = connexion.request.json.get("path", None) 6 | # if path is None: 7 | # path = "" 8 | # target = osp.join(data_base_dir, path) 9 | # target = osp.abspath(target) 10 | # # print(target, type(target)) 11 | 12 | # if not target[-1] == os.sep: 13 | # target += os.sep 14 | # if not target.startswith(osp.abspath(data_base_dir) + os.sep): 15 | # abort("Can only request folders under data_base_dir", 500) 16 | # if not osp.exists(target): 17 | # return [], 200 18 | # return next(os.walk(target))[1], 200 19 | -------------------------------------------------------------------------------- /paddlelabel/api/rpc/monitor.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import paddlelabel 3 | 4 | 5 | def get_version(): 6 | return paddlelabel.__version__, 200 7 | -------------------------------------------------------------------------------- /paddlelabel/api/rpc/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/api/rpc/util/__init__.py -------------------------------------------------------------------------------- /paddlelabel/api/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .project import ProjectSchema 3 | from .label import LabelSchema 4 | from .task import TaskSchema 5 | from .data import DataSchema 6 | from .annotation import AnnotationSchema 7 | from .user import UserSchema 8 | from .setting import TaskCategorySchema 9 | from .tag import TagSchema 10 | from .tag_task import TagTaskSchema 11 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/annotation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import fields 3 | 4 | 5 | from paddlelabel.api.model import Annotation 6 | from .base import BaseSchema 7 | 8 | 9 | class AnnotationSchema(BaseSchema): 10 | class Meta(BaseSchema.Meta): 11 | model = Annotation 12 | 13 | # not required when calling api 14 | project_id = fields.Integer() 15 | task_id = fields.Integer() 16 | # task = fields.Nested("TaskSchema", exclude=("annotations", "datas")) 17 | label = fields.Nested("LabelSchema") 18 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.config import ma, db 3 | 4 | 5 | class BaseSchema(ma.SQLAlchemyAutoSchema): 6 | class Meta: 7 | include_fk = True 8 | load_instance = True 9 | sqla_session = db.session 10 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import fields, post_dump 3 | 4 | from paddlelabel.api.model import Data 5 | from .base import BaseSchema 6 | from paddlelabel.api.schema.util import str2sault 7 | 8 | 9 | class DataSchema(BaseSchema): 10 | class Meta(BaseSchema.Meta): 11 | model = Data 12 | 13 | @post_dump 14 | def post_dump_action(self, data, **kwargs): 15 | data["sault"] = str2sault(data["path"] + data["created"]) 16 | return data 17 | 18 | # task = fields.Nested("TaskSchema", exclude=("datas", "annotations")) 19 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/label.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import fields 3 | 4 | from paddlelabel.api.model import Label 5 | from .base import BaseSchema 6 | 7 | 8 | class LabelSchema(BaseSchema): 9 | class Meta(BaseSchema.Meta): 10 | model = Label 11 | 12 | id = fields.Integer() 13 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/project.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | 4 | from marshmallow import pre_load, post_dump, fields 5 | 6 | from paddlelabel.api.model import Project 7 | from paddlelabel.api.schema.util import str2sault 8 | from paddlelabel.api.schema.base import BaseSchema 9 | 10 | 11 | class ProjectSchema(BaseSchema): 12 | class Meta(BaseSchema.Meta): 13 | model = Project 14 | # include_relationships = True 15 | 16 | label_dir = fields.String(allow_none=True) 17 | task_category = fields.Nested("TaskCategorySchema") 18 | labels = fields.List(fields.Nested("LabelSchema")) 19 | 20 | @pre_load 21 | def pre_load_action(self, data, **kwargs): 22 | if "label_dir" in data.keys() and data["label_dir"] == "": 23 | data["label_dir"] = None 24 | 25 | if "other_settings" in data.keys(): 26 | data["other_settings"] = json.dumps(data["other_settings"]) 27 | return data 28 | 29 | @post_dump 30 | def pre_dump_action(self, project, **kwargs): 31 | if "other_settings" in project.keys() and project["other_settings"] is not None: 32 | project["other_settings"] = json.loads(project["other_settings"]) 33 | project["upid"] = str2sault(project["data_dir"] + project["created"]) 34 | return project 35 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/setting.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from paddlelabel.api.model import TaskCategory 3 | from .base import BaseSchema 4 | 5 | 6 | class TaskCategorySchema(BaseSchema): 7 | class Meta(BaseSchema.Meta): 8 | model = TaskCategory 9 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/tag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import fields 3 | 4 | 5 | from paddlelabel.api.model import Tag 6 | from .base import BaseSchema 7 | 8 | 9 | class TagSchema(BaseSchema): 10 | class Meta(BaseSchema.Meta): 11 | model = Tag 12 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/tag_task.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import fields 3 | 4 | 5 | from paddlelabel.api.model import TagTask 6 | from .base import BaseSchema 7 | 8 | 9 | class TagTaskSchema(BaseSchema): 10 | class Meta(BaseSchema.Meta): 11 | model = TagTask 12 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | import time 4 | 5 | from marshmallow import post_load, pre_load, pre_dump, post_dump, fields 6 | from marshmallow.fields import Nested 7 | 8 | from paddlelabel.api.model import Task 9 | from paddlelabel.api.schema.util import str2sault 10 | from .base import BaseSchema 11 | 12 | 13 | class TaskSchema(BaseSchema): 14 | class Meta(BaseSchema.Meta): 15 | model = Task 16 | 17 | # project = Nested("ProjectSchema") 18 | annotations = fields.List(Nested("AnnotationSchema"), exclude=("task",)) 19 | data_paths = fields.List(fields.String()) 20 | # datas = fields.List(Nested("DataSchema"), exclude=("task",)) 21 | 22 | # # TODO: confirm data['result'] dont cause trouble 23 | @pre_dump 24 | def output(self, task, **kwargs): 25 | paths = [] 26 | for data in task.datas: 27 | paths.append(f"/datas/{data.data_id}/image?sault={str2sault(data.path+str(data.created))}") 28 | task.data_paths = paths 29 | return task 30 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/user.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from marshmallow import pre_load, fields 3 | 4 | from paddlelabel.api.model import User 5 | from .base import BaseSchema 6 | 7 | 8 | class UserSchema(BaseSchema): 9 | class Meta(BaseSchema.Meta): 10 | model = User 11 | 12 | uuid = fields.String() 13 | -------------------------------------------------------------------------------- /paddlelabel/api/schema/util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import hashlib 3 | 4 | 5 | def str2sault(seed): 6 | return hashlib.md5(seed.encode("utf-8")).hexdigest()[:20] 7 | -------------------------------------------------------------------------------- /paddlelabel/api/util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import functools 3 | import time 4 | 5 | # import logging 6 | 7 | import connexion 8 | import sqlalchemy as sa 9 | 10 | from paddlelabel.util import camel2snake 11 | 12 | 13 | # sa defaults to nullable=True 14 | nncol = functools.partial(sa.Column, nullable=False) 15 | 16 | # TODO: settle on how to use detail and title 17 | def abort(detail: str, status: int, title: str = ""): 18 | # logging.getLogger("paddlelabel").exception(detail) 19 | detail = detail.replace("\n", " ") 20 | title = title.replace("\n", " ") 21 | raise connexion.exceptions.ProblemException( 22 | detail=detail, 23 | title=title if len(title) != 0 else detail, 24 | status=status, 25 | headers={"charset": "utf-8"}, 26 | ) 27 | 28 | 29 | # TODO: move to config 30 | JWT_ISSUER = "paddlelabel" 31 | JWT_SECRET = "change_this" 32 | JWT_LIFETIME_SECONDS = 43200 # 12h 33 | JWT_ALGORITHM = "HS256" 34 | 35 | 36 | def generate_token(uuid): 37 | timestamp = int(time.time()) 38 | payload = { 39 | "iss": JWT_ISSUER, 40 | "iat": timestamp, 41 | "exp": timestamp + JWT_LIFETIME_SECONDS, 42 | "sub": uuid, 43 | } 44 | return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) 45 | 46 | 47 | def decode_token(token): 48 | try: 49 | return jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) 50 | except JWTError as e: 51 | raise Unauthorized from e 52 | 53 | 54 | def parse_order_by(modal, order_by): 55 | order_by = order_by.split(" ") 56 | if len(order_by) == 2: 57 | key, sort_dir = order_by 58 | # print(key, sort_dir) 59 | if "asc" in sort_dir: 60 | sort_dir = "asc" 61 | else: 62 | sort_dir = "desc" 63 | else: 64 | key = order_by[0] 65 | sort_dir = "acs" 66 | key = camel2snake(key) 67 | 68 | try: 69 | order = getattr(getattr(modal, key), sort_dir)() 70 | except: 71 | order = modal.created.asc() 72 | return order 73 | -------------------------------------------------------------------------------- /paddlelabel/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # TODO: move all functions in this file to serve.py 3 | from pathlib import Path 4 | import logging 5 | 6 | import connexion 7 | from flask_sqlalchemy import SQLAlchemy # TODO: remove 8 | from flask_marshmallow import Marshmallow # TODO: remove 9 | 10 | from paddlelabel.util import rand_string 11 | from paddlelabel import configs 12 | 13 | HERE = Path(__file__).parent.absolute() 14 | logger = logging.getLogger("paddlelabel") 15 | 16 | # if not configs.db_path.parent.exists(): 17 | # configs.db_path.parent.mkdir() 18 | 19 | logger.info(f"Database path: {configs.db_url}") 20 | 21 | connexion_app = connexion.App("PaddleLabel") 22 | app = connexion_app.app 23 | app.config["SQLALCHEMY_DATABASE_URI"] = configs.db_url 24 | app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 25 | app.config["SQLALCHEMY_ECHO"] = configs.SQLALCHEMY_ECHO 26 | app.config["SECRET_KEY"] = rand_string(30) 27 | 28 | app.static_url_path = "/static" 29 | app.static_folder = str((HERE / "static").absolute()) 30 | 31 | db = SQLAlchemy(app) 32 | se = db.session 33 | ma = Marshmallow(app) 34 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/README.md: -------------------------------------------------------------------------------- 1 | Generate new revision 2 | 3 | ```shell 4 | cd paddlelabel 5 | alembic revision --autogenerate -m "" 6 | ``` 7 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/dbmigration/__init__.py -------------------------------------------------------------------------------- /paddlelabel/dbmigration/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from logging.config import fileConfig 3 | 4 | from sqlalchemy import engine_from_config 5 | from sqlalchemy import pool 6 | 7 | from alembic import context 8 | 9 | # this is the Alembic Config object, which provides 10 | # access to the values within the .ini file in use. 11 | config = context.config 12 | # Interpret the config file for Python logging. 13 | # This line sets up loggers basically. 14 | if config.config_file_name is not None: 15 | fileConfig(config.config_file_name) 16 | 17 | # add your model's MetaData object here 18 | # for 'autogenerate' support 19 | from paddlelabel import config as pdlabel_config 20 | 21 | target_metadata = pdlabel_config.db.metadata 22 | # target_metadata = None 23 | 24 | # other values from the config, defined by the needs of env.py, 25 | # can be acquired: 26 | # my_important_option = config.get_main_option("my_important_option") 27 | # ... etc. 28 | 29 | 30 | def run_migrations_offline() -> None: 31 | """Run migrations in 'offline' mode. 32 | 33 | This configures the context with just a URL 34 | and not an Engine, though an Engine is acceptable 35 | here as well. By skipping the Engine creation 36 | we don't even need a DBAPI to be available. 37 | 38 | Calls to context.execute() here emit the given string to the 39 | script output. 40 | 41 | """ 42 | url = config.get_main_option("sqlalchemy.url") 43 | context.configure( 44 | url=url, 45 | target_metadata=target_metadata, 46 | literal_binds=True, 47 | dialect_opts={"paramstyle": "named"}, 48 | ) 49 | 50 | with context.begin_transaction(): 51 | context.run_migrations() 52 | 53 | 54 | def run_migrations_online() -> None: 55 | """Run migrations in 'online' mode. 56 | 57 | In this scenario we need to create an Engine 58 | and associate a connection with the context. 59 | 60 | """ 61 | connectable = engine_from_config( 62 | config.get_section(config.config_ini_section), 63 | prefix="sqlalchemy.", 64 | poolclass=pool.NullPool, 65 | ) 66 | 67 | with connectable.connect() as connection: 68 | context.configure(connection=connection, target_metadata=target_metadata) 69 | 70 | with context.begin_transaction(): 71 | context.run_migrations() 72 | 73 | 74 | if context.is_offline_mode(): 75 | run_migrations_offline() 76 | else: 77 | run_migrations_online() 78 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade() -> None: 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade() -> None: 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/versions/61968cbf48e8_v0_1_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """v0.1.3. Add annotation.predicted_by 3 | 4 | Revision ID: 61968cbf48e8 5 | Revises: 23c1bf9b7f48 6 | Create Date: 2022-10-19 02:03:41.383698 7 | 8 | """ 9 | from alembic import op 10 | import sqlalchemy as sa 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = "61968cbf48e8" 15 | down_revision = "23c1bf9b7f48" 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade() -> None: 21 | # ### commands auto generated by Alembic - please adjust! ### 22 | op.add_column("annotation", sa.Column("predicted_by", sa.String(), nullable=True)) 23 | # ### end Alembic commands ### 24 | 25 | 26 | def downgrade() -> None: 27 | # ### commands auto generated by Alembic - please adjust! ### 28 | op.drop_column("annotation", "predicted_by") 29 | # ### end Alembic commands ### 30 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/versions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/dbmigration/versions/__init__.py -------------------------------------------------------------------------------- /paddlelabel/dbmigration/versions/a609821ce310_v0_1_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """v0.1.4. Add data.predicted 3 | 4 | Revision ID: a609821ce310 5 | Revises: 61968cbf48e8 6 | Create Date: 2022-10-22 03:58:11.232173 7 | 8 | """ 9 | from alembic import op 10 | import sqlalchemy as sa 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = "a609821ce310" 15 | down_revision = "61968cbf48e8" 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade() -> None: 21 | # ### commands auto generated by Alembic - please adjust! ### 22 | op.add_column("data", sa.Column("predicted", sa.Boolean(), nullable=True)) 23 | # ### end Alembic commands ### 24 | 25 | 26 | def downgrade() -> None: 27 | # ### commands auto generated by Alembic - please adjust! ### 28 | op.drop_column("data", "predicted") 29 | # ### end Alembic commands ### 30 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/versions/e660f34b820d_v1_0_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """v1.0.1 3 | - reset sample folder 4 | 5 | Revision ID: e660f34b820d 6 | Revises: f47b7f5b73b9 7 | Create Date: 2023-01-24 06:35:13.150458 8 | 9 | """ 10 | from alembic import op 11 | import sqlalchemy as sa 12 | 13 | 14 | # revision identifiers, used by Alembic. 15 | revision = "e660f34b820d" 16 | down_revision = "f47b7f5b73b9" 17 | branch_labels = None 18 | depends_on = None 19 | 20 | 21 | def upgrade() -> None: 22 | # ### commands auto generated by Alembic - please adjust! ### 23 | from paddlelabel.api.controller.sample import reset_samples 24 | 25 | reset_samples() 26 | # ### end Alembic commands ### 27 | 28 | 29 | def downgrade() -> None: 30 | # ### commands auto generated by Alembic - please adjust! ### 31 | pass 32 | # ### end Alembic commands ### 33 | -------------------------------------------------------------------------------- /paddlelabel/dbmigration/versions/f47b7f5b73b9_v1_0_0.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """v1.0.0 3 | - Make sure the size of all tasks are 1,h,w 4 | 5 | Revision ID: f47b7f5b73b9 6 | Revises: a609821ce310 7 | Create Date: 2023-01-09 18:31:50.399688 8 | 9 | """ 10 | from pathlib import Path 11 | 12 | from paddlelabel.api.model import Project, Task 13 | from paddlelabel.config import se 14 | from paddlelabel.io.image import getSize 15 | 16 | # revision identifiers, used by Alembic. 17 | revision = "f47b7f5b73b9" 18 | down_revision = "a609821ce310" 19 | branch_labels = None 20 | depends_on = None 21 | 22 | 23 | def upgrade() -> None: 24 | # ### commands auto generated by Alembic - please adjust! ### 25 | projects = Project.query.all() 26 | pjid2data_dir = {p.project_id: Path(p.data_dir) for p in projects} 27 | 28 | tasks = Task.query.all() 29 | for task in tasks: 30 | data = task.datas[0] 31 | img_path = Path(pjid2data_dir[task.project_id]) / data.path 32 | s, _, _ = getSize(img_path) 33 | data.size = s 34 | se.commit() 35 | 36 | # ### end Alembic commands ### 37 | 38 | 39 | def downgrade() -> None: 40 | # ### commands auto generated by Alembic - please adjust! ### 41 | pass 42 | # ### end Alembic commands ### 43 | -------------------------------------------------------------------------------- /paddlelabel/default_setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "site": { 3 | "task_categories": { 4 | "1": [ 5 | "classification", 6 | "paddlelabel.task.Classification" 7 | ], 8 | "2": [ 9 | "detection", 10 | "paddlelabel.task.Detection" 11 | ], 12 | "3": [ 13 | "semantic_segmentation", 14 | "paddlelabel.task.SemanticSegmentation" 15 | ], 16 | "4": [ 17 | "instance_segmentation", 18 | "paddlelabel.task.InstanceSegmentation" 19 | ], 20 | "5": [ 21 | "keypoint_detection", 22 | "paddlelabel.task.BaseTask" 23 | ], 24 | "6": [ 25 | "remote_sensing", 26 | "paddlelabel.task.BaseTask" 27 | ], 28 | "7": [ 29 | "optical_character_recognition", 30 | "paddlelabel.task.OpticalCharacterRecognition" 31 | ], 32 | "8": [ 33 | "point", 34 | "paddlelabel.task.Point" 35 | ] 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /paddlelabel/io/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/io/__init__.py -------------------------------------------------------------------------------- /paddlelabel/io/image.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import annotations 3 | from pathlib import Path 4 | 5 | from PIL import Image 6 | 7 | 8 | def getSize(img_path: Path) -> tuple[str, int, int]: 9 | im = Image.open(img_path) 10 | width, height = im.size 11 | s = ",".join(map(str, (1,) + (height, width))) 12 | return s, height, width 13 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/multiClass/labels.txt: -------------------------------------------------------------------------------- 1 | red 2 | gray 3 | blue 4 | yellow 5 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/multiClass/test_list.txt: -------------------------------------------------------------------------------- 1 | image/3.jpeg 0 1 2 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/multiClass/train_list.txt: -------------------------------------------------------------------------------- 1 | image/1.jpeg 0 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/multiClass/val_list.txt: -------------------------------------------------------------------------------- 1 | image/2.jpeg 0 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/singleClass/labels.txt: -------------------------------------------------------------------------------- 1 | 1只熊 2 | 2只熊 3 | 3只熊 4 | 4只熊 5 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/singleClass/test_list.txt: -------------------------------------------------------------------------------- 1 | 3只熊/3.jpeg 2 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/singleClass/train_list.txt: -------------------------------------------------------------------------------- 1 | 1只熊/1.jpeg 0 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/classification/singleClass/val_list.txt: -------------------------------------------------------------------------------- 1 | 2只熊/2.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/coco/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 51939.0, 5 | "bbox": [ 6 | 252.0, 7 | 387.0, 8 | 261.0, 9 | 199.0 10 | ], 11 | "category_id": 1, 12 | "id": 1, 13 | "image_id": 1, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | } 19 | ], 20 | "categories": [ 21 | { 22 | "color": "#FF0000", 23 | "id": 1, 24 | "name": "xiaoduxiong", 25 | "supercategory": "toy" 26 | }, 27 | { 28 | "color": "#00FF00", 29 | "id": 2, 30 | "name": "toy", 31 | "supercategory": "none" 32 | } 33 | ], 34 | "images": [ 35 | { 36 | "coco_url": "", 37 | "date_captured": "", 38 | "file_name": "JPEGImages/1.jpeg", 39 | "flickr_url": "", 40 | "height": 1008, 41 | "id": 1, 42 | "license": "", 43 | "width": 756 44 | } 45 | ], 46 | "info": "", 47 | "licenses": [] 48 | } 49 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/coco/train.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 41940.0, 5 | "bbox": [ 6 | 366.0, 7 | 243.0, 8 | 180.0, 9 | 233.0 10 | ], 11 | "category_id": 1, 12 | "id": 2, 13 | "image_id": 2, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | }, 19 | { 20 | "area": 43930.0, 21 | "bbox": [ 22 | 219.0, 23 | 526.0, 24 | 230.0, 25 | 191.0 26 | ], 27 | "category_id": 1, 28 | "id": 3, 29 | "image_id": 2, 30 | "iscrowd": 0, 31 | "segmentation": [ 32 | [] 33 | ] 34 | } 35 | ], 36 | "categories": [ 37 | { 38 | "color": "#FF0000", 39 | "id": 1, 40 | "name": "xiaoduxiong", 41 | "supercategory": "toy" 42 | }, 43 | { 44 | "color": "#00FF00", 45 | "id": 2, 46 | "name": "toy", 47 | "supercategory": "none" 48 | } 49 | ], 50 | "images": [ 51 | { 52 | "coco_url": "", 53 | "date_captured": "", 54 | "file_name": "JPEGImages/2.jpeg", 55 | "flickr_url": "", 56 | "height": 1008, 57 | "id": 2, 58 | "license": "", 59 | "width": 756 60 | } 61 | ], 62 | "info": "", 63 | "licenses": [] 64 | } 65 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/coco/val.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 43120.0, 5 | "bbox": [ 6 | 212.0, 7 | 250.0, 8 | 245.0, 9 | 176.0 10 | ], 11 | "category_id": 1, 12 | "id": 4, 13 | "image_id": 3, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | }, 19 | { 20 | "area": 37422.0, 21 | "bbox": [ 22 | 224.0, 23 | 448.0, 24 | 231.0, 25 | 162.0 26 | ], 27 | "category_id": 1, 28 | "id": 5, 29 | "image_id": 3, 30 | "iscrowd": 0, 31 | "segmentation": [ 32 | [] 33 | ] 34 | }, 35 | { 36 | "area": 37518.0, 37 | "bbox": [ 38 | 236.0, 39 | 630.0, 40 | 222.0, 41 | 169.0 42 | ], 43 | "category_id": 1, 44 | "id": 6, 45 | "image_id": 3, 46 | "iscrowd": 0, 47 | "segmentation": [ 48 | [] 49 | ] 50 | } 51 | ], 52 | "categories": [ 53 | { 54 | "color": "#FF0000", 55 | "id": 1, 56 | "name": "xiaoduxiong", 57 | "supercategory": "toy" 58 | }, 59 | { 60 | "color": "#00FF00", 61 | "id": 2, 62 | "name": "toy", 63 | "supercategory": "none" 64 | } 65 | ], 66 | "images": [ 67 | { 68 | "coco_url": "", 69 | "date_captured": "", 70 | "file_name": "JPEGImages/3.jpeg", 71 | "flickr_url": "", 72 | "height": 1008, 73 | "id": 3, 74 | "license": "", 75 | "width": 756 76 | } 77 | ], 78 | "info": "", 79 | "licenses": [] 80 | } 81 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/Annotations/1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 1.jpeg 5 | 1 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | bear 13 | 14 | 252 15 | 387 16 | 513 17 | 586 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/Annotations/2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 2.jpeg 5 | 2 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | bear 13 | 14 | 366 15 | 243 16 | 546 17 | 476 18 | 19 | 20 | 21 | 22 | bear 23 | 24 | 219 25 | 526 26 | 449 27 | 717 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/Annotations/3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 3.jpeg 5 | 3 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | bear 13 | 14 | 212 15 | 250 16 | 457 17 | 426 18 | 19 | 20 | 21 | 22 | bear 23 | 24 | 224 25 | 448 26 | 455 27 | 610 28 | 29 | 30 | 31 | 32 | bear 33 | 34 | 236 35 | 630 36 | 458 37 | 799 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/labels.txt: -------------------------------------------------------------------------------- 1 | bear 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.xml 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.xml 2 | JPEGImages/4.jpeg Annotations/4.xml 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/voc/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.xml 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/Annotations/1.txt: -------------------------------------------------------------------------------- 1 | 0 0.5059523809523809 0.48263888888888884 0.34523809523809523 0.1974206349206349 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/Annotations/2.txt: -------------------------------------------------------------------------------- 1 | 0 0.6031746031746031 0.35664682539682535 0.23809523809523808 0.23115079365079366 2 | 0 0.44179894179894175 0.6165674603174603 0.30423280423280424 0.18948412698412698 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/Annotations/3.txt: -------------------------------------------------------------------------------- 1 | 0 0.4424603174603175 0.33531746031746035 0.32407407407407407 0.1746031746031746 2 | 0 0.44907407407407407 0.5248015873015873 0.3055555555555556 0.16071428571428573 3 | 0 0.45899470899470907 0.7088293650793651 0.29365079365079366 0.16765873015873015 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/classes.names: -------------------------------------------------------------------------------- 1 | xiaoduxiong 2 | toy 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.txt 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.txt 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/detection/yolo/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.txt 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/05.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/06.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/07.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/08.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/09.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/1.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/10.jpg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/11.png -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/2.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/3.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/img/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/img/4.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/coco/val.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 30124.5, 5 | "bbox": [ 6 | 258.0, 7 | 403.0, 8 | 250.0, 9 | 176.0 10 | ], 11 | "category_id": 1, 12 | "id": 10, 13 | "image_id": 4, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [ 17 | 481.0, 18 | 439.0, 19 | 501.0, 20 | 486.0, 21 | 495.0, 22 | 527.0, 23 | 508.0, 24 | 552.0, 25 | 487.0, 26 | 569.0, 27 | 470.0, 28 | 560.0, 29 | 429.0, 30 | 579.0, 31 | 388.0, 32 | 575.0, 33 | 365.0, 34 | 552.0, 35 | 333.0, 36 | 569.0, 37 | 318.0, 38 | 554.0, 39 | 310.0, 40 | 549.0, 41 | 294.0, 42 | 552.0, 43 | 270.0, 44 | 554.0, 45 | 261.0, 46 | 527.0, 47 | 286.0, 48 | 515.0, 49 | 259.0, 50 | 509.0, 51 | 258.0, 52 | 480.0, 53 | 277.0, 54 | 476.0, 55 | 297.0, 56 | 475.0, 57 | 297.0, 58 | 452.0, 59 | 322.0, 60 | 450.0, 61 | 349.0, 62 | 458.0, 63 | 368.0, 64 | 425.0, 65 | 411.0, 66 | 408.0, 67 | 449.0, 68 | 415.0, 69 | 469.0, 70 | 403.0, 71 | 482.0, 72 | 410.0, 73 | 489.0, 74 | 420.0 75 | ] 76 | ] 77 | } 78 | ], 79 | "categories": [ 80 | { 81 | "color": "#05AF56", 82 | "id": 1, 83 | "name": "xiaoduxiong", 84 | "supercategory": "toy" 85 | }, 86 | { 87 | "color": "#64F3BE", 88 | "id": 2, 89 | "name": "toy", 90 | "supercategory": "none" 91 | } 92 | ], 93 | "images": [ 94 | { 95 | "coco_url": "", 96 | "date_captured": "", 97 | "file_name": "image/1.jpeg", 98 | "flickr_url": "", 99 | "height": 1008, 100 | "id": 4, 101 | "license": "", 102 | "width": 756 103 | } 104 | ], 105 | "info": "", 106 | "licenses": [] 107 | } 108 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/1.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/1.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/2.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/2.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/3.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/instanceSegmentation/mask/Annotations/3.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/labels.txt: -------------------------------------------------------------------------------- 1 | background 2 | xiaoduxiong 3 | toy 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/4.jpeg Annotations/4.tiff 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.tiff 2 | JPEGImages/2.jpeg Annotations/2.tiff 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/instanceSegmentation/mask/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.tiff 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/placeholder/labels.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/placeholder/test_list.txt: -------------------------------------------------------------------------------- 1 | 2/2.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/placeholder/train_list.txt: -------------------------------------------------------------------------------- 1 | 1/1.jpeg 0 2 | 3/3.jpeg 2 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/placeholder/val_list.txt: -------------------------------------------------------------------------------- 1 | 4/4.jpeg 3 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/point/labelme/Annotations/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "flags": {}, 3 | "imageHeight": 1008, 4 | "imagePath": "../JPEGImages/1.jpeg", 5 | "imageWidth": 756, 6 | "shapes": [ 7 | { 8 | "flags": {}, 9 | "group_id": null, 10 | "label": "ear", 11 | "points": [ 12 | [ 13 | 471, 14 | 418 15 | ] 16 | ], 17 | "shape_type": "point" 18 | }, 19 | { 20 | "flags": {}, 21 | "group_id": null, 22 | "label": "ear", 23 | "points": [ 24 | [ 25 | 482, 26 | 551 27 | ] 28 | ], 29 | "shape_type": "point" 30 | }, 31 | { 32 | "flags": {}, 33 | "group_id": null, 34 | "label": "hand", 35 | "points": [ 36 | [ 37 | 311, 38 | 461 39 | ] 40 | ], 41 | "shape_type": "point" 42 | }, 43 | { 44 | "flags": {}, 45 | "group_id": null, 46 | "label": "hand", 47 | "points": [ 48 | [ 49 | 339, 50 | 552 51 | ] 52 | ], 53 | "shape_type": "point" 54 | }, 55 | { 56 | "flags": {}, 57 | "group_id": null, 58 | "label": "foot", 59 | "points": [ 60 | [ 61 | 267, 62 | 497 63 | ] 64 | ], 65 | "shape_type": "point" 66 | }, 67 | { 68 | "flags": {}, 69 | "group_id": null, 70 | "label": "foot", 71 | "points": [ 72 | [ 73 | 275, 74 | 537 75 | ] 76 | ], 77 | "shape_type": "point" 78 | } 79 | ], 80 | "version": "5.1.1" 81 | } 82 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/point/labelme/Annotations/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "flags": {}, 3 | "imageHeight": 1008, 4 | "imagePath": "../JPEGImages/2.jpeG", 5 | "imageWidth": 756, 6 | "shapes": [ 7 | { 8 | "flags": {}, 9 | "group_id": null, 10 | "label": "ear", 11 | "points": [ 12 | [ 13 | 384, 14 | 312 15 | ] 16 | ], 17 | "shape_type": "point" 18 | }, 19 | { 20 | "flags": {}, 21 | "group_id": null, 22 | "label": "ear", 23 | "points": [ 24 | [ 25 | 488, 26 | 258 27 | ] 28 | ], 29 | "shape_type": "point" 30 | }, 31 | { 32 | "flags": {}, 33 | "group_id": null, 34 | "label": "hand", 35 | "points": [ 36 | [ 37 | 460, 38 | 437 39 | ] 40 | ], 41 | "shape_type": "point" 42 | }, 43 | { 44 | "flags": {}, 45 | "group_id": null, 46 | "label": "hand", 47 | "points": [ 48 | [ 49 | 525, 50 | 393 51 | ] 52 | ], 53 | "shape_type": "point" 54 | }, 55 | { 56 | "flags": {}, 57 | "group_id": null, 58 | "label": "foot", 59 | "points": [ 60 | [ 61 | 497, 62 | 465 63 | ] 64 | ], 65 | "shape_type": "point" 66 | }, 67 | { 68 | "flags": {}, 69 | "group_id": null, 70 | "label": "foot", 71 | "points": [ 72 | [ 73 | 525, 74 | 449 75 | ] 76 | ], 77 | "shape_type": "point" 78 | }, 79 | { 80 | "flags": {}, 81 | "group_id": null, 82 | "label": "foot", 83 | "points": [ 84 | [ 85 | 236, 86 | 654 87 | ] 88 | ], 89 | "shape_type": "point" 90 | }, 91 | { 92 | "flags": {}, 93 | "group_id": null, 94 | "label": "foot", 95 | "points": [ 96 | [ 97 | 256, 98 | 692 99 | ] 100 | ], 101 | "shape_type": "point" 102 | }, 103 | { 104 | "flags": {}, 105 | "group_id": null, 106 | "label": "hand", 107 | "points": [ 108 | [ 109 | 307, 110 | 692 111 | ] 112 | ], 113 | "shape_type": "point" 114 | }, 115 | { 116 | "flags": {}, 117 | "group_id": null, 118 | "label": "hand", 119 | "points": [ 120 | [ 121 | 264, 122 | 638 123 | ] 124 | ], 125 | "shape_type": "point" 126 | }, 127 | { 128 | "flags": {}, 129 | "group_id": null, 130 | "label": "ear", 131 | "points": [ 132 | [ 133 | 384, 134 | 556 135 | ] 136 | ], 137 | "shape_type": "point" 138 | }, 139 | { 140 | "flags": {}, 141 | "group_id": null, 142 | "label": "ear", 143 | "points": [ 144 | [ 145 | 428, 146 | 658 147 | ] 148 | ], 149 | "shape_type": "point" 150 | } 151 | ], 152 | "version": "5.1.1" 153 | } 154 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/coco/val.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 30124.5, 5 | "bbox": [ 6 | 258.0, 7 | 403.0, 8 | 250.0, 9 | 176.0 10 | ], 11 | "category_id": 1, 12 | "id": 10, 13 | "image_id": 4, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [ 17 | 481.0, 18 | 439.0, 19 | 501.0, 20 | 486.0, 21 | 495.0, 22 | 527.0, 23 | 508.0, 24 | 552.0, 25 | 487.0, 26 | 569.0, 27 | 470.0, 28 | 560.0, 29 | 429.0, 30 | 579.0, 31 | 388.0, 32 | 575.0, 33 | 365.0, 34 | 552.0, 35 | 333.0, 36 | 569.0, 37 | 318.0, 38 | 554.0, 39 | 310.0, 40 | 549.0, 41 | 294.0, 42 | 552.0, 43 | 270.0, 44 | 554.0, 45 | 261.0, 46 | 527.0, 47 | 286.0, 48 | 515.0, 49 | 259.0, 50 | 509.0, 51 | 258.0, 52 | 480.0, 53 | 277.0, 54 | 476.0, 55 | 297.0, 56 | 475.0, 57 | 297.0, 58 | 452.0, 59 | 322.0, 60 | 450.0, 61 | 349.0, 62 | 458.0, 63 | 368.0, 64 | 425.0, 65 | 411.0, 66 | 408.0, 67 | 449.0, 68 | 415.0, 69 | 469.0, 70 | 403.0, 71 | 482.0, 72 | 410.0, 73 | 489.0, 74 | 420.0 75 | ] 76 | ] 77 | } 78 | ], 79 | "categories": [ 80 | { 81 | "color": "#05AF56", 82 | "id": 1, 83 | "name": "xiaoduxiong", 84 | "supercategory": "toy" 85 | }, 86 | { 87 | "color": "#64F3BE", 88 | "id": 2, 89 | "name": "toy", 90 | "supercategory": "none" 91 | } 92 | ], 93 | "images": [ 94 | { 95 | "coco_url": "", 96 | "date_captured": "", 97 | "file_name": "image/1.jpeg", 98 | "flickr_url": "", 99 | "height": 1008, 100 | "id": 4, 101 | "license": "", 102 | "width": 756 103 | } 104 | ], 105 | "info": "", 106 | "licenses": [] 107 | } 108 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/1.png -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/2.png -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/bear/semanticSegmentation/mask/Annotations/3.png -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/labels.txt: -------------------------------------------------------------------------------- 1 | background 2 | xiaoduxiong 3 | toy 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/4.jpeg Annotations/4.png 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.png 2 | JPEGImages/2.jpeg Annotations/2.png 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/bear/semanticSegmentation/mask/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.png 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/multiClass/labels.txt: -------------------------------------------------------------------------------- 1 | 梨 2 | 苹果 3 | 1 4 | 2 5 | 4 6 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/multiClass/test_list.txt: -------------------------------------------------------------------------------- 1 | image/1.jpeg 1 2 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/multiClass/train_list.txt: -------------------------------------------------------------------------------- 1 | image/3.jpeg 1 3 2 | image/4.jpeg 0 4 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/multiClass/val_list.txt: -------------------------------------------------------------------------------- 1 | image/2.jpeg 0 3 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/singleClass/labels.txt: -------------------------------------------------------------------------------- 1 | 苹果 2 | 梨 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/singleClass/paddlelabel.warning: -------------------------------------------------------------------------------- 1 | PP Label is using files stored under this folder! 2 | Changing file in this folder may cause issues. 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/singleClass/test_list.txt: -------------------------------------------------------------------------------- 1 | 梨/2.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/singleClass/train_list.txt: -------------------------------------------------------------------------------- 1 | 苹果/1.jpeg 0 2 | 苹果/3.jpeg 0 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/classification/singleClass/val_list.txt: -------------------------------------------------------------------------------- 1 | 梨/4.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/coco/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 137772.0, 5 | "bbox": [ 6 | 182.0, 7 | 322.0, 8 | 356.0, 9 | 387.0 10 | ], 11 | "category_id": 2, 12 | "id": 9, 13 | "image_id": 4, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | } 19 | ], 20 | "categories": [ 21 | { 22 | "color": "#4a90e2", 23 | "id": 1, 24 | "name": "梨", 25 | "supercategory": "none" 26 | }, 27 | { 28 | "color": "#008000", 29 | "id": 2, 30 | "name": "苹果", 31 | "supercategory": "none" 32 | } 33 | ], 34 | "images": [ 35 | { 36 | "coco_url": "", 37 | "date_captured": "", 38 | "file_name": "image/1.jpeg", 39 | "flickr_url": "", 40 | "height": 1008, 41 | "id": 4, 42 | "license": "", 43 | "width": 756 44 | } 45 | ], 46 | "info": "", 47 | "licenses": [] 48 | } 49 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/coco/train.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 167132.0, 5 | "bbox": [ 6 | 100.5, 7 | 233.5, 8 | 329.0, 9 | 508.0 10 | ], 11 | "category_id": 1, 12 | "id": 1, 13 | "image_id": 1, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | }, 19 | { 20 | "area": 71214.0, 21 | "bbox": [ 22 | 360.0, 23 | 391.0, 24 | 249.0, 25 | 286.0 26 | ], 27 | "category_id": 1, 28 | "id": 2, 29 | "image_id": 1, 30 | "iscrowd": 0, 31 | "segmentation": [ 32 | [] 33 | ] 34 | }, 35 | { 36 | "area": 41790.0, 37 | "bbox": [ 38 | 243.0, 39 | 269.0, 40 | 210.0, 41 | 199.0 42 | ], 43 | "category_id": 1, 44 | "id": 3, 45 | "image_id": 2, 46 | "iscrowd": 0, 47 | "segmentation": [ 48 | [] 49 | ] 50 | }, 51 | { 52 | "area": 47260.0, 53 | "bbox": [ 54 | 159.5, 55 | 380.5, 56 | 170.0, 57 | 278.0 58 | ], 59 | "category_id": 1, 60 | "id": 4, 61 | "image_id": 2, 62 | "iscrowd": 0, 63 | "segmentation": [ 64 | [] 65 | ] 66 | }, 67 | { 68 | "area": 75504.0, 69 | "bbox": [ 70 | 276.0, 71 | 367.0, 72 | 242.0, 73 | 312.0 74 | ], 75 | "category_id": 1, 76 | "id": 5, 77 | "image_id": 2, 78 | "iscrowd": 0, 79 | "segmentation": [ 80 | [] 81 | ] 82 | }, 83 | { 84 | "area": 42250.0, 85 | "bbox": [ 86 | 425.0, 87 | 381.0, 88 | 169.0, 89 | 250.0 90 | ], 91 | "category_id": 1, 92 | "id": 6, 93 | "image_id": 2, 94 | "iscrowd": 0, 95 | "segmentation": [ 96 | [] 97 | ] 98 | } 99 | ], 100 | "categories": [ 101 | { 102 | "color": "#4a90e2", 103 | "id": 1, 104 | "name": "梨", 105 | "supercategory": "none" 106 | }, 107 | { 108 | "color": "#008000", 109 | "id": 2, 110 | "name": "苹果", 111 | "supercategory": "none" 112 | } 113 | ], 114 | "images": [ 115 | { 116 | "coco_url": "", 117 | "date_captured": "", 118 | "file_name": "image/2.jpeg", 119 | "flickr_url": "", 120 | "height": 1008, 121 | "id": 1, 122 | "license": "", 123 | "width": 756 124 | }, 125 | { 126 | "coco_url": "", 127 | "date_captured": "", 128 | "file_name": "image/4.jpeg", 129 | "flickr_url": "", 130 | "height": 1008, 131 | "id": 2, 132 | "license": "", 133 | "width": 756 134 | } 135 | ], 136 | "info": "", 137 | "licenses": [] 138 | } 139 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/coco/val.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": [ 3 | { 4 | "area": 254241.0, 5 | "bbox": [ 6 | -76.0, 7 | 267.0, 8 | 477.0, 9 | 533.0 10 | ], 11 | "category_id": 2, 12 | "id": 7, 13 | "image_id": 3, 14 | "iscrowd": 0, 15 | "segmentation": [ 16 | [] 17 | ] 18 | }, 19 | { 20 | "area": 227700.0, 21 | "bbox": [ 22 | 407.0, 23 | 294.0, 24 | 460.0, 25 | 495.0 26 | ], 27 | "category_id": 2, 28 | "id": 8, 29 | "image_id": 3, 30 | "iscrowd": 0, 31 | "segmentation": [ 32 | [] 33 | ] 34 | } 35 | ], 36 | "categories": [ 37 | { 38 | "color": "#4a90e2", 39 | "id": 1, 40 | "name": "梨", 41 | "supercategory": "none" 42 | }, 43 | { 44 | "color": "#008000", 45 | "id": 2, 46 | "name": "苹果", 47 | "supercategory": "none" 48 | } 49 | ], 50 | "images": [ 51 | { 52 | "coco_url": "", 53 | "date_captured": "", 54 | "file_name": "image/3.jpeg", 55 | "flickr_url": "", 56 | "height": 1008, 57 | "id": 3, 58 | "license": "", 59 | "width": 756 60 | } 61 | ], 62 | "info": "", 63 | "licenses": [] 64 | } 65 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/Annotations/1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 1.jpeg 5 | 1 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | 苹果 13 | 14 | 182 15 | 322 16 | 538 17 | 709 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/Annotations/2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 2.jpeg 5 | 2 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | 13 | 14 | 100 15 | 233 16 | 429 17 | 741 18 | 19 | 20 | 21 | 22 | 23 | 24 | 360 25 | 391 26 | 609 27 | 677 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/Annotations/3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 3.jpeg 5 | 2 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | 苹果 13 | 14 | -76 15 | 267 16 | 401 17 | 800 18 | 19 | 20 | 21 | 22 | 苹果 23 | 24 | 407 25 | 294 26 | 867 27 | 789 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/Annotations/4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | JPEGImages 4 | 4.jpeg 5 | 4 6 | 7 | 756 8 | 1008 9 | 10 | 11 | 12 | 13 | 14 | 243 15 | 269 16 | 453 17 | 468 18 | 19 | 20 | 21 | 22 | 23 | 24 | 159 25 | 380 26 | 329 27 | 658 28 | 29 | 30 | 31 | 32 | 33 | 34 | 276 35 | 367 36 | 518 37 | 679 38 | 39 | 40 | 41 | 42 | 43 | 44 | 425 45 | 381 46 | 594 47 | 631 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/labels.txt: -------------------------------------------------------------------------------- 1 | 梨 2 | 苹果 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.xml 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.xml 2 | JPEGImages/4.jpeg Annotations/4.xml 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/voc/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.xml 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/Annotations/1.txt: -------------------------------------------------------------------------------- 1 | 1 0.46296296296296297 0.5264367816091954 0.7325102880658436 0.8896551724137931 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/Annotations/2.txt: -------------------------------------------------------------------------------- 1 | 0 0.32265625 0.47012302284710017 0.5140625 0.8927943760984183 2 | 0 0.66640625 0.5527240773286468 0.3890625 0.5026362038664324 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/Annotations/3.txt: -------------------------------------------------------------------------------- 1 | 1 0.3040909090909091 0.5400815217391304 0.43363636363636365 0.7241847826086957 2 | 1 0.7354545454545455 0.5509510869565217 0.41818181818181815 0.6725543478260869 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/Annotations/4.txt: -------------------------------------------------------------------------------- 1 | 0 0.43999999999999995 0.22900000000000004 0.42 0.398 2 | 0 0.232 0.53 0.34 0.556 3 | 0 0.538 0.538 0.484 0.624 4 | 0 0.763 0.504 0.338 0.5 5 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/classes.names: -------------------------------------------------------------------------------- 1 | 梨 2 | 苹果 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.txt 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.txt 2 | JPEGImages/4.jpeg Annotations/4.txt 3 | JPEGImages/5.jpeg Annotations/5.txt 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/detection/yolo/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/3.jpeg Annotations/3.txt 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/img/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/img/1.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/img/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/img/2.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/img/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/img/3.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/img/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/img/4.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/img/5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/img/5.jpeg -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/1.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/1.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/2.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/2.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/3.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/3.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/4.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/instanceSegmentation/mask/Annotations/4.tiff -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/labels.txt: -------------------------------------------------------------------------------- 1 | background 2 | 苹果 1 3 | 梨 2 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/4.jpeg Annotations/4.tiff 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.tiff 2 | JPEGImages/3.jpeg Annotations/3.tiff 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/instanceSegmentation/mask/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.tiff 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/placeholder/labels.txt: -------------------------------------------------------------------------------- 1 | 苹果 2 | 梨 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/placeholder/paddlelabel.warning: -------------------------------------------------------------------------------- 1 | PP Label is using files stored under this folder! 2 | Changing file in this folder may cause issues. 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/placeholder/test_list.txt: -------------------------------------------------------------------------------- 1 | 梨/2.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/placeholder/train_list.txt: -------------------------------------------------------------------------------- 1 | 苹果/1.jpeg 0 2 | 苹果/3.jpeg 0 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/placeholder/val_list.txt: -------------------------------------------------------------------------------- 1 | 梨/4.jpeg 1 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/1.png -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/2.png -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/3.png -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/paddlelabel/sample/fruit/semanticSegmentation/mask/Annotations/4.png -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/labels.txt: -------------------------------------------------------------------------------- 1 | background 2 | 梨 - 0 128 0 3 | 苹果 - 74 144 226 4 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/test_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/4.jpeg Annotations/4.png 2 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/train_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/2.jpeg Annotations/2.png 2 | JPEGImages/3.jpeg Annotations/3.png 3 | -------------------------------------------------------------------------------- /paddlelabel/sample/fruit/semanticSegmentation/mask/val_list.txt: -------------------------------------------------------------------------------- 1 | JPEGImages/1.jpeg Annotations/1.png 2 | -------------------------------------------------------------------------------- /paddlelabel/serve.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from pathlib import Path 3 | import shutil 4 | import logging 5 | 6 | from flask_cors import CORS # TODO: custom middleware, dont use this package 7 | import alembic 8 | from alembic.config import Config 9 | from alembic.script import ScriptDirectory 10 | 11 | from paddlelabel import configs 12 | from paddlelabel.util import Resolver, backend_error 13 | from paddlelabel.config import connexion_app 14 | from paddlelabel.api.controller.setting import init_site_settings 15 | from paddlelabel.api.model import AlembicVersion 16 | 17 | HERE = Path(__file__).parent.absolute() 18 | logger = logging.getLogger("paddlelabel") 19 | 20 | # 1. static routes 21 | @connexion_app.app.route("/") 22 | def index(): 23 | return "", 301, {"Location": "/static/index.html"} 24 | 25 | 26 | @connexion_app.app.route("/static/doc/") 27 | def doc_index(): 28 | return "", 301, {"Location": "/static/doc/index.html"} 29 | 30 | 31 | @connexion_app.app.route("/static/doc/CN/") 32 | def cn_doc_index(): 33 | return "", 301, {"Location": "/static/doc/CN/index.html"} 34 | 35 | 36 | @connexion_app.app.route("/static/doc/EN/") 37 | def en_doc_index(): 38 | return "", 301, {"Location": "/static/doc/EN/index.html"} 39 | 40 | 41 | # 2. update db version 42 | db_exists = configs.db_path.exists() 43 | alembic_cfg = alembic.config.Config(HERE / "alembic.ini") 44 | alembic_cfg.set_main_option("script_location", str(HERE / "dbmigration")) 45 | alembic_cfg.set_main_option("sqlalchemy.url", configs.db_url) 46 | # Create the alembic version table if it doesn’t exist already 47 | alembic.command.ensure_version(alembic_cfg) 48 | 49 | with connexion_app.app.app_context(): 50 | res = AlembicVersion.query.all() 51 | # get version in db 52 | curr_db_v = None if len(res) == 0 else res[0].version_num 53 | # get version of revision head 54 | script = ScriptDirectory.from_config(alembic_cfg) 55 | heads = script.get_revisions("heads") 56 | db_head_version = heads[0].revision 57 | 58 | # v0.1.0: db exists but doesn't have version 59 | if curr_db_v is None and db_exists: 60 | alembic.command.stamp(alembic_cfg, revision="23c1bf9b7f48") 61 | 62 | # need db backup 63 | if curr_db_v != db_head_version and db_exists: 64 | from datetime import datetime 65 | 66 | back_up_path = ( 67 | Path(configs.db_path).parent 68 | / f"{str(datetime.now()).split('.')[0].replace(' ', '_').replace(':', '_')}-paddlelabel.db.bk" 69 | ) 70 | shutil.copy(Path(configs.db_path), back_up_path) 71 | logger.warn( 72 | f"Performing database update. Should anything goes wrong during this update, you can find the old database at {str(back_up_path)}" 73 | ) 74 | 75 | # perform db upgrade 76 | alembic.command.upgrade(alembic_cfg, "head") 77 | 78 | # TODO: move this to be managed by alembic @lin 79 | init_site_settings(HERE / "default_setting.json") 80 | 81 | if configs.debug: 82 | alembic.command.check(alembic_cfg) # abort when model definition is changed and a new reversion is required 83 | 84 | logger.setLevel(configs.log_level) 85 | 86 | # 3. serve the app 87 | connexion_app.add_api( 88 | HERE / "openapi.yml", 89 | resolver=Resolver("paddlelabel.api", collection_endpoint_name="get_all"), 90 | # request with undefined param returns error, dont enforce body 91 | strict_validation=True, 92 | pythonic_params=True, 93 | options={"swagger_ui": configs.debug}, 94 | ) 95 | connexion_app.add_error_handler(Exception, backend_error) 96 | 97 | # TODO: use middleware, instead of flask-cors 98 | CORS(connexion_app.app) 99 | -------------------------------------------------------------------------------- /paddlelabel/task/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .base import BaseTask 3 | from .classification import Classification 4 | from .detection import Detection 5 | from .semantic_segmentation import SemanticSegmentation 6 | from .instance_segmentation import InstanceSegmentation 7 | from .optical_character_recognition import OpticalCharacterRecognition 8 | from .point import Point 9 | -------------------------------------------------------------------------------- /paddlelabel/task/point.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import annotations 3 | 4 | from pathlib import Path 5 | import shutil 6 | 7 | from paddlelabel.task.util.labelme import get_matching, parse_ann, write_ann 8 | from paddlelabel.api import Task 9 | from paddlelabel.task.base import BaseTask 10 | from paddlelabel.io.image import getSize 11 | 12 | 13 | class Point(BaseTask): 14 | def __init__(self, project, data_dir: Path | None = None, is_export=False): 15 | super(Point, self).__init__(project, data_dir=data_dir, skip_label_import=True, is_export=is_export) 16 | self.importers = { 17 | "labelme": self.labelme_importer, 18 | } 19 | self.exporters = { 20 | "labelme": self.labelme_exporter, 21 | } 22 | 23 | def labelme_importer(self, data_dir: Path): 24 | # 1. set params 25 | data_dir = Path(data_dir) 26 | self.create_warning(data_dir) 27 | 28 | # 2. import all datas 29 | for img_path, (ann_path, set_idx) in get_matching(data_dir).items(): 30 | if ann_path is not None: 31 | height, width, anns = parse_ann(ann_path, set(["point"])) 32 | size = f"1,{height},{width}" 33 | else: 34 | anns = [] 35 | size, _, _ = getSize(img_path) 36 | self.add_task([{"path": str(img_path), "size": size}], [anns], set_idx) 37 | 38 | self.commit() 39 | 40 | def labelme_exporter(self, export_dir: Path): 41 | # 1. set params, prep output folders 42 | project = self.project 43 | 44 | export_dir = Path(export_dir) 45 | export_dir.mkdir(exist_ok=True, parents=True) 46 | img_dst = export_dir / "JPEGImages" 47 | ann_dst = export_dir / "Annotations" 48 | img_dst.mkdir() 49 | ann_dst.mkdir() 50 | data_dir = Path(project.data_dir) 51 | 52 | # 2. move images and write ann json 53 | tasks = Task._get(project_id=project.project_id, many=True) 54 | new_paths = [] 55 | for task in tasks: 56 | data = task.datas[0] 57 | _, height, width = map(int, data.size.split(",")) 58 | img_path = img_dst / Path(data.path).name 59 | ann_path = ann_dst / (Path(data.path).name.split(".")[0] + ".json") 60 | shutil.copy(data_dir / data.path, img_path) 61 | write_ann(ann_path, img_path, height, width, data.annotations, with_data=False) 62 | 63 | new_paths.append([str(img_path.relative_to(export_dir))]) 64 | print(new_paths) 65 | 66 | # 3. write split files 67 | self.export_split(export_dir, tasks, new_paths, with_labels=False, annotation_ext=".json") 68 | -------------------------------------------------------------------------------- /paddlelabel/task/util/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .file import ( 3 | create_dir, 4 | listdir, 5 | copy, 6 | copy_content, 7 | image_extensions, 8 | ensure_unique_base_name, 9 | get_fname, 10 | match_by_base_name, 11 | break_path, 12 | ) 13 | from .manager import ComponentManager 14 | from .color import rgb_to_hex, hex_to_rgb, rand_hex_color, name_to_hex 15 | -------------------------------------------------------------------------------- /paddlelabel/task/util/color.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import random 3 | import time 4 | 5 | 6 | def rgb_to_hex(rgb): 7 | rgb = tuple(int(c) for c in rgb) 8 | return ("#%02x%02x%02x" % rgb).upper() 9 | 10 | 11 | def hex_to_rgb(value): 12 | value = value.lstrip("#") 13 | lv = len(value) 14 | return tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3)) 15 | 16 | 17 | def name_to_hex(name): 18 | color_map = { 19 | "red": "#FF0000", 20 | "white": "#FFFFFF", 21 | "cyan": "#00FFFF", 22 | "silver": "#C0C0C0", 23 | "blue": "#0000FF", 24 | "gray": "#808080", 25 | "darkblue": "#0000A0", 26 | "black": "#000000", 27 | "lightblue": "#ADD8E6", 28 | "orange": "#FFA500", 29 | "purple": "#800080", 30 | "brown": "#A52A2A", 31 | "yellow": "#FFFF00", 32 | "maroon": "#800000", 33 | "lime": "#00FF00", 34 | "green": "#008000", 35 | "magenta": "#FF00FF", 36 | "olive": "#808000", 37 | } 38 | if name[0] == "#" and len(name) == 7: 39 | return name 40 | 41 | name = name.lower() 42 | if name not in color_map.keys(): 43 | raise RuntimeError(f"Don't have hex value for color {name}") 44 | 45 | return color_map[name] 46 | 47 | 48 | # TODO: generate color with high contrast 49 | # TODO: generate color within certain range 50 | # TODO: even devide color space 51 | def rand_hex_color(current_colors=[]): 52 | random.seed(time.time()) 53 | r = lambda: random.randint(0, 255) 54 | while True: 55 | c = "#%02X%02X%02X" % (r(), r(), r()) 56 | c = c.upper() 57 | if c not in current_colors: 58 | break 59 | return c 60 | 61 | 62 | # Red #FF0000 63 | # White #FFFFFF 64 | # Cyan #00FFFF 65 | # Silver #C0C0C0 66 | # Blue #0000FF 67 | # Gray #808080 68 | # DarkBlue #0000A0 69 | # Black #000000 70 | # LightBlue #ADD8E6 71 | # Orange #FFA500 72 | # Purple #800080 73 | # Brown #A52A2A 74 | # Yellow #FFFF00 75 | # Maroon #800000 76 | # Lime #00FF00 77 | # Green #008000 78 | # Magenta #FF00FF 79 | # Olive #808000 80 | -------------------------------------------------------------------------------- /paddlelabel/tool/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from pathlib import Path 3 | import inspect 4 | 5 | from prompt_toolkit.shortcuts import message_dialog, radiolist_dialog, input_dialog 6 | from prompt_toolkit.styles import Style 7 | 8 | from simple_file_format import eiseg_label2_paddlelabel 9 | 10 | HERE = Path("__file__").parent.absolute() 11 | print(HERE) 12 | 13 | # print(inspect.signature(input_dialog)) 14 | # exit() 15 | 16 | 17 | def run(): 18 | # 0. 使用指南 19 | message_dialog( 20 | title="PaddleLabel Tools Tui 使用指南", 21 | text=""" 22 | - 按空格/回车进行选择 23 | - 完成选择/输入后按Tab切换到确定/退出按钮部分 24 | - 按空格/回车进行确定 25 | """, 26 | ).run() 27 | 28 | # 1. 工具选择 29 | result = radiolist_dialog( 30 | title="PaddleLabel Tools Tui", 31 | text="请选择需要使用的工具", 32 | values=[ 33 | ("eiseg_label2paddlelabel", "转换EISeg标签列表到PaddleLabel格式"), 34 | ], 35 | ).run() 36 | 37 | # 2.1 eiseg 格式标签列表转 PaddleLabel格式 38 | if result == "eiseg_label2paddlelabel": 39 | pj_category = radiolist_dialog( 40 | title="EISeg标签列表转PaddleLabel格式", 41 | text="请选择标签列表所属项目类型", 42 | values=[ 43 | ("detection", "目标检测"), 44 | ("semantic_segmentation", "语义分割"), 45 | ], 46 | ).run() 47 | 48 | eiseg_label_path = None 49 | while eiseg_label_path is None: 50 | eiseg_label_path = input_dialog( 51 | title="EISeg标签列表转PaddleLabel格式", 52 | text=f""" 53 | 请输入EISeg标签列表文件文件路径 54 | - 可以为绝对路径 55 | - 可以为相对 {str(HERE)} 的相对路径 56 | """, 57 | ).run() 58 | eiseg_label_path = Path(eiseg_label_path).absolute() 59 | if not eiseg_label_path.exists(): 60 | message_dialog( 61 | title="EISeg标签列表转PaddleLabel格式", 62 | text=f"未能找到 {str(eiseg_label_path)} 文件,请确认文件存在,路径输入正确", 63 | ok_text="重新输入", 64 | ).run() 65 | eiseg_label_path = None 66 | assert eiseg_label_path is not None 67 | eiseg_label2_paddlelabel( 68 | eiseg_label_path, 69 | add_background=pj_category == "semantic_segmentation", 70 | label_id_delta=1, 71 | ) 72 | 73 | 74 | if __name__ == "__main__": 75 | run() 76 | -------------------------------------------------------------------------------- /paddlelabel/tool/simple_file_format.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from pathlib import Path 3 | 4 | 5 | def eiseg_label2_paddlelabel(eiseg_label_path: Path, add_background: bool = False, label_id_delta: int = 0): 6 | # 1. read eiseg label 7 | eiseg_label = eiseg_label_path.read_text(encoding="utf-8").split("\n") 8 | eiseg_label = [l.split(" ") for l in eiseg_label if len(l) != 0] 9 | 10 | # 2.1 split 11 | pdlabel_label = [[l[1], l[0], *l[2:]] for l in eiseg_label] 12 | # # 2.2 change label id 13 | if label_id_delta != 0: 14 | for idx in range(len(pdlabel_label)): 15 | pdlabel_label[idx][1] = str(int(pdlabel_label[idx][1]) + label_id_delta) 16 | # 2.3 join to string 17 | pdlabel_label = [" ".join(l) for l in pdlabel_label] 18 | # 2.4 add background line 19 | pdlabel_label = ["background 0 0 0 0"] + pdlabel_label if add_background else pdlabel_label 20 | # 2.5 join to file 21 | pdlabel_label = "\n".join(pdlabel_label) 22 | 23 | # 3. rename eiseg format file and write pdlabel format file 24 | orig_name = eiseg_label_path.name 25 | name, ext = orig_name.split(".") 26 | eiseg_label_path.rename(eiseg_label_path.parent / f"{name}_eiseg.{ext}") 27 | pdlabel_label_path = eiseg_label_path.parent / orig_name 28 | pdlabel_label_path.write_text(pdlabel_label) 29 | -------------------------------------------------------------------------------- /paddlelabel/version: -------------------------------------------------------------------------------- 1 | 1.0.5 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | include = '\.pyi?$' 4 | exclude = ''' 5 | /( 6 | \.git 7 | | \.hg 8 | | \.mypy_cache 9 | | \.tox 10 | | \.venv 11 | | _build 12 | | buck-out 13 | | build 14 | | dist 15 | )/ 16 | ''' 17 | -------------------------------------------------------------------------------- /pyproject.toml.temp: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | dynamic = ["readme"] 7 | version = "0.0.30" 8 | 9 | name="paddlelabel", 10 | version=open((HERE / "paddlelabel" / "version"), "r").read().strip(), 11 | authors = [{ name="PaddleCV-SIG", email="me@linhan.email" }] 12 | description="Web Based Multi Purpose Annotation Software", 13 | long_description=README, 14 | long_description_content_type="text/markdown", 15 | url="https://github.com/PaddleCV-SIG/PaddleLabel", 16 | author="PaddleCV-SIG", 17 | author_email="me@linhan.email", 18 | license = { file="LICENSE" } 19 | classifiers=[ 20 | "License :: OSI Approved :: Apache Software License", 21 | "Programming Language :: Python :: 3", 22 | "Programming Language :: Python :: 3.9", 23 | ], 24 | requires-python = ">=3.6" 25 | packages=find_packages(exclude=("tool.*", "tool")), 26 | include_package_data=True, 27 | install_requires=REQUIRED_PACKAGES, 28 | entry_points={ 29 | "console_scripts": [ 30 | "paddlelabel=paddlelabel.__main__:run", 31 | "pdlabel=paddlelabel.__main__:run", 32 | ] 33 | }, 34 | 35 | [project] 36 | dynamic = ["dependencies"] 37 | [tool.setuptools.dynamic] 38 | dependencies = {file = ["requirements.txt"]} 39 | 40 | [tool.black] 41 | line-length = 120 42 | include = '\.pyi?$' 43 | exclude = ''' 44 | /( 45 | \.git 46 | | \.hg 47 | | \.mypy_cache 48 | | \.tox 49 | | \.venv 50 | | _build 51 | | buck-out 52 | | build 53 | | dist 54 | )/ 55 | ''' 56 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | connexion[swagger-ui] 2 | 3 | black 4 | pre-commit 5 | jake 6 | 7 | types-Pillow 8 | types-Flask-Cors 9 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Web related 2 | connexion 3 | marshmallow_sqlalchemy 4 | 5 | ## currently required, but will be removed in a future version 6 | flask_sqlalchemy 7 | flask_marshmallow 8 | flask_cors 9 | 10 | # Task related 11 | opencv-python 12 | numpy 13 | pycocotoolse 14 | tqdm 15 | tifffile 16 | 17 | # db migration 18 | alembic 19 | 20 | # paddlelabel_tools 21 | prompt_toolkit 22 | 23 | # imagecodecs 24 | # uuid 25 | # jwt 26 | # werkzeug 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import pathlib 3 | from setuptools import setup, find_packages, Extension 4 | 5 | HERE = pathlib.Path(__file__).parent 6 | 7 | README = (HERE / "README.md").read_text(encoding="utf-8") 8 | 9 | 10 | with open("requirements.txt", "r") as fin: 11 | REQUIRED_PACKAGES = fin.read() 12 | 13 | setup( 14 | name="paddlelabel", 15 | version=open((HERE / "paddlelabel" / "version"), "r").read().strip(), 16 | description="Web Based Multi Purpose Annotation Software", 17 | long_description=README, 18 | long_description_content_type="text/markdown", 19 | url="https://github.com/PaddleCV-SIG/PaddleLabel", 20 | author="PaddleCV-SIG", 21 | author_email="me@linhan.email", 22 | license="Apache Software License", 23 | classifiers=[ 24 | "License :: OSI Approved :: Apache Software License", 25 | "Programming Language :: Python :: 3", 26 | "Programming Language :: Python :: 3.9", 27 | ], 28 | packages=find_packages(exclude=("tool.*", "tool")), 29 | include_package_data=True, 30 | install_requires=REQUIRED_PACKAGES, 31 | entry_points={ 32 | "console_scripts": [ 33 | "paddlelabel=paddlelabel.__main__:run", 34 | "pdlabel=paddlelabel.__main__:run", 35 | "pt=paddlelabel.tool.__main__:run", 36 | "paddlelabel_tools=paddlelabel.tool.__main__:run", 37 | ] 38 | }, 39 | ) 40 | -------------------------------------------------------------------------------- /thunder-tests/thunderActivity.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /thunder-tests/thunderCollection.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": "f8fe5699-a721-439d-be48-4d18b9cd9672", 4 | "colName": "project", 5 | "created": "2023-01-28T14:41:00.442Z", 6 | "folders": [ 7 | { 8 | "_id": "34a30cd1-b515-4d22-bdd9-52e4b6762385", 9 | "containerId": "", 10 | "created": "2023-01-29T21:32:56.344Z", 11 | "name": "1_Import", 12 | "sortNum": 10000 13 | }, 14 | { 15 | "_id": "c16ef877-ffa3-4d81-98c1-2cc098656d96", 16 | "containerId": "", 17 | "created": "2023-01-30T01:24:16.287Z", 18 | "name": "2_Export", 19 | "sortNum": 10000 20 | } 21 | ], 22 | "sortNum": 10000 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /thunder-tests/thunderEnvironment.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": "d7b67eda-f60d-4050-905a-e0f1612c44b0", 4 | "created": "2023-01-28T14:40:04.587Z", 5 | "data": [ 6 | { 7 | "name": "host", 8 | "value": "http://localhost:17995/api" 9 | } 10 | ], 11 | "default": true, 12 | "modified": "2023-01-28T14:40:04.587Z", 13 | "name": "PaddleLabel", 14 | "sortNum": 10000 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /thunder-tests/thunderclient.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": "771fb38b-ad2d-4d33-ae4e-fffd90edbaaa", 4 | "colId": "f8fe5699-a721-439d-be48-4d18b9cd9672", 5 | "containerId": "", 6 | "created": "2023-01-28T14:41:11.511Z", 7 | "headers": [], 8 | "method": "GET", 9 | "modified": "2023-01-28T14:42:38.399Z", 10 | "name": "import_settings", 11 | "params": [ 12 | { 13 | "isPath": true, 14 | "name": "project_type", 15 | "value": "classification" 16 | } 17 | ], 18 | "sortNum": 10000, 19 | "tests": [], 20 | "url": "{{host}}/projects/importOptions/{project_type}" 21 | }, 22 | { 23 | "_id": "8027bc1d-6cba-45f8-a748-2827098334fd", 24 | "body": { 25 | "form": [], 26 | "raw": "{\n\t\"name\": \"Points - labelme format\",\n \"data_dir\": \"~/3rd_party/3rd_party/labelme/point/\",\n \"task_category_id\": 8,\n \"label_format\": \"labelme\"\n}", 27 | "type": "json" 28 | }, 29 | "colId": "f8fe5699-a721-439d-be48-4d18b9cd9672", 30 | "containerId": "34a30cd1-b515-4d22-bdd9-52e4b6762385", 31 | "created": "2023-01-29T21:33:11.773Z", 32 | "headers": [], 33 | "method": "POST", 34 | "modified": "2023-01-29T21:37:25.570Z", 35 | "name": "point", 36 | "params": [], 37 | "sortNum": 20000, 38 | "tests": [], 39 | "url": "{{host}}/projects" 40 | }, 41 | { 42 | "_id": "f6b820ca-74ea-47a7-bbbe-2f075f4ae812", 43 | "body": { 44 | "form": [], 45 | "raw": "{\n \"export_dir\": \"~/Desktop/test\",\n\t\"export_format\": \"labelme\"\n}", 46 | "type": "json" 47 | }, 48 | "colId": "f8fe5699-a721-439d-be48-4d18b9cd9672", 49 | "containerId": "c16ef877-ffa3-4d81-98c1-2cc098656d96", 50 | "created": "2023-01-30T01:24:16.287Z", 51 | "headers": [], 52 | "method": "POST", 53 | "modified": "2023-01-30T01:27:15.998Z", 54 | "name": "point", 55 | "params": [ 56 | { 57 | "isPath": true, 58 | "name": "project_id", 59 | "value": "1" 60 | } 61 | ], 62 | "sortNum": 20000, 63 | "tests": [], 64 | "url": "{{host}}/projects/{project_id}/export" 65 | } 66 | ] 67 | -------------------------------------------------------------------------------- /tool/build_frontend.sh: -------------------------------------------------------------------------------- 1 | # build frontend and copy to backend folder 2 | # run from and will return to /path/to/PaddleLabel/ 3 | cd ../PaddleLabel-Frontend/ 4 | pwd 5 | echo "Current frontend branch: $(git branch --show-current)" 6 | 7 | echo "Pulling update from github" 8 | git pull 9 | 10 | echo "Building frontend" 11 | 12 | npx browserslist@latest --update-db 13 | yarn run build --trace-deprecation 14 | cd ../PaddleLabel 15 | rm -rf paddlelabel/static/ 16 | mkdir paddlelabel/static/ 17 | cp -r ../PaddleLabel-Frontend/dist/* paddlelabel/static/ 18 | 19 | echo "Frontend built and copied to backend repo" 20 | 21 | echo "Downloading doc build and extracting to static" 22 | 23 | cd paddlelabel/static/ 24 | mkdir doc 25 | wget https://nightly.link/PaddleCV-SIG/PaddleLabel/workflows/build/develop/github-pages.zip 26 | unzip github-pages.zip 27 | tar -xvf artifact.tar --directory ./doc/ 28 | rm github-pages.zip 29 | rm artifact.tar 30 | cd - 31 | -------------------------------------------------------------------------------- /tool/bumpversion.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | version = open("paddlelabel/version", "r").read().strip().split(".") 3 | version = [int(v) for v in version] 4 | version[2] += 1 5 | version = [str(v) for v in version] 6 | version = ".".join(version) 7 | print(version, file=open("paddlelabel/version", "w")) 8 | -------------------------------------------------------------------------------- /tool/file.py: -------------------------------------------------------------------------------- 1 | ../paddlelabel/task/util/file.py -------------------------------------------------------------------------------- /tool/gen_sample_dst.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os.path as osp 3 | import os 4 | 5 | from file import listdir 6 | 7 | paths = listdir(osp.join(osp.expanduser("~"), ".paddlelabel/sample/")) 8 | 9 | paths = [p for p in paths if p[-len(".jpeg") :] == ".jpeg"] 10 | 11 | for p in paths: 12 | print(f'"{p}"', end=",\n") 13 | -------------------------------------------------------------------------------- /tool/get_frontend.sh: -------------------------------------------------------------------------------- 1 | # download built frontend from github action 2 | 3 | rm -rf paddlelabel/static/ 4 | mkdir paddlelabel/static/ 5 | cd paddlelabel/static/ 6 | wget https://nightly.link/PaddleCV-SIG/PaddleLabel-Frontend/workflows/build/develop/PaddleLabel_built_frontend.zip 7 | unzip -q PaddleLabel_built_frontend.zip 8 | rm PaddleLabel_built_frontend.zip 9 | 10 | echo "Downloading doc build and extracting to static" 11 | 12 | # cd paddlelabel/static/ 13 | mkdir doc 14 | wget https://nightly.link/PaddleCV-SIG/PaddleLabel/workflows/build/develop/github-pages.zip 15 | unzip github-pages.zip 16 | tar -xvf artifact.tar --directory ./doc/ 17 | rm github-pages.zip 18 | rm artifact.tar 19 | cd - 20 | -------------------------------------------------------------------------------- /tool/old/Procfile: -------------------------------------------------------------------------------- 1 | web: pwd; ls; bash /app/tool/heroku.sh 2 | tree: tree / 3 | -------------------------------------------------------------------------------- /tool/old/clas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaddleCV-SIG/PaddleLabel/f09b8b3fa5f31702164941d4b52c78e1b045c3a5/tool/old/clas/__init__.py -------------------------------------------------------------------------------- /tool/old/clas/mv_image_acc_split.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os.path as osp 3 | import argparse 4 | 5 | from tqdm import tqdm 6 | 7 | from ..file import listdir, create_dir, copy 8 | 9 | parser = argparse.ArgumentParser( 10 | description="Move single class classification images to class name folders based on xx_list.txt and labels.txt\n Note: only support consecutive label id" 11 | ) 12 | parser.add_argument( 13 | "-i", 14 | "--dataset_path", 15 | type=str, 16 | required=True, 17 | help="Dataset path, should have labels.txt, and at least one of train_list.txt, val_list.txt and test_list.txt", 18 | ) 19 | parser.add_argument("-o", "--output_path", type=str, required=True, help="The path to export dataset to") 20 | parser.add_argument( 21 | "-id", 22 | "--input_delimiter", 23 | default=" ", 24 | type=str, 25 | help='Delimiter for input labels.txt, warped with "". For example " " for space or "|" for |. Defaults to space', 26 | ) 27 | 28 | parser.add_argument( 29 | "-od", 30 | "--output_delimiter", 31 | default=" ", 32 | type=str, 33 | help="Delimiter for output labels.txt, same format as input_delimiter. Defaults to space", 34 | ) 35 | 36 | args = parser.parse_args() 37 | 38 | # 1. ensure essential files exist 39 | labes_txt_path = osp.join(args.dataset_path, "labels.txt") 40 | assert osp.exists(labes_txt_path), f"labels.txt not found under {args.dataset_path}" 41 | 42 | xx_list_found = 0 43 | list_paths = [osp.join(args.dataset_path, n) for n in ("train_list.txt", "val_list.txt", "test_list.txt")] 44 | for list_path in list_paths: 45 | if osp.exists(list_path): 46 | xx_list_found += 1 47 | assert xx_list_found != 0, f"No xx_list.txt found under {args.dataset_path}" 48 | 49 | # 2. read info 50 | all_files = set(listdir(args.dataset_path)) 51 | 52 | labels = open(labes_txt_path, "r").readlines() 53 | labels = [l.strip() for l in labels] 54 | labels = [l for l in labels if len(l) != 0] 55 | 56 | idx2label = {} 57 | for idx, name in enumerate(labels): 58 | idx2label[idx] = name 59 | 60 | list_lines = [] 61 | for list_path in list_paths: 62 | if osp.exists(list_path): 63 | list_lines += open(list_path, "r").readlines() 64 | list_lines = [l.strip() for l in list_lines] 65 | list_lines = [l for l in list_lines if len(l) != 0] 66 | list_info = [l.split(args.input_delimiter) for l in list_lines] 67 | 68 | # 3. create output dirs and move files 69 | for label_name in idx2label.values(): 70 | create_dir(osp.join(args.output_path, label_name)) 71 | 72 | for img_path, label_id in tqdm(list_info): 73 | label_name = idx2label[int(label_id)] 74 | copy(osp.join(args.dataset_path, img_path), osp.join(args.output_path, label_name)) 75 | all_files.remove(img_path) 76 | 77 | # move all remaining files 78 | for file in all_files: 79 | copy(osp.join(args.dataset_path, file), osp.join(args.output_path, file)) 80 | -------------------------------------------------------------------------------- /tool/old/cypress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage: $1: bf or anything else, whether to build frontend code before running 4 | # $2: all or anything else, test only on current py version or on py3.6 7 8 9 10 5 | # $3: pypi or anything, install from pypi or local source 6 | # $4: open or anything else 7 | # example: 8 | # bash tool/cypress.sh dbf all local 9 | # bash tool/cypress.sh dbf curr local open 10 | 11 | # colorful print helper 12 | RED='\033[0;31m' 13 | GREEN='\033[0;32m' 14 | NOCOLOR='\033[0m' 15 | print() { 16 | if [ $2 = 0 ]; then 17 | echo -e "${GREEN}$1${NOCOLOR}" 18 | else 19 | echo -e "${RED}$1${NOCOLOR}" 20 | fi 21 | } 22 | 23 | install_and_test() { 24 | if [ "$2" = "pypi" ]; then 25 | echo -e "\nInstalling PaddleLabel from pypi\n" 26 | pip install --upgrade paddlelabel >/dev/null 27 | else 28 | # test upgrade 29 | rm -rf ~/.paddlelabel/ 30 | pip install flask_sqlalchemy==2.5.1 31 | pip install --upgrade paddlelabel >/dev/null 32 | paddlelabel -d& 33 | sleep 3 34 | pip uninstall paddlelabel -y 35 | python tool/kill_by_port.py 36 | # 37 | 38 | echo -e "\nBuilding PaddleLabel from local code\n" 39 | source tool/install.sh $1 40 | fi 41 | 42 | python tool/kill_by_port.py 43 | 44 | sleep 5 45 | paddlelabel -d & 46 | 47 | cd ../PaddleLabel-Frontend/ 48 | echo -e "\nPaddleLabel started in background\n" 49 | 50 | py_version=$(python -c 'import platform; print(platform.python_version())') 51 | echo "Python version:" $py_version 52 | if [ "$3" = "" ]; then 53 | # echo -e "\nRunning in firefox" 54 | # # touch cypress/log/$py_version-firefox.log 55 | # # code cypress/log/$py_version-firefox.log 56 | # echo "cypress/log/${dt}_$py_version-firefox.log" 57 | 58 | # time npx cypress run -b firefox >"cypress/log/${dt}_$py_version-firefox.log" 59 | # print "Firefox test finished with code $?" $? 60 | 61 | echo -e "\nRunning in chromium" 62 | # touch cypress/log/$py_version-chromium.log 63 | # code cypress/log/$py_version-chromium.log 64 | time npx cypress run -b chromium >"cypress/log/${dt}_$py_version-chromium.log" 65 | print "Chromium test finished with code $?" $? 66 | 67 | else 68 | npx cypress $3 69 | fi 70 | cd ../PaddleLabel 71 | } 72 | 73 | clear 74 | echo -e "\n" 75 | dt=$(python -c 'import datetime; print(str(datetime.datetime.now()))') 76 | 77 | if [ "$2" = "all" ]; then 78 | echo "Testing on multiple py versions" 79 | # source ~/.conda.sh 80 | # conda shell.bash hook > source 81 | source ~/miniconda3/etc/profile.d/conda.sh 82 | 83 | [ -d ../PaddleLabel-Frontend/cypress/log/ ] || mkdir ../PaddleLabel-Frontend/cypress/log/ 84 | # rm ../PaddleLabel-Frontend/cypress/log/* 85 | if [ "$1" = 'bf' ]; then 86 | echo "Building frontend silently" 87 | bash tool/build_frontend.sh >/dev/null 88 | fi 89 | 90 | for ver in 7 8 9 10; do 91 | # for ver in 8; do 92 | echo "Testing in py 3.$ver" 93 | conda env remove -n test 94 | conda create -y -n test python=3.$ver >/dev/null 95 | conda activate test 96 | install_and_test "use_existing_frontend_build" $3 $4 97 | conda deactivate 98 | done 99 | else 100 | install_and_test $1 $3 $4 101 | fi 102 | -------------------------------------------------------------------------------- /tool/old/freeze_env.sh: -------------------------------------------------------------------------------- 1 | mamba update --all 2 | mamba env export -n PaddleLabel > env.yaml 3 | cat <> env.yaml 4 | - pip: 5 | - pycocotoolse 6 | - flask_marshmallow 7 | - flask_sqlalchemy 8 | - marshmallow_sqlalchemy 9 | EOF 10 | -------------------------------------------------------------------------------- /tool/old/install.sh: -------------------------------------------------------------------------------- 1 | # usage: bash ./tool/install.sh -> skip build frontend, build py package then install 2 | # bash ./tool/install.sh bf -> build frontend and py package then install 3 | 4 | exit_if_fail() { 5 | if [ $1 != 0 ] 6 | then 7 | echo $2 8 | exit -1 9 | fi 10 | } 11 | 12 | echo "Running local install script" 13 | echo "Current conda env is: $CONDA_DEFAULT_ENV, python version is $(python -c 'import platform; print(platform.python_version())')" 14 | 15 | if [ "$1" = "bf" ] 16 | then 17 | echo -e "\nBuilding frontend\n" 18 | source tool/build_frontend.sh > /dev/null 19 | exit_if_fail $? "Build frontend failed" 20 | echo "Finished building frontend" 21 | else 22 | echo "Skip front end build" 23 | fi 24 | 25 | 26 | # make python package and install 27 | pip install --upgrade pip > /dev/null 28 | rm -rf dist/ 29 | rm -rf build/ 30 | echo -e "\nBuilding python package\n" 31 | python setup.py sdist bdist_wheel > /dev/null 32 | exit_if_fail $? "Build package failed" 33 | echo "Finish building package" 34 | 35 | pip uninstall -y paddlelabel 36 | pip uninstall -y paddlelabel 37 | 38 | echo -e "\nInstalling\n" 39 | pip install --upgrade "dist/paddlelabel-$(cat paddlelabel/version).tar.gz" > /dev/null 40 | exit_if_fail $? "Install failed" 41 | echo "Finish installing" 42 | 43 | # clear pdlabel files 44 | # rm -rf ~/.paddlelabel/ 45 | -------------------------------------------------------------------------------- /tool/old/kill_by_port.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import sys 4 | 5 | 6 | if len(sys.argv) == 1: 7 | port = 17995 8 | else: 9 | port = sys.argv[1] 10 | 11 | while True: 12 | res = os.popen(f"lsof -i :{port}") 13 | res = res.read().split("\n") 14 | 15 | print("======") 16 | print(res) 17 | print("======") 18 | 19 | if len(res) == 1: 20 | print(f"no process on {port}") 21 | break 22 | 23 | res = res[1].strip().split(" ") 24 | pid = [r for r in res if r != ""][1] 25 | print(f"killing process on {port} with pid {pid}") 26 | os.popen(f"kill -9 {pid}") 27 | -------------------------------------------------------------------------------- /tool/old/labels/labels_remove_first_value.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import argparse 3 | import os 4 | import os.path as osp 5 | 6 | parser = argparse.ArgumentParser(description="Remove first value from labels.txt") 7 | parser.add_argument( 8 | "-l", "--labels_path", type=str, required=True, help="Path to labels.txt. Use absolute path to be safe." 9 | ) 10 | parser.add_argument( 11 | "-o", 12 | "--output_path", 13 | type=str, 14 | required=True, 15 | help="Path to output processed labels.txt. Use absolute path to be safe.", 16 | ) 17 | parser.add_argument( 18 | "-inpd", 19 | "--input_delimiter", 20 | default=" ", 21 | type=str, 22 | help='Delimiter for input labels.txt, warped with "". For example " " for space or "|" for |. Defaults to space', 23 | ) 24 | 25 | parser.add_argument( 26 | "-outd", 27 | "--output_delimiter", 28 | default=" ", 29 | type=str, 30 | help="Delimiter for output labels.txt, same format as input_delimiter. Defaults to space", 31 | ) 32 | 33 | args = parser.parse_args() 34 | 35 | if not osp.exists(args.labels_path): 36 | raise RuntimeError(f"Didn't find labels.txt at {args.labels_path}.") 37 | 38 | lines = open(args.labels_path, "r").readlines() 39 | lines = [l.strip() for l in lines if len(l.strip()) != 0] 40 | lines = [l.split(args.input_delimiter) for l in lines] 41 | lines = [l[1:] for l in lines] 42 | lines = [args.output_delimiter.join(l) for l in lines] 43 | 44 | os.makedirs(osp.dirname(args.output_path), exist_ok=True) 45 | with open(args.output_path, "w") as f: 46 | for line in lines: 47 | print(line, file=f) 48 | -------------------------------------------------------------------------------- /tool/old/pypi.sh: -------------------------------------------------------------------------------- 1 | res=$(lsof -i :17995) 2 | if ["$res" = ""] 3 | then 4 | echo "No running process found" 5 | else 6 | echo $res 7 | exit -1 8 | fi 9 | 10 | 11 | pip uninstall -y paddlelabel 12 | pip uninstall -y paddlelabel 13 | pip uninstall -y paddlelabel 14 | 15 | rm -rf ~/.paddlelabel 16 | 17 | pip install --upgrade paddlelabel 18 | 19 | paddlelabel & 20 | 21 | cd ../PaddleLabel-Frontend/ 22 | if [ "$1" = "" ] 23 | then 24 | npx cypress run 25 | else 26 | npx cypress $1 27 | fi 28 | -------------------------------------------------------------------------------- /tool/old/rm_workflow_runs.sh: -------------------------------------------------------------------------------- 1 | export TARGET_USER=PaddleCV-SIG 2 | # export TARGET_REPO=PaddleLabel 3 | export TARGET_REPO=PaddleLabel-ML 4 | export TARGET_WORKFLOW_ID="xx.yml" 5 | 6 | while : 7 | do 8 | SIZE=$(gh api repos/$TARGET_USER/$TARGET_REPO/actions/workflows/$TARGET_WORKFLOW_ID/runs | jq -r .total_count) 9 | echo "Found: $SIZE" 10 | 11 | 12 | if [[ $SIZE -eq 0 ]] 13 | then 14 | echo "All done" 15 | break 16 | fi 17 | 18 | gh api repos/$TARGET_USER/$TARGET_REPO/actions/workflows/$TARGET_WORKFLOW_ID/runs | \ 19 | jq -r '.workflow_runs[] | .id' | \ 20 | xargs -n1 -I % gh api --silent repos/$TARGET_USER/$TARGET_REPO/actions/runs/% -X DELETE 21 | sleep 1 22 | done 23 | -------------------------------------------------------------------------------- /tool/old/runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.9.10 2 | -------------------------------------------------------------------------------- /tool/zip_sample.sh: -------------------------------------------------------------------------------- 1 | cd /home/lin/Desktop/data/pdlabel 2 | rm paddlelabel_3rd_party_tests.zip 3 | zip -r paddlelabel_3rd_party_tests.zip * -x "*.zip" -x export/ 4 | --------------------------------------------------------------------------------