{"id":16224216,"url":"https://github.com/vladmandic/pigallery","last_synced_at":"2025-10-24T22:32:50.625Z","repository":{"id":43070834,"uuid":"261004459","full_name":"vladmandic/pigallery","owner":"vladmandic","description":"PiGallery: AI-powered Self-hosted Secure Multi-user Image Gallery and Detailed Image analysis using Machine Learning, EXIF Parsing and Geo Tagging","archived":true,"fork":false,"pushed_at":"2023-01-02T00:36:18.000Z","size":322904,"stargazers_count":102,"open_issues_count":0,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-10-27T10:34:48.258Z","etag":null,"topics":["deepdetect","detection-models","exif","face-detection","face-recognition","gallery","image-analysis","image-classification","image-database","image-gallery","image-metadata","image-processing","imagenet","inception","object-detection","openimages","pretrained-models","simmilar-images","tensorflow","tfjs"],"latest_commit_sha":null,"homepage":"https://pigallery.ddns.net/?share=qqlny1.0cyk#461017","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vladmandic.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null}},"created_at":"2020-05-03T19:24:28.000Z","updated_at":"2024-10-07T05:45:23.000Z","dependencies_parsed_at":"2023-02-01T01:30:37.192Z","dependency_job_id":null,"html_url":"https://github.com/vladmandic/pigallery","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladmandic%2Fpigallery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladmandic%2Fpigallery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladmandic%2Fpigallery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vladmandic%2Fpigallery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vladmandic","download_url":"https://codeload.github.com/vladmandic/pigallery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238043943,"owners_count":19407117,"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","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":["deepdetect","detection-models","exif","face-detection","face-recognition","gallery","image-analysis","image-classification","image-database","image-gallery","image-metadata","image-processing","imagenet","inception","object-detection","openimages","pretrained-models","simmilar-images","tensorflow","tfjs"],"created_at":"2024-10-10T12:23:22.576Z","updated_at":"2025-10-24T22:32:45.583Z","avatar_url":"https://github.com/vladmandic.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"![Version](https://img.shields.io/github/package-json/v/vladmandic/pigallery?style=flat-square?svg=true)\n![Last Commit](https://img.shields.io/github/last-commit/vladmandic/pigallery?style=flat-square?svg=true)\n![License](https://img.shields.io/github/license/vladmandic/pigallery?style=flat-square?svg=true)\n![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/vladmandic/pigallery?style=flat-square?svg=true)\n![Code Size](https://img.shields.io/github/languages/code-size/vladmandic/pigallery?style=flat-square?svg=true)\n\n# PiGallery\n\n## PiGallery: AI-powered Self-hosted Secure Multi-user Image Gallery and Detailed Image analysis using Machine Learning, EXIF Parsing and Geo Tagging\n\n\u003cbr\u003e\n\n## Key features\n\n### At it's core, **PiGallery** builds a searchable database of images  \n\n- Image thumbnails for fast display\n- Image analysis using machine learning using multiple image classification and object detection models\n- Image perception hash to quickly locate duplicate image regardless of size or to search for similar images\n- Image conditions using analysis of camera settings (light, dark, zoom, wide, etc.)\n- Person age, gender \u0026 emotion modelling and NSFW classification\n- Image geo-location including nearest city for quick searches\n- Lexicon definitions for complete image description\n\n### As an image gallery viewer, **PiGallery** provides\n\n- Secure, multi-user access to image database\n- Fully responsive design for desktop \u0026 mobile usage\n- Installable as an application (PWA) or can be used as a web page\n- Client-side caching with incremental updates\n- Flexible sorting and navigation using folders, locations or classes\n- Flexible natural language search\n- Quickly share generated albums with public users\n- Locate and select images on a world map\n- Find duplicate and/or similar images\n- View image slideshow\n- Multiple display themes (light \u0026 dark) and fully configurable user interface\n- Play with machine learning detection of live video using your camera\n\n### And on a server side\n\n- Analysis is always incremental so only new or modified images will be analyzed\n- All data is stored in a server-side database and original image is never modified\n\n### And it's **FAST**\n\n- Initial access (no cache) of database with 10,000 images completes in less than 1 minute  \n  (depending on your network speed)\n- Subsequent access (cached) with incremental database updates:\n  less than 5 seconds for application startup and gallery load\n\n\u003cbr\u003e\n\n*If you'd like to include any additional image analysis (additional machine models or static analysis), drop a note!*\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n## Screenshots\n\n\u003ccenter\u003e\n\n### Screenshot: Gallery view\n\n![alt text](assets/screenshot-gallery.png)\n\n### Screenshot: Detailed View\n\n![alt text](assets/screenshot-details1.png)\n\n![alt text](assets/screenshot-details2.png)\n\n\u003c/center\u003e\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n## Install, Configure \u0026 Run\n\n### Install\n\n- Install NodeJS: \u003chttps://nodejs.org/en/\u003e\n- Download PiGallery:  \n  using Git: `git clone --depth 1 https://github.com/vladmandic/pigallery`  \n  or download archive from \u003chttps://github.com/vladmandic/pigallery/releases/\u003e\n\n### Configure\n\n- Configure PiGallery:  \n  `./setup.js` or `npm run setup`:  \n  which automatically installs all dependencies  \n  and creates default configuration in `config.json` and `models.json`:\n\n  ```text\n  Starting Setup\n  @vladmandic/pigallery server v2.2.9\n  Platform=linux Arch=x64 Node=v15.4.0\n  Project dependencies\n  production: 19\n  development: 8\n  optional: 0\n  NPM install production modules completed in 7,516ms\n  NPM install development modules completed in 5,819ms\n  NPM update modules completed in 6,757ms\n  NPM deduplicate modules completed in 2,370ms\n  NPM prune unused modules completed in 2,513ms\n  Deleting module samples completed in 49ms\n  NPM outdated check completed in 6,257ms\n  NPM indirect outdated modules: 75\n  NPM list full completed in 1,225ms\n  Total dependencies: production=176 development=450 optional=2\n  Results written to setup.json\n  Configuration file not found: config.json\n  Creating default configuration\n  Enter default admin user email: demo@example.com\n  Enter default admin user password: demo\n  Using media/ as image root containing sample images\n  Using 10010 as default HTTP server port\n  Using 10011 as default HTTPS server port  \n  Default configuration created\n  Configuration file not found: models.json\n  Creating default configuration\n  Default models configuration created\n  ```\n\n### Run\n\n- Run server application:  \n  `npm start`  \n  - Optionally use provided `pigallery.service` as a template to run as a Linux **systemd** service\n  - Server monitors client files for changes and runs automatic client application rebuild as needed\n  - Server log is written to file specified in the `config.json` (default is `pigallery.log`)\n\n  ```js\n  2021-03-03 10:08:36 INFO:  @vladmandic/pigallery version 3.3.5\n  2021-03-03 10:08:36 INFO:  User: vlado Platform: linux Arch: x64 Node: v15.7.0\n  2021-03-03 10:08:36 STATE:  Application log: /home/vlado/dev/pigallery/pigallery.log\n  2021-03-03 10:08:36 INFO:  Authentication required: true\n  2021-03-03 10:08:36 INFO:  Media root: media/\n  2021-03-03 10:08:36 INFO:  Allowed image file types: [ '.jpeg', '.jpg', [length]: 2 ]\n  2021-03-03 10:08:36 DATA:  Build sources: [ 'client/compare/compare.js', 'client/index/index.js', 'client/process/process.js', 'client/video/video.js', [ 'client/index/worker.js', 'client/index/pwa-serviceworker.js' ]\n  2021-03-03 10:08:36 STATE:  Change log updated: /home/vlado/dev/pigallery/docs/change-log.md\n  2021-03-03 10:08:38 STATE:  Client application rebuild: 1545 ms 37 imports in 352312 bytes 1245 modules in 8452413 bytes 6 outputs in 16622342 bytes\n  2021-03-03 10:08:40 STATE:  Client CSS rebuild: 2491 ms imports 554134 byes outputs 453911 bytes\n  2021-03-03 10:08:40 STATE:  Mounted: auth from client/auth.html\n  2021-03-03 10:08:40 STATE:  Mounted: compare from client/compare.html\n  2021-03-03 10:08:40 STATE:  Mounted: index from client/index.html\n  2021-03-03 10:08:40 STATE:  Mounted: offline from client/offline.html\n  2021-03-03 10:08:40 STATE:  Mounted: process from client/process.html\n  2021-03-03 10:08:40 STATE:  Mounted: video from client/video.html\n  2021-03-03 10:08:40 STATE:  Server HTTP listening: { address: '::', family: 'IPv6', port: 10010 }\n  2021-03-03 10:08:40 STATE:  Server HTTPS listening: { address: '::', family: 'IPv6', port: 10011 }\n  2021-03-03 10:08:40 STATE:  Monitoring: [ 'config.json', 'package.json', 'server', 'client', 'assets' ]\n  2021-03-03 10:08:48 STATE:  Image DB loaded: pigallery.db records: 7581\n  2021-03-03 10:08:48 STATE:  Shares: Samples creator: mandic00@live.com key: qoy6ic.ibnwn images: 110\n  2021-03-03 10:08:48 STATE:  RESTful API ready\n  2021-03-03 10:08:48 STATE:  Loaded WordNet database: assets/wordnet-synset.json 60942 terms in 24034816 bytes\n  2021-03-03 10:08:50 STATE:  Loaded all cities database: assets/cities.json 195175 all cities 4426 large cities    ```\n\n- Use your browser to navigate to server:  \n  `https://localhost:10010` or `https://localhost:10011` (default values)\n  - Default view is image gallery.\n  - Client access is logged on server:\n\n  ```js\n  2021-02-16 11:41:57 INFO:  API/User/Auth demo@example.com@::1 demo@example.com true\n  2021-02-16 11:41:58 INFO:  API/User/Get demo@example.com@::1 { user: 'demo@example.com', admin: true, root: 'media/' }\n  2021-02-16 11:41:58 INFO:  API/Record/Get demo@example.com@::1 root: media/ images: 0 limit: 100000 chunk: 200 since: 2021-02-16T16:41:59.585Z\n  2021-02-16 11:41:58 INFO:  API/Record/Get Chunk page: 0 of 1 size: 2 total: 2\n  2021-02-16 11:41:58 INFO:  API/Log demo@example.com@::1 Stats: images:0, latency:54, fetch:118, interactive:217, complete:244, load:52, store:0, size:2, speed:0, initial:3, remaining:2, enumerate:73, ready:272, cache:0, pageMode:Standalone, appMode:Browser\n  ```\n\n- If there are no processed images, gallery view is empty  \n  Select `User`-\u003e`Update DB` to start image processing  \n  of provided sample images using default models  \n  specified in `models.json`:\n\n  ```js\n  12:09:03.640 Requesting file list from server ...\n  12:09:05.218   Analyzing folder: Samples/ matching: * recursive: false force: false pending: 110\n  12:09:05.219   Analyzing folder: People/ matching: * recursive: true force: false pending: 2309\n  12:09:05.219   Analyzing folder: Photos/ matching: * recursive: true force: false pending: 4368\n  12:09:05.220   Analyzing folder: Pictures/Samsung Gallery/Snapseed matching: * recursive: false force: false pending: 812\n  12:09:05.220   Analyzing folder: Pictures/Camera Roll/ matching: -01.jp recursive: false force: false pending: 0\n  12:09:05.221 Starting Image Analsys\n  12:09:05.239 Image Classification models:\n  12:09:05.239   ImageNet EfficientNet B4\n  12:09:05.239   DeepDetect Inception v3\n  12:09:05.239   Places365 ResNet-152\n  12:09:05.239 Object Detection models:\n  12:09:05.239   COCO CenterNet ResNet50-v2\n  12:09:05.240   OpenImages SSD MobileNet v2\n  12:09:05.240   NudeNet\n  12:09:05.240 Face Detection model:\n  12:09:05.240   Human\n  12:09:05.240 TensorFlow models loading ...\n  12:09:17.876 TensorFlow models loaded: 12,636ms\n  12:09:17.876 Initializing TensorFlow/JS version 3.3.0\n  12:09:17.881 Configuration:\n  12:09:17.882   Backend: WEBGL\n  12:09:17.882   Parallel processing: 1 parallel images\n  12:09:17.882   Forced image resize: 720px maximum shape: native\n  12:09:17.882   Auto reload on error: true\n  12:09:17.882   WebGL: Enabling memory deallocator\n  12:09:17.882   WebGL: webgl_delete_texture_threshold: 0\n  12:09:17.882   WebGL: webgl_force_f16_textures: false\n  12:09:17.882   WebGL: webgl_pack_depthwiseconv: false\n  12:09:17.882   WebGL: webgl_cpu_forward: true\n  12:09:17.905 TensorFlow engine state: Bytes: 781,759,369 Buffers: 10,345 Tensors: 10,345\n  12:09:17.916 TensorFlow flags: IS_BROWSER:true, IS_NODE:false, DEBUG:false, WEBGL_VERSION:2, HAS_WEBGL:true, PROD:true, WEBGL_CHECK_NUMERICAL_PROBLEMS:false, TENSORLIKE_CHECK_SHAPE_CONSISTENCY:false, WEBGL_DELETE_TEXTURE_THRESHOLD:0, WEBGL_FORCE_F16_TEXTURES:false, WEBGL_PACK_DEPTHWISECONV:false, WEBGL_CPU_FORWARD:true\n  12:09:17.916 TensorFlow warming up ...\n  12:09:47.239 TensorFlow warmed up in 29,323ms\n  12:09:47.245 Processing images: 7599 batch: 1\n  ```\n\n- Select `Live Video` to process live video from your device camera\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n### Configuration Details\n\n- [Server configuration documentation](/docs/config-server.md)\n- [Client configuration documentation](/docs/config-client.md)\n- [Model configuration documentation](/docs/config-models.md)\n\nAdditional nodes:\n\n- [Default models configuration](/docs/models-default.md)\n- [Recommended models configuration](/docs/models-recommended.md)\n- [Model conversion notes](/docs/models-convert.md)\n- [Server API](/docs/api.md)\n\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n## General Notes\n\n### Metadata\n\nProcessing builds tags from all available image metadata:\n\n- Image Metadata:\n  - Size, Creation and Modification timestamps\n  - Camera \u0026 lens details and settings used for image capture\n  - Software used for editing, etc.\n  - GPS Coordinates\n    Matched to location database for place description and location of nearest larger center for purpose of groupping\n- Image Analysis\n  - Multiple iamge classification models\n  - Multiple object detection models\n  - Face age/gender/emotion detection\n  - NSFW detection\n  - Perception hash calculation\n    Used to compare image similarity between any images or to find similar images\n- Lexicon lookups for any detected terms\n  - This includes hierarchical lookups - for example, *gown* will also include *dress, clothing, etc.*\n\nCollected metadata is additionally analyzed to render human-readable search terms\n\n- Age can be specified as: *20ies, 30ies, kid, old, etc.*\n- Camera settings can be specified as: *bright, dark, indoors, outdoors, etc.*\n- Lens settings can be specified as: *superzoom, zoom, portrait, wide, ultrawide*\n- Special words can be used in search terms to form a sentence: *the, a, in, wearing, having, etc.*\n\n\u003cbr\u003e\n\n### Image Processing\n\n- If you get `Error: Failed to link vertex and fragment shaders`, you've run out of GPU memory.  \n  Just restart processing and it will continue from the last known good result.  \n  But if it continues, you need to reduce number of active models or use smaller models.  \n- Model load time can be from few seconds to over a minute depending on model size (in MB)\n- Model warm-up time can be from few seconds to over a minute depending on model complexity (number of tensors)\n- Once models are loaded and ready, actual processing is ~0.1sec - ~1sec per image\n- Image analysis is maximized out-of-the-box for a GPU-accelerated system using WebGL acceleration and GPU with minimum of 4GB of memory  \n  For high-end systems with 8GB or higher, you can further enable ImageNet 21k models  \n  For low-end systems with 2GB or less, enable analysis based on MobileNet v2 and EfficientNet B0 and do not use complex models  \n- Usage without GPU acceleration is not recommended  \n  Note that GPU is not required for image gallery, only for initial processing  \n\n\u003cbr\u003e\n\n### Search\n\nResult of all metadata processing is a very flexbile search engine - take a look at this example:  \n\n  `\"Happy female in 20ies in Miami wearing dress and dining outdoors\"`\n\n\u003cbr\u003e\n\n### Navigation\n\n#### Keyboard shortcuts\n\n```text\n  ENTER : Execute any open input\n  ESC   : Close any dialogs and reset view\n  \\     : Reload data\n  /     : Open search input\n  .     : Open sort interface\n  ,     : Show/hide image descriptions in gallery view\n  Arrow Left \u0026 Right : Previous \u0026 Next image when in detailed view\n  Arrow Up \u0026 Down: Scroll up \u0026 down by one line when in gallery view\n  Page Up \u0026 Down: Scroll up \u0026 down by one page when in gallery view\n  Home \u0026 End: Scroll to start \u0026 end when in gallery view\n```\n\n#### Swipe controlss\n\n- Swipe down will refresh image database\n- Swipe left and right are previous and next image in details view\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n## Live Demo\n\nThis demo is an anonymous share of sample images on my home server:  \n\u003chttps://pigallery.ddns.net?share=qqlny1.0cyk\u003e\n\n\u003cbr\u003e\n\n## Links\n\n- **Code Repository**: \u003chttps://github.com/vladmandic/pigallery\u003e  \n- **Todo List**: \u003chttps://github.com/vladmandic/pigallery/docs/todo.md\u003e  \n- **Changelog**: \u003chttps://github.com/vladmandic/pigallery/CHANGELOG.md\u003e  \n- **License**: \u003chttps://github.com/vladmandic/pigallery/LICENSE\u003e  \n\n\u003cbr\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvladmandic%2Fpigallery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvladmandic%2Fpigallery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvladmandic%2Fpigallery/lists"}