├── .github └── workflows │ └── actinos_workflow.yml ├── .gitignore ├── LICENSE ├── README.md ├── calliar_dataset ├── dataset.npz ├── dataset.zip ├── dataset_imgs.zip ├── dataset_words.npz └── dataset_words_str.npz ├── calliar_server ├── calliar_server │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── db.sqlite3 ├── manage.py └── server │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── __init__.py │ └── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── __init__.cpython-38.pyc │ ├── models.py │ ├── static │ ├── explore.js │ ├── fabric.js │ ├── keyboard.css │ ├── keyboard.js │ ├── main.js │ ├── main2.js │ ├── paper-full.js │ ├── paper.js │ ├── unicode.js │ └── utils.js │ ├── templates │ └── server │ │ ├── explore.html │ │ ├── index.html │ │ └── index2.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── demo.ipynb ├── media ├── calliar_images │ ├── annotated_images │ │ ├── 1ان المتقين في جنات وعيون ادخلوها بسلام آمنين.jpg │ │ ├── الحمد لله copy.jpg │ │ ├── الحمد لله.jpg │ │ ├── خالد.jpg │ │ └── رب يسر ولا تعسر رب تمم بالخير.jpg │ ├── annotations │ │ ├── 1ان المتقين في جنات وعيون ادخلوها بسلام آمنين.json │ │ ├── الحمد لله copy.json │ │ ├── الحمد لله.json │ │ ├── خالد.json │ │ └── رب يسر ولا تعسر رب تمم بالخير.json │ └── images │ │ └── الحمد لله.jpg ├── data_format.PNG ├── data_format_colored.png ├── different_calls.PNG ├── sample_calliar_image.png ├── sample_calliar_image_2.png ├── sample_calliar_image_3.png ├── sample_calliar_video.mp4 ├── sample_calliar_video_2.mp4 └── sample_calliar_video_3.mp4 ├── notebooks ├── Check Wrong Annotations.ipynb ├── Clustering Characters.ipynb ├── Collect bism allah.ipynb ├── Colorize text and image.ipynb ├── Convert Strokes to Images.ipynb ├── Fix alignments of strokes .ipynb ├── Generate Characters and words.ipynb ├── Generate as minified json.ipynb ├── Split dataset .ipynb ├── data npz generator.ipynb ├── data word npz generator.ipynb └── data_visualizer.ipynb ├── page ├── index.html ├── index.js ├── index_ar.html ├── json.js └── json_sm.js ├── requirements.txt └── scripts ├── chars.py └── vis.py /.github/workflows/actinos_workflow.yml: -------------------------------------------------------------------------------- 1 | name: Deployment Workflow 2 | on: 3 | push: 4 | branches: [main] 5 | 6 | jobs: 7 | first_job: 8 | name: Deploy Calliar Website 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: SSH Remote Commands 12 | uses: appleboy/ssh-action@v0.1.4 13 | with: 14 | host: calliar.arbml.org 15 | username: arabicmachinelearning 16 | key: ${{ secrets.SECRET_SSHKEY }} 17 | port: 22 18 | script: | 19 | cd ~ 20 | 21 | if [ ! -d "atmatah" ]; 22 | then 23 | echo cloning atamatah as it does not exist 24 | git clone https://github.com/ARBML/atmatah.git 25 | cd atmatah 26 | else 27 | echo pulling latest changes from atmatah 28 | cd atmatah 29 | git pull 30 | fi 31 | 32 | echo creating venv if not exist and install requirements 33 | if [ ! -d "venv" ]; 34 | then 35 | python3 -m venv venv 36 | fi 37 | venv/bin/python3 -m pip install -r requirements.txt 38 | venv/bin/ansible-galaxy install -r requirements.yml 39 | 40 | echo prepare for deploy 41 | mkdir -p .config 42 | echo ${{ secrets.ANS_PASS }} > .config/ansible_pass.password 43 | 44 | echo deploy calliar app 45 | venv/bin/ansible-playbook -i apps/calliar/inventory apps/calliar/app.yml --vault-password-file=.config/ansible_pass.password --connection=local 46 | 47 | echo cleanup 48 | cd ~ 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # https://github.com/github/gitignore/blob/main/Python.gitignore 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 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 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # poetry 99 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 103 | #poetry.lock 104 | 105 | # pdm 106 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 107 | #pdm.lock 108 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 109 | # in version control. 110 | # https://pdm.fming.dev/#use-with-ide 111 | .pdm.toml 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json/page/index.html 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | # PyCharm 157 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 158 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 159 | # and can be added to the global gitignore or merged into this file. For a more nuclear 160 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 161 | #.idea/ 162 | 163 | 164 | #---------------------custom--------------------------_# 165 | 166 | *.pyc 167 | venv/* 168 | *.svg 169 | !media/* 170 | .vscode 171 | .ipynb_checkpoints 172 | */.ipynb_checkpoints/* 173 | calliar_server/calliar_server/__pycache__/*.pyc 174 | calliar_server/server/__pycache__/views.cpython-36.pyc 175 | calliar_server/db.sqlite3 176 | calliar_server/server/__pycache__/urls.cpython-36.pyc 177 | calliar_server/server/__pycache__/views.cpython-36.pyc 178 | .vscode/* 179 | calliar_server/calliar_server/local_settings.py 180 | calliar_server/db.sqlite3 181 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 ARBML 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calliar 2 | Calliar is a dataset for Arabic calligraphy. The dataset consists of 2500 json files that contain strokes manually annotated for Arabic calligraphy. This repository contains the dataset for the following paper : 3 | 4 | > **Calliar: An Online Handwritten Dataset for Arabic Calligraphy**
5 | > Zaid Alyafeai, Maged S. Al-shaibani, Mustafa Ghaleb, Yousif Ahmed Al-Wajih
6 | > https://arxiv.org/abs/2106.10745 7 | > 8 | > **Abstract:** *Calligraphy is an essential part of the Arabic heritage and culture. It has been used in the past for the decoration of houses and mosques. Usually, such calligraphy is designed manually by experts with aesthetic insights. In the past few years, there has been a considerable effort to digitize such type of art by either taking a photo of decorated buildings or drawing them using digital devices. The latter is considered an online form where the drawing is tracked by recording the apparatus movement, an electronic pen for instance, on a screen. In the literature, there are many offline datasets collected with a diversity of Arabic styles for calligraphy. However, there is no available online dataset for Arabic calligraphy. In this paper, we illustrate our approach for the collection and annotation of an online dataset for Arabic calligraphy called Calliar that consists of 2,500 sentences. Calliar is annotated for stroke, character, word and sentence level prediction.* 9 | 10 | ## Stats 11 | 12 | | Dataset | # of Samples | # of Words | # of Chars | # of Strokes | 13 | ---------|---------------|-----------|------------|--------------- 14 | | Train | 2,000 | 6,065 | 24,722 | 36,561 | 15 | | Valid | 250 | 738 | 2,946 | 4,410 | 16 | | Test | 250 | 753 |3,052 | 4,601 | 17 | 18 | ## Dataset Formats 19 | Mainly, we have two basic formats. 20 | ### .json 21 | 22 | Each `.json` file contains a list of strokes. Each list is a dictionary of the stroke character and the list of points. Each composite character like `ت` is mapped into a list of primitive strokes i.e `..ٮ `. Refer to the paper and to `chars.py` for more details on the mapping. 23 | 24 | ![](media/data_format_colored.png) 25 | 26 | ### .npz 27 | 28 | The compressed format of the dataset `dataset.npz` is only 8.6 MB and uses the Ramer-Douglas-Peucker Algorithm to decrease the number of points per stroke. The python library [rdp](https://github.com/fhirschmann/rdp) was used for such task. The `.npz` format follows the same approach as [QuickDraw](https://github.com/googlecreativelab/quickdraw-dataset). 29 | 30 | 31 | ## Visualization 32 | 33 | The `vis.py` file contains a list of python methods for easily visualizing the dataset. Here are two examples for drawing a sample json file and creating an animation. 34 | 35 | 36 | 37 | ```python 38 | import glob 39 | import matplotlib.pyplot as plt 40 | import json 41 | from IPython.core.display import display, HTML, Video 42 | from vis import * 43 | 44 | ## show an image of the strokes 45 | drawing = json.load(open(json_path)) 46 | print(get_annotation(json_path)) 47 | data = convert_3d(drawing) 48 | draw_strokes(data, stroke_width = 2, crop = True) 49 | 50 | ## create an animation. 51 | create_animation(json_path) 52 | Video("tmp/video.mp4") 53 | ``` 54 | 55 | ## Samples 56 | ![sample_calliar_image_3](media/sample_calliar_image_3.png) 57 | 58 | 59 | ## Annotation Server 60 | First `pip install django`, then traverse to the directory `calliar_server` and run 61 | 62 | ```basch 63 | python manage.py runserver 64 | ``` 65 | 66 | ## Animation 67 | 68 | 69 | https://user-images.githubusercontent.com/15667714/122690255-1acff980-d231-11eb-9752-730d8024041e.mp4 70 | 71 | 72 | 73 | https://user-images.githubusercontent.com/15667714/122690258-1c012680-d231-11eb-98d0-4c89afd8aba3.mp4 74 | 75 | 76 | 77 | https://user-images.githubusercontent.com/15667714/122690261-1d325380-d231-11eb-99ab-158455483561.mp4 78 | 79 | 80 | 81 | https://user-images.githubusercontent.com/15667714/122690265-1efc1700-d231-11eb-9830-328725a82c11.mp4 82 | 83 | 84 | ## Citation 85 | 86 | ``` 87 | @misc{alyafeai2021calliar, 88 | title={Calliar: An Online Handwritten Dataset for Arabic Calligraphy}, 89 | author={Zaid Alyafeai and Maged S. Al-shaibani and Mustafa Ghaleb and Yousif Ahmed Al-Wajih}, 90 | year={2021}, 91 | eprint={2106.10745}, 92 | archivePrefix={arXiv}, 93 | primaryClass={cs.CL} 94 | } 95 | ``` 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /calliar_dataset/dataset.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_dataset/dataset.npz -------------------------------------------------------------------------------- /calliar_dataset/dataset.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_dataset/dataset.zip -------------------------------------------------------------------------------- /calliar_dataset/dataset_imgs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_dataset/dataset_imgs.zip -------------------------------------------------------------------------------- /calliar_dataset/dataset_words.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_dataset/dataset_words.npz -------------------------------------------------------------------------------- /calliar_dataset/dataset_words_str.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_dataset/dataset_words_str.npz -------------------------------------------------------------------------------- /calliar_server/calliar_server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/calliar_server/__init__.py -------------------------------------------------------------------------------- /calliar_server/calliar_server/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for calliar_server project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calliar_server.settings") 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /calliar_server/calliar_server/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for calliar_server project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.2.2. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | 16 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 17 | BASE_DIR = Path(__file__).resolve().parent.parent 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = "django-insecure-c0eh)tcsdj2x#_3rcs7fokahj0vk*7&!3n!zi60%0_lqf1e-u^" 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | # ALLOWED_HOSTS = [] 30 | ALLOWED_HOSTS = ["*"] 31 | 32 | 33 | # Application definition 34 | 35 | INSTALLED_APPS = [ 36 | "django.contrib.admin", 37 | "django.contrib.auth", 38 | "django.contrib.contenttypes", 39 | "django.contrib.sessions", 40 | "django.contrib.messages", 41 | "django.contrib.staticfiles", 42 | "server", 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | "django.middleware.security.SecurityMiddleware", 47 | "django.contrib.sessions.middleware.SessionMiddleware", 48 | "django.middleware.common.CommonMiddleware", 49 | "django.middleware.csrf.CsrfViewMiddleware", 50 | "django.contrib.auth.middleware.AuthenticationMiddleware", 51 | "django.contrib.messages.middleware.MessageMiddleware", 52 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 53 | ] 54 | 55 | ROOT_URLCONF = "calliar_server.urls" 56 | 57 | TEMPLATES = [ 58 | { 59 | "BACKEND": "django.template.backends.django.DjangoTemplates", 60 | "DIRS": [], 61 | "APP_DIRS": True, 62 | "OPTIONS": { 63 | "context_processors": [ 64 | "django.template.context_processors.debug", 65 | "django.template.context_processors.request", 66 | "django.contrib.auth.context_processors.auth", 67 | "django.contrib.messages.context_processors.messages", 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = "calliar_server.wsgi.application" 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases 78 | 79 | DATABASES = { 80 | "default": { 81 | "ENGINE": "django.db.backends.sqlite3", 82 | "NAME": BASE_DIR / "db.sqlite3", 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators 89 | 90 | AUTH_PASSWORD_VALIDATORS = [ 91 | { 92 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 93 | }, 94 | {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, 95 | {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, 96 | {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, 97 | ] 98 | 99 | 100 | # Internationalization 101 | # https://docs.djangoproject.com/en/3.2/topics/i18n/ 102 | 103 | LANGUAGE_CODE = "en-us" 104 | 105 | TIME_ZONE = "UTC" 106 | 107 | USE_I18N = True 108 | 109 | USE_L10N = True 110 | 111 | USE_TZ = True 112 | 113 | 114 | # Static files (CSS, JavaScript, Images) 115 | # https://docs.djangoproject.com/en/3.2/howto/static-files/ 116 | 117 | STATIC_URL = "/static/" 118 | 119 | # Default primary key field type 120 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field 121 | 122 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 123 | 124 | CORS_ALLOW_ALL_ORIGINS = True 125 | MEDIA_ROOT = os.path.join(BASE_DIR, "../media") 126 | MEDIA_URL = "/media/" 127 | 128 | 129 | #---------------- CUSTOM ENV VARS ------------- 130 | IMAGES_DIR = '../media/calliar_images' 131 | 132 | 133 | try: 134 | from .local_settings import * 135 | except Exception as e: 136 | print('local settings file cannot be imported') 137 | 138 | # create these dirs if they do not exist, 139 | 140 | os.system(f'mkdir -p {IMAGES_DIR}/annotations') 141 | os.system(f'mkdir -p {IMAGES_DIR}/annoated_images') 142 | 143 | # assert required directories within IMAGES_DIR exists 144 | 145 | assert os.path.isdir(f'{IMAGES_DIR}/annotations'), 'annotations folder does not exist' 146 | assert os.path.isdir(f'{IMAGES_DIR}/images'), 'images folder does not exist' 147 | assert os.path.isdir(f'{IMAGES_DIR}/annoated_images'), 'processed_images folder does not exist' 148 | -------------------------------------------------------------------------------- /calliar_server/calliar_server/urls.py: -------------------------------------------------------------------------------- 1 | """calliar_server URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | 21 | 22 | urlpatterns = [path("admin/", admin.site.urls), path("", include("server.urls"))] 23 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 24 | -------------------------------------------------------------------------------- /calliar_server/calliar_server/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for calliar_server project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calliar_server.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /calliar_server/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/db.sqlite3 -------------------------------------------------------------------------------- /calliar_server/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calliar_server.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /calliar_server/server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/server/__init__.py -------------------------------------------------------------------------------- /calliar_server/server/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /calliar_server/server/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ServerConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'server' 7 | -------------------------------------------------------------------------------- /calliar_server/server/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/server/migrations/__init__.py -------------------------------------------------------------------------------- /calliar_server/server/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/server/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /calliar_server/server/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/calliar_server/server/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /calliar_server/server/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /calliar_server/server/static/explore.js: -------------------------------------------------------------------------------- 1 | /* 2 | variables 3 | */ 4 | var canvas; 5 | var paper; 6 | var curr_img; 7 | var strokeWidth = 3; 8 | var currJsonId = 0; 9 | var Strokeindex = 0; 10 | var paths = []; 11 | var colors = ['#7fc97f', '#beaed4', '#fdc086', '#008ecc', '#386cb0', '#f0027f', '#bf5b16', '#666666'] 12 | var w = 600; 13 | var h = 600; 14 | var drawing = false; 15 | var readonlyInput; 16 | var speed = 2; 17 | 18 | 19 | var canvas = Raphael('canvas', '600px', '600px'); 20 | canvas.setViewBox(0,0,w,h); 21 | 22 | var animatePath = function(paths) { 23 | color = colors[randomNumber(0, colors.length)] 24 | var line = canvas.path(paths[0]).attr({ 25 | stroke: color, 26 | 'stroke-opacity': 0, 27 | }); 28 | 29 | var rand = Date.now(); 30 | line.node.id = 'path'+rand; 31 | $('#'+line.node.id).css("transform", "translate(30,7)"); 32 | var length = line.getTotalLength(); 33 | var prev_path; 34 | $('#'+line.node.id).animate({ 35 | 'to': 1}, { 36 | duration: parseInt(length*speed), 37 | step: function(pos, fx) { 38 | var offset = length * fx.pos; 39 | 40 | var subpath = line.getSubpath(0, offset); 41 | if (prev_path != null) 42 | { 43 | prev_path.remove(); 44 | } 45 | 46 | prev_path = canvas.path(subpath).attr({ 47 | 'stroke-width': strokeWidth, 48 | stroke: color 49 | }); 50 | 51 | 52 | }, 53 | complete: function(){ 54 | if (paths.length > 0){ 55 | animatePath(paths.slice(1)) 56 | } 57 | else{ 58 | enableBtns() 59 | drawing = false 60 | } 61 | 62 | Strokeindex += 1; 63 | readonlyInput.focus(); 64 | readonlyInput.setSelectionRange(0, 2*Strokeindex); 65 | } 66 | }); 67 | 68 | }; 69 | function randomNumber(min, max) { 70 | return Math.floor(Math.random() * (max - min) + min); 71 | } 72 | 73 | function getJsonList(){ 74 | var xmlHttp = new XMLHttpRequest(); 75 | xmlHttp.open( "GET", '/explore/list-json?', false ); // false for synchronous request 76 | xmlHttp.send( null ); 77 | response = JSON.parse(xmlHttp.response) 78 | return response.json_names 79 | } 80 | 81 | function getJsonUrl(id = undefined){ 82 | 83 | if(id){ 84 | currJsonId = id 85 | } 86 | 87 | var xmlHttp = new XMLHttpRequest(); 88 | xmlHttp.open( "GET", '/explore/next-json?id='+currJsonId, false ); // false for synchronous request 89 | xmlHttp.send( null ); 90 | response = JSON.parse(xmlHttp.response) 91 | currJsonId = parseInt(response.id) 92 | return response.json_path 93 | } 94 | function disableBtns(){ 95 | $('button').prop('disabled', true); 96 | $(':radio').prop('disabled', true); 97 | } 98 | 99 | function enableBtns(){ 100 | $('button').prop('disabled', false); 101 | $(':radio').prop('disabled', false); 102 | } 103 | function generateNext(){ 104 | currJsonId += 1 105 | generate() 106 | } 107 | 108 | function generatePrev(){ 109 | currJsonId -= 1 110 | generate() 111 | } 112 | 113 | function setImage(w, h){ 114 | const scale = 600; 115 | if (w > h){ 116 | h = parseInt((h/w) * scale); 117 | w = scale; 118 | }else{ 119 | w = parseInt((w/h) * scale); 120 | h = scale; 121 | } 122 | 123 | cx = 300 124 | cy = 300 125 | 126 | canvas.image("/media/calliar_images/processed_images/"+imageName, cx - w/2, cy - h/2, w, h).attr({ 127 | opacity: .3, 128 | }); 129 | } 130 | function addRaster(imageName) 131 | { 132 | image_url = "/media/calliar_images/processed_images/"+imageName; 133 | const img = new Image(); 134 | img.src = image_url 135 | img.onload = function() { setImage(this.width, this.height); } 136 | } 137 | 138 | function generate(id = undefined) { 139 | 140 | canvas.clear(); 141 | Strokeindex = 0; 142 | 143 | disableBtns() 144 | drawing = true 145 | json_path = getJsonUrl(id = id) 146 | json_name = json_path.split('.json')[0] 147 | text = preprocess(json_name)[1] 148 | readonlyInput.value = text; 149 | 150 | imageName = json_name+'.jpg' 151 | addRaster(imageName) 152 | 153 | $.getJSON('/media/calliar_images/annotations/'+json_path , function(data) { 154 | paths = [] 155 | for (var char in data){ 156 | for (var key in data[char]){ 157 | paths.push(data[char][key]); 158 | } 159 | } 160 | animatePath(paths) 161 | }); 162 | } 163 | 164 | async function start() { 165 | 166 | generate() 167 | 168 | }; 169 | 170 | 171 | function onClick(id){ 172 | generate(id) 173 | } 174 | function createBtn(content, id = 0){ 175 | return ` 32 | 48 | 49 | 50 |
51 | 52 |

53 | Explore saved calligraphy as animated strokes. 54 |

55 |
56 |
57 | 58 |
59 |
60 | 61 |
62 | 63 |
64 |
65 | 66 |
67 | 68 | 69 |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 |
84 | 85 | 86 |
87 |
88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /calliar_server/server/templates/server/index.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | Calliar 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 51 | 52 |
53 | 54 |
55 | 0 56 | 57 | 58 |
59 | 60 |
61 |
62 | 63 |
64 |
65 | 66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 |
76 |
77 | 78 |
79 | 80 | 81 | 82 |
83 | 84 | 85 | 86 | 90 | 91 | -------------------------------------------------------------------------------- /calliar_server/server/templates/server/index2.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | Calliar 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 37 |
38 |
39 |
40 | 41 |
42 | 43 |
44 | 45 | 46 | 47 |
48 | 49 |
50 | 51 |
52 | 53 |
54 | 55 | 56 |
57 | 58 | 59 | 63 | 64 | -------------------------------------------------------------------------------- /calliar_server/server/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /calliar_server/server/urls.py: -------------------------------------------------------------------------------- 1 | from .views import EndpointView, NextImageView, ExploreView, NextJsonView, ListJsonView 2 | from django.urls import path 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | 6 | app_name = 'server' 7 | 8 | urlpatterns = [ 9 | path('', EndpointView.as_view(),name="home"), 10 | path('endpoint/', EndpointView.as_view(),name="endpoint"), 11 | path('endpoint/next-image/', NextImageView.as_view(),name="next_image"), 12 | path('explore/', ExploreView.as_view()), 13 | path('explore/next-json/', NextJsonView.as_view(),name="next_image"), 14 | path('explore/list-json/', ListJsonView.as_view(),name="list_jsons"), 15 | ] -------------------------------------------------------------------------------- /calliar_server/server/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.views.generic import View 3 | # Create your views here. 4 | from django.http import HttpResponse 5 | from django.views.decorators.csrf import csrf_exempt 6 | from django.utils.decorators import method_decorator 7 | import os 8 | from django.http import JsonResponse 9 | import json 10 | import shutil 11 | from django.conf import settings 12 | import base64 13 | import io 14 | from PIL import Image 15 | 16 | @method_decorator(csrf_exempt, name='dispatch') 17 | class EndpointView(View): 18 | 19 | template_name = 'server/index.html' 20 | def render_to_template(self): 21 | # context = {'next_image_name':self.get_next_image_name()} 22 | context = {} 23 | return render( 24 | self.request, 25 | self.template_name, 26 | context, 27 | ) 28 | 29 | def get(self, request, *args, **kwargs): 30 | return self.render_to_template() 31 | 32 | def post(self, request, *args, **kwargs): 33 | data = json.loads(request.body) 34 | file_name = data['newImageName'].split('.')[0] 35 | exist_on_Server = bool(data['existOnServer']) 36 | new_file_name = "" 37 | counter = '' 38 | while True: 39 | new_file_name = counter+file_name 40 | if new_file_name not in os.listdir(f'{settings.IMAGES_DIR}/annotated_images'): 41 | if exist_on_Server: 42 | shutil.move(f"{settings.IMAGES_DIR}/images/{data['oldImageName']}", 43 | f"{settings.IMAGES_DIR}/annotated_images/{new_file_name}.jpg") 44 | else: 45 | image_bin = data['imageBlob'].encode() 46 | save_path = f"{settings.IMAGES_DIR}/annotated_images/{new_file_name}.jpg" 47 | image_object = Image.open(io.BytesIO(base64.b64decode(image_bin[image_bin.find(b'/9'):]))) 48 | image_object.save(save_path) 49 | break 50 | else: 51 | if counter == '': 52 | counter = '1' 53 | else: 54 | counter = str(int(counter)+1) 55 | 56 | file_path = f"{settings.IMAGES_DIR}/annotations/{new_file_name}.json" 57 | json.dump(data['sketch'],open(file_path, 'w')) 58 | result = JsonResponse({'result':True}) 59 | return result 60 | 61 | class NextImageView(View): 62 | 63 | def get_next_image_name(self, curr_id): 64 | image_paths = os.listdir(f'{settings.IMAGES_DIR}/images/') 65 | processed_image_paths = os.listdir(f'{settings.IMAGES_DIR}/annotated_images/') 66 | 67 | if not any ([ 68 | os.path.isfile(f'{settings.IMAGES_DIR}/images/{file}') 69 | for file in os.listdir(f'{settings.IMAGES_DIR}/images/') 70 | ]): 71 | return JsonResponse({'result':False,'description':'No more images to return'},status=404) 72 | 73 | 74 | if curr_id >= len(image_paths): 75 | curr_id = 0 76 | elif curr_id == -1: 77 | curr_id = len(image_paths) - 1 78 | 79 | 80 | return JsonResponse({'image_path':image_paths[curr_id], 'num_images':len(image_paths), 81 | 'proc_num_images':len(processed_image_paths), 'id':curr_id}) 82 | 83 | 84 | def get(self, request, *args, **kwargs): 85 | return HttpResponse(self.get_next_image_name(int(request.GET['id']))) 86 | 87 | class ExploreView(View): 88 | 89 | template_name = 'server/explore.html' 90 | def render_to_template(self): 91 | # context = {'next_image_name':self.get_next_image_name()} 92 | context = {} 93 | return render( 94 | self.request, 95 | self.template_name, 96 | context, 97 | ) 98 | 99 | def get(self, request, *args, **kwargs): 100 | return self.render_to_template() 101 | 102 | class NextJsonView(View): 103 | 104 | def get_next_json_name(self, curr_id): 105 | json_paths = os.listdir(f'{settings.IMAGES_DIR}/annotations/') 106 | 107 | if curr_id >= len(json_paths): 108 | curr_id = 0 109 | elif curr_id == -1: 110 | curr_id = len(json_paths) - 1 111 | 112 | return JsonResponse({'json_path':json_paths[curr_id], 'id':curr_id}) 113 | 114 | 115 | def get(self, request, *args, **kwargs): 116 | return HttpResponse(self.get_next_json_name(int(request.GET['id']))) 117 | 118 | 119 | class ListJsonView(View): 120 | 121 | def get_json_list(self): 122 | json_paths = os.listdir(f'{settings.IMAGES_DIR}/annotations/') 123 | json_names = [json_path.split('.')[0] for json_path in json_paths] 124 | return JsonResponse({'json_names':json_names, 'size':len(json_paths)}) 125 | 126 | 127 | def get(self, request, *args, **kwargs): 128 | return HttpResponse(self.get_json_list()) 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /media/calliar_images/annotated_images/1ان المتقين في جنات وعيون ادخلوها بسلام آمنين.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/annotated_images/1ان المتقين في جنات وعيون ادخلوها بسلام آمنين.jpg -------------------------------------------------------------------------------- /media/calliar_images/annotated_images/الحمد لله copy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/annotated_images/الحمد لله copy.jpg -------------------------------------------------------------------------------- /media/calliar_images/annotated_images/الحمد لله.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/annotated_images/الحمد لله.jpg -------------------------------------------------------------------------------- /media/calliar_images/annotated_images/خالد.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/annotated_images/خالد.jpg -------------------------------------------------------------------------------- /media/calliar_images/annotated_images/رب يسر ولا تعسر رب تمم بالخير.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/annotated_images/رب يسر ولا تعسر رب تمم بالخير.jpg -------------------------------------------------------------------------------- /media/calliar_images/annotations/1ان المتقين في جنات وعيون ادخلوها بسلام آمنين.json: -------------------------------------------------------------------------------- 1 | [{"\u0627": "M592.5,252c0,11.66667 0,23.33333 0,35c0,1.912 -1.21678,10.78322 0,12c1.83333,1.83333 -0.83333,8.16667 1,10c2.45956,2.45956 2,19.06131 2,25"}, {".": "M577.5,284"}, {"\u06ba": "M579.5,316c0,3.21178 2.72211,27.27789 0,30c-2.18117,2.18117 -5.76906,4.76906 -8,7c-0.94536,0.94536 -5.16343,0.16343 -6,1c-5.3222,5.3222 -19.0342,5 -28,5c-1.75227,0 -9.88485,1.11515 -11,0c-6.6852,-6.6852 -8,-16.33055 -8,-27"}, {"\u0627": "M558.5,240c2.54116,2.54116 -0.06512,7.93488 2,10c1.78239,1.78239 1,7.58013 1,11c0,10.33333 0,20.66667 0,31c0,6.27327 3,9.87133 3,16c0,3.0663 3,7.15605 3,7"}, {"\u0644": "M537.5,251c0,21.54087 -4,33.94799 -4,55"}, {"\u0645": "M539.5,310c0,2.02874 8.82998,17.82998 10,19c2.56811,2.56811 7.08976,-7.91024 5,-10c-0.66667,-0.66667 -3.33333,0.66667 -4,0c-7.19368,-7.19368 -10.49663,8 -19,8c-2.49976,0 -16,0.82331 -16,-1"}, {".": "M512.5,308c0,0.66667 0,1.33333 0,2"}, {".": "M522.5,308c0.86036,0 2,2.32883 2,3"}, {"\u066e": "M514.5,325c-1.83405,1.83405 -1.62978,3.62978 -3,5c-1.83333,1.83333 -6.16667,1.16667 -8,3c-1.03689,1.03689 -7,0.01037 -7,-1"}, {".": "M494.5,290"}, {".": "M505.5,290"}, {"\u066f": "M495.5,331c0,-3.08377 -5.02711,-13.97289 -1,-18c4.53194,-4.53194 14.66896,7.33104 11,11c-2,2 -3,5 -5,7c-2.15733,2.15733 -18.65722,7.34278 -22,4c-2.96124,-2.96124 -3,-9.10335 -3,-15"}, {"\u0649": "M476.5,323c-0.51576,0 -3,-10 -3,-10c0,0 -2.62599,5.62599 -3,6c-1.31836,1.31836 -10.92835,0 -13,0"}, {".": "M463.5,353"}, {".": "M482.5,350"}, {".": "M447.5,328"}, {"\u06ba": "M457.5,315c3.99543,0 6.10905,20.89095 3,24c-5.58504,5.58504 -19.3898,9 -30,9c-2.05754,0 -7.22424,3.77576 -9,2c-7.85187,-7.85187 -15,-10.21955 -15,-26"}, {".": "M461.5,245"}, {"\u066f": "M470.5,276c-0.33333,-0.33333 -0.78918,-0.57836 -1,-1c-0.33333,-0.66667 -1.33333,-0.66667 -2,-1c-1.74127,-0.87064 -6.479,-3.479 -8,-5c-0.45779,-0.45779 -0.45779,-10.54221 0,-11c2.06163,-2.06163 6.62599,1.62599 7,2c1.72394,1.72394 5.03067,3.03067 7,5c3.98165,3.98165 -3,14.97272 -3,18"}, {"\u0649": "M472.5,275c0,6.50868 -11.59253,11.79626 -16,14c-1.77186,0.88593 -10.26914,4.73086 -7,8c3.66667,3.66667 12.33333,2.33333 16,6c2.66667,2.66667 13.33333,-2.66667 16,0c3.60867,3.60867 22.7102,1 29,1c14,0 28,0 42,0c5.07865,0 13.34553,0.65447 16,-2c1.44243,-1.44243 7.10225,0.94887 9,0c1.39352,-0.69676 7.18,-0.18 8,-1c1.8656,-1.8656 5.8168,-6 9,-6"}, {".": "M484.5,287"}, {".": "M509.5,289"}, {"\u062d": "M409.5,311c3.56365,-3.56365 26.04238,-3.95762 29,-1c0.17173,0.17173 8,1 8,1c0,0 -10.50042,0.50042 -11,1c-5.73813,5.73813 -19.41161,5.41161 -25,11c-1.14493,1.14493 -9,-0.05445 -9,-1"}, {".": "M449.5,327"}, {".": "M388.5,309c0.33333,0 0.66667,0 1,0"}, {"\u06ba": "M397.5,313c0,5.75093 -3.99549,8.99549 -7,12c-3.76355,3.76355 -13,-2.13878 -13,-6"}, {"\u0627": "M377.5,322c0,-13 0,-26 0,-39c0,-2.07165 1.31836,-11.68164 0,-13c-0.70484,-0.70484 -4,-25.43843 -4,-28"}, {".": "M364.5,270"}, {".": "M364.5,284"}, {"\u066e": "M420.5,302c0,-3.43075 7.17546,-9.82454 3,-14c-2.01339,-2.01339 -16.72585,3.72585 -17,4c-0.45564,0.45564 -15.95134,1 -18,1c-22.2275,0 -29,-5.75449 -29,-28"}, {"\u0648": "M366.5,329c-0.47678,0 -7.40516,-1.40516 -8,-2c-0.49958,-0.49958 -2.49703,-9.50297 -1,-11c6.00566,-6.00566 14.92782,14.07218 11,18c-7.53714,7.53714 -23.3871,26.6129 -36,14c-1.33333,-1.33333 -4.66667,-0.66667 -6,-2c-1.32502,-1.32502 -1,-5.9295 -1,-8"}, {"\u0639": "M340.5,296c0,-2.24609 -16.79747,-5.10126 -21,-3c-1.26405,0.63202 -3.85111,5.14889 -2,7c2.45839,2.45839 4.51128,7.51128 7,10c1.25715,1.25715 4.82678,1.82678 6,3c2.84311,2.84311 14.29181,-1.29181 15,-2c0.66667,-0.66667 2.33333,-0.33333 3,-1c0.2357,-0.2357 0.2357,-0.7643 0,-1c-0.2357,-0.2357 -0.66667,0 -1,0c-4.80456,0 -8.85192,12 -14,12c-0.33333,0 -0.7643,-0.2357 -1,0c-0.2357,0.2357 0.2357,0.7643 0,1c-0.33333,0.33333 -1,0.5286 -1,1c0,0.33333 0.2357,0.7643 0,1c-1.62285,1.62285 -14,2.32085 -14,-1"}, {"\u0649": "M311.5,314c0,6.34374 -3.22848,13 -9,13"}, {".": "M303.5,349"}, {".": "M315.5,348"}, {"\u0648": "M306.5,325c0,2.68122 -16.17512,6.91244 -20,5c-1.10682,-0.55341 -1.94702,-8.05298 -1,-9c6.99117,-6.99117 17.52811,12.47189 14,16c-1.03071,1.03071 -0.96929,4.96929 -2,6c-1.54195,1.54195 -9.1408,11.5704 -10,12c-9.47755,4.73878 -20.68448,3.31552 -27,-3c-2.81174,-2.81174 0,-11.06753 0,-14"}, {".": "M287.5,281"}, {"\u06ba": "M309.5,273c1.56667,0 1,0.66667 1,2c0,3.48908 3.69387,15.30613 0,19c-5.84631,5.84631 -27.2832,7 -37,7c-3.4041,0 -11.6583,1.3417 -14,-1c-2.00729,-2.00729 -3.88618,-5.88618 -6,-8c-3.0521,-3.0521 2,-13.65777 2,-16"}, {"\u0627": "M275.5,255c0,32.57742 -3,61.00821 -3,93"}, {"\u062f": "M240.5,294c0,2.28577 4.0261,2.0261 5,3c3.66667,3.66667 8.33333,6.33333 12,10c0.83333,0.83333 3.16667,0.16667 4,1c1,1 0,4 1,5c1.27567,1.27567 1,3.37668 1,6c0,9.26244 -4.96857,11.96857 -10,17c-0.83333,0.83333 -3.16667,0.16667 -4,1c-0.74536,0.74536 -0.05719,2.5286 -1,3c-0.11511,0.05756 -15.37359,1.62641 -16,1c-0.52705,-0.52705 -0.25464,-2 -1,-2"}, {".": "M204.5,276"}, {"\u062d": "M211.5,335c0,-2.66907 -3.57344,-16.42656 -1,-19c0.80955,-0.80955 6.72812,0 8,0c0.33333,0 0.66667,0 1,0c0.33333,0 0.66667,0 1,0c0.33333,0 0.7643,-0.2357 1,0c1.06165,1.06165 18,3.20195 18,1c0,-1.33333 1,-1 1,-1c0,0 -1.33333,0 -2,0c-0.38867,0 -5.27119,2.54238 -6,4c-3.80739,7.61479 -13.45347,9.45347 -19,15c-4.9022,4.9022 -15,-3.72212 -15,-8"}, {"\u0644": "M197.5,328c0,-20.93691 -2,-43.23376 -2,-63c0,-5.97678 -3,-12.26316 -3,-16c0,-0.2 0,-3 0,-3c0,0 0,2 0,3c0,6.1837 -1.21339,13.93307 0,20c2.49974,12.4987 2,23.79897 2,37c0,1.912 1.21678,10.78322 0,12c-4.03165,4.03165 -5.62515,11 -14,11"}, {"\u0648": "M183.5,329c-8.7171,0 -12,-0.70352 -12,-10c0,-0.94832 -0.60389,-5.39611 0,-6c1.26586,-1.26586 7.62599,0.62599 8,1c2.60777,2.60777 15.0616,12.9384 9,19c-5.36019,5.36019 -12.53111,10.53111 -17,15c-1.4951,1.4951 -7.65515,-0.34485 -9,1c-1.49971,1.49971 -6.50029,1.49971 -8,0c-1.5,-1.5 -5.5,-0.5 -7,-2c-3.47454,-3.47454 -4,-12.29009 -4,-19"}, {"\u0647": "M221.5,270c0,7.94842 18.41822,24.58178 9,34c-1,1 -5,-1 -6,0c-6.66672,6.66672 -23.5235,-9.953 -19,-19c1.89258,-3.78516 5.32585,-7.16293 9,-9c4.5684,-2.2842 5.55098,7.89805 4,11c-4.27838,8.55676 -27.59707,9 -40,9c-4.34003,0 -17,-0.21417 -17,-4"}, {"\u0627": "M162.5,291c-1.83752,0 -1,-18.47991 -1,-21c0,-4.09678 0.43263,-26.13474 -1,-29c-1.17603,-2.35205 -2,-4.10946 -2,-7"}, {"\u066e": "M158.5,302c3.60135,3.60135 8.82954,21.17046 7,23c-1.11515,1.11515 -9.24773,0 -11,0"}, {".": "M158.5,337"}, {"\u0633": "M149.5,321c0,6.90169 -5.01461,6.98539 -9,3c-0.33333,-0.33333 -1,-1 -1,-1c0,0 0,1.33333 0,2c0,2.1978 -3.48331,9.51669 -7,6c-1.5,-1.5 -3.5,-2.5 -5,-4c-0.60173,-0.60173 -3.49259,-6.50741 -4,-6c-2.17894,2.17894 -2.67272,7.67272 -5,10c-2.86747,2.86747 -21,-0.86363 -21,-5"}, {"\u0644": "M100.5,327c0,-10.54351 -2,-20.97206 -2,-32c0,-12.98484 -0.2321,-28.2321 -7,-35c-1.00046,-1.00046 -4,-12 -4,-12c0,0 0,6.69155 0,7c0,4.08581 0.15836,6.31672 2,10c0.86015,1.7203 -1.35264,7.64736 0,9c4.33499,4.33499 -0.94954,16.10091 2,22c7.72669,15.45337 -4.29148,38.29148 -10,44c-1.39217,1.39217 -4.94196,7 -7,7"}, {"\u0627": "M49.5,248c0,4.34545 8.74786,13.74786 12,17c1.76249,1.76249 3.48478,10.48478 5,12c5.29467,5.29467 19,32.00069 19,40"}, {"\u0645": "M66.5,321c1.64061,1.64061 3.47175,1.47175 5,3c0.5881,0.5881 3.20934,4.79066 4,4c0.66667,-0.66667 -0.66667,-3.33333 0,-4c5.56024,-5.56024 -6.89851,-16.10149 -10,-13c-0.35737,0.35737 -2.3772,15.3772 -4,17c-8.0005,8.0005 -23.8461,10.42305 -35,16c-1.80904,0.90452 -10.83083,6.16917 -13,4c-4.78528,-4.78528 -5,-11.3034 -5,-19"}, {"\u0605": "M111.5,246c3.16455,0 6.80238,5.59881 12,3c0.95479,-0.47739 12,-6.62571 12,-3"}, {"\u0627": "M140.5,246c0,22.83577 3,47.49839 3,72"}, {"\u0645": "M127.5,295c2.38053,0 7.62345,4.37655 9,3c3.39563,-3.39563 -2.31304,-12.31304 -3,-13c-6.43165,-6.43165 -12.84319,15.42159 -16,17c-2.8581,1.42905 -13,0.43354 -13,-2"}, {".": "M107.5,278"}, {"\u06ba": "M106.5,297c0,-1.61958 -2.90982,-7.09018 -3,-7c-0.60776,0.60776 -3.1783,6.1783 -6,9c-2.82,2.82 -11.7924,-2 -13,-2"}, {"\u0649": "M91.5,296c-0.95813,0 -3.39242,-1.39242 -4,-2c-1.2179,-1.2179 -17.43747,-2.56253 -19,-1c-2.33333,2.33333 -4.66667,4.66667 -7,7c-0.99572,0.99572 -4,0.01138 -4,2"}, {".": "M83.5,350"}, {".": "M102.5,348"}, {".": "M24.5,308"}, {"\u06ba": "M56.5,302c0,4.13753 -4.03159,2.03159 -6,4c-5.89586,5.89586 -18.73035,7.73035 -25,14c-0.2357,0.2357 -0.66667,0 -1,0c-2.11928,0 -9.62886,5.37114 -12,3c-4.47561,-4.47561 -10.71665,-24.28335 -4,-31c2.65979,-2.65979 8,-8.49178 8,-14"}] -------------------------------------------------------------------------------- /media/calliar_images/annotations/الحمد لله copy.json: -------------------------------------------------------------------------------- 1 | [{"\u0627": "M318.27277,269.69035c1.37437,0 2.69616,0.56539 4,1"}, {"\u0644": "M280.27277,295.69035"}, {"\u062d": "M268.27277,312.69035"}, {"\u0645": "M258.27277,340.69035c6,0 12,0 18,0"}, {"\u062f": "M386.27277,335.69035"}, {"\u0644": "M352.27277,371.69035c0,0.33333 0,0.66667 0,1"}, {"\u0644": "M227.27277,359.69035"}, {"\u0647": "M213.27277,331.69035c4.83449,-2.41725 7.1817,-7.10902 12,-10"}, {"c": "M269.27277,286.69035c0,-1.20185 1.15016,-2.15016 2,-3"}, {"o": "M291.27277,251.69035"}, {"p": "M328.27277,209.69035"}, {"y": "M327.27277,244.69035"}] -------------------------------------------------------------------------------- /media/calliar_images/annotations/الحمد لله.json: -------------------------------------------------------------------------------- 1 | [{"\u0627": "M356.27277,351.69035"}, {"\u0644": "M345.27277,343.69035c-0.74536,0 -2,-0.25464 -2,-1"}, {"\u062d": "M336.27277,340.69035"}, {"\u0645": "M330.27277,340.69035"}, {"\u062f": "M288.27277,342.69035"}, {"\u0644": "M280.27277,344.69035c-0.52705,0.52705 -1.25464,1 -2,1"}, {"\u0644": "M200.27277,353.69035"}, {"\u0647": "M200.27277,353.69035"}] -------------------------------------------------------------------------------- /media/calliar_images/annotations/خالد.json: -------------------------------------------------------------------------------- 1 | [{".": "M385.39999,291c1.01843,0 3,1.98157 3,3"}, {"\u062d": "M346.39999,397c0,-7.6845 1,-14.70921 1,-22c0,-1.27188 0.80955,-7.19045 0,-8c-2.57457,-2.57457 -4,-13.02227 -4,-17c0,-2.7925 -3.4248,-14.5752 -1,-17c3.01244,-3.01244 6.84019,-6.84019 10,-10c0.4714,-0.4714 1.33333,0 2,0c1.79222,0 11.73994,-3.26006 14,-1c1.83333,1.83333 7.16667,0.16667 9,2c5.22892,5.22892 29.9349,9.96745 40,15c4.05984,2.02992 14.97686,1 19,1c0.49342,0 6,0 6,0c0,0 -4.7973,-0.2027 -5,0c-2.85765,2.85765 -8.68321,1.68321 -12,5c-6.99662,6.99662 -20.982,8.982 -29,17c-1.88679,1.88679 -9.26953,2.26953 -12,5c-1.87971,1.87971 -21.08702,4.08702 -23,6c-0.80955,0.80955 -6.72812,0 -8,0c-6.93059,0 -23,0.26496 -23,-5"}, {"\u0627": "M333.39999,369c-9.26127,0 -11.49899,-22.99797 -16,-32c-1.05449,-2.10899 1.60293,-8.39707 0,-10c-2.20682,-2.20682 -4,-19.73791 -4,-25c0,-1.912 1.21678,-10.78322 0,-12c-3.20286,-3.20286 -1,-19.3479 -1,-25c0,-12.88489 -1,-26.53523 -1,-38c0,-2.39077 1.52143,-13.47857 0,-15c-2.76517,-2.76517 -3,-11.45295 -3,-16"}, {"\u0644": "M298.39999,220c-3.6138,0 -14.03586,-14.03586 -17,-17c-0.49958,-0.49958 -4,-8 -4,-8c0,0 -0.28958,6.71042 0,7c2.83333,2.83333 1.16667,10.16667 4,13c1.33333,1.33333 -1.33333,6.66667 0,8c1.84809,1.84809 3.55197,19.55197 4,20c2,2 2,6 4,8c1.33333,1.33333 -1.33333,6.66667 0,8c2.19439,2.19439 3,9.19779 3,13c0,0.33333 -0.2357,0.7643 0,1c1.98533,1.98533 1,9.26119 1,13c0,6.87645 2,15.46015 2,24c0,7.66667 0,15.33333 0,23c0,1.11076 0.70711,6.29289 0,7c-2.11382,2.11382 0.00729,9.99271 -2,12c-3.70067,3.70067 -5.29933,11.29933 -9,15c-9.50466,9.50466 -25.31959,-5.31959 -30,-10c-0.83333,-0.83333 -0.16667,-3.16667 -1,-4c-1.24567,-1.24567 -6,-2.14538 -6,-5"}, {"\u062f": "M233.39999,262c-1.56667,0 -1,0.66667 -1,2c0,6.80599 0.09197,18.18395 3,24c2.0147,4.0294 3,10.07083 3,15c0,0.33333 -0.2357,0.7643 0,1c3.32002,3.32002 1.29251,12.29251 4,15c4.83898,4.83898 2.86933,22.86933 7,27c0.37401,0.37401 0.37401,8.62599 0,9c-1.22575,1.22575 -2.52501,3.52501 -4,5c-10.97297,10.97297 -40.5192,27 -59,27c-2.74232,0 -23.8784,2.1216 -25,1c-2.16667,-2.16667 -1.83333,-6.83333 -4,-9c-0.29532,-0.29532 0,-16.98247 0,-19c0,-0.33333 -0.2357,-0.7643 0,-1c3.61561,-3.61561 4.914,-9.914 8,-13c5.01129,-5.01129 20,-9.33953 20,-19"}] -------------------------------------------------------------------------------- /media/calliar_images/annotations/رب يسر ولا تعسر رب تمم بالخير.json: -------------------------------------------------------------------------------- 1 | [{"\u0631": "M245.5,424c0,-11.33423 -33.5198,-12.4802 -42,-4c-4.15064,4.15064 -11.48051,5.48051 -15,9c-10.92615,10.92615 -19.6842,16.6842 -29,26c-1.55011,1.55011 -14.79716,5.20284 -17,3c-7.8597,-7.8597 -10,-21.19424 -10,-37"}, {"\u066e": "M235.5,395c0,-0.83401 9.71807,-23.28193 6,-27c-4.04871,-4.04871 -21.63648,-0.68176 -25,1c-1.89766,0.94883 -7.59229,-0.40771 -9,1c-3.14115,3.14115 -12.16147,3.16147 -15,6c-7.07342,7.07342 -16.54699,10.54699 -23,17c-1.23029,1.23029 -11.03694,5.03694 -14,8c-1.72628,1.72628 -9.41634,2.41634 -12,5c-1.83333,1.83333 -8.16667,-0.83333 -10,1c-10.07979,10.07979 -23.45414,-13.45414 -27,-17c-1.36981,-1.36981 0.20891,-13 1,-13"}, {".": "M147.5,436"}, {"\u0649": "M465.5,338c0,12.1534 1.37263,29.37263 8,36c2.66667,2.66667 -0.66667,11.33333 2,14c1.62321,1.62321 2.62551,17.74899 1,21c-5.26585,10.5317 -11.95701,10.04299 -19,3c-2.86868,-2.86868 -9,-2.23907 -9,-8"}, {".": "M445.5,469c0.33333,0 0.66667,0 1,0"}, {".": "M474.5,462"}, {"\u0633": "M449.5,397c0,7.95047 -7.82128,16.64256 -11,23c-0.53193,1.06387 -6.03779,5.96221 -8,4c-0.2357,-0.2357 0.2357,-0.7643 0,-1c-3.1189,-3.1189 -3.66255,-7.32509 -6,-12c-0.21082,-0.42164 -1,-1 -1,-1c0,0 0,1.33333 0,2c0,1.53465 -1.58452,7.58452 -3,9c-3,3 -6,6 -9,9c-1.30142,1.30142 -6.44594,-0.89189 -7,-2c-1.46644,-2.93289 -18.01928,-9 -22,-9"}, {"\u0631": "M382.5,419c-10.25241,0 -13.47552,12.23776 -23,17c-10.93993,5.46996 -25.01756,37.01756 -34,46c-1.48181,1.48181 -12.6982,8.3018 -14,7c-3.13581,-3.13581 -6.53664,-14.53664 -8,-16c-3.30106,-3.30106 -4,-7.19721 -4,-14"}, {"\u0648": "M474.5,322c0,-2.89268 -3.81163,-0.81163 -5,-2c-3.38216,-3.38216 -14.45658,-3 -21,-3c-1.06468,0 -6.33453,2.66547 -8,1c-0.80955,-0.80955 0,-6.72812 0,-8c0,-9.06332 3.5412,-15 12,-15c1.11076,0 6.29289,-0.70711 7,0c1.66667,1.66667 3.33333,3.33333 5,5c4.39101,4.39101 -0.56771,29.56771 -3,32c-0.69285,0.69285 -0.30715,4.30715 -1,5c-7.36982,7.36982 -16.01723,16.01723 -23,23c-2.96377,2.96377 -8.27799,4.27799 -11,7c-1.63285,1.63285 -8.36715,0.36715 -10,2c-2.74599,2.74599 -10.2918,0.7082 -12,-1c-1.20595,-1.20595 -3.37478,-1.18739 -5,-2c-5.66442,-2.83221 -14,-15.48292 -14,-23"}, {"\u0644": "M370.5,309c6.89887,0 9.14127,-9.14127 13,-13c14.48073,-14.48073 27.57009,-32.57009 40,-45c3.7938,-3.7938 7.8607,-13.72139 10,-18c0.17509,-0.35017 2,-2 2,-2c0,0 -1.79461,7.58921 -2,8c-1.12375,2.24749 -8.67517,19.67517 -10,21c-3.44427,3.44427 -4.19994,13.19994 -8,17c-1.33333,1.33333 0.33333,5.66667 -1,7c-3.73073,3.73073 -4.28604,14.28604 -7,17c-4.10244,4.10244 -12.31855,25.63711 -16,33c-0.63126,1.26252 0.95999,5.04001 0,6c-1.17629,1.17629 -1.37553,12.37553 2,9c8.5854,-8.5854 12.65007,-19.65007 21,-28c4.08808,-4.08808 -3,-15.24783 -3,-17"}, {"\u0627": "M411.5,312c0,-5.06576 -1.61321,-12.61321 -4,-15c-0.83333,-0.83333 -3.16667,-0.16667 -4,-1c-6.46039,-6.46039 -15.86532,-9.86532 -22,-16c-0.83333,-0.83333 -3.16667,-0.16667 -4,-1c-5.67273,-5.67273 -11.66604,-10.66604 -17,-16c-0.93882,-0.93882 -4.89052,-1.89052 -6,-3c-2.34815,-2.34815 -3.93659,-6.46829 -7,-8c-8.36423,-4.18212 -8.75619,-14.75619 -15,-21c-0.41594,-0.41594 -5,-5 -5,-5c0,0 4.56408,0.56408 5,1c1.85245,1.85245 6.61033,9 11,9"}, {".": "M307.5,316"}, {".": "M317.5,303"}, {"\u066e": "M351.5,350c0,7.77957 11,20.37661 11,31c0,3.83478 1.06299,11.93701 -1,14c-5.53534,5.53534 -27.72298,-0.27702 -32,4c-0.33193,0.33193 -7.66807,0.33193 -8,0c-1.33333,-1.33333 -0.66667,-4.66667 -2,-6c-1.48186,-1.48186 -4,-3.1592 -4,-6"}, {"\u0639": "M292.5,337c-11.3917,0 -28.96839,-0.03161 -36,7c-4.27899,4.27899 -6.33454,11.33454 -10,15c-1.21202,1.21202 -8.56246,15.43754 -5,19c3.30321,3.30321 5.58452,8.58452 10,13c3.33333,3.33333 12.66667,0.66667 16,4c1.41991,1.41991 11.76877,0 14,0c14.326,0 28.14202,-7.14202 35,-14c0.58132,-0.58132 7.43894,-8.56106 6,-10c-0.4714,-0.4714 -1.40372,-0.29814 -2,0c-3.72605,1.86303 -5.9452,7.9452 -9,11c-4.38154,4.38154 -14.62231,9.24462 -18,16c-1.2978,2.59561 -5.17456,5.17456 -7,7c-3.62705,3.62705 -4.9075,11.9075 -9,16c-5.87369,5.87369 -9.19837,13.79755 -14,21c-0.3698,0.5547 -1.70186,-0.59628 -2,0c-3.48494,6.96988 -7.71539,15.43077 -12,24c-1.70777,3.41553 0.75166,7.49669 -1,11c-1.26651,2.53301 -2.22458,27.55084 -1,30c11.11864,22.23728 17.58735,27 49,27c8.47601,0 19.1702,0.8298 24,-4c3.99954,-3.99954 9.78515,-9.78515 14,-14c3.84015,-3.84015 5.03854,-10.03854 8,-13c4.62492,-4.62492 3.69785,-16.69785 8,-21c0.70114,-0.70114 1,-15.83534 1,-18c0,-8.49951 1.36177,-20.63823 -3,-25c-4.85692,-4.85692 -14,-11.52252 -14,-20"}, {"\u0633": "M336.5,418c0,8.44596 1.25057,18.74943 -3,23c-3.62621,3.62621 -12.69837,-9.69837 -13,-10c-0.2357,-0.2357 0,-0.66667 0,-1c0,-0.43333 -1,-2 -1,-2c0,0 0.15584,3.84416 0,4c-2.61202,2.61202 -5.38798,6.38798 -8,9c-2.42926,2.42926 -8.9339,0.9339 -11,3c-0.37401,0.37401 -8.62599,0.37401 -9,0c-3.95704,-3.95704 -16.01154,-11 -23,-11"}, {"\u0631": "M270.5,433c-5.03425,0 -15.71839,1.71839 -19,5c-1.73425,1.73425 -7.46886,0.46886 -9,2c-3.30894,3.30894 -8.53067,4.53067 -12,8c-2.10318,2.10318 -2.52764,7.52764 -5,10c-5.68799,5.68799 -6.51629,12.51629 -12,18c-0.69285,0.69285 -0.30715,4.30715 -1,5c-4.83503,4.83503 -8.86812,11.86812 -13,16c-1.1843,1.1843 -18.19546,4.60908 -20,1c-1.62694,-3.25387 -9.14992,-26.14992 -10,-27c-3.22402,-3.22402 2,-16.11381 2,-17"}, {"\u0631": "M484.5,443c0,-5.3235 -12.40908,-12.79546 -20,-9c-3.87357,1.93678 -7.87827,4.62609 -12,6c-1.51053,0.50351 -5.91175,-0.08825 -7,1c-8.82241,8.82241 -19.31706,20.31706 -29,30c-4.34501,4.34501 -7.85848,11.92924 -14,15c-1.60484,0.80242 -16.56219,7.43781 -19,5c-5.661,-5.661 -12,-17.84585 -12,-28c0,-8.39607 3,-13.78873 3,-19"}, {"\u066e": "M484.5,392c0,-7.01089 9,-14.34599 9,-22c0,-1.45645 2.47231,-6.52769 1,-8c-0.33193,-0.33193 -7.66807,-0.33193 -8,0c-5.0563,5.0563 -16.57066,8.78533 -23,12c-20.30846,10.15423 -34.75752,21 -61,21c-8.55877,0 -21.68699,1.31301 -27,-4c-6.73077,-6.73077 -9,-17.59076 -9,-31"}, {".": "M391.5,465"}, {".": "M307.5,171"}, {".": "M308.5,148"}, {"\u066e": "M304.5,242c0,-3.03629 -15.52738,-7.47262 -17,-6c-3.91165,3.91165 -12.42508,24.42508 -19,31c-2.52427,2.52427 -6.60114,6 -10,6c-1.33333,0 -2,0.56667 -2,-1"}, {"\u0645": "M257.5,272c-3.87845,0 -12.60634,-1.69683 -16,0c-7.75674,3.87837 -10.28384,16.43232 -7,23c0.69794,1.39589 7.58824,7.41176 10,5c3.24366,-3.24366 -1.8282,-10.8282 -3,-12c-4.95633,-4.95633 -8.56094,-6 -19,-6"}, {"\u0645": "M222.5,281c-10.52624,10.52624 -11.28727,30.71273 -2,40c2.63495,2.63495 3.69459,6.69459 6,9c1.20185,1.20185 5,2.69967 5,1c0,-4.44846 -18.83866,-9.16134 -23,-5c-2.17106,2.17106 -9.4673,1.4673 -12,4c-4.19308,4.19308 -24.93995,15.96997 -31,19c-4.98452,2.49226 -10.31298,1.31298 -14,5c-0.38964,0.38964 -3.38976,0 -4,0c-6.29144,0 -11.55392,1 -18,1c-0.75115,0 -6.77123,0.45755 -7,0c-2.98399,-5.96799 -5,-16.17206 -5,-24c0,-1.61737 -0.92137,-8.07863 0,-9c1.63549,-1.63549 2.03726,-5.03726 4,-7c1.38147,-1.38147 5.61853,-2.61853 7,-4c1.08864,-1.08864 2.98494,-3 5,-3"}, {"\u066e": "M380.5,194c0,13.20157 2.21771,30.78229 -5,38c-4.77388,4.77388 -15.95302,-9 -17,-9c-0.4714,0 -1,-0.5286 -1,-1c0,-0.4714 -0.66667,-0.66667 -1,-1c-0.4714,-0.4714 0,-1.33333 0,-2"}, {".": "M393.5,256"}, {"\u0627": "M362.5,228c0,-1.0744 -3.71233,-5.71233 -5,-7c-1.14924,-1.14924 -5.89274,-21.78548 -8,-26c-3.42829,-6.85658 1.35638,-19.64362 -4,-25c-2,-2 2,-10 0,-12c-2.89414,-2.89414 0.05535,-7.8893 -2,-12c-5.50105,-11.0021 -8.96654,-27.96654 -17,-36c-11.61035,-11.61035 -30.25346,-14 -53,-14"}, {"\u0644": "M271.5,100c0,13.84284 -1,28.56508 -1,43c0,4.05773 -1.18827,12.81173 1,15c3.33333,3.33333 -2.33333,15.66667 1,19c2.20778,2.20778 2.03942,20.03942 4,22c1.24558,1.24558 5.3447,10 4,10"}, {".": "M231.5,156"}, {"\u062d": "M251.5,211c0,-5.16462 12.053,-6 17,-6c7.80206,0 16.71278,-0.64361 22,2c1.33815,0.66908 5.95196,-1.04804 7,0c2.92313,2.92313 12.22822,4 17,4c6.18317,0 11.52845,1 18,1c0.49342,0 6,0 6,0c0,0 -9.16811,0 -10,0c-3.70359,0 -10.59794,3.59794 -13,6c-0.66667,0.66667 -3.33333,-0.66667 -4,0c-4.98346,4.98346 -23.00928,6.00928 -27,10c-4.63881,4.63881 -11.06191,6.06191 -15,10c-0.83333,0.83333 -0.16667,3.16667 -1,4c-2.68169,2.68169 -9,6.07099 -9,11"}, {"\u0649": "M259.5,249c-4.13742,0 -4.3773,5.3773 -7,8c-3.01692,3.01692 -2.76969,12.76969 -4,14c-3.08613,3.08613 -5,23.66736 -5,30c0,1.85553 -0.2064,18.7936 0,19c2.11382,2.11382 2.99271,6.99271 5,9c11.67187,11.67187 27.34538,21 50,21c4.41756,0 18.05352,1.94648 21,-1c6.47796,-6.47796 14.54877,-11.54877 22,-19c1.97051,-1.97051 5.50735,-15.50735 6,-16c1.58487,-1.58487 2.58964,-19.41036 0,-22c-1.09276,-1.09276 -3.03286,-2.06572 -4,-4c-3.83757,-7.67514 -14.30489,-15.43496 -25,-19c-6.79361,-2.26454 -18.85478,0.14522 -23,-4c-1.5,-1.5 -6.5,0.5 -8,-1c-0.2357,-0.2357 -0.66667,0 -1,0c-4.83957,0 -12.87202,1.06399 -17,-1c-2.74727,-1.37363 -11.09012,-2.09012 -13,-4c-3.2342,-3.2342 -13.59111,-14 -19,-14"}, {".": "M289.5,305"}, {".": "M303.5,294"}, {"\u0631": "M239.5,247c-25.56308,0 -43.3135,20.3135 -58,35c-6.54055,6.54055 -14.38079,10.19039 -22,14c-2.15083,1.07542 -3.53814,-0.46186 -5,1c-2.84741,2.84741 -15.33982,-0.66991 -18,-2c-9.65454,-4.82727 -15,-17.74091 -15,-29c0,-6.50622 1.05493,-19 6,-19"}] -------------------------------------------------------------------------------- /media/calliar_images/images/الحمد لله.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/calliar_images/images/الحمد لله.jpg -------------------------------------------------------------------------------- /media/data_format.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/data_format.PNG -------------------------------------------------------------------------------- /media/data_format_colored.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/data_format_colored.png -------------------------------------------------------------------------------- /media/different_calls.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/different_calls.PNG -------------------------------------------------------------------------------- /media/sample_calliar_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_image.png -------------------------------------------------------------------------------- /media/sample_calliar_image_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_image_2.png -------------------------------------------------------------------------------- /media/sample_calliar_image_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_image_3.png -------------------------------------------------------------------------------- /media/sample_calliar_video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_video.mp4 -------------------------------------------------------------------------------- /media/sample_calliar_video_2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_video_2.mp4 -------------------------------------------------------------------------------- /media/sample_calliar_video_3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARBML/Calliar/dc1b9f8b58bf026f79c12fc92284ea5190d04991/media/sample_calliar_video_3.mp4 -------------------------------------------------------------------------------- /notebooks/Collect bism allah.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 5, 6 | "id": "graduate-blake", 7 | "metadata": { 8 | "scrolled": true 9 | }, 10 | "outputs": [], 11 | "source": [ 12 | "import os\n", 13 | "from shutil import copyfile\n", 14 | "data_path = 'server/larger_data'" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 9, 20 | "id": "induced-chicken", 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "os.makedirs('bism_data', exist_ok = True)\n", 25 | "for file in os.listdir(data_path):\n", 26 | " if 'بسم' in file:\n", 27 | " copyfile(f'{data_path}/{file}', f'bism_data/{file}')" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 11, 33 | "id": "arctic-blame", 34 | "metadata": {}, 35 | "outputs": [ 36 | { 37 | "name": "stdout", 38 | "output_type": "stream", 39 | "text": [ 40 | "updating: bism_data/ (stored 0%)\n", 41 | " adding: bism_data/106بسم الله الرحمن الرحيم.jpg (deflated 13%)\n", 42 | " adding: bism_data/47بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 43 | " adding: bism_data/31بسم الله الرحمن الرحيم.jpg (deflated 8%)\n", 44 | " adding: bism_data/24بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 45 | " adding: bism_data/92بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 46 | " adding: bism_data/109بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 47 | " adding: bism_data/4بسم الله.jpg (deflated 1%)\n", 48 | " adding: bism_data/37بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 49 | " adding: bism_data/76بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 50 | " adding: bism_data/22بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 51 | " adding: bism_data/104بسم الله الرحمن الرحيم.jpg (deflated 3%)\n", 52 | " adding: bism_data/بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 53 | " adding: bism_data/81بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 54 | " adding: bism_data/15بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 55 | " adding: bism_data/162بسم الله الرحمن الرحيم.jpg (deflated 20%)\n", 56 | " adding: bism_data/79بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 57 | " adding: bism_data/85بسم الله الرحمن الرحيم.jpg (deflated 10%)\n", 58 | " adding: bism_data/113بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 59 | " adding: bism_data/123بسم الله الرحمن الرحيم.jpg (deflated 53%)\n", 60 | " adding: bism_data/بسم الله الرحمن الرجيم.jpg (deflated 13%)\n", 61 | " adding: bism_data/127بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 62 | " adding: bism_data/161بسم الله الرحمن الرحيم.jpg (deflated 3%)\n", 63 | " adding: bism_data/124بسم الله الرحمن الرحيم.jpg (deflated 7%)\n", 64 | " adding: bism_data/99بسم الله الرحمن الرحيم.jpg (deflated 6%)\n", 65 | " adding: bism_data/125بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 66 | " adding: bism_data/145بسم الله الرحمن الرحيم.jpg (deflated 18%)\n", 67 | " adding: bism_data/39بسم الله الرحمن الرحيم.jpg (deflated 29%)\n", 68 | " adding: bism_data/4بسم الله الرحمن الرحيم .jpg (deflated 4%)\n", 69 | " adding: bism_data/67بسم الله الرحمن الرحيم.jpg (deflated 9%)\n", 70 | " adding: bism_data/10بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 71 | " adding: bism_data/32بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 72 | " adding: bism_data/3بسم الله.jpg (deflated 0%)\n", 73 | " adding: bism_data/73بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 74 | " adding: bism_data/44بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 75 | " adding: bism_data/137بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 76 | " adding: bism_data/2بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 77 | " adding: bism_data/8بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 78 | " adding: bism_data/143بسم الله الرحمن الرحيم.jpg (deflated 8%)\n", 79 | " adding: bism_data/بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 80 | " adding: bism_data/26بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 81 | " adding: bism_data/80بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 82 | " adding: bism_data/133بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 83 | " adding: bism_data/33بسم الله الرحمن الرحيم.jpg (deflated 47%)\n", 84 | " adding: bism_data/53بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 85 | " adding: bism_data/46بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 86 | " adding: bism_data/129بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 87 | " adding: bism_data/115بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 88 | " adding: bism_data/111بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 89 | " adding: bism_data/151بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 90 | " adding: bism_data/156بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 91 | " adding: bism_data/17بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 92 | " adding: bism_data/3بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 93 | " adding: bism_data/38بسم الله الرحمن الرحيم.jpg (deflated 31%)\n", 94 | " adding: bism_data/114بسم الله الرحمن الرحيم.jpg (deflated 32%)\n", 95 | " adding: bism_data/40بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 96 | " adding: bism_data/108بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 97 | " adding: bism_data/71بسم الله الرحمن الرحيم.jpg (deflated 31%)\n", 98 | " adding: bism_data/بسم الله الرحمن الحريم.jpg (deflated 14%)\n", 99 | " adding: bism_data/97بسم الله الرحمن الرحيم.jpg (deflated 7%)\n", 100 | " adding: bism_data/66بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 101 | " adding: bism_data/112بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 102 | " adding: bism_data/140بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 103 | " adding: bism_data/56بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 104 | " adding: bism_data/52بسم الله الرحمن الرحيم.jpg (deflated 50%)\n", 105 | " adding: bism_data/163بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 106 | " adding: bism_data/90بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 107 | " adding: bism_data/117بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 108 | " adding: bism_data/3بسم الله الرحمن الرحيم .jpg (deflated 1%)\n", 109 | " adding: bism_data/36بسم الله الرحمن الرحيم.jpg (deflated 29%)\n", 110 | " adding: bism_data/27بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 111 | " adding: bism_data/51بسم الله الرحمن الرحيم.jpg (deflated 33%)\n", 112 | " adding: bism_data/11بسم الله الرحمن الرحيم.jpg (deflated 6%)\n", 113 | " adding: bism_data/105بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 114 | " adding: bism_data/94بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 115 | " adding: bism_data/28بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 116 | " adding: bism_data/9بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 117 | " adding: bism_data/اقرأ بسم ربك.jpg (deflated 39%)\n", 118 | " adding: bism_data/148بسم الله الرحمن الرحيم.jpg (deflated 25%)\n", 119 | " adding: bism_data/1بسم الله.jpg (stored 0%)\n", 120 | " adding: bism_data/82بسم الله الرحمن الرحيم.jpg (deflated 44%)\n", 121 | " adding: bism_data/18بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 122 | " adding: bism_data/100بسم الله الرحمن الرحيم.jpg (deflated 7%)\n", 123 | " adding: bism_data/41بسم الله الرحمن الرحيم.jpg (deflated 15%)\n", 124 | " adding: bism_data/75بسم الله الرحمن الرحيم.jpg (deflated 39%)\n", 125 | " adding: bism_data/2بسم الله الرحمن الرحيم .jpg (deflated 23%)\n", 126 | " adding: bism_data/154بسم الله الرحمن الرحيم.jpg (deflated 4%)\n", 127 | " adding: bism_data/بسم الله ماشاء الله.jpg (stored 0%)\n", 128 | " adding: bism_data/87بسم الله الرحمن الرحيم.jpg (deflated 34%)\n", 129 | " adding: bism_data/98بسم الله الرحمن الرحيم.jpg (deflated 3%)\n", 130 | " adding: bism_data/157بسم الله الرحمن الرحيم.jpg (deflated 39%)\n", 131 | " adding: bism_data/59بسم الله الرحمن الرحيم.jpg (deflated 6%)\n", 132 | " adding: bism_data/65بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 133 | " adding: bism_data/5بسم الله.jpg (deflated 46%)\n", 134 | " adding: bism_data/58بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 135 | " adding: bism_data/69بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 136 | " adding: bism_data/155بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 137 | " adding: bism_data/131بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 138 | " adding: bism_data/55بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 139 | " adding: bism_data/93بسم الله الرحمن الرحيم.jpg (deflated 24%)\n", 140 | " adding: bism_data/126بسم الله الرحمن الرحيم.jpg (deflated 5%)\n", 141 | " adding: bism_data/89بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 142 | " adding: bism_data/116بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 143 | " adding: bism_data/30بسم الله الرحمن الرحيم.jpg (deflated 30%)\n", 144 | " adding: bism_data/142بسم الله الرحمن الرحيم.jpg (deflated 4%)\n", 145 | " adding: bism_data/78بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 146 | " adding: bism_data/70بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 147 | " adding: bism_data/4بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 148 | " adding: bism_data/29بسم الله الرحمن الرحيم.jpg (deflated 45%)\n", 149 | " adding: bism_data/158بسم الله الرحمن الرحيم.jpg (deflated 64%)\n", 150 | " adding: bism_data/13بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 151 | " adding: bism_data/144بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 152 | " adding: bism_data/160بسم الله الرحمن الرحيم.jpg (deflated 3%)\n", 153 | " adding: bism_data/14بسم الله الرحمن الرحيم.jpg (deflated 6%)\n", 154 | " adding: bism_data/45بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 155 | " adding: bism_data/86بسم الله الرحمن الرحيم.jpg (deflated 55%)\n", 156 | " adding: bism_data/42بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 157 | " adding: bism_data/7بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 158 | " adding: bism_data/136بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 159 | " adding: bism_data/بسم الله الرحمن الرحيم .jpg (deflated 0%)\n", 160 | " adding: bism_data/120بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 161 | " adding: bism_data/50بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 162 | " adding: bism_data/147بسم الله الرحمن الرحيم.jpg (deflated 7%)\n", 163 | " adding: bism_data/118بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 164 | " adding: bism_data/بسم الله.jpg (deflated 18%)\n", 165 | " adding: bism_data/60بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 166 | " adding: bism_data/110بسم الله الرحمن الرحيم.jpg (deflated 5%)\n", 167 | " adding: bism_data/83بسم الله الرحمن الرحيم.jpg (deflated 34%)\n", 168 | " adding: bism_data/150بسم الله الرحمن الرحيم.jpg (deflated 37%)\n", 169 | " adding: bism_data/101بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 170 | " adding: bism_data/49بسم الله الرحمن الرحيم.jpg (deflated 27%)\n", 171 | " adding: bism_data/77بسم الله الرحمن الرحيم.jpg (deflated 41%)\n", 172 | " adding: bism_data/بسم الله الرحمن الرحيم و انك لعلى خلق عظيم.jpg (deflated 1%)\n", 173 | " adding: bism_data/95بسم الله الرحمن الرحيم.jpg (deflated 5%)\n" 174 | ] 175 | }, 176 | { 177 | "name": "stdout", 178 | "output_type": "stream", 179 | "text": [ 180 | " adding: bism_data/74بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 181 | " adding: bism_data/159بسم الله الرحمن الرحيم.jpg (deflated 5%)\n", 182 | " adding: bism_data/138بسم الله الرحمن الرحيم.jpg (deflated 21%)\n", 183 | " adding: bism_data/96بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 184 | " adding: bism_data/121بسم الله الرحمن الرحيم.jpg (deflated 22%)\n", 185 | " adding: bism_data/16بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 186 | " adding: bism_data/88بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 187 | " adding: bism_data/34بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 188 | " adding: bism_data/153بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 189 | " adding: bism_data/141بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 190 | " adding: bism_data/102بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 191 | " adding: bism_data/91بسم الله الرحمن الرحيم.jpg (deflated 24%)\n", 192 | " adding: bism_data/1بسم الله الرحمن الرحيم .jpg (deflated 0%)\n", 193 | " adding: bism_data/بسم الله ما شاء الله.jpg (deflated 0%)\n", 194 | " adding: bism_data/152بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 195 | " adding: bism_data/54بسم الله الرحمن الرحيم.jpg (deflated 51%)\n", 196 | " adding: bism_data/135بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 197 | " adding: bism_data/128بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 198 | " adding: bism_data/بسم اله الرحمن الرحيم.jpg (deflated 48%)\n", 199 | " adding: bism_data/119بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 200 | " adding: bism_data/64بسم الله الرحمن الرحيم.jpg (deflated 19%)\n", 201 | " adding: bism_data/25بسم الله الرحمن الرحيم.jpg (deflated 2%)\n", 202 | " adding: bism_data/23بسم الله الرحمن الرحيم.jpg (stored 0%)\n", 203 | " adding: bism_data/12بسم الله الرحمن الرحيم.jpg (deflated 30%)\n", 204 | " adding: bism_data/68بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 205 | " adding: bism_data/146بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 206 | " adding: bism_data/130بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 207 | " adding: bism_data/84بسم الله الرحمن الرحيم.jpg (deflated 3%)\n", 208 | " adding: bism_data/139بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 209 | " adding: bism_data/103بسم الله الرحمن الرحيم.jpg (deflated 5%)\n", 210 | " adding: bism_data/43بسم الله الرحمن الرحيم.jpg (deflated 22%)\n", 211 | " adding: bism_data/21بسم الله الرحمن الرحيم.jpg (deflated 10%)\n", 212 | " adding: bism_data/134بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 213 | " adding: bism_data/20بسم الله الرحمن الرحيم.jpg (deflated 4%)\n", 214 | " adding: bism_data/149بسم الله الرحمن الرحيم.jpg (deflated 4%)\n", 215 | " adding: bism_data/107بسم الله الرحمن الرحيم.jpg (deflated 7%)\n", 216 | " adding: bism_data/132بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 217 | " adding: bism_data/72بسم الله الرحمن الرحيم.jpg (deflated 17%)\n", 218 | " adding: bism_data/1بسم الله الرحمن الحريم.jpg (deflated 42%)\n", 219 | " adding: bism_data/57بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 220 | " adding: bism_data/61بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 221 | " adding: bism_data/48بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 222 | " adding: bism_data/122بسم الله الرحمن الرحيم.jpg (deflated 49%)\n", 223 | " adding: bism_data/5بسم الله الرحمن الرحيم.jpg (deflated 1%)\n", 224 | " adding: bism_data/62بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 225 | " adding: bism_data/1بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 226 | " adding: bism_data/35بسم الله الرحمن الرحيم.jpg (deflated 37%)\n", 227 | " adding: bism_data/6بسم الله الرحمن الرحيم.jpg (deflated 35%)\n", 228 | " adding: bism_data/19بسم الله الرحمن الرحيم.jpg (deflated 0%)\n", 229 | " adding: bism_data/2بسم الله.jpg (deflated 17%)\n", 230 | " adding: bism_data/63بسم الله الرحمن الرحيم.jpg (deflated 0%)\n" 231 | ] 232 | } 233 | ], 234 | "source": [ 235 | "!zip -r bism_data.zip bism_data" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "id": "compatible-minimum", 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [] 245 | } 246 | ], 247 | "metadata": { 248 | "kernelspec": { 249 | "display_name": "Python 3", 250 | "language": "python", 251 | "name": "python3" 252 | }, 253 | "language_info": { 254 | "codemirror_mode": { 255 | "name": "ipython", 256 | "version": 3 257 | }, 258 | "file_extension": ".py", 259 | "mimetype": "text/x-python", 260 | "name": "python", 261 | "nbconvert_exporter": "python", 262 | "pygments_lexer": "ipython3", 263 | "version": "3.6.9" 264 | } 265 | }, 266 | "nbformat": 4, 267 | "nbformat_minor": 5 268 | } 269 | -------------------------------------------------------------------------------- /notebooks/Colorize text and image.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "binding-membrane", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "\u001b[31mhello\u001b[0m \u001b[32mworld\u001b[0m\n", 14 | "\u001b[31mhello red world\u001b[0m\n" 15 | ] 16 | } 17 | ], 18 | "source": [ 19 | "from termcolor import colored\n", 20 | "print(colored('hello', 'red'), colored('world', 'green'))\n", 21 | "print(colored(\"hello red world\", 'red'))" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 198, 27 | "id": "sitting-blend", 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "out = [{'.': [[332, 124]]},\n", 32 | "{'ح': [[331, 150], [336, 149], [354, 169], [318, 169]]},\n", 33 | "{'ا': [[321, 170], [315, 169], [308, 162], [303, 124]]},\n", 34 | "{'ل': [[286, 119], [286, 157], [282, 163], [268, 163]]},\n", 35 | "{'د': [[250, 144], [260, 156], [264, 172], [259, 176], [244, 176], [238, 171]]}]" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 199, 41 | "id": "engaging-hopkins", 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "colors = ['red', 'green', 'blue', 'magenta', 'grey']" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 200, 51 | "id": "convertible-bookmark", 52 | "metadata": {}, 53 | "outputs": [ 54 | { 55 | "name": "stdout", 56 | "output_type": "stream", 57 | "text": [ 58 | "\u001b[31m{'.': [[332, 124]]}\u001b[0m\n", 59 | "\u001b[32m{'ح': [[331, 150], [336, 149], [354, 169], [318, 169]]}\u001b[0m\n", 60 | "\u001b[34m{'ا': [[321, 170], [315, 169], [308, 162], [303, 124]]}\u001b[0m\n", 61 | "\u001b[35m{'ل': [[286, 119], [286, 157], [282, 163], [268, 163]]}\u001b[0m\n", 62 | "\u001b[30m{'د': [[250, 144], [260, 156], [264, 172], [259, 176], [244, 176], [238, 171]]}\u001b[0m\n" 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "for i, ins in enumerate(out):\n", 68 | " print(colored(ins, colors[i]))" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 25, 74 | "id": "several-botswana", 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "from PIL import Image, ImageDraw\n", 79 | "import json\n", 80 | "import numpy as np\n", 81 | "\n", 82 | "def img_from_stroke(drawing):\n", 83 | " img_A = Image.new('RGB', (600, 600), (255, 255, 255)) \n", 84 | " draw = ImageDraw.Draw(img_A) \n", 85 | " for j, item in enumerate(drawing):\n", 86 | " char = list(item.keys())[0]\n", 87 | " stroke = item[char]\n", 88 | " if len(stroke) == 1:\n", 89 | " x, y = stroke[0]\n", 90 | " stroke.append([x+5, y+5])\n", 91 | " for i, point in enumerate(stroke):\n", 92 | " if i == 0:\n", 93 | " x_prev, y_prev = point\n", 94 | " continue\n", 95 | " x, y = point \n", 96 | " draw.line([x_prev, y_prev, x, y], fill=colors[j], width = 3)\n", 97 | " x_prev, y_prev = x, y\n", 98 | " return img_A" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 26, 104 | "id": "cordless-ticket", 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "data": { 109 | "image/png": "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AGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCECaEAKQJoQApAkhAGlCCEDaX/417q9wP9g1AAAAAElFTkSuQmCC\n", 110 | "text/plain": [ 111 | "" 112 | ] 113 | }, 114 | "execution_count": 26, 115 | "metadata": {}, 116 | "output_type": "execute_result" 117 | } 118 | ], 119 | "source": [ 120 | "img_from_stroke(out)" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 31, 126 | "id": "specified-comedy", 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "import numpy as np\n", 131 | "import math, json\n", 132 | "from rdp import rdp\n", 133 | "import numpy as np\n", 134 | "import matplotlib.pyplot as plt\n", 135 | "from IPython.display import HTML\n", 136 | "import tqdm.notebook as tq\n", 137 | "import pickle\n", 138 | "from collections import defaultdict\n", 139 | "import cairosvg\n", 140 | "from PIL import Image,ImageDraw\n", 141 | "import glob\n", 142 | "import os \n", 143 | "import re\n", 144 | "import svgwrite" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 32, 150 | "id": "neither-pharmacy", 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "def convert_3d(drawing, return_flag = False, threshold=50):\n", 155 | " out = []\n", 156 | " corrupted = False\n", 157 | " for item in drawing:\n", 158 | " char = list(item.keys())[0]\n", 159 | " stroke = item[char]\n", 160 | " if len(stroke) == 1:\n", 161 | " x, y = stroke[0]\n", 162 | " out.append([x, y, 0])\n", 163 | " out.append([x+5, y+5, 1])\n", 164 | " continue\n", 165 | " segment = []\n", 166 | " for i, point in enumerate(stroke):\n", 167 | " x, y = point \n", 168 | " if i == len(stroke) - 1:\n", 169 | " segment.append([x, y, 1])\n", 170 | " else:\n", 171 | " segment.append([x, y, 0])\n", 172 | " \n", 173 | " start = 0 \n", 174 | " out += segment[start:]\n", 175 | " if return_flag:\n", 176 | " return out, corrupted\n", 177 | " return out" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 190, 183 | "id": "severe-immigration", 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "def get_bounds(data):\n", 188 | " minx, miny = 600, 600 \n", 189 | " maxx, maxy = 0, 0\n", 190 | " \n", 191 | " for i, (x, y, z) in enumerate(data): \n", 192 | " if minx > x:\n", 193 | " minx = x\n", 194 | " if miny > y:\n", 195 | " miny = y \n", 196 | "\n", 197 | " if maxx < x:\n", 198 | " maxx = x\n", 199 | " if maxy < y:\n", 200 | " maxy = y \n", 201 | " return minx, maxx, miny, maxy\n", 202 | "\n", 203 | "def draw_strokes(data, factor=1, svg_filename = 'tmp/sample.svg', stroke_width = 3, square = False, return_res = False):\n", 204 | " min_x, max_x, min_y, max_y = get_bounds(data)\n", 205 | " margin_x = (600 - max_x - min_x)/2\n", 206 | " margin_y = (600 - max_y - min_y)/2\n", 207 | " \n", 208 | " data = [[x + margin_x, y + margin_y, z] for [x, y, z] in data]\n", 209 | " \n", 210 | " min_x, max_x, min_y, max_y = get_bounds(data)\n", 211 | " dims = ( 5 + max_x - min_x, 5 +max_y - min_y)\n", 212 | " dwg = svgwrite.Drawing(svg_filename, size = dims)\n", 213 | " dwg.add(dwg.rect(insert=(0, 0), size=dims,fill='white'))\n", 214 | " lift_pen = 0\n", 215 | " abs_x = 25 - min_x \n", 216 | " abs_y = 25 - min_y\n", 217 | " p = \"M%s,%s \" % (min_x, min_y)\n", 218 | " command = \"M\"\n", 219 | " j = 0 \n", 220 | " for i in range(0, len(data)):\n", 221 | " x = float(data[i][0]) - min_x\n", 222 | " y = float(data[i][1]) - min_y\n", 223 | " lift_pen = data[i][2]\n", 224 | " p += command+str(x)+\" \"+str(y)+\" \" \n", 225 | " \n", 226 | " if (lift_pen == 1):\n", 227 | " command = \"M\"\n", 228 | " dwg.add(dwg.path(p).stroke(colors[j],stroke_width).fill(\"none\"))\n", 229 | " p = \"\"\n", 230 | " j += 1\n", 231 | " else:\n", 232 | " command = \"\" \n", 233 | " \n", 234 | " dwg.save()\n", 235 | " cairosvg.svg2png(url=\"tmp/sample.svg\", write_to=\"tmp/sample.png\")\n", 236 | " img = Image.open('tmp/sample.png')\n", 237 | " img = make_square(img)\n", 238 | " return img" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 194, 244 | "id": "fresh-strategy", 245 | "metadata": {}, 246 | "outputs": [], 247 | "source": [ 248 | "import json \n", 249 | "file = 'dataset/train/'+'عمر_15.json'\n", 250 | "drawing = json.load(open(file, 'r'))" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 195, 256 | "id": "thick-portfolio", 257 | "metadata": {}, 258 | "outputs": [ 259 | { 260 | "data": { 261 | "image/png": "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\n", 262 | "text/plain": [ 263 | "
" 264 | ] 265 | }, 266 | "metadata": {}, 267 | "output_type": "display_data" 268 | } 269 | ], 270 | "source": [ 271 | "data = convert_3d(drawing)\n", 272 | "plt.imshow(draw_strokes(data, stroke_width = 5))\n", 273 | "plt.xticks([])\n", 274 | "plt.yticks([])\n", 275 | "plt.show()" 276 | ] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "execution_count": null, 281 | "id": "sweet-estate", 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [] 285 | } 286 | ], 287 | "metadata": { 288 | "kernelspec": { 289 | "display_name": "Python 3", 290 | "language": "python", 291 | "name": "python3" 292 | }, 293 | "language_info": { 294 | "codemirror_mode": { 295 | "name": "ipython", 296 | "version": 3 297 | }, 298 | "file_extension": ".py", 299 | "mimetype": "text/x-python", 300 | "name": "python", 301 | "nbconvert_exporter": "python", 302 | "pygments_lexer": "ipython3", 303 | "version": "3.6.9" 304 | } 305 | }, 306 | "nbformat": 4, 307 | "nbformat_minor": 5 308 | } 309 | -------------------------------------------------------------------------------- /notebooks/Generate as minified json.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "alternative-quality", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "test train valid\r\n" 14 | ] 15 | } 16 | ], 17 | "source": [ 18 | "!ls dataset" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 5, 24 | "id": "tested-boxing", 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "import json \n", 29 | "import glob" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 6, 35 | "id": "sacred-closing", 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "name": "stdout", 40 | "output_type": "stream", 41 | "text": [ 42 | "2000\n" 43 | ] 44 | } 45 | ], 46 | "source": [ 47 | "json_files = glob.glob('dataset/train/**.json')\n", 48 | "print(len(json_files))" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 30, 54 | "id": "listed-wilson", 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "out = \"\"\n", 59 | "threshold = 20 \n", 60 | "\n", 61 | "for i in range(100):\n", 62 | " file = json_files[i]\n", 63 | " drawing = json.load(open(file))\n", 64 | " drawing_name = f\"stroke_{i}\"\n", 65 | " curr_drawing = \"[\"\n", 66 | " for d, item in enumerate(drawing):\n", 67 | " char = list(item.keys())[0]\n", 68 | " stroke = item[char]\n", 69 | " new_stroke = \"\"\n", 70 | " start = 0 \n", 71 | " for i, point in enumerate(stroke):\n", 72 | " if i < len(stroke) -1:\n", 73 | " x, y = point\n", 74 | " next_x, next_y = stroke[i+1]\n", 75 | " if any((\n", 76 | " abs(x-next_x)>threshold,\n", 77 | " abs(y-next_y>threshold),\n", 78 | " )):\n", 79 | " corrupted=True\n", 80 | " start = i +1\n", 81 | " \n", 82 | " for j, (x, y) in enumerate(stroke[start:]):\n", 83 | " new_stroke += f\"[{int(x)}, {int(y)}]\"\n", 84 | " if j != len(stroke) - 1:\n", 85 | " new_stroke += \",\"\n", 86 | " curr_drawing += f\"[{new_stroke}]\"\n", 87 | " if d != len(drawing) - 1:\n", 88 | " curr_drawing += \",\"\n", 89 | " \n", 90 | " out += f\"{drawing_name} = {curr_drawing}] \\n\"" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 31, 96 | "id": "guided-thread", 97 | "metadata": {}, 98 | "outputs": [ 99 | { 100 | "data": { 101 | "text/plain": [ 102 | "794698" 103 | ] 104 | }, 105 | "execution_count": 31, 106 | "metadata": {}, 107 | "output_type": "execute_result" 108 | } 109 | ], 110 | "source": [ 111 | "open(\"json_sm.js\", 'w').write(out)" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 32, 117 | "id": "challenging-milan", 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "name": "stdout", 122 | "output_type": "stream", 123 | "text": [ 124 | "-rw-rw-r-- 1 esp1 esp1 777K Jun 24 20:23 json_sm.js\r\n", 125 | "-rw-rw-r-- 1 esp1 esp1 17M Jun 24 08:35 new_js.js\r\n" 126 | ] 127 | } 128 | ], 129 | "source": [ 130 | "!ls -lh *.js" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "id": "protected-canal", 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [] 140 | } 141 | ], 142 | "metadata": { 143 | "kernelspec": { 144 | "display_name": "Python 3", 145 | "language": "python", 146 | "name": "python3" 147 | }, 148 | "language_info": { 149 | "codemirror_mode": { 150 | "name": "ipython", 151 | "version": 3 152 | }, 153 | "file_extension": ".py", 154 | "mimetype": "text/x-python", 155 | "name": "python", 156 | "nbconvert_exporter": "python", 157 | "pygments_lexer": "ipython3", 158 | "version": "3.6.9" 159 | } 160 | }, 161 | "nbformat": 4, 162 | "nbformat_minor": 5 163 | } 164 | -------------------------------------------------------------------------------- /notebooks/data npz generator.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 6, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 13 | "The text.latex.preview rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 14 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 15 | "The mathtext.fallback_to_cm rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 16 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: Support for setting the 'mathtext.fallback_to_cm' rcParam is deprecated since 3.3 and will be removed two minor releases later; use 'mathtext.fallback : 'cm' instead.\n", 17 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 18 | "The validate_bool_maybe_none function was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 19 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 20 | "The savefig.jpeg_quality rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 21 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 22 | "The keymap.all_axes rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 23 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 24 | "The animation.avconv_path rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n", 25 | "In /home/esp1/.local/lib/python3.6/site-packages/matplotlib/mpl-data/stylelib/_classic_test.mplstyle: \n", 26 | "The animation.avconv_args rcparam was deprecated in Matplotlib 3.3 and will be removed two minor releases later.\n" 27 | ] 28 | }, 29 | { 30 | "ename": "ModuleNotFoundError", 31 | "evalue": "No module named 'rdb'", 32 | "output_type": "error", 33 | "traceback": [ 34 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 35 | "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", 36 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtqdm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnotebook\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mtq\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mpickle\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mrdb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 37 | "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'rdb'" 38 | ] 39 | } 40 | ], 41 | "source": [ 42 | "import numpy as np\n", 43 | "import math, json\n", 44 | "from rdp import rdp\n", 45 | "import numpy as np\n", 46 | "import matplotlib.pyplot as plt\n", 47 | "from matplotlib import animation\n", 48 | "from IPython.display import HTML\n", 49 | "import tqdm.notebook as tq\n", 50 | "import pickle\n", 51 | "import rdb" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "from PIL import Image, ImageDraw\n", 61 | "import json\n", 62 | "import numpy as np\n", 63 | "\n", 64 | "def img_from_stroke(drawing):\n", 65 | " img_A = Image.new('RGB', (600, 600), (255, 255, 255)) \n", 66 | " draw = ImageDraw.Draw(img_A) \n", 67 | " for item in drawing:\n", 68 | " char = list(item.keys())[0]\n", 69 | " stroke = item[char]\n", 70 | " if len(stroke) == 1:\n", 71 | " x, y = stroke[0]\n", 72 | " stroke.append([x+5, y+5])\n", 73 | " for i, point in enumerate(stroke):\n", 74 | " if i == 0:\n", 75 | " x_prev, y_prev = point\n", 76 | " continue\n", 77 | " x, y = point \n", 78 | " draw.line([x_prev, y_prev, x, y], fill=(0, 0, 0), width = 3)\n", 79 | " x_prev, y_prev = x, y\n", 80 | " return img_A" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 7, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "def apply_rdb(drawing, verbose = 0):\n", 90 | " new_drawing = []\n", 91 | " total_prev_strokes = 0\n", 92 | " total_post_strokes = 0\n", 93 | " for item in drawing:\n", 94 | " char = list(item.keys())[0]\n", 95 | " stroke = item[char]\n", 96 | " processed_stroke = []\n", 97 | " if len(stroke):\n", 98 | " if verbose:\n", 99 | " print('processing ', char)\n", 100 | " post_stroke = rdp(stroke, epsilon = 2.0)\n", 101 | " total_post_strokes += len(post_stroke)\n", 102 | " total_prev_strokes += len(stroke)\n", 103 | " new_drawing.append({char:post_stroke})\n", 104 | " if verbose:\n", 105 | " print('reduced from ', total_prev_strokes, ' to ', total_post_strokes)\n", 106 | " return new_drawing" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 8, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "import glob\n", 116 | "npy_files = glob.glob('dataset/**/*.json')" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 9, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "data": { 126 | "image/png": "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\n", 127 | "text/plain": [ 128 | "" 129 | ] 130 | }, 131 | "execution_count": 9, 132 | "metadata": {}, 133 | "output_type": "execute_result" 134 | } 135 | ], 136 | "source": [ 137 | "file = np.random.choice(npy_files)\n", 138 | "drawing = json.load(open(file))\n", 139 | "new_drawing = apply_rdb(drawing, verbose = 0)\n", 140 | "img_from_stroke(drawing)" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 12, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "def add_z(drawing):\n", 150 | " new_data = []\n", 151 | " x_prev, y_prev = None, None\n", 152 | " for item in drawing:\n", 153 | " char = list(item.keys())[0]\n", 154 | " if x_prev is None:\n", 155 | " x_prev, y_prev = item[char][0]\n", 156 | " stroke = item[char]\n", 157 | " x_data = []\n", 158 | " y_data = []\n", 159 | " segments = []\n", 160 | " \n", 161 | " if len(stroke) == 1:\n", 162 | " x, y = stroke[0]\n", 163 | " stroke.append([x+1, y+1])\n", 164 | " \n", 165 | " for i, point in enumerate(stroke):\n", 166 | " x, y = point\n", 167 | " if i == len(stroke) - 1:\n", 168 | " z = 1\n", 169 | " else:\n", 170 | " z = 0\n", 171 | " if i >=0:\n", 172 | " segments.append([x-x_prev, y-y_prev, z])\n", 173 | " x_prev, y_prev = [x, y]\n", 174 | " new_data += segments\n", 175 | " return np.array(new_data)" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 15, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "def create_dataset():\n", 185 | " train_data = []\n", 186 | " valid_data = []\n", 187 | " test_data = []\n", 188 | " count = 0 \n", 189 | " valid_size = 100 \n", 190 | " test_size = 100\n", 191 | " pbar = tq.tqdm(total = 2500)\n", 192 | " for file in glob.glob('dataset/**/*.json'):\n", 193 | " drawing = json.load(open(file))\n", 194 | " new_drawing = apply_rdb(drawing)\n", 195 | " strokes = add_z(new_drawing)\n", 196 | " \n", 197 | " count += 1\n", 198 | " pbar.update(1)\n", 199 | " if 'train' in file:\n", 200 | " train_data.append(strokes)\n", 201 | " elif 'valid' in file:\n", 202 | " valid_data.append(strokes)\n", 203 | " elif 'test' in file:\n", 204 | " test_data.append(strokes)\n", 205 | " else:\n", 206 | " pbar.close()\n", 207 | " break\n", 208 | " \n", 209 | " print(\"save dataset\")\n", 210 | " with open('dataset.npz', 'wb') as f:\n", 211 | " pickle.dump({'train':train_data, 'valid':valid_data, 'test':test_data}, f, protocol=2)" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 16, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "application/vnd.jupyter.widget-view+json": { 222 | "model_id": "5cc19408197a40028ee948c1a5c6ac32", 223 | "version_major": 2, 224 | "version_minor": 0 225 | }, 226 | "text/plain": [ 227 | "HBox(children=(IntProgress(value=0, max=2500), HTML(value='')))" 228 | ] 229 | }, 230 | "metadata": {}, 231 | "output_type": "display_data" 232 | }, 233 | { 234 | "name": "stdout", 235 | "output_type": "stream", 236 | "text": [ 237 | "save dataset\n" 238 | ] 239 | } 240 | ], 241 | "source": [ 242 | "create_dataset()" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": null, 248 | "metadata": {}, 249 | "outputs": [], 250 | "source": [] 251 | } 252 | ], 253 | "metadata": { 254 | "kernelspec": { 255 | "display_name": "Python 3", 256 | "language": "python", 257 | "name": "python3" 258 | }, 259 | "language_info": { 260 | "codemirror_mode": { 261 | "name": "ipython", 262 | "version": 3 263 | }, 264 | "file_extension": ".py", 265 | "mimetype": "text/x-python", 266 | "name": "python", 267 | "nbconvert_exporter": "python", 268 | "pygments_lexer": "ipython3", 269 | "version": "3.6.9" 270 | } 271 | }, 272 | "nbformat": 4, 273 | "nbformat_minor": 2 274 | } 275 | -------------------------------------------------------------------------------- /page/index.js: -------------------------------------------------------------------------------- 1 | var w = 600; 2 | var h = 600; 3 | var canvas = Raphael('canvas', '300px', '300px'); 4 | canvas.setViewBox(0,0,w,h); 5 | canvas.setSize('100%', '100%'); 6 | 7 | function create_data(drawing){ 8 | var data = [] 9 | var new_data = [] 10 | var x; 11 | var y; 12 | var xs = []; 13 | var ys = []; 14 | 15 | for (let i = 0; i < drawing.length; i++){ 16 | const stroke = drawing[i]; 17 | if (stroke.length > 1) 18 | for(let j = 0 ; j < stroke.length; j++){ 19 | [x, y] = stroke[j] 20 | var z = 0; 21 | if (j == stroke.length - 1) 22 | { 23 | z = 1; 24 | } 25 | 26 | data.push([x, y, z]) 27 | xs.push(x) 28 | ys.push(y) 29 | } 30 | 31 | else if (stroke.length == 1){ 32 | [x, y] = stroke[0] 33 | data.push([x, y, 0]) 34 | xs.push(x) 35 | ys.push(y) 36 | data.push([x, y+3, 1]) 37 | xs.push(x) 38 | ys.push(y + 3) 39 | } 40 | } 41 | 42 | const min_x = Math.min(...xs); 43 | const max_x = Math.max(...xs); 44 | 45 | const min_y = Math.min(...ys); 46 | const max_y = Math.max(...ys); 47 | 48 | const margin_x = (600 - max_x - min_x)/2; 49 | const margin_y = (600 - max_y - min_y)/2; 50 | 51 | var new_data = []; 52 | 53 | for (let i = 0; i < data.length; i++){ 54 | [x, y, z] = data[i]; 55 | new_data.push([x+ margin_x , y + margin_y, z]) 56 | } 57 | 58 | return new_data 59 | } 60 | function getSvgPathFromStroke(stroke) { 61 | if (!stroke.length) return "" 62 | 63 | const d = stroke.reduce( 64 | (acc, [x0, y0]) => { 65 | acc.push(x0, y0) 66 | return acc 67 | }, 68 | ["M", ...stroke[0], "Q"] 69 | ) 70 | 71 | return d 72 | } 73 | 74 | 75 | var animatePath = function(paths) { 76 | color = colors[randomNumber(0, colors.length)] 77 | // console.log(paths.length) 78 | document.getElementById("generate").disabled = true; 79 | var line = canvas.path(paths[0]).attr({ 80 | stroke: color, 81 | 'stroke-opacity': 0, 82 | }); 83 | 84 | var rand = Date.now(); 85 | line.node.id = 'path'+rand; 86 | $('#'+line.node.id).css("transform", "translate(30,7)"); 87 | var length = line.getTotalLength(); 88 | var prev_path; 89 | $('#'+line.node.id).animate({ 90 | 'to': 1}, { 91 | duration: parseInt(length*2), 92 | step: function(pos, fx) { 93 | var offset = length * fx.pos; 94 | var subpath = line.getSubpath(0, offset); 95 | if (prev_path != null) 96 | { 97 | prev_path.remove(); 98 | } 99 | 100 | prev_path = canvas.path(subpath).attr({ 101 | 'stroke-width': strokeWidth, 102 | stroke: color 103 | }); 104 | 105 | 106 | }, 107 | complete: function(){ 108 | if (paths.length > 0){ 109 | animatePath(paths.slice(1)) 110 | // console.log('#'+line.node.id) 111 | } 112 | else{ 113 | document.getElementById("generate").disabled = false; 114 | } 115 | 116 | index += 1; 117 | } 118 | }); 119 | 120 | }; 121 | function randomNumber(min, max) { 122 | return Math.floor(Math.random() * (max - min) + min); 123 | } 124 | 125 | var b = document.querySelector('button') 126 | var p = []; 127 | var total = 0; 128 | var notFinished = true; 129 | var next_path = 0 ; 130 | var index = 0 ; 131 | var paths = []; 132 | var myVar; 133 | var colors = ['#7fc97f', '#beaed4', '#fdc086', '#008ecc', '#386cb0', '#f0027f', '#bf5b16', '#666666'] 134 | var strokeWidth; 135 | 136 | b.onclick = function(){ 137 | paper.install(window); 138 | paper.setup('myCanvas'); 139 | strokeWidth = document.getElementById('slider').value 140 | canvas.clear(); 141 | index = 0; 142 | var drawing = eval("stroke_"+randomNumber(0, 100)); 143 | var path; 144 | const data = create_data(drawing) 145 | var currStroke = []; 146 | paths = [] ; 147 | 148 | for(var i = 0 ; i < data.length ; i++){ 149 | [x, y , z] = data[i] 150 | currStroke.push([x, y]) 151 | if (z == 1) 152 | { 153 | path = new Path({ 154 | strokeColor: 'black', 155 | fullySelected: true, 156 | }); 157 | for(var j = 0 ; j < currStroke.length ; j++){ 158 | var point = currStroke[j] 159 | path.add(new Point(point[0], point[1])) 160 | } 161 | path.simplify(10) 162 | paths.push(path.exportSVG().getAttribute("d")); 163 | currStroke = []; 164 | } 165 | } 166 | animatePath(paths) 167 | }; -------------------------------------------------------------------------------- /page/index_ar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | كاليار 14 | 15 | 16 | 17 | 506 | 507 | 508 | 509 | 510 | 514 | 515 |
516 |
517 |
518 |

519 | كاليار: مجموعة بيانات موسمة للخطوط العربية 520 |

521 |
522 | 562 |
563 |
564 | 565 |
566 |

567 | ملخص 568 |

569 |

570 | يعد الخط جزءًا أساسيًا من التراث والثقافة العربية. وقد استخدم قديماً لتزيين المنازل والمساجد. عادةً ما يتم تصميم هذا الخط يدويًا بواسطة خبراء يتمتعون برؤى جمالية. في السنوات القليلة الماضية ، كان هناك جهد كبير لرقمنة هذا النوع من الفن إما عن طريق التقاط صورة للمباني المزخرفة أو رسمها باستخدام الأجهزة الرقمية. يعتبر هذا الأخير نموذجًا عبر الإنترنت حيث يتم تتبع الرسم عن طريق تسجيل حركة الجهاز ، مثل القلم الإلكتروني ، على الشاشة. في البحوث المنشورة ، هناك العديد من مجموعات البيانات لرقمنة الخطوط العربية التي تم جمعها مع مجموعة متنوعة من أنماط الخط العربي. ومع ذلك ، لا توجد مجموعة بيانات متاحة لتتبع الرسم للخط العربي. في هذه الورقة، نوضح منهجنا في جمع مجموعة بيانات عبر الإنترنت للخط العربي تسمى كاليار 571 | . تم جمع 2500 صورة وتوسيمها بالرسم ليمكن اتمتة العملية بسهولة تامة في المستقبل. 572 | 573 |

574 | 575 |

576 | تجربة 577 |

578 |

579 | يمكنك إنشاء رسم متحرك لمجموعة صغيرة من الملفات من مجموعة البيانات بالنقر فوق الزر أدناه. لاحظ أن هذا يعمل مباشرة في المتصفح ومن ثم استخدمنا 100 عينة فقط للتوضيح. تم تحويل 100 ملف json إلى إصدار مصغر حيث تم تحويل جميع النقاط إلى أعداد صحيحة . عند كل ضغطة على إنشاء ، يتم تقديم رسم جديد حيث يتم رسم كل حد بلون مختلف. 580 |

581 | 582 |
583 |
584 |
585 | 586 | 587 | 590 |
591 | 592 |

593 | توسيم البيانات 594 |

595 |

596 | 597 | تم إجراء عملية جمع البيانات خلال عدة أشهر. استخدمنا بعض الصور التي جمعناها لإنشاء الخط بشكل اتوماتيكي كما هو موضح في الصورة أدناه. أحد المواقع الرئيسية التي استخدمناها في البداية هو موقع الأسماء العربية. لحسن الحظ ، كانت مجموعة البيانات هذه تحتوي على بعض التعليقات التوضيحية النصية وكان علينا فقط قضاء بضع ساعات لتوسميها برسم بضع مئات من الصور. بالنسبة لمجموعات البيانات الأخرى ، كان علينا أن نوسم الصور بالنص ثم بالرسم التخطيطي. استغرق إجراء التعليق التوضيحي بضعة أسابيع. استخدمنا جهازي تابليت لوحي Samsung Galaxy Tab S6 كأجهزة رئيسية لإجراء التعليقات التوضيحية. استغرق الأمر مرحلتين رئيسيتين: الأولى تعلق على كل صورة بنص. في المرحلة الثانية ، استخدمنا قلم الكمبيوتر اللوحي لرسم التعليق التوضيحي. كررنا هذه الخطوات عدة مرات لزيادة حجم مجموعة البيانات. نظرًا لأن مجموعة البيانات الأولية كانت 600 × 600 ، فقد قررنا تحويل البعد الأقصى إلى 600 وإعادة قياس البعد الآخر وفقًا لذلك للحفاظ على نسبة أبعاد الصورة. أثناء عملية التعليقات التوضيحية ، واجهنا العديد من المشكلات مثل التعليقات التوضيحية الفارغة ، الرسوم متكررة ومشاكل في شاشة اللمس أدت إلى إنشاء تعليقات توضيحية خاطئة. للتعامل مع هذه المشاكل ، اتخذنا الكثير من خطوات التحقق بشكل دوري عن طريق رسمها بواسطة بايثون. في بعض الأوقات نضع رسومات على بعض الصور ثم نزيلها لأن لديهم بعض المشاكل. أحد عمليات التحقق من الصحة المستخدمة هو مقارنة نص الصورة مع وسم الحروف المختلفة . هذا يعطينا فكرة سريعة عن الأخطاء الشائعة. من الصعب التعامل مع المشاكل الأخرى خاصة مشكلة وجود رسومات خاطئة على الجهاز اللوحي. لقد اعتمدنا على معالجة الملفات المحفوظة على شكل json لتتخلص من هذه المشاكل. 598 |

599 | 600 | 601 | 602 | 603 |

604 | التطبيقات الذكية 605 |

606 |

607 | هناك الكثير من الجدل في مجال الذكاء الاصطناعي حول ما إذا كان بإمكاننا استخدامه لإنشاء بعض البرامج الذكية والفنية. في السنوات القليلة الماضية ، كان هناك الكثير من الأبحاث في تطبيق الذكاء الاصطناعي بشكل إبداعي مثل Style Transfer [1] و Deep Dream [2] و GauGAN [3] وما إلى ذلك. تنطبق معظم هذه التقنيات على الصور. من ناحية أخرى ، فهي أكثر صعوبة في معالجة اللغة الطبيعية (NLP). تكمن الصعوبة الجوهرية في تعقيد لغة النمذجة ، ناهيك عن إنشاء بعض التطبيقات الإبداعية. يعد إنشاء الرسومات أحد أكثر التطبيقات إثارة للاهتمام. واحدة من أكثر الأوراق إثارة للاهتمام هي ورقة Alex Gravesتوليد تسلسلات مع الشبكات العصبية المتكررة . تفترض الورقة وجود مجموعة بيانات موسمة بالرسم لتوليد الخطوط باللغة الإنجليزية. بناءً على ذلك ، كان هناك العديد من الأوراق في هذا المجال مثل sketchRNN [4] و GANwriting [5] و Scrabble-GANs [6] و DF-GANs [7] و BézierSketch [8] و DoodlerGAN [9]. معظم هذه الأوراق مخصصة للبيانات باللغة الإنجليزية ولا داعي لذكر مدى بساطة اللغة الإنجليزية مقارنة باللغات الأخرى مثل العربية. ينشأ تعقيد اللغة العربية من الطبيعة المتصلة للحروف. ناهيك عن التاريخ الطويل للخط العربي الذي يستخدم على نطاق واسع في الوقت الحاضر. تترافق الأنماط المختلفة للخط العربي مع حرية رسم بعض الحروف مما يجعل المشكلة أكثر صعوبة. نظرًا لكون كاليار مجموعة البيانات الوحيدة التي تجمع معلومات الرسوم للخطوط العربية لأنماط الخط المختلفة ، فإن هذا يفتح الباب للعديد من التطبيقات. لا تزال الصعوبة تكمن في نمذجة اللغة الطبيعية من وإنشاء خطوط يمكن فهمها . هناك مفاضلة بين إنشاء خطوط جميلة وتوليد لغة منطقية. 608 |

609 |

610 | منشور التويتر 611 |

612 | 613 | 614 | 615 |

616 | فيديو 617 |

618 | 619 |
620 | 624 |
625 |
626 | 627 | الفيديو 1 أ: 628 | 629 | تحريك أنماط الخط المختلفة 630 |
631 |
632 |
633 | 634 |
635 | 639 |
640 |
641 | 642 | الفيديو 1 ب: 643 | 644 | تحريك أنماط الخط المختلفة 645 |
646 |
647 |
648 | 649 |
650 | 654 |
655 |
656 | 657 | فيديو 3: 658 | 659 | تحريك نفس العبارة باستخدام أنماط متعددة 660 |
661 |
662 |
663 | 664 | 665 | 666 |
667 | 671 |
672 |
673 | 674 | الفيديو 4: 675 | 676 | تحريك الأنماط الخطية المعقدة 677 |
678 |
679 |
680 | 681 |

682 |     @misc{alyafeai2021calliar,
683 |         title={Calliar: An Online Handwritten Dataset for Arabic Calligraphy}, 
684 |         author={Zaid Alyafeai and Maged S. Al-shaibani and Mustafa Ghaleb and Yousif Ahmed Al-Wajih},
685 |         year={2021},
686 |         eprint={2106.10745},
687 |         archivePrefix={arXiv},
688 |         primaryClass={cs.CL}
689 |   }
690 | 691 |

692 | المصادر 693 |

694 |
    695 |
  1. Johnson, Justin, Alexandre Alahi, and Li Fei-Fei. "Perceptual losses for real-time style transfer and super-resolution." European conference on computer vision. Springer, Cham, 2016.
  2. 696 |
  3. Mordvintsev, Alexander, Christopher Olah, and Mike Tyka. "Inceptionism: Going deeper into neural networks." (2015).
  4. 697 |
  5. Park, Taesung, et al. "GauGAN: semantic image synthesis with spatially adaptive normalization." ACM SIGGRAPH 2019 Real-Time Live!. 2019. 1-1.
  6. 698 |
  7. Ha, David, and Douglas Eck. "A neural representation of sketch drawings." arXiv preprint arXiv:1704.03477 (2017).
  8. 699 |
  9. Kang, Lei, et al. "GANwriting: Content-conditioned generation of styled handwritten word images." European Conference on Computer Vision. Springer, Cham, 2020.
  10. 700 |
  11. Fogel, Sharon, et al. "ScrabbleGAN: semi-supervised varying length handwritten text generation." Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2020.
  12. 701 |
  13. Tao, Ming, et al. "Df-gan: Deep fusion generative adversarial networks for text-to-image synthesis." arXiv preprint arXiv:2008.05865 (2020).
  14. 702 |
  15. Das, Ayan, et al. "BézierSketch: A generative model for scalable vector sketches." arXiv preprint arXiv:2007.02190 (2020).
  16. 703 |
  17. Ge, Songwei, et al. "Creative Sketch Generation." arXiv preprint arXiv:2011.10039 (2020).
  18. 704 |
705 | 706 | 707 | 708 |
709 | This website uses the template from alias-free-gan. 710 |
711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | cairosvg 2 | svgwrite 3 | rdp 4 | matplotlib 5 | numpy 6 | tqdm 7 | django~=3.2 8 | backcall==0.2.0 -------------------------------------------------------------------------------- /scripts/chars.py: -------------------------------------------------------------------------------- 1 | #https:#jrgraphix.net/r/Unicode/0600-06FF 2 | map_chars = { 3 | "\u0623":["\u0621", "\u0627"], # أ 4 | "\u0622":["\u0605", "\u0627"], # آ 5 | "\u0625":["\u0627", "\u0621"], # إ 6 | "\u0628":["\u066E", "."], # ب 7 | "\u062A":[".", ".", "\u066E"], # ت 8 | "\u062B":[".", ".", ".", "\u066E"], # ث 9 | "\u062C":["\u062D", "."], # ج 10 | "\u062E":[".", "\u062D"], # خ 11 | "\u0630":[".", "\u062F"], # ذ 12 | "\u0632":[".", "\u0631"], # ز 13 | "\u0634":[".", ".", ".", "\u0633"], # ش 14 | "\u0636":[".", "\u0635"], # ض 15 | "\u0637":["\u0627", "\uFEBB"], # ط 16 | "\u0638":[".", "\u0627", "\uFEBB"], # ظ 17 | "\u063A":[".", "\u0639"], # غ 18 | "\u0641":[".", "\u066F"], # ف 19 | "\u0642":[".", ".", "\u066F"], # ق 20 | "\u06A4":[".", ".", ".", "\u066F"], # ڤ 21 | "\u0643":["\u0621", "\u0644"], # ك 22 | "\u0646":[".", "\u06BA"], # ن 23 | "\u0624":["\u0621", "\u0648"], # ؤ 24 | "\u064A":["\u0649", ".", "."], #ي 25 | "\u0626":["\u0621", "\u0649"], #ئ 26 | "\u0629":[".", ".", "\u0647"], #ه 27 | } -------------------------------------------------------------------------------- /scripts/vis.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import json 3 | import math 4 | import os 5 | import pickle 6 | import re 7 | from collections import defaultdict 8 | 9 | import cairosvg 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import svgwrite 13 | import tqdm.notebook as tq 14 | from IPython.display import HTML 15 | from matplotlib import animation 16 | from PIL import Image, ImageDraw 17 | from rdp import rdp 18 | 19 | from scripts.chars import map_chars 20 | 21 | 22 | def get_bounds(data): 23 | minx, miny = 600, 600 24 | maxx, maxy = 0, 0 25 | 26 | for i, (x, y, z) in enumerate(data): 27 | if minx > x: 28 | minx = x 29 | if miny > y: 30 | miny = y 31 | 32 | if maxx < x: 33 | maxx = x 34 | if maxy < y: 35 | maxy = y 36 | return minx, maxx, miny, maxy 37 | 38 | def convert_3d(drawing, return_flag = False, threshold=10): 39 | out = [] 40 | corrupted = False 41 | for item in drawing: 42 | char = list(item.keys())[0] 43 | stroke = item[char] 44 | if len(stroke) == 1: 45 | x, y = stroke[0] 46 | out.append([x, y, 0]) 47 | out.append([x+1, y+1, 1]) 48 | continue 49 | segment = [] 50 | for i, point in enumerate(stroke): 51 | x, y = point 52 | if i == len(stroke) - 1: 53 | segment.append([x, y, 1]) 54 | else: 55 | segment.append([x, y, 0]) 56 | 57 | start = 0 58 | for i, point in enumerate(segment): 59 | if i < len(segment) -1: 60 | x, y, _ = point 61 | next_x, next_y, _ = segment[i+1] 62 | if any(( 63 | abs(x-next_x)>threshold, 64 | abs(y-next_y>threshold), 65 | )): 66 | corrupted=True 67 | start = i +1 68 | start = 0 69 | out += segment[start:] 70 | if return_flag: 71 | return out, corrupted 72 | return out 73 | 74 | def make_square(im, min_size=256, fill_color=(255, 255, 255)): 75 | x, y = im.size 76 | size = max(min_size, x, y) 77 | new_im = Image.new('RGBA', (size, size), fill_color) 78 | new_im.paste(im, (int((size - x) / 2), int((size - y) / 2))) 79 | return new_im 80 | 81 | def draw_strokes(data, factor=1, svg_filename = 'tmp/sample.svg', stroke_width = 3, 82 | square = False, return_res = False, crop = True): 83 | 84 | os.makedirs('tmp', exist_ok=True) 85 | if crop: 86 | min_x, max_x, min_y, max_y = get_bounds(data) 87 | else: 88 | min_x, max_x, min_y, max_y = 0, 600, 0, 600 89 | 90 | dims = (50 + max_x - min_x, 50 + max_y - min_y) 91 | dwg = svgwrite.Drawing(svg_filename, size = dims) 92 | dwg.add(dwg.rect(insert=(0, 0), size=dims,fill='white')) 93 | lift_pen = 1 94 | abs_x = 25 - min_x 95 | abs_y = 25 - min_y 96 | p = "M%s,%s " % (abs_x, abs_y) 97 | command = "M" 98 | for i in range(len(data)): 99 | if (lift_pen == 1): 100 | command = "M" 101 | elif (command != "L"): 102 | command = "L" 103 | else: 104 | command = "" 105 | x = float(data[i][0]) - min_x 106 | y = float(data[i][1]) - min_y 107 | lift_pen = data[i][2] 108 | p += command+str(x)+" "+str(y)+" " 109 | the_color = "black" 110 | 111 | dwg.add(dwg.path(p).stroke(the_color,stroke_width).fill("none")) 112 | dwg.save() 113 | cairosvg.svg2png(url="tmp/sample.svg", write_to="tmp/sample.png") 114 | img = Image.open('tmp/sample.png') 115 | if square: 116 | img = make_square(img) 117 | if return_res: 118 | return img, dims 119 | else: 120 | return img 121 | 122 | def apply_rdb(drawing, verbose = 0): 123 | new_drawing = [] 124 | total_prev_strokes = 0 125 | total_post_strokes = 0 126 | for item in drawing: 127 | char = list(item.keys())[0] 128 | stroke = item[char] 129 | processed_stroke = [] 130 | if len(stroke): 131 | if verbose: 132 | print('processing ', char) 133 | post_stroke = rdp(stroke, epsilon = 2.0) 134 | total_post_strokes += len(post_stroke) 135 | total_prev_strokes += len(stroke) 136 | new_drawing.append({char:post_stroke}) 137 | if verbose: 138 | print('reduced from ', total_prev_strokes, ' to ', total_post_strokes) 139 | return new_drawing 140 | 141 | def preprocess(text): 142 | char_comps = [] 143 | 144 | diacritics = "[ًٌٍَُِّْ]" 145 | numbers = '0123456789' 146 | for diac in diacritics: 147 | text = text.replace(diac, '') 148 | 149 | for num in numbers: 150 | text = text.replace(num, '') 151 | 152 | outText = "" 153 | 154 | for i in range(len(text)): 155 | 156 | if (text[i] == " "): 157 | continue 158 | 159 | if text[i] in map_chars: 160 | if (i < len(text) - 1 and text[i] == "\u0643"): 161 | if text[i+1] != ' ': 162 | char_comps.append({text[i] : '\uFEDB'}) 163 | else: 164 | char_comps.append({text[i] : map_chars[text[i]]}) 165 | else: 166 | char_comps.append({text[i] : map_chars[text[i]]}) 167 | else: 168 | char_comps.append({text[i] : text[i]}) 169 | 170 | return char_comps 171 | 172 | def concatenate(images, mode='h', margin=10): 173 | widths, heights = zip(*(i.size for i in images)) 174 | if mode =='h': 175 | total_width = sum(widths) 176 | max_height = max(heights) 177 | 178 | new_im = Image.new('RGB', (total_width, max_height), (255, 255, 255)) 179 | 180 | x_offset = 0 181 | for im in images[::-1]: 182 | new_im.paste(im, (x_offset,0)) 183 | x_offset += im.size[0] 184 | elif mode == 'v': 185 | total_height = sum(heights) 186 | max_width = max(widths) 187 | 188 | new_im = Image.new('RGB', (max_width, total_height+margin*(len(images)-1)), (255, 255, 255)) 189 | draw = ImageDraw.Draw(new_im) 190 | y_offset = 0 191 | for im in images: 192 | new_im.paste(im, (0,y_offset+margin)) 193 | y_offset += im.size[1] 194 | draw.line((0,y_offset+margin-5, max_width,y_offset+margin-5), fill=(0, 0, 0), width=3) 195 | return new_im 196 | 197 | def generate_characters(file): 198 | char_drawings = [] 199 | annot = file.split('/')[-1][:-5] 200 | char_comps = preprocess(annot) 201 | drawing = json.load(open(file)) 202 | new_drawing = apply_rdb(drawing, verbose = 0) 203 | i = 0 204 | for comp in char_comps: 205 | char = list(comp.keys())[0] 206 | j = i + len(comp[char]) 207 | char_drawings.append({char:new_drawing[i:j]}) 208 | i = j 209 | return char_drawings 210 | 211 | def generate_words(file): 212 | word_drawings = [] 213 | annot = file.split('/')[-1][:-5] 214 | annot = re.sub('[0-9]', '', annot) 215 | char_comps = preprocess(annot) 216 | indices = [m.start() - i - 1 for i, m in enumerate(re.finditer(' ', annot))] 217 | indices = indices + [len(annot) - len(indices)- 1] 218 | drawing = json.load(open(file)) 219 | # new_drawing = apply_rdb(drawing, verbose = 0) 220 | i, j = 0, 0 221 | c = 0 222 | word = "" 223 | for cntr, comp in enumerate(char_comps): 224 | char = list(comp.keys())[0] 225 | j += len(comp[char]) 226 | word += char 227 | if cntr == indices[c]: 228 | word_drawings.append({word:drawing[i:i+j]}) 229 | i = i+j 230 | j = 0 231 | c += 1 232 | word = "" 233 | return word_drawings 234 | 235 | def get_annotation(json_path): 236 | return json_path.split('_')[0].split('/')[-1] 237 | 238 | def clean_text(text): 239 | char_comps = [] 240 | 241 | diacritics = "[ًٌٍَُِّْ]" 242 | 243 | text = re.sub("[ًٌٍَُِّْ]", "", text) 244 | text = re.sub('[0-9]', '', text) 245 | text = re.sub('[a-zA-Zö\xa0]', '', text) 246 | return text.replace('_', '') 247 | 248 | def concatenate(images, mode='h', margin=10): 249 | widths, heights = zip(*(i.size for i in images)) 250 | if mode =='h': 251 | total_width = sum(widths) 252 | max_height = max(heights) 253 | 254 | new_im = Image.new('RGB', (total_width, max_height), (255, 255, 255)) 255 | 256 | x_offset = 0 257 | for im in images[::-1]: 258 | new_im.paste(im, (x_offset,0)) 259 | x_offset += im.size[0] 260 | elif mode == 'v': 261 | total_height = sum(heights) 262 | max_width = max(widths) 263 | 264 | new_im = Image.new('RGB', (max_width, total_height+margin*(len(images)-1)), (255, 255, 255)) 265 | draw = ImageDraw.Draw(new_im) 266 | y_offset = 0 267 | for im in images: 268 | new_im.paste(im, (0,y_offset+margin)) 269 | y_offset += im.size[1] 270 | draw.line((0,y_offset+margin-5, max_width,y_offset+margin-5), fill=(0, 0, 0), width=3) 271 | return new_im 272 | 273 | def save_video(drawing, mx): 274 | num_sketches = 1 275 | global line_data, line 276 | line_data = ([], []) 277 | sqrt = int(math.sqrt(num_sketches)) 278 | fig, ax = plt.subplots(sqrt, sqrt, figsize=(5,5)) 279 | ax.set_ylim(600, 0) 280 | ax.set_xlim(0, 600) 281 | ax.set_xticks([]) 282 | ax.set_yticks([]) 283 | ax.set_aspect('equal', adjustable='box') 284 | line, = ax.plot([], [], lw=2, color = 'k') 285 | 286 | def data_gen(): 287 | for point in drawing: 288 | yield point 289 | 290 | 291 | # initialize the data arrays 292 | def run(point): 293 | global line_data, line 294 | x, y, z = point 295 | line_data[0].append(x) 296 | line_data[1].append(y) 297 | line.set_data(line_data[0], line_data[1]) 298 | if z == 1: 299 | line, = ax.plot([], [], lw=2, color = 'k') 300 | line_data = ([], []) 301 | 302 | return line 303 | 304 | ani = animation.FuncAnimation(fig, run, data_gen, interval=10, repeat=False, save_count=mx) 305 | d = ani.save(f'tmp/video.mp4', extra_args=['-vcodec', 'libx264']) 306 | 307 | def create_animation(json_path): 308 | max_count = 1000 309 | min_count = 100 310 | 311 | drawing = convert_3d(json.load(open(json_path))) 312 | save_video(drawing, len(drawing)) 313 | return 'tmp/video.mp4' 314 | --------------------------------------------------------------------------------