# maskilayer
`maskilayer` is a Python tool for compositing two images using one or more mask images.
- Composite two images (background + overlay) using one or more mask images
- Supply positive masks (overlay is preferred in bright areas of the mask) or negative masks (overlay is preferred in dark mask areas)
- Normalize masks with adjustable levels (0-5)
## 1. Installation
Install `maskilayer` using pip:
```bash
pip install --upgrade maskilayer
```
or the development version in a specific Python:
```bash
python3.11 -m pip install --upgrade git+https://github.com/twardoch/maskilayer
```
## 2. Rationale
### 2.1. Selective image sharpening
Combine a sharpened image with its original version using a segmentation mask:
1. Process an original image with an automatic sharpening method.
2. Use a segmentation model to generate a segmentation mask that isolates a specific subject.
3. Use `maskilayer` to composite:
- background: original image
- overlay: sharpened version
- mask: segmentation mask
`maskilayer` will save a result, which will be a composite image where only the subject is sharpened, while the rest remains as in the original.
### 2.2. Creative upscaling with depth based compositing
Blend two differently upscaled versions of an image using a depth mask:
1. Upscale an image using a conservative upscaler like [Codeformer](https://replicate.com/sczhou/codeformer) to get predictable details for the background areas of the image. Supply the conservative upscale as background to `maskilayer`.
2. Upscale the same image using a creative upscaler like [Ultimate SD Upscale](https://replicate.com/fewjative/ultimate-sd-upscale) to get additional details for foreground (subject) areas of the image. Supply the creative upscale as overlay (compositing image) to `maskilayer`.
3. Generate a depth mask using [Depth Anything](https://replicate.com/cjwbw/depth-anything) or [Midas](https://replicate.com/cjwbw/midas) (where the far areas are dark, and the close areas are bright). Supply the result as the (positive) mask to `maskilayer`. Or use a model like [Marigold](https://replicate.com/adirik/marigold) (where the close subjects are dark), and supply the resulting mask as inverted (negative) mask.
4. Use `maskilayer` to composite:
- background: conservative upscale
- overlay: creative upscale
- mask: depth mask (inverted mask if close areas are dark)
`maskilayer` will save a result, which will be a composite image with creative details for close subjects, and more conservative rendering for distant areas.
## 3. Usage
### 3.1. Command Line Interface
#### 3.1.1. Basic usage
```bash
maskilayer -b background.png -c overlay.png -o output.png
```
#### 3.1.2. Selective image sharpening example
```bash
maskilayer --back original.png --comp sharpened.png --out sharpened_subject.png --masks segmentation_mask.png --norm 3 --verbose
```
#### 3.1.3. Creative upscaling with depth based compositing example
```bash
maskilayer --back conservative_upscale.png --comp creative_upscale.png --out composite_upscale.png --masks "depth_mask1.png;depth_mask2.png" --imasks "inverted_depth_mask3.png" --norm 2 --verbose
```
#### 3.1.4. CLI documentation
```text
NAME
maskilayer - Composite two images using mask(s).
SYNOPSIS
maskilayer <flags>
DESCRIPTION
Composite two images using mask(s).
FLAGS
-b, --back=BACK
Type: str
Default: ''
layer 0 (background image path)
-c, --comp=COMP
Type: str
Default: ''
layer 1 (overlay image path that will be composited via masks)
-o, --out=OUT
Type: str
Default: ''
output composite image
-s, --smask=SMASK
Type: str
Default: ''
path to save the final mask (optional)
-m, --masks=MASKS
Type: Optional
Default: None
;-separated mask image paths (optional)
-i, --imasks=IMASKS
Type: Optional
Default: None
;-separated negative mask image paths (optional)
-n, --norm=NORM
Type: int
Default: 0
perform mask normalization with level 0-5
-v, --verbose=VERBOSE
Type: bool
Default: False
print additional output
-f, --fast=FAST
Type: bool
Default: False
save fast but larger files
```
### 3.2. Python API
#### 3.2.1. Basic usage
```python
from pathlib import Path
from maskilayer import comp_images
comp_images(
background=Path("background.png"),
overlay=Path("overlay.png"),
output=Path("output.png")
)
```
#### 3.2.2. Selective image sharpening example
```python
from pathlib import Path
from maskilayer import comp_images
comp_images(
background=Path("original.png"),
overlay=Path("sharpened.png"),
output=Path("sharpened_subject.png"),
masks=[Path("segmentation_mask.png")],
normalize_level=3,
verbose=True
)
```
#### 3.2.3. Creative upscaling with depth based compositing example
```python
from pathlib import Path
from maskilayer import comp_images
comp_images(
background=Path("conservative_upscale.png"),
overlay=Path("creative_upscale.png"),
output=Path("composite_upscale.png"),
masks=[Path("depth_mask1.png"), Path("depth_mask2.png")],
invert_masks=[Path("inverted_depth_mask3.png")],
normalize_level=2,
verbose=True
)
```
## 4. Mask handling
- If you supply multiple masks, `maskilayer` averages them for the final composition.
- `maskilayer` always converts the mask images to grayscale.
- If you supply a normalization level, `maskilayer` will adjust the mask contrast:
- Level 0 uses masks as-is
- Level 1 stretches grayscale range to full black-white spectrum
- Levels 2-5 progressively increase contrast for more abrupt transitions between bright and dark (level values higher than 5 are permitted but not supported)
### 4.1. Tips for handling multiple mask paths
#### 4.1.1. In CLI
- Use semicolons (`;`) to separate multiple mask paths (you also may use commas):
```bash
maskilayer --masks mask1.png;mask2.png;mask3.png
```
- For inverted masks, use the `--imasks` flag:
```bash
maskilayer --imasks inverted_mask1.png;inverted_mask2.png
```
- You can use both positive and negative masks in the same command:
```bash
maskilayer --masks positive_mask.png --imasks negative_mask.png
```
#### 4.1.2. In Python
- Use lists to provide multiple mask paths:
```python
masks=[Path("mask1.png"), Path("mask2.png"), Path("mask3.png")]
```
- For inverted masks, use the `invert_masks` parameter:
```python
invert_masks=[Path("inverted_mask1.png"), Path("inverted_mask2.png")]
```
- You can use both positive and negative masks in the same function call:
```python
comp_images(
...,
masks=[Path("positive_mask.png")],
invert_masks=[Path("negative_mask.png")]
)
```
## 5. License
- Idea & Copyright (c) 2024 Adam Twardoch
- [Python code](https://github.com/twardoch/maskilayer) written with assistance from OpenAI GPT-4o and Anthropic Claude 3
- Licensed under the [Apache License 2.0](./LICENSE.txt)
Raw data
{
"_id": null,
"home_page": "https://github.com/twardoch/maskilayer",
"name": "maskilayer",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": null,
"author": "Adam Twardoch",
"author_email": "adam+github@twardoch.com",
"download_url": "https://files.pythonhosted.org/packages/0c/0a/45f262ad5ce2627b5d8a433375f4ddf9ed3a1677ea5e4c2446d4e40378e4/maskilayer-1.0.6.tar.gz",
"platform": "any",
"description": "# maskilayer\n\n`maskilayer` is a Python tool for compositing two images using one or more mask images.\n\n- Composite two images (background + overlay) using one or more mask images\n- Supply positive masks (overlay is preferred in bright areas of the mask) or negative masks (overlay is preferred in dark mask areas)\n- Normalize masks with adjustable levels (0-5)\n\n## 1. Installation\n\nInstall `maskilayer` using pip:\n\n```bash\npip install --upgrade maskilayer\n```\n\nor the development version in a specific Python:\n\n```bash\npython3.11 -m pip install --upgrade git+https://github.com/twardoch/maskilayer\n```\n\n## 2. Rationale\n\n### 2.1. Selective image sharpening\n\nCombine a sharpened image with its original version using a segmentation mask:\n\n1. Process an original image with an automatic sharpening method.\n2. Use a segmentation model to generate a segmentation mask that isolates a specific subject.\n3. Use `maskilayer` to composite:\n - background: original image\n - overlay: sharpened version\n - mask: segmentation mask\n\n`maskilayer` will save a result, which will be a composite image where only the subject is sharpened, while the rest remains as in the original.\n\n### 2.2. Creative upscaling with depth based compositing\n\nBlend two differently upscaled versions of an image using a depth mask:\n\n1. Upscale an image using a conservative upscaler like [Codeformer](https://replicate.com/sczhou/codeformer) to get predictable details for the background areas of the image. Supply the conservative upscale as background to `maskilayer`.\n2. Upscale the same image using a creative upscaler like [Ultimate SD Upscale](https://replicate.com/fewjative/ultimate-sd-upscale) to get additional details for foreground (subject) areas of the image. Supply the creative upscale as overlay (compositing image) to `maskilayer`.\n3. Generate a depth mask using [Depth Anything](https://replicate.com/cjwbw/depth-anything) or [Midas](https://replicate.com/cjwbw/midas) (where the far areas are dark, and the close areas are bright). Supply the result as the (positive) mask to `maskilayer`. Or use a model like [Marigold](https://replicate.com/adirik/marigold) (where the close subjects are dark), and supply the resulting mask as inverted (negative) mask.\n4. Use `maskilayer` to composite:\n - background: conservative upscale\n - overlay: creative upscale\n - mask: depth mask (inverted mask if close areas are dark)\n\n`maskilayer` will save a result, which will be a composite image with creative details for close subjects, and more conservative rendering for distant areas.\n\n## 3. Usage\n\n### 3.1. Command Line Interface\n\n#### 3.1.1. Basic usage\n\n```bash\nmaskilayer -b background.png -c overlay.png -o output.png\n```\n\n#### 3.1.2. Selective image sharpening example\n\n```bash\nmaskilayer --back original.png --comp sharpened.png --out sharpened_subject.png --masks segmentation_mask.png --norm 3 --verbose\n```\n\n#### 3.1.3. Creative upscaling with depth based compositing example\n\n```bash\nmaskilayer --back conservative_upscale.png --comp creative_upscale.png --out composite_upscale.png --masks \"depth_mask1.png;depth_mask2.png\" --imasks \"inverted_depth_mask3.png\" --norm 2 --verbose\n```\n\n#### 3.1.4. CLI documentation\n\n```text\nNAME\n maskilayer - Composite two images using mask(s).\n\nSYNOPSIS\n maskilayer <flags>\n\nDESCRIPTION\n Composite two images using mask(s).\n\nFLAGS\n -b, --back=BACK\n Type: str\n Default: ''\n layer 0 (background image path)\n -c, --comp=COMP\n Type: str\n Default: ''\n layer 1 (overlay image path that will be composited via masks)\n -o, --out=OUT\n Type: str\n Default: ''\n output composite image\n -s, --smask=SMASK\n Type: str\n Default: ''\n path to save the final mask (optional)\n -m, --masks=MASKS\n Type: Optional\n Default: None\n ;-separated mask image paths (optional)\n -i, --imasks=IMASKS\n Type: Optional\n Default: None\n ;-separated negative mask image paths (optional)\n -n, --norm=NORM\n Type: int\n Default: 0\n perform mask normalization with level 0-5\n -v, --verbose=VERBOSE\n Type: bool\n Default: False\n print additional output\n -f, --fast=FAST\n Type: bool\n Default: False\n save fast but larger files\n```\n\n### 3.2. Python API\n\n#### 3.2.1. Basic usage\n\n```python\nfrom pathlib import Path\nfrom maskilayer import comp_images\n\ncomp_images(\n background=Path(\"background.png\"),\n overlay=Path(\"overlay.png\"),\n output=Path(\"output.png\")\n)\n```\n\n#### 3.2.2. Selective image sharpening example\n\n```python\nfrom pathlib import Path\nfrom maskilayer import comp_images\n\ncomp_images(\n background=Path(\"original.png\"),\n overlay=Path(\"sharpened.png\"),\n output=Path(\"sharpened_subject.png\"),\n masks=[Path(\"segmentation_mask.png\")],\n normalize_level=3,\n verbose=True\n)\n```\n\n#### 3.2.3. Creative upscaling with depth based compositing example\n\n```python\nfrom pathlib import Path\nfrom maskilayer import comp_images\n\ncomp_images(\n background=Path(\"conservative_upscale.png\"),\n overlay=Path(\"creative_upscale.png\"),\n output=Path(\"composite_upscale.png\"),\n masks=[Path(\"depth_mask1.png\"), Path(\"depth_mask2.png\")],\n invert_masks=[Path(\"inverted_depth_mask3.png\")],\n normalize_level=2,\n verbose=True\n)\n```\n\n## 4. Mask handling\n\n- If you supply multiple masks, `maskilayer` averages them for the final composition.\n- `maskilayer` always converts the mask images to grayscale.\n- If you supply a normalization level, `maskilayer` will adjust the mask contrast:\n - Level 0 uses masks as-is\n - Level 1 stretches grayscale range to full black-white spectrum\n - Levels 2-5 progressively increase contrast for more abrupt transitions between bright and dark (level values higher than 5 are permitted but not supported)\n\n### 4.1. Tips for handling multiple mask paths\n\n#### 4.1.1. In CLI\n\n- Use semicolons (`;`) to separate multiple mask paths (you also may use commas):\n ```bash\n maskilayer --masks mask1.png;mask2.png;mask3.png\n ```\n- For inverted masks, use the `--imasks` flag:\n ```bash\n maskilayer --imasks inverted_mask1.png;inverted_mask2.png\n ```\n- You can use both positive and negative masks in the same command:\n ```bash\n maskilayer --masks positive_mask.png --imasks negative_mask.png\n ```\n\n#### 4.1.2. In Python\n\n- Use lists to provide multiple mask paths:\n ```python\n masks=[Path(\"mask1.png\"), Path(\"mask2.png\"), Path(\"mask3.png\")]\n ```\n- For inverted masks, use the `invert_masks` parameter:\n ```python\n invert_masks=[Path(\"inverted_mask1.png\"), Path(\"inverted_mask2.png\")]\n ```\n- You can use both positive and negative masks in the same function call:\n ```python\n comp_images(\n ...,\n masks=[Path(\"positive_mask.png\")],\n invert_masks=[Path(\"negative_mask.png\")]\n )\n ```\n\n## 5. License\n\n- Idea & Copyright (c) 2024 Adam Twardoch\n- [Python code](https://github.com/twardoch/maskilayer) written with assistance from OpenAI GPT-4o and Anthropic Claude 3\n- Licensed under the [Apache License 2.0](./LICENSE.txt)\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Python tool to composite two images using multiple mask images",
"version": "1.0.6",
"project_urls": {
"Homepage": "https://github.com/twardoch/maskilayer",
"Source": "https://github.com/twardoch/maskilayer",
"Tracker": "https://github.com/twardoch/maskilayer/issues"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8692f7289c0595b3f7aa25cd4e2a0cb1c74575ea19d2202c6a915c5d85d14663",
"md5": "f4d9774151724dfcb3f2e6939ea7f0ce",
"sha256": "0a2778ede017b02e41fc0a1eb26fd5317428e72bf9a4125b8aa3cd3c29cd4821"
},
"downloads": -1,
"filename": "maskilayer-1.0.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f4d9774151724dfcb3f2e6939ea7f0ce",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 11757,
"upload_time": "2024-06-24T00:30:49",
"upload_time_iso_8601": "2024-06-24T00:30:49.387285Z",
"url": "https://files.pythonhosted.org/packages/86/92/f7289c0595b3f7aa25cd4e2a0cb1c74575ea19d2202c6a915c5d85d14663/maskilayer-1.0.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0c0a45f262ad5ce2627b5d8a433375f4ddf9ed3a1677ea5e4c2446d4e40378e4",
"md5": "2772b2d411372a757cf1da979b6e7c05",
"sha256": "999798a6749b0c375e658d148c88398e6e96ee7a05b00a7223ea25fba5519140"
},
"downloads": -1,
"filename": "maskilayer-1.0.6.tar.gz",
"has_sig": false,
"md5_digest": "2772b2d411372a757cf1da979b6e7c05",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 23909,
"upload_time": "2024-06-24T00:30:54",
"upload_time_iso_8601": "2024-06-24T00:30:54.438629Z",
"url": "https://files.pythonhosted.org/packages/0c/0a/45f262ad5ce2627b5d8a433375f4ddf9ed3a1677ea5e4c2446d4e40378e4/maskilayer-1.0.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-24 00:30:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "twardoch",
"github_project": "maskilayer",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"tox": true,
"lcname": "maskilayer"
}