{"id":21928850,"url":"https://github.com/alex-developer/allskyannotate","last_synced_at":"2025-03-22T12:25:36.889Z","repository":{"id":150931257,"uuid":"437652450","full_name":"Alex-developer/allskyannotate","owner":"Alex-developer","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-04T11:59:12.000Z","size":6237,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-27T11:50:03.257Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/Alex-developer.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}},"created_at":"2021-12-12T20:44:37.000Z","updated_at":"2021-12-30T23:35:37.000Z","dependencies_parsed_at":"2023-05-05T15:30:32.476Z","dependency_job_id":null,"html_url":"https://github.com/Alex-developer/allskyannotate","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alex-developer%2Fallskyannotate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alex-developer%2Fallskyannotate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alex-developer%2Fallskyannotate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alex-developer%2Fallskyannotate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alex-developer","download_url":"https://codeload.github.com/Alex-developer/allskyannotate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244955490,"owners_count":20537974,"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":[],"created_at":"2024-11-28T22:28:21.168Z","updated_at":"2025-03-22T12:25:36.859Z","avatar_url":"https://github.com/Alex-developer.png","language":"Python","readme":"# allskyannotate\n\nA script to allow annotation of images created by Thomas Jacquin's allsky software - https://github.com/thomasjacquin/allsky\n\n**This is BETA Software and should only be used if you are comfortable installing and configuring software**\n\n![ZWO Example 1](docimages/zwo-example1.png?raw=true \"Example 1\")\n\n**Please read all of this document before using this script**\n\n**Go Easy this is my first 'proper' Python project ;-)**\n\nThis script will allow the following to be overlayed on the captured image\n\n* Text\n* Inbuilt data (Such as the Moon's phase)\n* Images\n* Extra text, as the current allsky softare does\n* Data passed on the command line\n\nIt is intended to replace the 'extra' text functionality that is a little limited in respect to where text can be placed.\n\nThe annotater will work for any camera used.\n\n## Why Write This?\nI originally wrote the 'extra' text feature to allow me to display data from my camera, I have several external sensors capturing data. This was fine at the time but as I have added more to my camera I found myself wanting a lot more data to be displayed on each captured image and wanted to use different fonts.\nI played around with a few ideas, like imagemagick but found then really quite slow and cumbersom to setup and maintain. I settled on an approach that keeps all of the configuration for the data to be displayed in a single file.\n\n## How does it work?\nThe idea is quite simple\n\n1) In the saveImageNight script once all of the image processing is complete, but before its been copied to its final locations, call this script passing it the relevant data\n2) This script will annotate the image and write it back to allsky\n3) The allsky sofware can then continue to process the image\n\n![Data Flow](docimages/flow.png?raw=true \"Flow\")\n\n# Annotater command line\n\nBefore looking at the setup its worth seeing how the annotater runs. The annotater is invoked using the annotater.py script, the installer documented below will automatically add this the the allsky sabe image script.\n\n```usage: annotate.py [-h] [-v] [-d DATA] [-c CONFIG] [-i IMAGE] [-k [KWARGS ...]]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -v, --verbose         Verbose output\n  -d DATA, --data DATA  Path to extra data\n  -c CONFIG, --config CONFIG\n                        Path to config file, if none will use annotate.json\n  -i IMAGE, --image IMAGE\n                        Image file to use, if none latest allsky image will be used\n  -k [KWARGS ...], --kwargs [KWARGS ...]\n                        list of key pair values for field data --kwargs sensor=32.1 date=20211207 231234\n```\n\nThe options are\n\n| Option | Required? |Description |\n| ------ | --------- |----------- |\n| -v | No  | Enable more verbose output |\n| -d | No  | The path to the datafile containing extra information, see 'Data Files' below |\n| -c | No  | The full path to the config file. If not specified annotate.json is used |\n| -i | No  | The full path to the image to annotate. If not specified the current allsky image is used |\n| -k | No  | List of additional variables, mainly intended to be used for allsk to pass data |\n\nWith no options specified the annotated will use the last image captured by the allsky software and the default configuration, annotate.json.\n\nWhen testing its best to use the -v option as it will tell you if there are any issues. If you see any errors reported when using the -v option these should be fixed.\n\n## Data Files\nThe annotater can either use the extra data file from allsky or a new file format that you specify on the command line with the -d option. This file is either a json or etxt file with key pair values. This file would be created by any other software you are using.\n\n### json format\n\n```javascript\n{\n    \"fields\": {\n        \"skystate\": \"Clear\",\n        \"teapot\": \"Empty\"\n    }\n}\n```\n\n### name pair format\n\n```\nskystate=Clear\nteapot=Empty\n```\n\n# Setting things up\n\n## Permissions\nIts important that the annotation script can access all of the allsky data and configuration so please ensure that the annotation script is setup as the same user as the allsky software. Normally this will just be the default pi user.\n\n## Dependencies\n\n### Python3\nThe annotater requires python3 and will **not** run on python2. Python3 does not have to be the default on your system but it must be installed\n\n### Allsky\nThe allsky software must be setup and working correctly before attempting to install this script.\nPlease make a backup of any scripts that you change in the allsky software and note that you will have to make the changes again should you update the allsky software\n\n### Python libraries\nThe code requires several Python libraries. The installer script will install these if not present.\n\n* opencv\n* numpy\n* ephem\n* pillow\n\n## Getting the code\nClone the repository into a location of your choice\n\n```\ngit clone https://github.com/Alex-developer/allskyannotate.git\n```\n\n## Run the installer\nAn installation script is provided that will automate most of the installation and setup process. To run the script change into the allskyannotate directory and enter\n\n```\n./installer/install.sh\n```\n\nThe installer will guide you through a series of promts to install the annotater. You will also have the option to automatically modify the default allsky scripts to call the annotater at the correct point after an imge has been captured. The installer will make a backup copy of the allsky scripts in case you wish to remove the annotater.\n\n## Copy the default config file\n**Only do this step if you did not setup a config during the installation process**\n\nBy default the annotater will use a configuration file called annotate.json. When the repository is cloned you will find an empty config file called annotate.json.repo so copy this\n\n```\ncp examples/configs/empty-config.json annotate.json\n```\n\n## Config Setup\nThe config is all defined in a json file, by defaulgithubt called annotate.json. The file contains three sections\n\n| Section | Description |\n| ------- | ----------- |\n| fields  | This defines the fields to display on the allsky captured image |\n| images  | This defines any images to display on the allsky captured image |\n| fonts   | This section defines any custom fonts you wish to use |\n\n### Fonts\nThe annotater is capable of displaying information using TruType fonts. There is a vast collection of these availble online, https://www.dafont.com for example.\nTo install the fonts first find the TrueType font you wish to use and copy it into the fonts folder.\n\nAn example fonts ection of the config might look liek the following\n\n```javascript\n    \"fonts\": {\n        \"fontbig\": {\n            \"fontPath\": \"fonts/Comfortaa-Regular.ttf\",\n            \"fontSize\": 60\n        },\n        \"font1\": {\n            \"fontPath\": \"fonts/Comfortaa-Regular.ttf\",\n            \"fontSize\": 24\n        },\n        \"font3\": {\n            \"fontPath\": \"fonts/Comfortaa-Regular.ttf\",\n            \"fontSize\": 20\n        },\n        \"moon\": {\n            \"fontPath\": \"fonts/moon_phases.ttf\",\n            \"fontSize\": 48\n        },\n        \"we\": {\n            \"fontPath\": \"fonts/DS-DIGI.TTF\",\n            \"fontSize\": 16\n        },\n        \"we1\": {\n            \"fontPath\": \"fonts/DS-DIGI.TTF\",\n            \"fontSize\": 32\n        }\n    }\n```\nEach entry in the fonts section specifies a font name that can then be applied to a field definition. Looking at each of the fonts entries in a little more detail\n\n```javascript\n        \"fontbig\": { \u003c!-- The name of this font entry. This Must be unique --\u003e\n            \"fontPath\": \"fonts/Comfortaa-Regular.ttf\", \u003c!-- The path to the font file --\u003e\n            \"fontSize\": 60 \u003c! --\u003e- The size of the font\n        }\n```\n\nFonts should be installed in the fonts directory. The annotater will support any TrueType font. \n\nIf you are not comfortable editing the json files then a script is available in the scripts directory to install fonts for you. To run the script cd into the script directory and run the addfont.py script. The script takes several arguments\n\n```\nusage: addfont.py [-h] [-v] [-c CONFIG] -f FONT\n\noptional arguments:\n  -h, --help            show this help message and exit\n\nrequired arguments:\n  -f FONT, --font FONT  The URL of the font on daFont.com. Make sure ints the font page uRL NOT a search page url\n\noptional arguments:\n  -v, --verbose         Verbose output\n  -c CONFIG, --config CONFIG\n                        Path to config file, if none will use annotate.json\n```\n\nFor most users the only option required is the -f option which specifies the URL to the font on dafont.com. An example might look like\n\n```\n./addfont.py -f https://www.dafont.com/chernobyl.font\n```\n\nThis will download the font and then prompt you for two sets of entries. The first is the names you wish to use as a comma seperated list and the second the sizes you require for each name. Since a font from dafont may contain more than one font, light/bold etc, you will be prompted for these values for each font found in the download. If you do not wish to use a specific font just hit enter when prmompted for the names.\n\nOnce you have entered the data and its been validated the fonts selected will be installed in the fonts folder and the config file updated.\n\n### Images\nThe annotater is capable of adding images to the frame catured by the allsky software. I use this to add a small compass to my images indicating North and also to add a small signature.\n\nAn example images section might look like\n\n```javascript\n    \"images\": {\n        \"compass\": {\n            \"position\": {\n                \"x\": 1800,\n                \"y\": 100\n            },\n            \"rotate\": 10,\n            \"image\": \"images/compass150.png\"\n        },\n        \"signature\": {\n            \"position\": {\n                \"x\": 1540,\n                \"y\": 1800\n            },\n            \"image\": \"images/signature.png\"\n        } \n    }\n```\n\nIn the above example two images will be added to every frame captured by the AllSky Software. The first is a compass at 1800,100 rotated by 10 degrees and the second a signature added at 1540, 1800.\n\nThe images typically reside in the images folder inside the annotater main folder but can be anywhere as long as a full path to the image is provided.\n\nCare should be taken when adding images to make sure they do not go outside the bounds of the main image.\n\nIf you are not comfortable editing the config the a script is available in the scripts directory to assist in adding images. The script is called addimages.py\n\n```\nusage: addimage.py [-h] [-v] [-r ROTATION] [-c CONFIG] -i IMAGE -x XPOS -y YPOS -n NAME\n\noptional arguments:\n  -h, --help            show this help message and exit\n\nrequired arguments:\n  -i IMAGE, --image IMAGE\n                        Full path to the image\n  -x XPOS, --xpos XPOS  The x coordinate for the field\n  -y YPOS, --ypos YPOS  The y coordinate for the field\n  -n NAME, --name NAME  The name for the field\n\noptional arguments:\n  -v, --verbose         Verbose output\n  -r ROTATION, --rotation ROTATION\n                        Image rotation in degrees\n  -c CONFIG, --config CONFIG\n                        Path to config file, if none will use annotate.json\n```\n\nThe script takes several parameters some optional and some mandatory. \n\n| Option | Required? |Description |\n| ------ | --------- |----------- |\n| -i | Yes | The FULL path to the image file |\n| -x | Yes | The x coordinate in the image  |\n| -y | Yes | The y coordinate in the image |\n| -r | No  | The rotation of the image in degrees |\n| -v | No  | Enable more verbose output |\n\n### Fields\nFields are the data that is added to the image. There are four sources of data that can be added\n\n* From the AllSky software\n* From an extra text file\n* passed on the command line to the annotater\n* inbuilt fields\n\n#### Extra Text\nSince most people will be migrating from using the Extra Text feature in allsky the first type of field allows for the extra text to be added to the images easily.\n\n```\n\"file\": {\n    \"file\": \"\",\n    \"position\": {\n        \"x\": 10,\n        \"y\": 220\n    },\n    \"colour\": \"red\",\n    \"font\": \"font3\"\n}\n```\n\nIn the above example the extra text is displayed starting at 10,220 (pixels) in the captured image using font3, this is defined in the fonts section and coloured red.\n\nThe file entry is blank which means the annoater will look at he AllSky config to find the extra text file. You can also specify a FULL path to the file here, see the previous notes about permissions on files.\n\n**NOTE: The Extra Text feature was never implemented on the pi HQ camera so if you are using one you will need to specify the path to the file in the 'file' setting**\n\nThe colour field supports a lot of different ways of specifying the colour, see the colours section below.\n\n#### Other Fields\nThe annotater is also capable of adding information from an external source or via its internal data. The external source is intended to be a replacement for the 'Extra Text' feature in allsky. Whilst this can still be used, see above, if you are in control of the extra data the new way of doing it is far more flexible.\n\nIn this first example we will look at using a data field provoided from the data file specified using the -d option when running the annotater.\n\n```javascript\n\"skystate\": {\n    \"variable\": \"%skystate\",\n    \"label\": \"Sky State: \",\n    \"position\": {\n        \"x\": 10,\n        \"y\": 1940\n    },\n    \"colour\": \"#6f2232\",\n    \"font\": \"font3\"\n}\n```\nThis example is displaying the 'skystate' variable from the data file. Looking at the fields \n\n| field | Description |\n| ------- | ----------- |\n| variable  | The variable name to use. The % indicates that this is from the external data source or commad line |\n| label  | The label for the field. This can be blank if no label is required |\n| Position   | This specifies the position on the image to display the field |\n| colour | This specifies the colour of the field, see the 'colouurs' section below |\n| font | This specifies the name in the fonts entry for the font to use |\n\nThis second example is displaying an internal field. Internal fields are data that the annotater generates automatically and makes avaialble.\n\n```\n\"moonphase\": {\n    \"variable\": \"^moonphase\",\n    \"label\": \"\",\n    \"position\": {\n        \"x\": 200,\n        \"y\": 1790\n    },\n    \"colour\": \"white\",\n    \"font\": \"moon\"\n}\n```\nThe only real difference between this and the previous example is the 'variable'. In this case it is prefixed with a ^ indicating that its an internal variable.\n\nAvailable internal variables. At present the only variables available relate to the Moon and the calculation use the lat/lon defined in the main allsk configuration\n\n| variable | Description |\n| ------- | ----------- |\n| ^moonphase  | Special variable to be used with the Moon font to display the Moon Phase |\n| ^moonillumination | The percentage of the Moon illuminated |\n| ^moonazimuth | The Azimuth of the Moon |\n| ^moonelevation | The Moons elevation |\n\nThe last example is using a field to display a label with no data\n\n```\n        \"moonlabel\": {\n            \"variable\": \"\",\n            \"label\": \"Moon Phase\",\n            \"position\": {\n                \"x\": 10,\n                \"y\": 1800\n            },\n            \"colour\": \"#950740\",\n            \"font\": \"font1\"\n        }\n```\n\nThe only real difference with this example is the variable is empty and a label defined.\n\n#### Fields Script\nAs with the other config sections a basic helper script is provided to add fields.\n\n```\nusage: addfield.py [-h] [-v] [-i FILE] [-c CONFIG] [-l LABEL] -f FIELD -a VARIABLE -x XPOS -y YPOS -r COLOUR -o FONT\n\noptional arguments:\n  -h, --help            show this help message and exit\n\nrequired arguments:\n  -f FIELD, --field FIELD\n                        The name of the field to add/edit\n  -a VARIABLE, --variable VARIABLE\n                        The name of the variable to display\n  -x XPOS, --xpos XPOS  The x coordinate for the field\n  -y YPOS, --ypos YPOS  The y coordinate for the field\n  -r COLOUR, --colour COLOUR\n                        The colour of the field\n  -o FONT, --font FONT  The font name to use\n\noptional arguments:\n  -v, --verbose         Verbose output\n  -i FILE, --file FILE  Filename for extra text\n  -c CONFIG, --config CONFIG\n                        Path to config file, if none will use annotate.json\n  -l LABEL, --label LABEL\n                        The fields label\n```\n\n#### Checking the configuration\nA script is provided in the scripts directory that will do basic validation of the configuration file. To run it change to the scripts directory and enter\n\n```\n./validate.py\n```\n\nThe script will run thru the configuration and report on any issues. There are two types of issues reported\n\n| Issue | Notes |\n| ----- | ----------- |\n| ERROR  | This is an issue that will prevent the annotater runnign so **must** be fixed |\n| WARNING | There is a problem with the config but it will nto prevent the annotater from running |\n\nExample output from the validation script\n\n```\nAttempting To Load Config File From /home/pi/allskyannotate/annotate.json\nConfig File Loaded From /home/pi/allskyannotate/annotate.json\n\nConfig Info\n-----------\nFields : 13\nImages : 2\nFonts  : 6\n\nChecking Fonts\n--------------\nChecked Font fontbig Font Installed, Font Used, Font Size OK\nChecked Font font1 Font Installed, Font Used, Font Size OK\nChecked Font font3 Font Installed, Font Used, Font Size OK\nChecked Font moon Font Installed, Font Used, Font Size OK\nWarning Checked Font we Font Installed, Font Not Used, Font Size OK\nWarning Checked Font we1 Font Installed, Font Not Used, Font Size OK\n\nChecking Images\n---------------\nImage /home/pi/allskyannotate/images/compass150.png Found OK, Position Found\nImage /home/pi/allskyannotate/images/signature.png Found OK, Position Found\n\nChecking Fields\n---------------\nChecked Field date, Position Found, Variable Valid, Font valid\nChecked Field sensor temp, Position Found, Variable Valid, Font valid\nChecked Field exposure, Position Found, Variable Valid, Font valid\nChecked Field gain, Position Found, Variable Valid, Font valid\nERROR Checked Field brightness, Position Found, Variable Valid, Font Name 'font31' Not found in the fonts section\nChecked Field file, Position Found, Variable Valid, Font valid\nChecked Field moonlabel, Position Found, Variable Valid, Font valid\nChecked Field moonphase, Position Found, Variable Valid, Font valid\nChecked Field moonillumination, Position Found, Variable Valid, Font valid\nChecked Field moonazimuth, Position Found, Variable Valid, Font valid\nChecked Field moonelevation, Position Found, Variable Valid, Font valid\nChecked Field skystate, Position Found, Variable Valid, Font valid\nChecked Field date1, Position Found, Variable Valid, Font valid\n\nResults\n-------\nError: There are errors in your configuration. These will prevent the annotater from running and must be fixed\nWarning: There are warnings in your configuration. These will not prevent the annotater from running but should be fixed\n```\n\n#### Colours\nHexadecimal color specifiers, given as #rgb, #rgba, #rrggbb or #rrggbbaa, where r is red, g is green, b is blue and a is alpha (also called ‘opacity’). For example, #ff0000 specifies pure red, and #ff0000cc specifies red with 80% opacity (cc is 204 in decimal form, and 204 / 255 = 0.8).\n\nRGB functions, given as rgb(red, green, blue) where the color values are integers in the range 0 to 255. Alternatively, the color values can be given as three percentages (0% to 100%). For example, rgb(255,0,0) and rgb(100%,0%,0%) both specify pure red.\n\nHue-Saturation-Lightness (HSL) functions, given as hsl(hue, saturation%, lightness%) where hue is the color given as an angle between 0 and 360 (red=0, green=120, blue=240), saturation is a value between 0% and 100% (gray=0%, full color=100%), and lightness is a value between 0% and 100% (black=0%, normal=50%, white=100%). For example, hsl(0,100%,50%) is pure red.\n\nHue-Saturation-Value (HSV) functions, given as hsv(hue, saturation%, value%) where hue and saturation are the same as HSL, and value is between 0% and 100% (black=0%, normal=100%). For example, hsv(0,100%,100%) is pure red. This format is also known as Hue-Saturation-Brightness (HSB), and can be given as hsb(hue, saturation%, brightness%), where each of the values are used as they are in HSV.\n\nCommon HTML color names. The ImageColor module provides some 140 standard color names, based on the colors supported by the X Window system and most web browsers. color names are case insensitive. For example, red and Red both specify pure red.\n\n# Testing\nThe best way to test is to keep things simple to start with. \n\n- Run the install script but **DO NOT** allow the installer to modify the allsky save script.\n  - Setup te annoatet.json config as required\n  - Run the annotate.py script with the -v option and check the resulting image\n  - Fix any issues and repeat the above steps untill you are happy\n- Re run the installer and modify the allsky scripts\n\n# Performance\nPerformance is important as the annotater runs inline withe the main allsky software. I have tried to optimise the code as much as possible.\n\nSome statistics from a Pi4B with 8 Gig of RAM\n\n| Benchmark | Time |\n| ------- | ----------- |\n| Replacement for default extra text functionality in allksy  | 0.39 Seconds |\n| 13 Fields, 2 Images and 6 Fonts | 0.50 Seconds |\n\n# Debugging tips\n\n## Displaying more verbose output from the annotater\n\nThe best way to debug any issues is to use the verbose logging mode of the annotater. To enable this find the following bit of code in the allsky saveimageNight script\n\n```\n# Run the image annotation script. Added by the annotater installer on Sun 26 Dec 21:26:45 GMT 2021\nif [[ -x \"/home/pi/allskyannotate/annotate.py\" ]]\nthen\n  /home/pi/allskyannotate/annotate.py\nfi\n```\n\nAnd change it to add a -v to the annotate.py\n\n```\n# Run the image annotation script. Added by the annotater installer on Sun 26 Dec 21:26:45 GMT 2021\nif [[ -x \"/home/pi/allskyannotate/annotate.py\" ]]\nthen\n  /home/pi/allskyannotate/annotate.py -v\nfi\n```\n\nThen tail the allsk log file\n\n# Uninstalling\nIf you wish to remove the annotater then run the uninstall script from the annotater directory\n\n```\n./installer/uninstall.py\n```\n\nThe uninstaller will replace the allsky save image script with the backup made during the installation. It will NOT remove the annotater code or directory.\n\n# Upgrading AllSky\n\nAfter ugrading allsky its very **IMPORTANT** that you re run the installer","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-developer%2Fallskyannotate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falex-developer%2Fallskyannotate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-developer%2Fallskyannotate/lists"}