├── .flake8 ├── .github └── workflows │ ├── docker-develop.yaml │ └── docker-production.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── Dockerfile ├── LICENSE.md ├── Pipfile ├── Pipfile.lock ├── README.md ├── contributors.txt ├── docs ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── GETTING_STARTED.md ├── INSTALLATION.md ├── app_running.png ├── captured_image.png ├── face_recognized.png └── first_startup.png ├── find_taipy_gui_dir.py ├── src ├── classifiers │ ├── haarcascade_frontalface_default.xml │ └── lbpcascade_frontalface_improved.xml ├── demo │ ├── __init__.py │ ├── faces.py │ └── image.py ├── main.css ├── main.py ├── requirements.txt ├── temp.png └── webcam │ ├── __init__.py │ ├── webcam.py │ └── webui │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── canvas.ts │ ├── index.ts │ ├── video.ts │ └── webcam.tsx │ ├── tsconfig.json │ └── webpack.config.js └── temp.png /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | extend-ignore = E203 4 | -------------------------------------------------------------------------------- /.github/workflows/docker-develop.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated. 2 | # Please, do not edit it manually. 3 | 4 | name: Build Docker Image develop 5 | 6 | on: 7 | release: 8 | types: 9 | - prereleased 10 | 11 | permissions: 12 | id-token: write 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | environment: develop 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: 'Az CLI login' 24 | uses: azure/login@v1 25 | with: 26 | client-id: ${{ secrets.AZURE_CLIENT_ID }} 27 | tenant-id: ${{ secrets.AZURE_TENANT_ID }} 28 | subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 29 | 30 | - name: 'Login to ACR' 31 | run: | 32 | az acr login --name ${{ vars.DOCKER_REGISTRY }} 33 | 34 | - name: 'Build & push image' 35 | run: | 36 | docker build -t ${{ vars.DOCKER_REGISTRY }}/face-recognition:develop . 37 | docker push ${{ vars.DOCKER_REGISTRY }}/face-recognition:develop 38 | -------------------------------------------------------------------------------- /.github/workflows/docker-production.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated. 2 | # Please, do not edit it manually. 3 | 4 | name: Build Docker Image production 5 | 6 | on: 7 | release: 8 | types: 9 | - released 10 | 11 | permissions: 12 | id-token: write 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | environment: production 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: 'Az CLI login' 24 | uses: azure/login@v1 25 | with: 26 | client-id: ${{ secrets.AZURE_CLIENT_ID }} 27 | tenant-id: ${{ secrets.AZURE_TENANT_ID }} 28 | subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 29 | 30 | - name: 'Login to ACR' 31 | run: | 32 | az acr login --name ${{ vars.DOCKER_REGISTRY }} 33 | 34 | - name: 'Build & push image' 35 | run: | 36 | docker build -t ${{ vars.DOCKER_REGISTRY }}/face-recognition:production . 37 | docker push ${{ vars.DOCKER_REGISTRY }}/face-recognition:production 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # Taipy 132 | .data/ 133 | 134 | # VSCode 135 | .vscode 136 | 137 | # Demo Images 138 | images/ 139 | src.zip 140 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/Lucas-C/pre-commit-hooks 3 | rev: v1.1.13 4 | hooks: 5 | - id: forbid-crlf 6 | - id: remove-crlf 7 | - id: forbid-tabs 8 | - id: remove-tabs 9 | - repo: https://github.com/pre-commit/pre-commit-hooks 10 | rev: v4.0.1 11 | hooks: 12 | - id: trailing-whitespace 13 | - id: end-of-file-fixer 14 | - repo: https://github.com/ambv/black 15 | rev: 22.3.0 16 | hooks: 17 | - id: black 18 | args: [--line-length=120] 19 | language_version: python3 20 | - repo: https://github.com/pycqa/flake8 21 | rev: 3.9.2 22 | hooks: 23 | - id: flake8 24 | additional_dependencies: [flake8-typing-imports==1.10.0] 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | FROM python:3.11 13 | 14 | WORKDIR /app 15 | 16 | # Install application dependencies. 17 | COPY src/requirements.txt . 18 | RUN pip install -r requirements.txt 19 | 20 | RUN curl -sL https://deb.nodesource.com/setup_18.x | bash && apt install nodejs 21 | 22 | # Install the node components. 23 | COPY src/webcam/webui /tmp/webui 24 | RUN npm i /tmp/webui/ 25 | 26 | # Copy the application source code. 27 | COPY src . 28 | 29 | # Build the extension. 30 | RUN cd webcam/webui && rm package-lock.json && npm i && \ 31 | npm i /usr/local/lib/python3.11/site-packages/taipy/gui/webapp && \ 32 | npm run build && cd - 33 | 34 | CMD ["taipy", "run", "--no-debug", "--no-reloader", "main.py", "-H", "0.0.0.0", "-P", "5000"] -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2022 Avaiga Private Limited 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | opencv-python = ">=4.7.0" 8 | opencv-contrib-python = ">=4.7.0" 9 | numpy = ">=1.24.1" 10 | pandas = ">=1.5.2" 11 | taipy = ">=2.2.0" 12 | 13 | [dev-packages] 14 | black = "*" 15 | flake8 = "*" 16 | flake8-docstrings = "*" 17 | isort = "*" 18 | mypy = "*" 19 | pre-commit = "*" 20 | pytest = "*" 21 | pytest-cov = "*" 22 | pytest-mock = ">=3.6" 23 | tox = ">=3.24" 24 | types-toml = ">=0.10.0" 25 | autopep8 = "*" 26 | 27 | [requires] 28 | python_version = "3.11" 29 | 30 | [pipenv] 31 | allow_prereleases = true 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo Face Recognition 2 | 3 | ## What is Demo Face Recognition 4 | 5 | This demo shows how to use Taipy with a custom GUI component to capture video from your webcam and do realtime face detection. 6 | 7 | What this application demonstrates: 8 | * How to build a complex custom UI component for Taipy. 9 | * How to detect and recognize faces in the image in real time using OpenCV. 10 | 11 | ## Usage 12 | 13 | A Webcam component is shown at the center of the application. It can detect faces and identify them. To be able to recognize your face, capture multiple photos of your face (click on the "Capture" button) and write your name when the dialog appears. At the end, click "Retrain" and the model should now recognize your face. 14 | 15 | ## Demo Type 16 | 17 | - **Level**: Advanced 18 | - **Topic**: Taipy-GUI, Computer Vision 19 | - **Components/Controls**: 20 | - Taipy GUI: custom GUI component 21 | - **Other**: OpenCV 22 | ## Installation 23 | Want to install this demo? Check out our [`INSTALLATION.md`](docs/INSTALLATION.md) file. 24 | ## Getting Started 25 | 26 | Check out our [`GETTING_STARTED.md`](docs/GETTING_STARTED.md) file. 27 | 28 | ## Directory Structure 29 | 30 | - `src/`: Main folder for the application code 31 | - `main.py`: Main file containing the demo application code. 32 | - `demo/`: Contains additional demo source code. 33 | - `demo/faces.py`: Contains the code to do face detection and face recognition. 34 | - `src/image.py`: Contains shared facility functions. 35 | - `webcam/`: Contains custom component code. The directory contains the Python files to declare the custom component to Taipy. 36 | - `webcam/webui`: Contains the TypeScript source code for the custom React component. 37 | - `classifiers`: Contains the OpenCV classifiers used in the app for face detection. 38 | - `images`: Contains the files to train the face detection of the demo. This folder is created at first startup. All image captures will go into this directory. 39 | - `docs/`: contains the images for the documentation 40 | - `CODE_OF_CONDUCT.md`: Code of conduct for members and contributors of _demo-covid-dashboard_. 41 | - `CONTRIBUTING.md`: Instructions to contribute to _demo-covid-dashboard_. 42 | - `INSTALLATION.md`: Instructions to install _demo-covid-dashboard_. 43 | - `LICENSE`: The Apache 2.0 License. 44 | - `Pipfile`: File used by the Pipenv virtual environment to manage project dependencies. 45 | - `README.md`: Current file. 46 | 47 | ## Contributing 48 | 49 | Want to help build this demo? Check out our [`CONTRIBUTING.md`](docs/CONTRIBUTING.md) file. 50 | 51 | ## License 52 | 53 | Licensed under the Apache License, Version 2.0. See [`LICENSE.md`](LICENSE.md). 54 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | gmarabout 2 | FlorianJacta 3 | -------------------------------------------------------------------------------- /docs/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people. 21 | * Being respectful of differing opinions, viewpoints, and experiences. 22 | * Giving and gracefully accepting constructive feedback. 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience. 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community. 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind. 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment. 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission. 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting. 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | rnd@avaiga.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributions 2 | 3 | Thanks for your interest in helping improve Taipy! Contributions are welcome, and they are greatly appreciated! 4 | Every little help and credit will always be given. 5 | 6 | There are multiple ways to contribute to Taipy: code, but also reporting bugs, creating feature requests, helping 7 | other users in our forums, [stack**overflow**](https://stackoverflow.com/), etc. 8 | 9 | Today the only way to communicate with the Taipy team is by GitHub issues. 10 | 11 | ## Never contributed on an open source project before ? 12 | 13 | Have a look on this [GitHub documentation](https://docs.github.com/en/get-started/quickstart/contributing-to-projects). 14 | 15 | ## Report bugs 16 | 17 | Reporting bugs is through [GitHub issues](https://github.com/Avaiga/taipy/issues). 18 | 19 | Please report relevant information and preferably code that exhibits the problem. We provide templates to help you 20 | describe the issue. 21 | 22 | The Taipy team will analyse and try to reproduce the bug to provide feedback. If confirmed, we will add a priority 23 | to the issue and add it in our backlog. Feel free to propose a pull request to fix it. 24 | 25 | ## Issue reporting, feedback, proposal, design or any other comment 26 | 27 | Any feedback or proposal is greatly appreciated! Do not hesitate to create an issue with the appropriate template on 28 | [GitHub](https://github.com/Avaiga/taipy/issues). 29 | 30 | The Taipy team will analyse your issue and return to you as soon as possible. 31 | 32 | ## Improve Documentation 33 | 34 | Do not hesitate to create an issue or pull request directly on the 35 | [taipy-doc repository](https://github.com/Avaiga/taipy-doc). 36 | 37 | ## Implement Features 38 | 39 | The Taipy team manages its backlog in private. Each issue that will be done during our current sprint is 40 | attached to the `current sprint`. Please, do not work on it, the Taipy team is on it. 41 | 42 | ## Coding style and best practices 43 | 44 | ### Python 45 | 46 | Taipy's repositories follow the [PEP 8](https://www.python.org/dev/peps/pep-0008/) and 47 | [PEP 484](https://www.python.org/dev/peps/pep-0484/) coding convention. 48 | 49 | ## TypeScript 50 | 51 | Taipy's repositories use the [ESLint](https://eslint.org/) and 52 | [TypeScript ESLint](https://github.com/typescript-eslint/typescript-eslint) plugin to ensure a common set of rules. 53 | 54 | ### Git branches 55 | 56 | All new development happens in the `develop` branch. All pull requests should target that branch. 57 | We are following a strict branch naming convention based on the pattern: `/#[IssueSummary]`. 58 | 59 | Where: 60 | 61 | - `` would be one of: 62 | - feature: new feature implementation, or improvement of a feature. 63 | - bug: bug fix. 64 | - review: change provoked by review comment not immediately taken care of. 65 | - refactor: refactor of a piece of code. 66 | - doc: doc changes (complement or typo fixes…). 67 | - build: in relation with the build process. 68 | - `` is the processed issue identifier. The advantage of explicitly indicating the issue number is that in 69 | GitHub, a pull request page shows a direct link to the issue description. 70 | - `[IssueSummary]` is a short summary of the issue topic, not including spaces, using Camel case or lower-case, 71 | dash-separated words. This summary, with its dash (‘-’) symbol prefix, is optional. 72 | 73 | 74 | ## Contribution workflow 75 | 76 | Find an issue without the label `current sprint` and add a comment on it to inform the community that you are 77 | working on it. 78 | 79 | 1. Make your [own fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) of the repository 80 | target by the issue. Clone it on our local machine, then go inside the directory. 81 | 82 | 2. We are working with [Pipenv](https://github.com/pypa/pipenv) for our virtualenv. 83 | Create a local env and install development package by running `pipenv install --dev`, then run tests with `pipenv 84 | run pytest` to verify your setup. 85 | 86 | 3. For convention help, we provide a [pre-commit](https://pre-commit.com/hooks.html) file. 87 | This tool will run before each commit and will automatically reformat code or raise warnings and errors based on the 88 | code format or Python typing. 89 | You can install and setup it up by doing: 90 | ``` 91 | pipenv install pre-commit 92 | pipenv run python -m pre-commit install 93 | ``` 94 | 95 | 4. Make the change and create a 96 | [pull request from your fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). 97 | Keep your pull request in __draft__ until your work is finished. 98 | Do not hesitate to add a comment for help or questions. 99 | Before you submit a pull request read to review from your forked repo, check that it meets these guidelines: 100 | - Include tests. 101 | - Code is [rebase](http://stackoverflow.com/a/7244456/1110993). 102 | - License is present. 103 | - pre-commit works - without mypy error. 104 | - GitHub's actions are passing. 105 | 106 | 6. The taipy team will have a look at your Pull Request and will give feedback. If every requirement is valid, your 107 | work will be added in the next release, congratulation! 108 | 109 | 110 | ## Dependency management 111 | 112 | Taipy comes with multiple optional packages. You can find the list directly in the product or Taipy's packages. 113 | The back-end Pipfile does not install by default optional packages due to `pyodbc` requiring a driver's manual 114 | installation. This is not the behaviour for the front-end that installs all optional packages through its Pipfile. 115 | 116 | If you are a contributor on Taipy, be careful with dependencies, do not forget to install or uninstall depending on 117 | your issue. 118 | 119 | If you need to add a new dependency to Taipy, do not forget to add it in the `Pipfile` and the `setup.py`. 120 | Keep in mind that dependency is a vector of attack. The Taipy team limits the usage of external dependencies at the 121 | minimum. 122 | -------------------------------------------------------------------------------- /docs/GETTING_STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Installation 4 | First you need to install the dependencies and build the front-end. Please refer to [INSTALLATION.md](INSTALLATION.md). 5 | 6 | 7 | ## How to use the demo 8 | 9 | Once you started the application, your default Web browser should open automatically. If not, open this URL: [http://127.0.0.1:9090](http://127.0.0.1:9090). 10 | The browser should ask you for the authorization to use the camera. Press "Allow". 11 |

12 | drawing 13 |

14 | 15 | 16 | Once allowed, your camera should activate and you will see a live view of the video. Notice that your face your already be detected and the label "None" is displayed. This is because the application does not know you yet. 17 | 18 |

19 | drawing 20 |

21 | 22 | To train the app to recognize your face, press the "Capture" button. This will show a dialog with a captured image. Enter a name for that face and press "validate". 23 | The more training examples, the better. So add few more captured images of your faces. 24 | 25 | Notice that the case of the given name is important. So always use the same name for captured image. 26 | Example: "Greg" and "greg" will be considered as two different names. 27 | 28 |

29 | drawing 30 |

31 | 32 | After say 6 different images, you can ask the system to learn from them by pressing the "Re-train" button. 33 | Depending on the number of images to process, this can take from a second to a dozen of seconds. 34 | 35 | The application will then be able to recognize the new face, and the name should be displayed on screen! 36 | 37 |

38 | drawing 39 |

40 | -------------------------------------------------------------------------------- /docs/INSTALLATION.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | This demo requires Python 3.9 or 3.10. Python 3.11 is currently not supported by Taipy. 4 | 5 | **Important Note**: To visualize images in Taipy, the package `python-magic` is required (and `python-magic-bin` on Windows). Please see the [python-magic](https://pypi.org/project/python-magic/) page for installation. 6 | 7 | 8 | To install this demo: 9 | 10 | ``` 11 | git clone git@github.com:Avaiga/demo-demo-face-recognition.git 12 | cd demo-face-recognition/src 13 | ``` 14 | 15 | To install the dependencies: 16 | ``` 17 | pip install -r requirements.txt 18 | ``` 19 | 20 | ## Building the Webam component 21 | 22 | - Clone the taipy-2-2 branch to build the front-end JavaScript, 23 | 24 | ``` 25 | pip install taipy==2.2 26 | pip install opencv-python-headless==4.7.0.72 27 | pip install opencv-contrib-python-headless==4.7.0.72 28 | pip install pillow 29 | ``` 30 | 31 | - Run this command: 32 | 33 | ``` 34 | cd demo-face-recognition/webcam/webui 35 | npm i 36 | ``` 37 | 38 | - Find the location of taipy-gui with the `find_taipy_gui_dir.py` script and run: 39 | 40 | ``` 41 | npm i 42 | ``` 43 | 44 | - Change `webpack.config.js` with taipy-gui path and run: 45 | 46 | ``` 47 | npm run build 48 | ``` 49 | 50 | 51 | Finally, to run the demo: 52 | ``` 53 | python main.py 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/app_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/docs/app_running.png -------------------------------------------------------------------------------- /docs/captured_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/docs/captured_image.png -------------------------------------------------------------------------------- /docs/face_recognized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/docs/face_recognized.png -------------------------------------------------------------------------------- /docs/first_startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/docs/first_startup.png -------------------------------------------------------------------------------- /find_taipy_gui_dir.py: -------------------------------------------------------------------------------- 1 | # This Python script tries to locate the taipy.gui package, and 2 | # prints its absolute path if it finds it. 3 | import importlib.util 4 | import os 5 | 6 | taipy_gui = importlib.util.find_spec("taipy.gui") 7 | if taipy_gui is None: 8 | print("Cannot find 'taipy.gui'\nPlease run 'pip install taipy-gui'.") 9 | else: 10 | print(f"Taipy GUI location: {os.path.dirname(taipy_gui.origin)}") 11 | -------------------------------------------------------------------------------- /src/classifiers/lbpcascade_frontalface_improved.xml: -------------------------------------------------------------------------------- 1 | 2 | 66 | 67 | 68 | 69 | BOOST 70 | LBP 71 | 45 72 | 45 73 | 74 | GAB 75 | 9.9500000476837158e-001 76 | 5.0000000000000000e-001 77 | 9.4999999999999996e-001 78 | 1 79 | 100 80 | 81 | 256 82 | 1 83 | 19 84 | 85 | 86 | <_> 87 | 6 88 | -4.1617846488952637e+000 89 | 90 | <_> 91 | 92 | 0 -1 26 -1 -1 -17409 -1 -1 -1 -1 -1 93 | 94 | -9.9726462364196777e-001 -3.8938775658607483e-001 95 | <_> 96 | 97 | 0 -1 18 -1 -1 -21569 -20545 -1 -1 -20545 -1 98 | 99 | -9.8648911714553833e-001 -2.5386649370193481e-001 100 | <_> 101 | 102 | 0 -1 30 -21569 -16449 1006578219 -20801 -16449 -1 -21585 -1 103 | 104 | -9.6436238288879395e-001 -1.4039695262908936e-001 105 | <_> 106 | 107 | 0 -1 54 -1 -1 -16402 -4370 -1 -1 -1053010 -4456466 108 | 109 | -8.4081345796585083e-001 3.8321062922477722e-001 110 | <_> 111 | 112 | 0 -1 29 -184747280 -705314819 1326353 1364574079 -131073 -5 113 | 2147481147 -1 114 | 115 | -8.1084597110748291e-001 4.3495711684226990e-001 116 | <_> 117 | 118 | 0 -1 89 -142618625 -4097 -37269 -20933 872350430 -268476417 119 | 1207894255 2139032115 120 | 121 | -7.3140043020248413e-001 4.3799084424972534e-001 122 | 123 | <_> 124 | 6 125 | -4.0652265548706055e+000 126 | 127 | <_> 128 | 129 | 0 -1 19 -1 -1 -17409 -1 -1 -1 -1 -1 130 | 131 | -9.9727255105972290e-001 -7.2050148248672485e-001 132 | <_> 133 | 134 | 0 -1 38 -1 1073741823 -1 -1 -1 -1 -1 -1 135 | 136 | -9.8717331886291504e-001 -5.3031939268112183e-001 137 | <_> 138 | 139 | 0 -1 28 -16385 -1 -21569 -20545 -1 -1 -21569 -1 140 | 141 | -9.3442338705062866e-001 6.5213099122047424e-002 142 | <_> 143 | 144 | 0 -1 112 -2097153 -1 -1 -1 -1 -8193 -1 -35467 145 | 146 | -7.9567342996597290e-001 4.2883640527725220e-001 147 | <_> 148 | 149 | 0 -1 48 -134239573 -16465 58663467 -1079022929 -1073758273 150 | -81937 -8412501 -404766817 151 | 152 | -7.1264797449111938e-001 4.1050794720649719e-001 153 | <_> 154 | 155 | 0 -1 66 -17047555 -1099008003 2147479551 -1090584581 -69633 156 | -1342177281 -1090650121 -1472692240 157 | 158 | -7.6119172573089600e-001 4.2042696475982666e-001 159 | 160 | <_> 161 | 7 162 | -4.6904473304748535e+000 163 | 164 | <_> 165 | 166 | 0 -1 12 -1 -1 -17409 -1 -1 -1 -1 -1 167 | 168 | -9.9725550413131714e-001 -8.3142280578613281e-001 169 | <_> 170 | 171 | 0 -1 31 -1 -168429569 -1 -1 -1 -1 -1 -1 172 | 173 | -9.8183268308639526e-001 -3.6373397707939148e-001 174 | <_> 175 | 176 | 0 -1 38 -1 1073741759 -1 -1 -1 -1 -1 -1 177 | 178 | -9.1890293359756470e-001 7.8322596848011017e-002 179 | <_> 180 | 181 | 0 -1 27 -17409 -2097153 -134372726 -21873 -65 -536870913 182 | -161109 -4215889 183 | 184 | -8.0752444267272949e-001 1.9565649330615997e-001 185 | <_> 186 | 187 | 0 -1 46 -469779457 -286371842 -33619971 -212993 -1 -41943049 188 | -134217731 -1346863620 189 | 190 | -6.9232726097106934e-001 3.8141927123069763e-001 191 | <_> 192 | 193 | 0 -1 125 -1896950780 -1964839052 -9 707723004 -34078727 194 | -1074266122 -536872969 -262145 195 | 196 | -8.1760478019714355e-001 3.4172961115837097e-001 197 | <_> 198 | 199 | 0 -1 80 -402657501 654311423 -419533278 -452984853 200 | 1979676215 -1208090625 -167772569 -524289 201 | 202 | -6.3433408737182617e-001 4.3154156208038330e-001 203 | 204 | <_> 205 | 8 206 | -4.2590322494506836e+000 207 | 208 | <_> 209 | 210 | 0 -1 42 -1 -655361 -1 -1 -1 -1 -1 -1 211 | 212 | -9.9715477228164673e-001 -8.6178696155548096e-001 213 | <_> 214 | 215 | 0 -1 40 -1 -705300491 -1 -1 -1 -1 -1 -1 216 | 217 | -9.8356908559799194e-001 -5.7423096895217896e-001 218 | <_> 219 | 220 | 0 -1 43 -65 872413111 -2049 -1 -1 -1 -1 -1 221 | 222 | -9.2525935173034668e-001 -1.3835857808589935e-001 223 | <_> 224 | 225 | 0 -1 111 -1 -5242881 -1 -524289 -4194305 -1 -1 -43148 226 | 227 | -7.8076487779617310e-001 1.8362471461296082e-001 228 | <_> 229 | 230 | 0 -1 25 -145227841 868203194 -1627394049 935050171 231 | 2147483647 1006600191 -268439637 1002437615 232 | 233 | -7.2554033994674683e-001 3.3393219113349915e-001 234 | <_> 235 | 236 | 0 -1 116 -214961408 50592514 -2128 1072162674 -1077940293 237 | -1084489966 -134219854 -1074790401 238 | 239 | -6.1547595262527466e-001 3.9214438199996948e-001 240 | <_> 241 | 242 | 0 -1 3 -294987948 -1124421633 -73729 -268435841 -33654928 243 | 2122317823 -268599297 -33554945 244 | 245 | -6.4863425493240356e-001 3.8784855604171753e-001 246 | <_> 247 | 248 | 0 -1 22 -525585 -26738821 -17895690 1123482236 1996455758 249 | -8519849 -252182980 -461898753 250 | 251 | -5.5464369058609009e-001 4.4275921583175659e-001 252 | 253 | <_> 254 | 8 255 | -4.0009465217590332e+000 256 | 257 | <_> 258 | 259 | 0 -1 82 -1 -1 -1 -1 -33685505 -1 -1 -1 260 | 261 | -9.9707120656967163e-001 -8.9196771383285522e-001 262 | <_> 263 | 264 | 0 -1 84 -1 -1 -1 -1 2147446783 -1 -1 -1 265 | 266 | -9.8670446872711182e-001 -7.5064390897750854e-001 267 | <_> 268 | 269 | 0 -1 79 -1 -1 -262145 -1 -252379137 -1 -1 -1 270 | 271 | -8.9446705579757690e-001 7.0268943905830383e-002 272 | <_> 273 | 274 | 0 -1 61 -1 -8201 -1 -2097153 -16777217 -513 -16777217 275 | -1162149889 276 | 277 | -7.2166109085083008e-001 2.9786801338195801e-001 278 | <_> 279 | 280 | 0 -1 30 -21569 -1069121 1006578211 -134238545 -16450 281 | -268599297 -21617 -14680097 282 | 283 | -6.2449234724044800e-001 3.8551881909370422e-001 284 | <_> 285 | 286 | 0 -1 75 -268701913 -1999962377 1995165474 -453316822 287 | 1744684853 -2063597697 -134226057 -50336769 288 | 289 | -5.5207914113998413e-001 4.2211884260177612e-001 290 | <_> 291 | 292 | 0 -1 21 -352321825 -526489 -420020626 -486605074 1155483470 293 | -110104705 -587840772 -25428801 294 | 295 | -5.3324747085571289e-001 4.4535955786705017e-001 296 | <_> 297 | 298 | 0 -1 103 70270772 2012790229 -16810020 -245764 -1208090635 299 | -753667 -1073741828 -1363662420 300 | 301 | -6.4402890205383301e-001 3.8995954394340515e-001 302 | 303 | <_> 304 | 8 305 | -4.6897511482238770e+000 306 | 307 | <_> 308 | 309 | 0 -1 97 -1 -1 -1 -1 -524289 -524289 -1 -1 310 | 311 | -9.9684870243072510e-001 -8.8232177495956421e-001 312 | <_> 313 | 314 | 0 -1 84 -1 -1 -1 -1 2147438591 -1 -1 -1 315 | 316 | -9.8677414655685425e-001 -7.8965580463409424e-001 317 | <_> 318 | 319 | 0 -1 113 -1 -1 -1 -1 -1048577 -262149 -1048577 -35339 320 | 321 | -9.2621946334838867e-001 -2.9984828829765320e-001 322 | <_> 323 | 324 | 0 -1 33 -2249 867434291 -32769 -33562753 -1 -1073758209 325 | -4165 -1 326 | 327 | -7.2429555654525757e-001 2.2348840534687042e-001 328 | <_> 329 | 330 | 0 -1 98 1659068671 -142606337 587132538 -67108993 577718271 331 | -294921 -134479873 -129 332 | 333 | -5.5495566129684448e-001 3.5419258475303650e-001 334 | <_> 335 | 336 | 0 -1 100 -268441813 788267007 -286265494 -486576145 -8920251 337 | 2138505075 -151652570 -2050 338 | 339 | -5.3362584114074707e-001 3.9479774236679077e-001 340 | <_> 341 | 342 | 0 -1 51 -1368387212 -537102978 -98305 -163843 1065109500 343 | -16777217 -67321939 -1141359619 344 | 345 | -5.6162708997726440e-001 3.8008108735084534e-001 346 | <_> 347 | 348 | 0 -1 127 -268435550 1781120906 -251658720 -143130698 349 | -1048605 -1887436825 1979700688 -1008730125 350 | 351 | -5.1167154312133789e-001 4.0678605437278748e-001 352 | 353 | <_> 354 | 10 355 | -4.2179841995239258e+000 356 | 357 | <_> 358 | 359 | 0 -1 97 -1 -1 -1 -1 -524289 -524289 -1 -1 360 | 361 | -9.9685418605804443e-001 -8.8037383556365967e-001 362 | <_> 363 | 364 | 0 -1 90 -1 -1 -1 -1 -8912897 -524297 -8912897 -1 365 | 366 | -9.7972750663757324e-001 -5.7626229524612427e-001 367 | <_> 368 | 369 | 0 -1 96 -1 -1 -1 -1 -1 -65 -1 -2249 370 | 371 | -9.0239793062210083e-001 -1.7454113066196442e-001 372 | <_> 373 | 374 | 0 -1 71 -1 -4097 -1 -513 -16777217 -268468483 -16797697 375 | -1430589697 376 | 377 | -7.4346423149108887e-001 9.4165161252021790e-002 378 | <_> 379 | 380 | 0 -1 37 1364588304 -581845274 -536936460 -3 -308936705 381 | -1074331649 -4196865 -134225953 382 | 383 | -6.8877440690994263e-001 2.7647304534912109e-001 384 | <_> 385 | 386 | 0 -1 117 -37765187 -540675 -3 -327753 -1082458115 -65537 387 | 1071611901 536827253 388 | 389 | -5.7555085420608521e-001 3.4339720010757446e-001 390 | <_> 391 | 392 | 0 -1 85 -269490650 -1561395522 -1343312090 -857083986 393 | -1073750223 -369098755 -50856110 -2065 394 | 395 | -5.4036927223205566e-001 4.0065473318099976e-001 396 | <_> 397 | 398 | 0 -1 4 -425668880 -34427164 1879048177 -269570140 790740912 399 | -196740 2138535839 -536918145 400 | 401 | -4.8439365625381470e-001 4.4630467891693115e-001 402 | <_> 403 | 404 | 0 -1 92 74726960 -1246482434 -1 -246017 -1078607916 405 | -1073947163 -1644231687 -1359211496 406 | 407 | -5.6686979532241821e-001 3.6671569943428040e-001 408 | <_> 409 | 410 | 0 -1 11 -135274809 -1158173459 -353176850 540195262 411 | 2139086600 2071977814 -546898600 -96272673 412 | 413 | -5.1499199867248535e-001 4.0788397192955017e-001 414 | 415 | <_> 416 | 9 417 | -4.0345416069030762e+000 418 | 419 | <_> 420 | 421 | 0 -1 78 -1 -1 -1 -1 -8912897 -1 -8912897 -1 422 | 423 | -9.9573624134063721e-001 -8.5452395677566528e-001 424 | <_> 425 | 426 | 0 -1 93 -1 -1 -1 -1 -148635649 -524297 -8912897 -1 427 | 428 | -9.7307401895523071e-001 -5.2884924411773682e-001 429 | <_> 430 | 431 | 0 -1 77 -1 -8209 -1 -257 -772734977 -1 -201850881 -1 432 | 433 | -8.6225658655166626e-001 4.3712578713893890e-002 434 | <_> 435 | 436 | 0 -1 68 -570427393 -16649 -69633 -131073 -536944677 -1 -8737 437 | -1435828225 438 | 439 | -6.8078064918518066e-001 2.5120577216148376e-001 440 | <_> 441 | 442 | 0 -1 50 -1179697 -34082849 -3278356 -37429266 -1048578 443 | -555753474 -1015551096 -37489685 444 | 445 | -6.1699724197387695e-001 3.0963841080665588e-001 446 | <_> 447 | 448 | 0 -1 129 -1931606992 -17548804 -16842753 -1075021827 449 | 1073667572 -81921 -1611073620 -1415047752 450 | 451 | -6.0499197244644165e-001 3.0735063552856445e-001 452 | <_> 453 | 454 | 0 -1 136 -269754813 1761591286 -1073811523 2130378623 -17580 455 | -1082294665 -159514800 -1026883840 456 | 457 | -5.6772041320800781e-001 3.5023149847984314e-001 458 | <_> 459 | 460 | 0 -1 65 2016561683 1528827871 -10258447 960184191 125476830 461 | -8511618 -1078239365 187648611 462 | 463 | -5.5894804000854492e-001 3.4856522083282471e-001 464 | <_> 465 | 466 | 0 -1 13 -207423502 -333902 2013200231 -202348848 1042454451 467 | -16393 1073117139 2004162321 468 | 469 | -5.7197356224060059e-001 3.2818377017974854e-001 470 | 471 | <_> 472 | 9 473 | -3.4892759323120117e+000 474 | 475 | <_> 476 | 477 | 0 -1 78 -1 -1 -1 -1 -8912897 -1 -8912897 -1 478 | 479 | -9.8917990922927856e-001 -7.3812037706375122e-001 480 | <_> 481 | 482 | 0 -1 93 -1 -1 -1 -1 -148635649 -524297 -8912897 -1 483 | 484 | -9.3414896726608276e-001 -2.6945295929908752e-001 485 | <_> 486 | 487 | 0 -1 83 -1 -524289 -1 -1048577 1879011071 -32769 -524289 488 | -3178753 489 | 490 | -7.6891708374023438e-001 5.2568886429071426e-002 491 | <_> 492 | 493 | 0 -1 9 -352329729 -17891329 -16810117 -486871042 -688128841 494 | -1358954675 -16777218 -219217968 495 | 496 | -6.2337344884872437e-001 2.5143685936927795e-001 497 | <_> 498 | 499 | 0 -1 130 -2157 -1548812374 -1343233440 -418381854 -953155613 500 | -836960513 -713571200 -709888014 501 | 502 | -4.7277018427848816e-001 3.9616456627845764e-001 503 | <_> 504 | 505 | 0 -1 121 -1094717701 -67240065 -65857 -32899 -5783756 506 | -136446081 -134285352 -2003298884 507 | 508 | -5.1766264438629150e-001 3.5814732313156128e-001 509 | <_> 510 | 511 | 0 -1 23 -218830160 -119671186 5505075 1241491391 -1594469 512 | -2097185 2004828075 -67649541 513 | 514 | -6.5394639968872070e-001 3.0377501249313354e-001 515 | <_> 516 | 517 | 0 -1 115 -551814749 2099511088 -1090732551 -2045546512 518 | -1086341441 1059848178 800042912 252705994 519 | 520 | -5.2584588527679443e-001 3.3847147226333618e-001 521 | <_> 522 | 523 | 0 -1 99 -272651477 578776766 -285233490 -889225217 524 | 2147448656 377454463 2012701952 -68157761 525 | 526 | -6.1836904287338257e-001 2.8922611474990845e-001 527 | 528 | <_> 529 | 9 530 | -3.0220029354095459e+000 531 | 532 | <_> 533 | 534 | 0 -1 36 -1 -570425345 -1 -570425345 -1 -50331649 -6291457 -1 535 | 536 | -9.7703826427459717e-001 -6.2527233362197876e-001 537 | <_> 538 | 539 | 0 -1 124 -1430602241 -33619969 -1 -3 -1074003969 -1073758209 540 | -1073741825 -1073768705 541 | 542 | -8.9538317918777466e-001 -3.1887885928153992e-001 543 | <_> 544 | 545 | 0 -1 88 -1 -268439625 -65601 -268439569 -393809 -270532609 546 | -42076889 -288361721 547 | 548 | -6.8733429908752441e-001 1.2978810071945190e-001 549 | <_> 550 | 551 | 0 -1 132 -755049252 2042563807 1795096575 465121071 552 | -1090585188 -20609 -1459691784 539672495 553 | 554 | -5.7038843631744385e-001 3.0220884084701538e-001 555 | <_> 556 | 557 | 0 -1 20 -94377762 -25702678 1694167798 -231224662 1079955016 558 | -346144140 2029995743 -536918961 559 | 560 | -5.3204691410064697e-001 3.4054222702980042e-001 561 | <_> 562 | 563 | 0 -1 47 2143026943 -285278225 -3 -612438281 -16403 -131074 564 | -1 -1430749256 565 | 566 | -4.6176829934120178e-001 4.1114711761474609e-001 567 | <_> 568 | 569 | 0 -1 74 203424336 -25378820 -35667973 1073360894 -1912815660 570 | -573444 -356583491 -1365235056 571 | 572 | -4.9911966919898987e-001 3.5335537791252136e-001 573 | <_> 574 | 575 | 0 -1 6 -1056773 -1508430 -558153 -102747408 2133997491 576 | -269043865 2004842231 -8947721 577 | 578 | -4.0219521522521973e-001 4.3947893381118774e-001 579 | <_> 580 | 581 | 0 -1 70 -880809694 -1070282769 -1363162108 -838881281 582 | -680395161 -2064124929 -34244753 1173880701 583 | 584 | -5.3891533613204956e-001 3.2062566280364990e-001 585 | 586 | <_> 587 | 8 588 | -2.5489892959594727e+000 589 | 590 | <_> 591 | 592 | 0 -1 39 -1 -572522497 -8519681 -570425345 -4195329 -50333249 593 | -1 -1 594 | 595 | -9.4647216796875000e-001 -3.3662387728691101e-001 596 | <_> 597 | 598 | 0 -1 124 -1430735362 -33619971 -8201 -3 -1677983745 599 | -1073762817 -1074003969 -1142979329 600 | 601 | -8.0300611257553101e-001 -3.8466516882181168e-002 602 | <_> 603 | 604 | 0 -1 91 -67113217 -524289 -671482265 -786461 1677132031 605 | -268473345 -68005889 -70291765 606 | 607 | -5.8367580175399780e-001 2.6507318019866943e-001 608 | <_> 609 | 610 | 0 -1 17 -277872641 -553910292 -268435458 -16843010 611 | 1542420439 -1342178311 -143132940 -2834 612 | 613 | -4.6897178888320923e-001 3.7864661216735840e-001 614 | <_> 615 | 616 | 0 -1 137 -1312789 -290527285 -286326862 -5505280 -1712335966 617 | -2045979188 1165423617 -709363723 618 | 619 | -4.6382644772529602e-001 3.6114525794982910e-001 620 | <_> 621 | 622 | 0 -1 106 1355856590 -109445156 -96665606 2066939898 623 | 1356084692 1549031917 -30146561 -16581701 624 | 625 | -6.3095021247863770e-001 2.9294869303703308e-001 626 | <_> 627 | 628 | 0 -1 104 -335555328 118529 1860167712 -810680357 -33558656 629 | -1368391795 -402663552 -1343225921 630 | 631 | -5.9658926725387573e-001 2.7228885889053345e-001 632 | <_> 633 | 634 | 0 -1 76 217581168 -538349634 1062631419 1039868926 635 | -1090707460 -2228359 -1078042693 -1147128518 636 | 637 | -4.5812287926673889e-001 3.7063929438591003e-001 638 | 639 | <_> 640 | 9 641 | -2.5802578926086426e+000 642 | 643 | <_> 644 | 645 | 0 -1 35 -513 -706873891 -270541825 1564475391 -120602625 646 | -118490145 -3162113 -1025 647 | 648 | -8.9068460464477539e-001 -1.6470588743686676e-001 649 | <_> 650 | 651 | 0 -1 41 -1025 872144563 -2105361 -1078076417 -1048577 652 | -1145061461 -87557413 -1375993973 653 | 654 | -7.1808964014053345e-001 2.2022204473614693e-002 655 | <_> 656 | 657 | 0 -1 95 -42467849 967946223 -811601986 1030598351 658 | -1212430676 270856533 -1392539508 147705039 659 | 660 | -4.9424821138381958e-001 3.0048963427543640e-001 661 | <_> 662 | 663 | 0 -1 10 -218116370 -637284625 -87373174 -521998782 664 | -805355450 -615023745 -814267322 -12069282 665 | 666 | -5.5306458473205566e-001 2.9137542843818665e-001 667 | <_> 668 | 669 | 0 -1 105 -275849241 -527897 -11052049 -69756067 -15794193 670 | -1141376839 -564771 -287095455 671 | 672 | -4.6759819984436035e-001 3.6638516187667847e-001 673 | <_> 674 | 675 | 0 -1 24 -1900898096 -18985228 -44056577 -24675 -1074880639 676 | -283998 796335613 -1079041957 677 | 678 | -4.2737138271331787e-001 3.9243003726005554e-001 679 | <_> 680 | 681 | 0 -1 139 -555790844 410735094 -32106513 406822863 -897632192 682 | -912830145 -117771560 -1204027649 683 | 684 | -4.1896930336952209e-001 3.6744937300682068e-001 685 | <_> 686 | 687 | 0 -1 0 -1884822366 -1406613148 1135342180 -1979127580 688 | -68174862 246469804 1001386992 -708885872 689 | 690 | -5.7093089818954468e-001 2.9880744218826294e-001 691 | <_> 692 | 693 | 0 -1 45 -469053950 1439068142 2117758841 2004671078 694 | 207931006 1265321675 970353931 1541343047 695 | 696 | -6.0491901636123657e-001 2.4652053415775299e-001 697 | 698 | <_> 699 | 9 700 | -2.2425732612609863e+000 701 | 702 | <_> 703 | 704 | 0 -1 58 1481987157 282547485 -14952129 421131223 -391065352 705 | -24212488 -100094241 -1157907473 706 | 707 | -8.2822084426879883e-001 -2.1619293093681335e-001 708 | <_> 709 | 710 | 0 -1 126 -134217889 -543174305 -75497474 -16851650 -6685738 711 | -75834693 -2097200 -262146 712 | 713 | -5.4628932476043701e-001 2.7662658691406250e-001 714 | <_> 715 | 716 | 0 -1 133 -220728227 -604288517 -661662214 413104863 717 | -627323700 -251915415 -626200872 -1157958657 718 | 719 | -4.1643124818801880e-001 4.1700571775436401e-001 720 | <_> 721 | 722 | 0 -1 2 -186664033 -44236961 -1630262774 -65163606 -103237330 723 | -3083265 -1003729 2053105955 724 | 725 | -5.4847818613052368e-001 2.9710745811462402e-001 726 | <_> 727 | 728 | 0 -1 62 -256115886 -237611873 -620250696 387061799 729 | 1437882671 274878849 -8684449 1494294023 730 | 731 | -4.6202757954597473e-001 3.3915829658508301e-001 732 | <_> 733 | 734 | 0 -1 1 -309400577 -275864640 -1056864869 1737132756 735 | -272385089 1609671419 1740601343 1261376789 736 | 737 | -4.6158722043037415e-001 3.3939516544342041e-001 738 | <_> 739 | 740 | 0 -1 102 818197248 -196324552 286970589 -573270699 741 | -1174099579 -662077381 -1165157895 -1626859296 742 | 743 | -4.6193107962608337e-001 3.2456985116004944e-001 744 | <_> 745 | 746 | 0 -1 69 -1042550357 14675409 1367955200 -841482753 747 | 1642443255 8774277 1941304147 1099949563 748 | 749 | -4.9091196060180664e-001 3.3870378136634827e-001 750 | <_> 751 | 752 | 0 -1 72 -639654997 1375720439 -2129542805 1614801090 753 | -626787937 -5779294 1488699183 -525406458 754 | 755 | -4.9073097109794617e-001 3.0637946724891663e-001 756 | 757 | <_> 758 | 9 759 | -1.2258235216140747e+000 760 | 761 | <_> 762 | 763 | 0 -1 118 302046707 -16744240 1360106207 -543735387 764 | 1025700851 -1079408512 1796961263 -6334981 765 | 766 | -6.1358314752578735e-001 2.3539231717586517e-001 767 | <_> 768 | 769 | 0 -1 5 -144765953 -116448726 -653851877 1934829856 722021887 770 | 856564834 1933919231 -540838029 771 | 772 | -5.1209545135498047e-001 3.2506987452507019e-001 773 | <_> 774 | 775 | 0 -1 140 -170132825 -1438923874 1879300370 -1689337194 776 | -695606496 285911565 -1044188928 -154210028 777 | 778 | -5.1769560575485229e-001 3.2290914654731750e-001 779 | <_> 780 | 781 | 0 -1 131 -140776261 -355516414 822178224 -1039743806 782 | -1012208926 134887424 1438876097 -908591660 783 | 784 | -5.0321841239929199e-001 3.0263835191726685e-001 785 | <_> 786 | 787 | 0 -1 64 -2137211696 -1634281249 1464325973 498569935 788 | -1580152080 -2001687927 721783561 265096035 789 | 790 | -4.6532225608825684e-001 3.4638473391532898e-001 791 | <_> 792 | 793 | 0 -1 101 -255073589 -211824417 -972195129 -1063415417 794 | 1937994261 1363165220 -754733105 1967602541 795 | 796 | -4.9611270427703857e-001 3.3260712027549744e-001 797 | <_> 798 | 799 | 0 -1 81 -548146862 -655567194 -2062466596 1164562721 800 | 416408236 -1591631712 -83637777 975344427 801 | 802 | -4.9862930178642273e-001 3.2003280520439148e-001 803 | <_> 804 | 805 | 0 -1 55 -731904652 2147179896 2147442687 2112830847 -65604 806 | -131073 -42139667 -1074907393 807 | 808 | -3.6636069416999817e-001 4.5651626586914063e-001 809 | <_> 810 | 811 | 0 -1 67 1885036886 571985932 -1784930633 724431327 812 | 1940422257 -1085746880 964888398 731867951 813 | 814 | -5.2619713544845581e-001 3.2635414600372314e-001 815 | 816 | <_> 817 | 9 818 | -1.3604533672332764e+000 819 | 820 | <_> 821 | 822 | 0 -1 8 -287609985 -965585953 -2146397793 -492129894 823 | -729029645 -544619901 -645693256 -6565484 824 | 825 | -4.5212322473526001e-001 3.8910505175590515e-001 826 | <_> 827 | 828 | 0 -1 122 -102903523 -145031013 536899675 688195859 829 | -645291520 -1165359094 -905565928 171608223 830 | 831 | -4.9594074487686157e-001 3.4109055995941162e-001 832 | <_> 833 | 834 | 0 -1 134 -790640459 487931983 1778450522 1036604041 835 | -904752984 -954040118 -2134707506 304866043 836 | 837 | -4.1148442029953003e-001 3.9666590094566345e-001 838 | <_> 839 | 840 | 0 -1 141 -303829117 1726939070 922189815 -827983123 841 | 1567883042 1324809852 292710260 -942678754 842 | 843 | -3.5154473781585693e-001 4.8011952638626099e-001 844 | <_> 845 | 846 | 0 -1 59 -161295376 -159215460 -1858041315 2140644499 847 | -2009065472 -133804007 -2003265301 1263206851 848 | 849 | -4.2808216810226440e-001 3.9841541647911072e-001 850 | <_> 851 | 852 | 0 -1 34 -264248081 -667846464 1342624856 1381160835 853 | -2104716852 1342865409 -266612310 -165954877 854 | 855 | -4.3293288350105286e-001 4.0339657664299011e-001 856 | <_> 857 | 858 | 0 -1 32 -1600388464 -40369901 285344639 1394344275 859 | -255680312 -100532214 -1031663944 -7471079 860 | 861 | -4.1385015845298767e-001 4.5087572932243347e-001 862 | <_> 863 | 864 | 0 -1 15 1368521651 280207469 35779199 -105983261 1208124819 865 | -565870452 -1144024288 -591535344 866 | 867 | -4.2956474423408508e-001 4.2176279425621033e-001 868 | <_> 869 | 870 | 0 -1 109 1623607527 -661513115 -1073217263 -2142994420 871 | -1339883309 -89816956 436308899 1426178059 872 | 873 | -4.7764992713928223e-001 3.7551075220108032e-001 874 | 875 | <_> 876 | 9 877 | -4.2518746852874756e-001 878 | 879 | <_> 880 | 881 | 0 -1 135 -116728032 -1154420809 -1350582273 746061691 882 | -1073758277 2138570623 2113797566 -138674182 883 | 884 | -1.7125381529331207e-001 6.5421247482299805e-001 885 | <_> 886 | 887 | 0 -1 63 -453112432 -1795354691 -1342242964 494112553 888 | 209458404 -2114697500 1316830362 259213855 889 | 890 | -3.9870172739028931e-001 4.5807033777236938e-001 891 | <_> 892 | 893 | 0 -1 52 -268172036 294715533 268575185 486785157 -1065303920 894 | -360185856 -2147476808 134777113 895 | 896 | -5.3581339120864868e-001 3.5815808176994324e-001 897 | <_> 898 | 899 | 0 -1 86 -301996882 -345718921 1877946252 -940720129 900 | -58737369 -721944585 -92954835 -530449 901 | 902 | -3.9938014745712280e-001 4.9603295326232910e-001 903 | <_> 904 | 905 | 0 -1 14 -853281886 -756895766 2130706352 -9519120 906 | -1921059862 394133373 2138453959 -538200841 907 | 908 | -4.0230083465576172e-001 4.9537116289138794e-001 909 | <_> 910 | 911 | 0 -1 128 -2133448688 -641138493 1078022185 294060066 912 | -327122776 -2130640896 -2147466247 -1910634326 913 | 914 | -5.8290809392929077e-001 3.4102553129196167e-001 915 | <_> 916 | 917 | 0 -1 53 587265978 -2071658479 1108361221 -578448765 918 | -1811905899 -2008965119 33900729 762301595 919 | 920 | -4.5518967509269714e-001 4.7242793440818787e-001 921 | <_> 922 | 923 | 0 -1 138 -1022189373 -2139094976 16658 -1069445120 924 | -1073555454 -1073577856 1096068 -978351488 925 | 926 | -4.7530207037925720e-001 4.3885371088981628e-001 927 | <_> 928 | 929 | 0 -1 7 -395352441 -1073541103 -1056964605 1053186 269111298 930 | -2012184576 1611208714 -360415095 931 | 932 | -5.0448113679885864e-001 4.1588482260704041e-001 933 | 934 | <_> 935 | 7 936 | 2.7163455262780190e-002 937 | 938 | <_> 939 | 940 | 0 -1 49 783189748 -137429026 -257 709557994 2130460236 941 | -196611 -9580 585428708 942 | 943 | -2.0454545319080353e-001 7.9608374834060669e-001 944 | <_> 945 | 946 | 0 -1 108 1284360448 1057423155 1592696573 -852672655 947 | 1547382714 -1642594369 125705358 797134398 948 | 949 | -3.6474677920341492e-001 6.0925579071044922e-001 950 | <_> 951 | 952 | 0 -1 94 1347680270 -527720448 1091567712 1073745933 953 | -1073180671 0 285745154 -511192438 954 | 955 | -4.6406838297843933e-001 5.5626088380813599e-001 956 | <_> 957 | 958 | 0 -1 73 1705780944 -145486260 -115909 -281793505 -418072663 959 | -1681064068 1877454127 -1912330993 960 | 961 | -4.7043186426162720e-001 5.8430361747741699e-001 962 | <_> 963 | 964 | 0 -1 110 -2118142016 339509033 -285260567 1417764573 965 | 68144392 -468879483 -2033291636 231451911 966 | 967 | -4.8700931668281555e-001 5.4639810323715210e-001 968 | <_> 969 | 970 | 0 -1 119 -1888051818 489996135 -65539 849536890 2146716845 971 | -1107542088 -1275615746 -1119617586 972 | 973 | -4.3356490135192871e-001 6.5175366401672363e-001 974 | <_> 975 | 976 | 0 -1 44 -1879021438 336830528 1073766659 1477541961 8560696 977 | -1207369568 8462472 1493893448 978 | 979 | -5.4343086481094360e-001 5.2777874469757080e-001 980 | 981 | <_> 982 | 7 983 | 4.9174150824546814e-001 984 | 985 | <_> 986 | 987 | 0 -1 57 644098 15758324 1995964260 -463011882 893285175 988 | 83156983 2004317989 16021237 989 | 990 | -1.7073170840740204e-001 9.0782123804092407e-001 991 | <_> 992 | 993 | 0 -1 123 268632845 -2147450864 -2143240192 -2147401728 994 | 8523937 -1878523840 16777416 616824984 995 | 996 | -4.8744434118270874e-001 7.3311311006546021e-001 997 | <_> 998 | 999 | 0 -1 120 -2110735872 803880886 989739810 1673281312 91564930 1000 | -277454958 997709514 -581366443 1001 | 1002 | -4.0291741490364075e-001 8.2450771331787109e-001 1003 | <_> 1004 | 1005 | 0 -1 87 941753434 -1067128905 788512753 -1074450460 1006 | 779101657 -1346552460 938805167 -2050424642 1007 | 1008 | -3.6246949434280396e-001 8.7103593349456787e-001 1009 | <_> 1010 | 1011 | 0 -1 60 208 1645217920 130 538263552 33595552 -1475870592 1012 | 16783361 1375993867 1013 | 1014 | -6.1472141742706299e-001 5.9707164764404297e-001 1015 | <_> 1016 | 1017 | 0 -1 114 1860423179 1034692624 -285213187 -986681712 1018 | 1576755092 -1408205463 -127714 -1246035687 1019 | 1020 | -4.5621752738952637e-001 8.9482426643371582e-001 1021 | <_> 1022 | 1023 | 0 -1 107 33555004 -1861746688 1073807361 -754909184 1024 | 645922856 8388608 134250648 419635458 1025 | 1026 | -5.2466005086898804e-001 7.1834069490432739e-001 1027 | 1028 | <_> 1029 | 2 1030 | 1.9084988832473755e+000 1031 | 1032 | <_> 1033 | 1034 | 0 -1 16 536064 131072 -20971516 524288 576 1048577 0 40960 1035 | 1036 | -8.0000001192092896e-001 9.8018401861190796e-001 1037 | <_> 1038 | 1039 | 0 -1 56 67108864 0 4096 1074003968 8192 536870912 4 262144 1040 | 1041 | -9.6610915660858154e-001 9.2831486463546753e-001 1042 | 1043 | <_> 1044 | 1045 | 0 0 1 1 1046 | <_> 1047 | 1048 | 0 0 3 2 1049 | <_> 1050 | 1051 | 0 1 13 6 1052 | <_> 1053 | 1054 | 0 2 3 14 1055 | <_> 1056 | 1057 | 0 2 4 2 1058 | <_> 1059 | 1060 | 0 6 2 3 1061 | <_> 1062 | 1063 | 0 6 3 2 1064 | <_> 1065 | 1066 | 0 16 1 3 1067 | <_> 1068 | 1069 | 0 20 3 3 1070 | <_> 1071 | 1072 | 0 22 2 3 1073 | <_> 1074 | 1075 | 0 28 4 4 1076 | <_> 1077 | 1078 | 0 35 2 3 1079 | <_> 1080 | 1081 | 1 0 14 7 1082 | <_> 1083 | 1084 | 1 5 3 2 1085 | <_> 1086 | 1087 | 1 6 2 1 1088 | <_> 1089 | 1090 | 1 14 10 9 1091 | <_> 1092 | 1093 | 1 21 4 4 1094 | <_> 1095 | 1096 | 1 23 4 2 1097 | <_> 1098 | 1099 | 2 0 13 7 1100 | <_> 1101 | 1102 | 2 0 14 7 1103 | <_> 1104 | 1105 | 2 33 5 4 1106 | <_> 1107 | 1108 | 2 36 4 3 1109 | <_> 1110 | 1111 | 2 39 3 2 1112 | <_> 1113 | 1114 | 3 1 13 11 1115 | <_> 1116 | 1117 | 3 2 3 2 1118 | <_> 1119 | 1120 | 4 0 7 8 1121 | <_> 1122 | 1123 | 4 0 13 7 1124 | <_> 1125 | 1126 | 5 0 12 6 1127 | <_> 1128 | 1129 | 5 0 13 7 1130 | <_> 1131 | 1132 | 5 1 10 13 1133 | <_> 1134 | 1135 | 5 1 12 7 1136 | <_> 1137 | 1138 | 5 2 7 13 1139 | <_> 1140 | 1141 | 5 4 2 1 1142 | <_> 1143 | 1144 | 5 8 7 4 1145 | <_> 1146 | 1147 | 5 39 3 2 1148 | <_> 1149 | 1150 | 6 3 5 2 1151 | <_> 1152 | 1153 | 6 3 6 2 1154 | <_> 1155 | 1156 | 6 5 4 12 1157 | <_> 1158 | 1159 | 6 9 6 3 1160 | <_> 1161 | 1162 | 7 3 5 2 1163 | <_> 1164 | 1165 | 7 3 6 13 1166 | <_> 1167 | 1168 | 7 5 6 4 1169 | <_> 1170 | 1171 | 7 7 6 10 1172 | <_> 1173 | 1174 | 7 8 6 4 1175 | <_> 1176 | 1177 | 7 32 5 4 1178 | <_> 1179 | 1180 | 7 33 5 4 1181 | <_> 1182 | 1183 | 8 0 1 1 1184 | <_> 1185 | 1186 | 8 0 2 1 1187 | <_> 1188 | 1189 | 8 2 10 7 1190 | <_> 1191 | 1192 | 9 0 6 2 1193 | <_> 1194 | 1195 | 9 2 9 3 1196 | <_> 1197 | 1198 | 9 4 1 1 1199 | <_> 1200 | 1201 | 9 6 2 1 1202 | <_> 1203 | 1204 | 9 28 6 4 1205 | <_> 1206 | 1207 | 10 0 9 3 1208 | <_> 1209 | 1210 | 10 3 1 1 1211 | <_> 1212 | 1213 | 10 10 11 11 1214 | <_> 1215 | 1216 | 10 15 4 3 1217 | <_> 1218 | 1219 | 11 4 2 1 1220 | <_> 1221 | 1222 | 11 27 4 3 1223 | <_> 1224 | 1225 | 11 36 8 2 1226 | <_> 1227 | 1228 | 12 0 2 2 1229 | <_> 1230 | 1231 | 12 23 4 3 1232 | <_> 1233 | 1234 | 12 25 4 3 1235 | <_> 1236 | 1237 | 12 29 5 3 1238 | <_> 1239 | 1240 | 12 33 3 4 1241 | <_> 1242 | 1243 | 13 0 2 2 1244 | <_> 1245 | 1246 | 13 36 8 3 1247 | <_> 1248 | 1249 | 14 0 2 2 1250 | <_> 1251 | 1252 | 15 15 2 2 1253 | <_> 1254 | 1255 | 16 13 3 4 1256 | <_> 1257 | 1258 | 17 0 1 3 1259 | <_> 1260 | 1261 | 17 1 3 3 1262 | <_> 1263 | 1264 | 17 31 5 3 1265 | <_> 1266 | 1267 | 17 35 3 1 1268 | <_> 1269 | 1270 | 18 13 2 3 1271 | <_> 1272 | 1273 | 18 39 2 1 1274 | <_> 1275 | 1276 | 19 0 7 15 1277 | <_> 1278 | 1279 | 19 2 7 2 1280 | <_> 1281 | 1282 | 19 3 7 13 1283 | <_> 1284 | 1285 | 19 14 2 2 1286 | <_> 1287 | 1288 | 19 24 7 4 1289 | <_> 1290 | 1291 | 20 1 6 13 1292 | <_> 1293 | 1294 | 20 8 7 3 1295 | <_> 1296 | 1297 | 20 9 7 3 1298 | <_> 1299 | 1300 | 20 13 1 1 1301 | <_> 1302 | 1303 | 20 14 2 3 1304 | <_> 1305 | 1306 | 20 30 3 2 1307 | <_> 1308 | 1309 | 21 0 3 4 1310 | <_> 1311 | 1312 | 21 0 6 8 1313 | <_> 1314 | 1315 | 21 3 6 2 1316 | <_> 1317 | 1318 | 21 6 6 4 1319 | <_> 1320 | 1321 | 21 37 2 1 1322 | <_> 1323 | 1324 | 22 3 6 2 1325 | <_> 1326 | 1327 | 22 13 1 2 1328 | <_> 1329 | 1330 | 22 22 4 3 1331 | <_> 1332 | 1333 | 23 0 2 3 1334 | <_> 1335 | 1336 | 23 3 6 2 1337 | <_> 1338 | 1339 | 23 9 5 4 1340 | <_> 1341 | 1342 | 23 11 1 1 1343 | <_> 1344 | 1345 | 23 15 1 1 1346 | <_> 1347 | 1348 | 23 16 3 2 1349 | <_> 1350 | 1351 | 23 35 2 1 1352 | <_> 1353 | 1354 | 23 36 1 1 1355 | <_> 1356 | 1357 | 23 39 6 2 1358 | <_> 1359 | 1360 | 24 0 2 3 1361 | <_> 1362 | 1363 | 24 8 6 11 1364 | <_> 1365 | 1366 | 24 28 2 2 1367 | <_> 1368 | 1369 | 24 33 4 4 1370 | <_> 1371 | 1372 | 25 16 4 3 1373 | <_> 1374 | 1375 | 25 31 5 3 1376 | <_> 1377 | 1378 | 26 0 1 2 1379 | <_> 1380 | 1381 | 26 0 2 2 1382 | <_> 1383 | 1384 | 26 0 3 2 1385 | <_> 1386 | 1387 | 26 24 4 4 1388 | <_> 1389 | 1390 | 27 30 4 5 1391 | <_> 1392 | 1393 | 27 36 5 3 1394 | <_> 1395 | 1396 | 28 0 2 2 1397 | <_> 1398 | 1399 | 28 4 2 1 1400 | <_> 1401 | 1402 | 28 21 2 5 1403 | <_> 1404 | 1405 | 29 8 2 1 1406 | <_> 1407 | 1408 | 33 0 2 1 1409 | <_> 1410 | 1411 | 33 0 4 2 1412 | <_> 1413 | 1414 | 33 0 4 6 1415 | <_> 1416 | 1417 | 33 3 1 1 1418 | <_> 1419 | 1420 | 33 6 4 12 1421 | <_> 1422 | 1423 | 33 21 4 2 1424 | <_> 1425 | 1426 | 33 36 4 3 1427 | <_> 1428 | 1429 | 35 1 2 2 1430 | <_> 1431 | 1432 | 36 5 1 1 1433 | <_> 1434 | 1435 | 36 29 3 4 1436 | <_> 1437 | 1438 | 36 39 2 2 1439 | <_> 1440 | 1441 | 37 5 2 2 1442 | <_> 1443 | 1444 | 38 6 2 1 1445 | <_> 1446 | 1447 | 38 6 2 2 1448 | <_> 1449 | 1450 | 39 1 2 12 1451 | <_> 1452 | 1453 | 39 24 1 2 1454 | <_> 1455 | 1456 | 39 36 2 2 1457 | <_> 1458 | 1459 | 40 39 1 2 1460 | <_> 1461 | 1462 | 42 4 1 1 1463 | <_> 1464 | 1465 | 42 20 1 2 1466 | <_> 1467 | 1468 | 42 29 1 2 1469 | 1470 | -------------------------------------------------------------------------------- /src/demo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/src/demo/__init__.py -------------------------------------------------------------------------------- /src/demo/faces.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from pathlib import Path 3 | import os 4 | import numpy as np 5 | import logging 6 | from .image import crop_image 7 | import pandas as pd 8 | 9 | logging.basicConfig(level=logging.DEBUG) 10 | 11 | # Create our face detector. Both HAAR and LBP classifiers are somehow equivelent and both give good results. 12 | # Up to you to choose one or the other. 13 | face_detector = cv2.CascadeClassifier("classifiers/haarcascade_frontalface_default.xml") 14 | # face_cascade = cv2.CascadeClassifier("classifiers/lbpcascade_frontalface_improved.xml") 15 | 16 | # Create our face recognizer 17 | face_recognizer = cv2.face.LBPHFaceRecognizer_create() 18 | 19 | # The subjects that can be recognized 20 | subjects = {} 21 | 22 | FACE_DETECTOR_SCALE_FACTOR = 1.1 23 | FACE_DETECTOR_MIN_NEIGHBORS = 5 24 | 25 | 26 | def detect_faces(image): 27 | gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 28 | detected_faces = face_detector.detectMultiScale( 29 | gray_image, 30 | scaleFactor=FACE_DETECTOR_SCALE_FACTOR, 31 | minNeighbors=FACE_DETECTOR_MIN_NEIGHBORS, 32 | ) 33 | if len(detected_faces) == 0: 34 | return [] 35 | 36 | return [(rect, crop_image(image, rect)) for rect in detected_faces] 37 | 38 | 39 | def recognize_face(image): 40 | gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 41 | if len(subjects) == 0: 42 | # No subject, the model hasn't been trained, let's do nothing. 43 | return (None, None) 44 | try: 45 | face = face_recognizer.predict(gray_image) 46 | except Exception: 47 | logging.warning("Could not run face recognizer", exc_info=True) 48 | # Return the name of the recognize subject and the confident level 49 | return (subjects[face[0]], face[1]) 50 | 51 | 52 | def train_face_recognizer(training_data_directory="images"): 53 | data_file_path = Path(training_data_directory, "data.csv") 54 | if not data_file_path.exists(): 55 | # Create file 56 | with data_file_path.open("w") as f: 57 | f.write("image,label\n") 58 | 59 | # Load file as CSV file 60 | data = pd.read_csv(data_file_path, delimiter=",", header=0).to_numpy() 61 | 62 | # Subjects that can be recognized from these data: 63 | identified_subjects = np.unique(data[:, 1]) 64 | global subjects 65 | 66 | if len(identified_subjects) == 0: 67 | # No subject... We stop here 68 | subjects = {} 69 | return 70 | else: 71 | # Update subjects (persons who can be recognized) 72 | subjects = {e[0]: e[1] for e in enumerate(identified_subjects)} 73 | 74 | # Prepare training data 75 | faces, labels = [], [] 76 | for row in data: 77 | file_name = row[0] 78 | label = np.where(identified_subjects == row[1])[0][0] 79 | file_path = Path(training_data_directory, file_name) 80 | if os.path.exists(file_path): 81 | img = cv2.imread(str(file_path), cv2.IMREAD_GRAYSCALE) 82 | faces.append(img) 83 | labels.append(label) 84 | 85 | # Run training! 86 | logging.debug(f"Run training for {subjects}...") 87 | face_recognizer.train(faces, np.array(labels)) 88 | -------------------------------------------------------------------------------- /src/demo/image.py: -------------------------------------------------------------------------------- 1 | def crop_image(img, rect): 2 | """An utility function to crop an image to the given rect""" 3 | x, y, w, h = rect 4 | return img[y : y + h, x : x + w] 5 | -------------------------------------------------------------------------------- /src/main.css: -------------------------------------------------------------------------------- 1 | .face_detector>canvas { 2 | width: 800px; 3 | height: 600px; 4 | } -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from taipy.gui import Gui, notify 2 | from webcam import Webcam 3 | import cv2 4 | 5 | import PIL.Image 6 | import io 7 | 8 | import logging 9 | import uuid 10 | from pathlib import Path 11 | from demo.faces import detect_faces, recognize_face, train_face_recognizer 12 | 13 | logging.basicConfig(level=logging.DEBUG) 14 | 15 | training_data_folder = Path("images") 16 | 17 | 18 | def on_action_captured_image(state, id, payload): 19 | print("Captured image") 20 | choice = payload["args"][0] 21 | if choice == 0: 22 | notify(state, "i", "Adding image to database...") 23 | # Add image to training data: 24 | img = state.captured_image 25 | file_name = str(uuid.uuid4()) + ".jpg" 26 | label = state.captured_label 27 | image_path = Path(training_data_folder, file_name) 28 | with image_path.open("wb") as f: 29 | f.write(img) 30 | label_file_path = Path(training_data_folder, "data.csv") 31 | with label_file_path.open("a") as f: 32 | f.write(f"{file_name},{label}\n") 33 | notify(state, "s", "Image added to database") 34 | 35 | state.captured_image = None 36 | state.captured_label = "" 37 | state.show_capture_dialog = False 38 | 39 | 40 | def process_image(state, frame): 41 | print("Processing image...") 42 | found = detect_faces(frame) 43 | 44 | labeled_images = [] 45 | for rect, img in found: 46 | (label, _) = recognize_face(img) 47 | labeled_images.append((img, rect, label)) 48 | 49 | # Return this to the UI component so that it can display a rect around recognized faces: 50 | state.labeled_faces = [str([*rect, label]) for (_, rect, label) in labeled_images] 51 | 52 | # Capture image (actually we consider only the first detected face) 53 | if state.capture_image and len(labeled_images) > 0: 54 | notify(state, "i", "Capturing image...") 55 | img = labeled_images[0][0] 56 | label = labeled_images[0][2] 57 | state.captured_image = cv2.imencode(".jpg", img)[1].tobytes() 58 | state.captured_label = label 59 | state.show_capture_dialog = True 60 | state.capture_image = False 61 | 62 | 63 | def handle_image(state, action, args): 64 | print("Handling image...") 65 | payload = args["args"][0] 66 | bytes = payload["data"] 67 | logging.debug(f"Received data: {len(bytes)}") 68 | 69 | temp_path = "temp.png" 70 | 71 | # Write Data into temp file (OpenCV is unable to load from memory) 72 | image = PIL.Image.open(io.BytesIO(bytes)) 73 | image.save(temp_path) 74 | # Load image file 75 | try: 76 | img = cv2.imread(temp_path, cv2.IMREAD_UNCHANGED) 77 | except cv2.error as e: 78 | logging.error(f"Failed to read image file: {e}") 79 | notify(state, "e", f"Failed to read image file: {e}") 80 | return 81 | process_image(state, img) 82 | # Finish. Tempfile is removed. 83 | 84 | 85 | def button_retrain_clicked(state): 86 | print("Retraining...") 87 | notify(state, "i", "Retraining...") 88 | train_face_recognizer(training_data_folder) 89 | notify(state, "s", "Retrained!") 90 | 91 | 92 | if __name__ == "__main__": 93 | show_capture_dialog = False 94 | capture_image = False 95 | show_add_captured_images_dialog = False 96 | 97 | labeled_faces = [] # Contains rect with label (for UI component) 98 | 99 | captured_image = None 100 | captured_label = "" 101 | 102 | webcam_md = """<|toggle|theme|> 103 | 104 | 117 | 118 | 123 | 124 | <|Capture|button|on_action={lambda s: s.assign("capture_image", True)}|> 125 | <|RE-train|button|on_action=button_retrain_clicked|> 126 | > 127 | |card> 128 | |container> 129 | 130 | 131 | <|{show_capture_dialog}|dialog|labels=Validate;Cancel|on_action=on_action_captured_image|title=Add new training image| 132 | <|{captured_image}|image|width=300px|height=300px|> 133 | 134 | <|{captured_label}|input|> 135 | |> 136 | """ 137 | 138 | # Create dir where the pictures will be stored 139 | if not training_data_folder.exists(): 140 | training_data_folder.mkdir() 141 | 142 | train_face_recognizer(training_data_folder) 143 | 144 | gui = Gui(webcam_md) 145 | gui.add_library(Webcam()) 146 | gui.run(title='Face Recognition') 147 | -------------------------------------------------------------------------------- /src/requirements.txt: -------------------------------------------------------------------------------- 1 | taipy==3.0 2 | opencv-python-headless==4.7.0.72 3 | opencv-contrib-python-headless==4.7.0.72 4 | pillow -------------------------------------------------------------------------------- /src/temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/src/temp.png -------------------------------------------------------------------------------- /src/webcam/__init__.py: -------------------------------------------------------------------------------- 1 | from .webcam import Webcam 2 | -------------------------------------------------------------------------------- /src/webcam/webcam.py: -------------------------------------------------------------------------------- 1 | from taipy.gui.extension import ElementLibrary, Element, ElementProperty, PropertyType 2 | 3 | 4 | class Webcam(ElementLibrary): 5 | def get_name(self) -> str: 6 | return "webcam" 7 | 8 | def get_elements(self) -> dict: 9 | return { 10 | "Webcam": Element( 11 | "faces", 12 | { 13 | "faces": ElementProperty(PropertyType.dynamic_list), 14 | "id": ElementProperty(PropertyType.string), 15 | "classname": ElementProperty(PropertyType.dynamic_string), 16 | "on_data_receive": ElementProperty(PropertyType.string), 17 | "sampling_rate": ElementProperty(PropertyType.number), 18 | }, 19 | react_component="Webcam", 20 | ) 21 | } 22 | 23 | def get_scripts(self) -> list[str]: 24 | return ["webui/dist/webcam.js"] 25 | -------------------------------------------------------------------------------- /src/webcam/webui/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ -------------------------------------------------------------------------------- /src/webcam/webui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "taipy-gui-doc-extension", 3 | "version": "1.0.0", 4 | "private": true, 5 | "devDependencies": { 6 | "@types/react": "^18.0.15", 7 | "@types/w3c-image-capture": "^1.0.7", 8 | "@typescript-eslint/eslint-plugin": "^5.30.7", 9 | "@typescript-eslint/parser": "^5.30.7", 10 | "copy-webpack-plugin": "^11.0.0", 11 | "eslint": "^8.20.0", 12 | "eslint-plugin-react": "^7.30.1", 13 | "eslint-plugin-react-hooks": "^4.6.0", 14 | "eslint-webpack-plugin": "^4.0.1", 15 | "ts-loader": "^9.3.1", 16 | "typescript": "^5.0.4", 17 | "webpack": "^5.74.0", 18 | "webpack-cli": "^5.0.2" 19 | }, 20 | "dependencies": { 21 | "react": "^18.2.0", 22 | "taipy-gui": "file:../../../../../../../.conda/envs/face/lib/site-packages/taipy/gui/webapp" 23 | }, 24 | "scripts": { 25 | "build:dev": "webpack --mode development", 26 | "build": "webpack --mode production" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/webcam/webui/src/canvas.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | 3 | const updateCanvasSize = (canvas) => { 4 | const { width, height } = canvas.getBoundingClientRect() 5 | if (canvas.width !== width || canvas.height !== height) { 6 | canvas.width = width 7 | canvas.height = height 8 | return true 9 | } 10 | return false 11 | }; 12 | 13 | 14 | export const useCanvas = (videoRef, draw, options = {}) => { 15 | const canvasRef = useRef(null); 16 | useEffect(() => { 17 | const canvas = canvasRef.current; 18 | const context = canvas.getContext(options['context'] || '2d') 19 | const video = videoRef.current; 20 | 21 | let frameCount = 0; 22 | let animationFrameId; 23 | 24 | const render = () => { 25 | frameCount++ 26 | context.save(); 27 | updateCanvasSize(canvas); 28 | draw(context, video, frameCount) 29 | context.restore(); 30 | animationFrameId = window.requestAnimationFrame(render) 31 | } 32 | render() 33 | 34 | return () => { 35 | window.cancelAnimationFrame(animationFrameId) 36 | } 37 | }, [draw]); 38 | 39 | return canvasRef; 40 | } -------------------------------------------------------------------------------- /src/webcam/webui/src/index.ts: -------------------------------------------------------------------------------- 1 | import Webcam from "./webcam"; 2 | 3 | export { Webcam as Webcam } -------------------------------------------------------------------------------- /src/webcam/webui/src/video.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from "react"; 2 | 3 | export function useMediaStream(requestedMedia) { 4 | const [mediaStream, setMediaStream] = useState(null); 5 | 6 | useEffect(() => { 7 | async function enableStream() { 8 | try { 9 | const stream = await navigator.mediaDevices.getUserMedia(requestedMedia); 10 | setMediaStream(stream); 11 | } catch (err) { 12 | console.log("Something bad happend: " + err); 13 | } 14 | } 15 | 16 | if (!mediaStream) { 17 | enableStream(); 18 | } 19 | }, [mediaStream, requestedMedia]); 20 | 21 | return mediaStream; 22 | } 23 | 24 | export const useVideo = (mediaStream) => { 25 | const videoRef = useRef(); 26 | useEffect(() => { 27 | const video = videoRef.current; 28 | video.srcObject = mediaStream; 29 | }); 30 | return videoRef; 31 | } -------------------------------------------------------------------------------- /src/webcam/webui/src/webcam.tsx: -------------------------------------------------------------------------------- 1 | 2 | import { useDispatch, useDynamicProperty, createSendActionNameAction, useModule } from "taipy-gui"; 3 | import { useMediaStream, useVideo } from "./video"; 4 | import { useCanvas } from "./canvas"; 5 | 6 | interface WebcamProps { 7 | id?: string; 8 | onDataReceive: string; 9 | classname?: string; 10 | defaultClassname?: string; 11 | faces?: string[]; 12 | defaultFaces?: string[]; 13 | samplingRate?: number; 14 | } 15 | 16 | const Webcam = (props: WebcamProps) => { 17 | const { id, samplingRate = 50, onDataReceive = "data_received" } = props; 18 | 19 | const faces = useDynamicProperty(props.faces, props.defaultFaces, []); 20 | const classname = useDynamicProperty(props.classname, props.defaultClassname, ""); 21 | 22 | const mediaStream = useMediaStream({ video: true, audio: false }); 23 | const dispatch = useDispatch(); 24 | const module = useModule(); 25 | 26 | const sendImage = (blob) => { 27 | new Response(blob).arrayBuffer().then((data) => { 28 | const bytes = new Uint8Array(data); 29 | console.log("Sending " + bytes.length + " bytes.") 30 | const action = createSendActionNameAction(id, module, onDataReceive, { 31 | "data": bytes, 32 | }); 33 | dispatch(action); 34 | }); 35 | }; 36 | 37 | // Draw callback function 38 | const draw = (ctx, video, frameCount) => { 39 | // Draw video on canvas 40 | ctx.drawImage(video, 0, 0); 41 | 42 | // Take snapshot from video every x frames (TODO: add prop for sample rate): 43 | if (frameCount % samplingRate == 0) { 44 | ctx.canvas.toBlob(sendImage, 'image/jpeg', 0.95); 45 | } 46 | 47 | // Draw rectangles on detected faces 48 | ctx.strokeStyle = "#ff2600"; 49 | ctx.lineWidth = 5; 50 | 51 | for (const face of faces) { 52 | const [x, y, width, height, name] = face.slice(1, -1).split(", "); 53 | ctx.strokeRect(x, y, width, height) 54 | if (name) { 55 | // Remove quotes around text 56 | const display = name.replace(/[']/g, ''); 57 | ctx.font = "20px Arial"; 58 | ctx.fillStyle = "red"; 59 | ctx.strokeStyle = "#ff2600"; 60 | ctx.fillText(display, x, +y - 10); 61 | } 62 | } 63 | 64 | }; 65 | 66 | const videoRef = useVideo(mediaStream); 67 | const canvasRef = useCanvas(videoRef, draw); 68 | 69 | return ( 70 |
71 | 72 | 73 |
74 | ) 75 | } 76 | 77 | 78 | export default Webcam; -------------------------------------------------------------------------------- /src/webcam/webui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "outDir": "./dist/", 10 | "sourceMap": true, 11 | "allowJs": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "allowSyntheticDefaultImports": true, 15 | "strict": false, 16 | "forceConsistentCasingInFileNames": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "module": "esnext", 19 | "moduleResolution": "node", 20 | "resolveJsonModule": true, 21 | "isolatedModules": true, 22 | "noEmit": false, 23 | "jsx": "react-jsx", 24 | "noImplicitAny": false, 25 | }, 26 | "include": [ 27 | "src" 28 | ], 29 | } -------------------------------------------------------------------------------- /src/webcam/webui/webpack.config.js: -------------------------------------------------------------------------------- 1 | // webpack should be in the node_modules directory, install if not. 2 | const path = require("path"); 3 | const webpack = require("webpack"); 4 | 5 | module.exports = (env, options) => { 6 | return { 7 | mode: options.mode, //'development', //'production', 8 | entry: ["./src/index.ts"], 9 | output: { 10 | filename: "webcam.js", 11 | path: path.resolve(__dirname, "dist"), 12 | library: { 13 | name: "Webcam", 14 | type: "umd" 15 | }, 16 | publicPath: "/", 17 | }, 18 | // 'taipy-gui' is declared as external so that it is *not* bundled. 19 | externals: { "taipy-gui": "TaipyGui" }, 20 | 21 | // Enable sourcemaps for debugging webpack's output. 22 | devtool: options.mode === "development" && "inline-source-map", 23 | 24 | resolve: { 25 | // Add '.ts' and '.tsx' as resolvable extensions. 26 | extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"], 27 | }, 28 | 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.tsx?$/, 33 | use: "ts-loader", 34 | exclude: /node_modules/, 35 | }, 36 | ], 37 | }, 38 | 39 | plugins: [ 40 | new webpack.DllReferencePlugin({ 41 | // This pathname should point to the location of /webapp/taipy-gui-deps-manifest.json 42 | // where is the installation directory for Taipy GUI on your filesystem. 43 | // You may want to use the script 'find_taipy_gui_dir.py' to get this information. 44 | manifest: path.resolve('/usr/local/lib/python3.11/site-packages/taipy/gui/webapp/taipy-gui-deps-manifest.json'), 45 | name: 'TaipyGuiDependencies' 46 | }), 47 | ] 48 | 49 | }; 50 | }; -------------------------------------------------------------------------------- /temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Avaiga/demo-face-recognition/e57631dda2f20b27f715dc21c8ca1b1dc7e172d8/temp.png --------------------------------------------------------------------------------