{"id":26719797,"url":"https://github.com/rosteleset/falprs","last_synced_at":"2025-10-08T06:09:21.602Z","repository":{"id":282886853,"uuid":"949404423","full_name":"rosteleset/falprs","owner":"rosteleset","description":"Face and License Plate Recognition System","archived":false,"fork":false,"pushed_at":"2025-09-02T14:30:06.000Z","size":26593,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-02T16:23:58.376Z","etag":null,"topics":["cplusplus-20","cpp20","face-recognition","license-plate-recognition","neural-network","userver","userver-framework"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rosteleset.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-16T11:41:46.000Z","updated_at":"2025-09-02T14:30:09.000Z","dependencies_parsed_at":"2025-08-11T10:20:04.292Z","dependency_job_id":null,"html_url":"https://github.com/rosteleset/falprs","commit_stats":null,"previous_names":["rosteleset/falprs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rosteleset/falprs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosteleset%2Ffalprs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosteleset%2Ffalprs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosteleset%2Ffalprs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosteleset%2Ffalprs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rosteleset","download_url":"https://codeload.github.com/rosteleset/falprs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosteleset%2Ffalprs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278897846,"owners_count":26064890,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cplusplus-20","cpp20","face-recognition","license-plate-recognition","neural-network","userver","userver-framework"],"created_at":"2025-03-27T18:23:20.978Z","updated_at":"2025-10-08T06:09:21.596Z","avatar_url":"https://github.com/rosteleset.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n## [![Generic badge](https://img.shields.io/badge/LANG-RU-blue.svg)](./README_ru.md) Description of the FALPRS project\nThis project is a replacement for the [old](https://github.com/rosteleset/frs) one. Main differences:\n* PostgreSQL is used as a DBMS.\n* The project uses [userver](https://github.com/userver-framework/userver), an open-source asynchronous framework.\n* Strict adherence to data types in [API](https://rosteleset.github.io/falprs/) requests. For example, if a numeric field is expected, it cannot be enclosed in quotation marks.\n* Added a license plate recognition system (LPRS).\n\n### Content\n* [LPRS](#lprs)\n  * [Neural network models used](#lprs_used_dnn)\n  * [General scheme of interaction with LPRS](#lprs_scheme)\n  * [Automatic number ban](#lprs_auto_ban)\n* [FRS](#frs)\n  * [Neural network models used](#frs_used_dnn)\n  * [General scheme of interaction with FRS](#frs_scheme)\n* [Building and setting up the project](#build_and_setup_falprs)\n   * [System requirements](#system_requirements)\n   * [Installing NVIDIA drivers](#install_drivers)\n   * [Installing Docker Engine](#install_de)\n   * [Installing NVIDIA Container Toolkit](#install_ct)\n   * [Installing PostgreSQL](#install_pg)\n   * [Building the project](#build_falprs)\n   * [Creating TensorRT neural network model plans](#create_models)\n   * [Project configuration](#config_falprs)\n   * [Managing video stream groups](#vstream_groups)\n* [Examples](#examples)\n   * [LPRS](#lprs_examples)\n   * [FRS](#frs_examples)\n* [Tests](#tests)\n   * [LPRS](#lprs_tests)\n   * [FRS](#frs_tests)\n * [Synchronizing data with an old FRS project](#frs_sync_data)\n\n\u003ca id=\"lprs\"\u003e\u003c/a\u003e\n## LPRS\nThe system is designed to recognize license plates and detect special vehicles with flashing lights: ambulance, emergency, police, etc. Currently, Russian registration plates of type 1 (ГОСТ Р 50577-93) and 1А (ГОСТ Р 50577-2018) are supported:\n![](./docs/ru1.webp)\n![](./docs/ru1a.webp)\n\n\u003ca id=\"lprs_used_dnn\"\u003e\u003c/a\u003e\n### Neural network models used\nThe service works with four neural networks: VDNet, VCNet, LPDNet and LPRNet. VDNet is designed to search for vehicles using a received image from a video camera. VCNet determines whether each vehicle found is a special one. LPDNet is designed to search for license plates. LPRNet is designed to recognize license plates from data received by LPDNet. VDNet, LPDNet and LPRNet models are trained using [Ultralytics](https://github.com/ultralytics/ultralytics). The VCNet model was obtained by transfer learning with fine-tuning. Based on [this](https://huggingface.co/WinKawaks/vit-small-patch16-224) model.\n[NVIDIA Triton Inference Server](https://developer.nvidia.com/triton-inference-server) is used for inference of neural networks.\n\n\u003ca id=\"lprs_scheme\"\u003e\u003c/a\u003e\n### General scheme of interaction with LPRS \n To interact with the service, an [API](https://rosteleset.github.io/falprs/) is used, a detailed description of which is in the repository in the file **docs/openapi.yaml**. First you need to register the video streams that the system will work with. The API method **addStream** is used for this. Main parameters:\n - **streamId** - internal for your backend (external for LPRS) video stream identifier;\n - **config** - configuration parameters.\nExample request body:\n```json\n{\n  \"streamId\": \"1234\",\n  \"config\": {\n    \"screenshot-url\": \"https://my.video.stream/capture\",\n    \"callback-url\": \"https://my.host/callback?streamId=1\"\n  }\n}\n```\nNow LPRS knows that frames should be captured using the specified **screenshot-url** parameter, and when a special vehicle is detected or license plate recognition is detected, a short HTTP information should be sent using the POST method to **callback-url**.\nIn order for LPRS to process frames, you need to call the **startWorkflow** API method.\nExample request body:\n```json\n{\n  \"streamId\": \"1234\"\n}\n```\nThe system will begin a cyclical process: receiving a frame, processing it using neural networks, sending, if required, information to **callback-url**. Pause for a while and again receive the frame, process it, etc. To stop the process, you need to call the **stopWorkflow** API method.\nExample request body:\n```json\n{\n  \"streamId\": \"1234\"\n}\n```\nTo reduce the load on the system, we recommend calling **startWorkflow** and **stopWorkflow**, for example, according to camera video analytics: motion detection, line crossing, intrusion detection, etc. When receiving brief information about recognized license plates, your backend must process it. For example, check the received numbers with the list of allowed ones and open the gate or simply ignore them. License plate recognition events are stored in LPRS for some time. If complete information about an event is required, then you need to use the **getEventData** API method.\nTo remove a video stream, use the **removeStream** API method. Using **listStreams** you can get information about video streams registered in LPRS.\n\n\u003ca id=\"lprs_auto_ban\"\u003e\u003c/a\u003e\n### Automatic number ban\nTo prevent spam requests to **callback-url**, a two-stage number ban is used. If the system sees the number for the first time, then after processing it will be at the first stage of the ban: for some time (configuration parameter **ban-duration**), the number is ignored, regardless of its location in the frame. If the system sees this number again at the first stage, the ban time will be extended. At the end of the first stage, the number will be included in the next one. At the second stage of the ban (configuration parameter **ban-duration-area**), the number is ignored until it changes its location in the frame. When changing the location (configuration parameter **ban-iou-threshold**), the number will be processed and will again go to the first stage. At the end of the second stage, the number is removed from the ban. If you do not want automatic banning of numbers to be applied, then you need to set the value of the **ban-duration** or **ban-duration-area** configuration parameter to a zero value, for example 0s (0 seconds).\n\n\u003ca id=\"frs\"\u003e\u003c/a\u003e\n## FRS\nThe system is designed for facial recognition.\n\n\u003ca id=\"frs_used_dnn\"\u003e\u003c/a\u003e\n### Neural network models used\nAt the moment, FRS uses three models in its work:\n- **scrfd** - designed to search for faces in an image. [Link](https://github.com/deepinsight/insightface/tree/master/detection/scrfd) to the project.\n- **genet** - designed to determine whether a mask or dark glasses is on the face. Based on [this](https://github.com/idstcv/GPU-Efficient-Networks) project. The model was obtained by transfer learning with fine-tuning on three classes: an open face, a face in a mask, a face in dark glasses.\n- **arcface** - designed to calculate a biometric face template. [Link](https://github.com/deepinsight/insightface/tree/master/recognition/arcface_torch) to the project.\n\n\u003ca id=\"frs_scheme\"\u003e\u003c/a\u003e\n### General scheme of interaction with FRS\nTo interact with the service, an [API](https://rosteleset.github.io/falprs/) is used, a detailed description of which is in the repository in the file **docs/openapi.yaml**. First of all, your backend registers video streams using the **addStream** API call. The main parameters of the method are:\n- **streamId** - internal for the backend (external for FRS) identifier of the video stream;\n- **url** is the URL for capturing a frame from the video stream. FRS does not decode video, but works with individual frames (screenshots). For example, the URL might look like ***http://hostname/cgi-bin/images_cgi?channel=0\u0026user=admin\u0026pwd=password***\n- **callback** is the URL that FRS will use when recognizing a registered person. For example, ***http://backend-address/face_recognized?stream_id=1***\n\nTo register faces, the **registerFace** method is used. Main parameters of the method:\n- **streamId** - video stream identifier;\n- **url** is the URL of the face you want to register. For example, ***http://backend-address/image_to_register.jpg***\nIn case of successful registration, the internal for FRS (external for the backend) unique identifier of the registered person - **faceId** - is returned.\n\nTo start and end frame processing, the **motionDetection** method is used. The main idea is for FRS to process frames only when motion is detected in front of the video camera. Method parameters:\n- **streamId** - video stream identifier;\n- **start** - sign of the beginning or end of movement. If **start=true**, then FRS starts processing a frame from the video stream every second (set by the *delay-between-frames* parameter). If **start=false**, then FRS stops processing.\n\nFrame processing means the following chain of actions:\n1. Finding faces using the *scrfd* neural network.\n2. If faces are found, then each one is checked for “blur” and “frontality”.\n3. If the face is not blurred (clear image) and is frontal, then the presence of a mask and dark glasses is determined using the *genet* neural network.\n4. For each face without a mask and without dark glasses, using the *arcface* neural network, a biometric face template, also known as a descriptor, is calculated. Mathematically, a descriptor is a 512-dimensional vector.\n5. Next, each such descriptor is compared in pairs with those registered in the system. The comparison is made by calculating the cosine of the angle between the descriptor vectors: the closer the value is to one, the more similar the face is to the registered one. If the maximum cosine value is greater than the threshold value (*tolerance* parameter), then the face is considered recognized and FRS calls a callback (face recognition event) and specifies the descriptor identifier (*faceId*) and the internal identifier for FRS (external for the backend) as parameters events (*eventId*). If there are several recognized faces in one frame, then the callback will be called for the highest quality (\"best\") face (*blur* parameter).\n6. Every unblurred, frontal, maskless, sunglasses-free, best face found is temporarily stored in the FRS log.\n\nUsing the **bestQuality** method, you can request the “best” frame from the log from FRS. For example, a person unfamiliar to the system approached the intercom and opened the door with a key. The backend knows the opening time with the key (date) and requests the best frame from FRS. FRS looks in its log for a frame with the maximum *blur* from the time range [date - best-quality-interval-before; date + best-quality-interval-after] and produces it as a result. Such a frame is a good candidate for registering a face using the **registerFace** method. As a rule, for good recognition it is necessary to register several faces of one person, including from frames taken in the dark, when the camera switches to infrared operating mode.\n\n\u003ca id=\"build_and_setup_falprs\"\u003e\u003c/a\u003e\n## Building and setting up the project\n\u003ca id=\"system_requirements\"\u003e\u003c/a\u003e\n### System requirements\n* CPU with AVX instructions.\n* NVIDIA GPU with Compute Capability greater than or equal to 6.0 and 4 GB memory or more. Details can be found, for example, [here](https://developer.nvidia.com/cuda-gpus).\n* DBMS PostgreSQL 14 or higher.\n\nTo get the source code you need git. If not installed, then run the command:\n```bash\nsudo apt-get install -y git\n```\nGetting the project source code:\n```bash\ncd ~\ngit clone --recurse-submodules https://github.com/rosteleset/falprs.git\n```\n\u003ca id=\"install_drivers\"\u003e\u003c/a\u003e\n### Installing NVIDIA drivers\nIf the system already has the latest NVIDIA drivers installed, skip this step. To install, you can use the script **scripts/setup_nvidia_drivers.sh**. Basic commands taken from [here](https://docs.nvidia.com/datacenter/tesla/driver-installation-guide/index.html#ubuntu).\n```bash\nsudo ~/falprs/scripts/setup_nvidia_drivers.sh\n```\nAfter installation, you need to restart the operating system:\n```bash\nsudo reboot\n```\n\n\u003ca id=\"install_de\"\u003e\u003c/a\u003e\n### Installing Docker Engine\nIf Docker Engine is already installed on the system, then skip this step. To install, you can use the script **scripts/setup_docker.sh**. Basic commands taken from [here](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository).\n```bash\nsudo ~/falprs/scripts/setup_docker.sh\n```\n\n\u003ca id=\"install_ct\"\u003e\u003c/a\u003e\n### Installing NVIDIA Container Toolkit\nIf NVIDIA Container Toolkit is already installed on the system, then skip this step. To install, you can use the script **scripts/setup_nvidia_container_toolkit.sh**. Basic commands taken from [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html).\n```bash\nsudo ~/falprs/scripts/setup_nvidia_container_toolkit.sh\n```\nAfter installation, you are prompted to restart docker:\n```bash\nsudo systemctl restart docker\n```\n\n\u003ca id=\"install_pg\"\u003e\u003c/a\u003e\n### Установка PostgreSQL\nIf PostgreSQL is not installed, then run the command:\n```.bash\nsudo apt-get install -y postgresql\n```\nRun psql:\n```bash\nsudo -u postgres psql\n```\nRun the SQL commands, specifying your password instead of \"123\":\n```sql\ndrop user if exists falprs;\ncreate user falprs with encrypted password '123';\ncreate database frs;\ngrant all on database frs to falprs;\nalter database frs owner to falprs;\ncreate database lprs;\ngrant all on database lprs to falprs;\nalter database lprs owner to falprs;\n\\q\n```\n\n\u003ca id=\"build_falprs\"\u003e\u003c/a\u003e\n### Building the project\nTo build the project, you can use the script **scripts/build_falprs.sh**. The major PostgreSQL version is set by the **PG_VERSION** variable. You can find out the installed version of PostgreSQL with the command:\n```bash\npsql --version\n```\nThe project's working directory is specified by the **FALPRS_WORKDIR** variable (default value */opt/falprs*), the version of the container with Triton Inference Server is specified by the **TRITON_VERSION** variable.\n\n##### Compute Capability and Latest Container Version Support Matrix\n|Compute Capability|GPU Architecture|Container Version|TensorRT|\n|--|--|--|--|\n|6.x|Pascal|24.04|8.6.3|\n|7.0|Volta|24.09|10.4.0.26|\n\nView Compute Capability:\n```bash\nnvidia-smi --query-gpu=compute_cap --format=csv\n```\nIf you have a GPU with Compute Capability 7.5 or higher, you can use the latest version of the [container](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver/tags). For example, build for Ubuntu 24.04 and GPU with Volta architecture:\n```bash\nsudo PG_VERSION=16 TRITON_VERSION=24.09 ~/falprs/scripts/build_falprs.sh\n```\n\n\u003ca id=\"create_models\"\u003e\u003c/a\u003e\n### Creating TensorRT neural network model plans\nFor inference, TensorRT plans are used, which can be obtained from neural network models in the ONNX (Open Neural Network Exchange) format. To create plans in the working directory, you can use the script **scripts/tensorrt_plans.py**. The project's working directory is specified by the **FALPRS_WORKDIR** variable (default value */opt/falprs*), the Triton Inference Server version is specified by the **TRITON_VERSION** variable.\n**Important:** if you are migrating from an old project, you also need to use the *sha1sum* utility to specify the hash sum of the ONNX file that you used to create the TensorRT *arcface* model plan. This value is specified in the **ARCFACE_SHA1** variable.\nExample of execution without migration:\n```bash\nsudo TRITON_VERSION=24.09 python3 ~/falprs/scripts/tensorrt_plans.py\n```\nExamples of execution with migration for the old file *glint_r50.onnx*. Calculating the hash sum:\n```bash\nsha1sum glint_r50.onnx\n4fd7dce20b6987ba89910eda8614a33eb3593216  glint_r50.onnx\n```\nCreating TensorRT plans:\n```bash\nsudo TRITON_VERSION=24.09 ARCFACE_SHA1=4fd7dce20b6987ba89910eda8614a33eb3593216 python3 ~/falprs/scripts/tensorrt_plans.py\n```\n\n\u003ca id=\"config_falprs\"\u003e\u003c/a\u003e\n### Project configuration\nTo initially populate the databases, run the commands, specifying the values ​​of the variables with the prefix **pg_** (replace the password “123” with the one you specified when creating the PostgreSQL user):\n```bash\npg_user=falprs pg_passwd=123 pg_host=localhost pg_port=5432 pg_db=frs ~/falprs/scripts/sql_frs.sh\npg_user=falprs pg_passwd=123 pg_host=localhost pg_port=5432 pg_db=lprs ~/falprs/scripts/sql_lprs.sh\n```\nThe project configuration is in the file **/opt/falprs/config.yaml**\nThe main parameters have a description in the comments. Some values ​​need to be replaced.\n* In the sections *components_manager -\u003e components -\u003e lprs-postgresql-database* and *components_manager -\u003e components -\u003e frs-postgresql-database* in the values ​​of the **dbconnection** attributes, replace the password \"123\" with the one you specified when creating the PostgreSQL user, as well as other access details, if they differ.\n* In the *components_manager -\u003e task_processors -\u003e main-task-processor* section, replace the **worker_threads** value with the number of CPU cores of your server. The quantity can be viewed, for example, using the command:\n```bash\ncat /proc/cpuinfo | grep processor | wc -l\n```\n* In the *components_manager -\u003e task_processors -\u003e fs-task-processor* section, replace the **worker_threads** value with the number of CPUs on your server multiplied by 4.\n\nTo start a container with **Triton Inference Server** run the command:\n```bash\nsudo TRITON_VERSION=24.09 ~/falprs/scripts/triton_service.sh\n```\nTo create the **falprs** service and rotate logs, run the command:\n```bash\nsudo ~/falprs/scripts/falprs_service.sh\n```\n\n\u003ca id=\"vstream_groups\"\u003e\u003c/a\u003e\n### Managing video stream groups\nEach video stream belongs to a single group. When filling in the initial data, a group named *default* is automatically created. When calling API methods for this group, you do not have to specify an authorization token. To view, add, and delete groups, you can use the **utils/vstream_groups.py** script.\nInstalling dependencies:\n```bash\nsudo apt-get install -y python3-psycopg2 python3-prettytable\n```\nShow list of commands:\n```bash\npython3 ~/falprs/utils/vstream_groups.py -h\n```\nExample of adding a new group to FRS:\n```bash\npython3 ~/falprs/utils/vstream_groups.py -t frs -a \"My new group\"\n```\nShow list of groups in LPRS:\n```bash\npython3 ~/falprs/utils/vstream_groups.py -t lprs -l\n```\nExample output:\n```bash\n+----------+--------------+--------------------------------------+\n| id_group |  group_name  |              auth_token              |\n+----------+--------------+--------------------------------------+\n|    1     |   default    | 4b05cce8-d29e-4e7f-a1fa-247a91f3fd46 |\n|    2     | My new group | 74c0e0f0-ea70-47fb-b715-8932baf7e049 |\n+----------+--------------+--------------------------------------+\n```\nWhen calling API methods for new groups, you must specify an authorization token. If you want the authorization token to become mandatory for the default group, then set the value 0 for the *allow-group-id-without-auth* parameters in the corresponding sections of the project configuration file (*/opt/falprs/config.yaml*) and restart the service.\n\n\u003ca id=\"examples\"\u003e\u003c/a\u003e\n## Examples\nInstalling dependencies:\n```bash\nsudo apt-get install -y nodejs npm libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev\n```\n\n\u003ca id=\"lprs_examples\"\u003e\u003c/a\u003e\n### LPRS\nGo to the directory with examples:\n```bash\ncd ~/falprs/examples/lprs\n```\nInstalling dependencies:\n```bash\nnpm i\n```\nLaunch a test service to process callbacks:\n```bash\nnode lprs_backend.js\n```\nAdd a “test” video stream. In the new console:\n```bash\ncd ~/falprs/examples/lprs\n./test_add_stream.sh\n```\nCheck that the stream is in the database:\n```bash\n./test_list_streams.sh | jq\n```\nThe response must contain a json file. Wait a minute for new data to appear in the FALPRS cache, execute the command:\n```bash\n./test_workflow.sh\n```\nAs a result of executing this command in the console with the test service *lprs_backend.js*, we should see lines like:\n```bash\n[2024-10-16 12:37:16.108] Callback: {\"streamId\":\"test001\",\"date\":\"2024-10-16T09:37:16.103891056+00:00\",\"eventId\":1,\"plates\":[\"O588OA68\"],\"hasSpecial\":false}\n[2024-10-16 12:37:16.108] Matched numbers: O588OA68\n[2024-10-16 12:37:16.162] Save image to file: /tmp/lprs_backend/screenshots/49b507ac-9b7d-43a6-94f0-18f647fc1f5c.jpg\n```\nAnd in the directory */tmp/lprs_backend/screenshots* a file with an image should appear:\n![](./examples/lprs/test001_draw.jpg)\n\nDeleting the “test” video stream:\n```bash\n./test_remove_stream.sh\n```\nGo to the console from which we launched the test service to process callbacks and stop it.\n\n\u003ca id=\"frs_examples\"\u003e\u003c/a\u003e\n### FRS\nGo to the directory with examples:\n```bash\ncd ~/falprs/examples/frs\n```\nInstalling dependencies:\n```bash\nnpm i\n```\nLaunch a test service to process callbacks:\n```bash\nnode frs_backend.js\n```\nAdd a “test” video stream. In the new console:\n```bash\ncd ~/falprs/examples/frs\n./test_add_stream.sh\n```\nCheck that the stream is in the database:\n```bash\n./test_list_streams.sh | jq\n```\nThe response must contain a json file. Wait 10 seconds for the new data to enter the FALPRS cache, and execute the face registration command:\n```bash\n./test_register_face.sh\n```\nCheck that the person is in the database:\n```bash\n./test_list_all_faces.sh | jq\n```\nThe response must contain a json file. Wait 10 seconds for the new data to enter the FALPRS cache, execute the command:\n```bash\n./test_workflow.sh\n```\nAs a result of executing this command in the console with the test service *frs_backend.js*, we should see lines like:\n```bash\n[2024-10-21 15:34:29.180] Callback: {\"faceId\":1,\"eventId\":1}\n[2024-10-21 15:34:29.180] This is Albert Einstein\n[2024-10-21 15:34:29.220] Save image to file: /tmp/frs_backend/screenshots/492d7722d038434d9e2676648991e65e.jpg\n```\nAnd in the directory */tmp/frs_backend/screenshots* a file with an image should appear:\n![](./examples/frs/einstein_001_draw.jpg)\n\n\u003ca id=\"tests\"\u003e\u003c/a\u003e\n## Tests\nInstalling dependencies:\n```bash\nsudo apt-get install -y python3-requests python3-pytest python3-pytest-order\n```\nCreating directories and test databases:\n```bash\ncd ~/falprs/tests\n./test_prepare.sh\n```\n\n\u003ca id=\"lprs_tests\"\u003e\u003c/a\u003e\n### LPRS\n```bash\npytest -v -s test_api_lprs.py\n```\n\n\u003ca id=\"frs_tests\"\u003e\u003c/a\u003e\n### FRS\n```bash\npytest -v -s test_api_frs.py\n```\nAfter finishing the tests, delete the directories and test databases:\n```bash\n./test_clean.sh\n```\n\n\u003ca id=\"frs_sync_data\"\u003e\u003c/a\u003e\n### Synchronizing data with an old FRS project\nThe *sync_data.py* script from the *utils* directory of this repository performs a full synchronization: it deletes unnecessary records in the new database and adds missing ones. Before running the script, make sure that your old service is stopped, and that the new one is correctly configured and stopped. Installing dependencies:\n```bash\nsudo apt-get install -y pip python3-virtualenv\n```\nGo to the directory with the script:\n```bash\ncd ~/falprs/utils\n```\nCopying the file:\n```bash\ncp config.sample.py config.py\n```\nIn the *config.py* file, replace the variable values ​​according to your configuration of the old and new service. Variables of the form *mysql_** and *\\*_old* refer to the old project, *pg_** and *\\*_new* - to the new one. Run the commands:\n```bash\nvirtualenv venv\nsource venv/bin/activate\npip install -r requirements.txt\npython3 sync_data.py\n```\nAfter the script runs, a success message should appear.\nDelete the virtual environment:\n```bash\ndeactivate\nrm -rf ./__pycache__/\nrm -rf venv\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosteleset%2Ffalprs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frosteleset%2Ffalprs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosteleset%2Ffalprs/lists"}