# Olympict
![coverage](https://gitlab.com/gabraken/olympict/badges/master/coverage.svg?job=tests)![status](https://gitlab.com/gabraken/olympict/badges/master/pipeline.svg)
![Olympict](https://gitlab.com/gabraken/olympict/-/raw/master/Olympict.png)
Based on [olympipe](https://pypi.org/project/olympipe/), this project will make image processing pipelines easy to use using the basic multiprocessing module.
This module uses type checking to ensure your data process validity from the start.
## Basic image processing pipeline
### Loading images from a folder and resize them to a new folder
```python
from olympict import ImagePipeline
p0 = ImagePipeline.load_folder("./examples") # path containing the images
p1 = p0.resize((150, 250)) # new width, new height
p2 = p1.save_to_folder("./resized_examples") # path to save the images
p2.wait_for_completion() # the code blocks here until all images are processed
print("Finished resizing")
```
### Loading images from a folder and overwrite them with a new size
```python
from olympict import ImagePipeline
p0 = ImagePipeline.load_folder("./examples") # path containing the images
p1 = p0.resize((150, 250))
p2 = p1.save() # overwrite the images
p2.wait_for_completion()
```
### Loading images from a folder and resize them keeping the aspect ratio using a padding color
```python
from olympict import ImagePipeline
blue = (255, 0, 0) # Colors are BGR to match opencv format
p0 = ImagePipeline.load_folder("./examples")
p1 = p0.resize((150, 250), pad_color=blue)
p2 = p1.save() # overwrite the images
p2.wait_for_completion()
```
### Load image to make a specific operation
```python
from olympict import ImagePipeline, Img
def operation(image: Img) -> Img:
# set the green channel as a mean of blue and red channels
img[:, :, 1] = (img[:, :, 0] + img[:, :, 2]) / 2
return img
p0 = ImagePipeline.load_folder("./examples")
p1 = p0.task_img(operation)
p2 = p1.save() # overwrite the images
p2.wait_for_completion()
```
### Check ongoing operation
```python
from olympict import ImagePipeline, Img
def operation(image: Img) -> Img:
# set the green channel as a mean of blue and red channels
img[:, :, 1] = (img[:, :, 0] + img[:, :, 2]) / 2
return img
p0 = ImagePipeline.load_folder("./examples").debug_window("Raw image")
p1 = p0.task_img(operation).debug_window("Processed image")
p2 = p1.save() # overwrite the images
p2.wait_for_completion()
```
### Load a video and process each individual frame
```python
from olympict import VideoPipeline
p0 = VideoPipeline.load_folder("./examples") # will load .mp4 and .mkv files
p1 = p0.to_sequence() # split each video frame into a basic image
p2 = p1.resize((100, 3), (255, 255, 255)) # resize each image with white padding
p3 = p2.save_to_folder("./sequence") # save images individually
p3.wait_for_completion()
img_paths = glob("./sequence/*.png") # count images
print("Number of images:", len(img_paths))
```
### Complex example with preview windows
```python
import os
from random import randint
import re
import time
from olympict import ImagePipeline
from olympict.files.o_image import OlympImage
def img_simple_order(path: str) -> int:
number_pattern = r"\d+"
res = re.findall(number_pattern, os.path.basename(path))
return int(res[0])
if __name__ == "__main__":
def wait(x: OlympImage):
time.sleep(0.1)
print(x.path)
return x
def generator():
for i in range(96):
img = np.zeros((256, 256, 3), np.uint8)
img[i, :, :] = (255, 255, 255)
o = OlympImage()
o.path = f'/tmp/{i}.png'
o.img = img
yield o
return
p = (
ImagePipeline(generator())
.task(wait)
.debug_window("start it")
.task_img(lambda x: x[::-1, :, :])
.debug_window("flip it")
.keep_each_frame_in(1, 3)
.debug_window("stuttered")
.draw_bboxes(
lambda x: [
(
(
randint(0, 50),
randint(0, 50),
randint(100, 200),
randint(100, 200),
"change",
0.5,
),
(randint(0, 255), 25, 245),
)
]
)
.debug_window("bboxed")
)
p.wait_for_completion()
```
## /!\ To use Huggingface Models, you must install this package with [hf] extras
```bash
poetry add olympict[hf]
or
pip install olympict[hf]
```
### Use with Huggingface image classification models
```python
from olympict import ImagePipeline
from olympict.files.o_image import OlympImage
def print_metas(x: OlympImage):
print(x.metadata)
return x
if __name__ == "__main__":
# very important, without this processes will get stuck
from torch.multiprocessing import set_start_method
set_start_method("spawn")
(
ImagePipeline.load_folder("./classif")
.classify("google/mobilenet_v2_1.0_224")
.task(print_metas)
).wait_for_completion()
```
This project is still an early version, feedback is very helpful.
Raw data
{
"_id": null,
"home_page": "https://gitlab.com/gabraken/olympict",
"name": "olympict",
"maintainer": null,
"docs_url": null,
"requires_python": "<3.13,>=3.9",
"maintainer_email": null,
"keywords": "image, parallel, multiprocessing, pipeline",
"author": "Gabriel Kasser",
"author_email": "gabriel.kasser@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/72/f9/d98a6d6864127c82cb26c2b50bf4dac03ed3506ef502ef3f24a9142c18fc/olympict-1.4.0.tar.gz",
"platform": null,
"description": "# Olympict\n\n![coverage](https://gitlab.com/gabraken/olympict/badges/master/coverage.svg?job=tests)![status](https://gitlab.com/gabraken/olympict/badges/master/pipeline.svg)\n\n![Olympict](https://gitlab.com/gabraken/olympict/-/raw/master/Olympict.png)\n\n\nBased on [olympipe](https://pypi.org/project/olympipe/), this project will make image processing pipelines easy to use using the basic multiprocessing module. \nThis module uses type checking to ensure your data process validity from the start.\n\n## Basic image processing pipeline\n\n### Loading images from a folder and resize them to a new folder\n\n```python\nfrom olympict import ImagePipeline\n\np0 = ImagePipeline.load_folder(\"./examples\") # path containing the images\np1 = p0.resize((150, 250)) # new width, new height\np2 = p1.save_to_folder(\"./resized_examples\") # path to save the images\np2.wait_for_completion() # the code blocks here until all images are processed\n\nprint(\"Finished resizing\")\n```\n\n### Loading images from a folder and overwrite them with a new size\n\n```python\nfrom olympict import ImagePipeline\n\np0 = ImagePipeline.load_folder(\"./examples\") # path containing the images\np1 = p0.resize((150, 250))\np2 = p1.save() # overwrite the images\np2.wait_for_completion()\n```\n\n### Loading images from a folder and resize them keeping the aspect ratio using a padding color\n\n```python\nfrom olympict import ImagePipeline\nblue = (255, 0, 0) # Colors are BGR to match opencv format\n\np0 = ImagePipeline.load_folder(\"./examples\")\np1 = p0.resize((150, 250), pad_color=blue)\np2 = p1.save() # overwrite the images\np2.wait_for_completion()\n```\n\n### Load image to make a specific operation\n\n```python\nfrom olympict import ImagePipeline, Img\n\ndef operation(image: Img) -> Img:\n # set the green channel as a mean of blue and red channels\n img[:, :, 1] = (img[:, :, 0] + img[:, :, 2]) / 2\n return img\n\np0 = ImagePipeline.load_folder(\"./examples\")\np1 = p0.task_img(operation)\np2 = p1.save() # overwrite the images\np2.wait_for_completion()\n```\n\n\n### Check ongoing operation\n\n```python\nfrom olympict import ImagePipeline, Img\n\ndef operation(image: Img) -> Img:\n # set the green channel as a mean of blue and red channels\n img[:, :, 1] = (img[:, :, 0] + img[:, :, 2]) / 2\n return img\n\np0 = ImagePipeline.load_folder(\"./examples\").debug_window(\"Raw image\")\np1 = p0.task_img(operation).debug_window(\"Processed image\")\np2 = p1.save() # overwrite the images\np2.wait_for_completion()\n```\n\n### Load a video and process each individual frame\n\n```python\nfrom olympict import VideoPipeline\n\np0 = VideoPipeline.load_folder(\"./examples\") # will load .mp4 and .mkv files\n\np1 = p0.to_sequence() # split each video frame into a basic image\n\np2 = p1.resize((100, 3), (255, 255, 255)) # resize each image with white padding\n\np3 = p2.save_to_folder(\"./sequence\") # save images individually\n\np3.wait_for_completion()\n\nimg_paths = glob(\"./sequence/*.png\") # count images\n\nprint(\"Number of images:\", len(img_paths))\n```\n\n\n### Complex example with preview windows\n```python\nimport os\nfrom random import randint\nimport re\nimport time\nfrom olympict import ImagePipeline\nfrom olympict.files.o_image import OlympImage\n\n\ndef img_simple_order(path: str) -> int:\n number_pattern = r\"\\d+\"\n res = re.findall(number_pattern, os.path.basename(path))\n\n return int(res[0])\n\n\nif __name__ == \"__main__\":\n\n def wait(x: OlympImage):\n time.sleep(0.1)\n print(x.path)\n return x\n\n def generator():\n for i in range(96):\n img = np.zeros((256, 256, 3), np.uint8)\n img[i, :, :] = (255, 255, 255)\n\n o = OlympImage()\n o.path = f'/tmp/{i}.png'\n o.img = img\n yield o\n return\n\n p = (\n ImagePipeline(generator())\n .task(wait)\n .debug_window(\"start it\")\n .task_img(lambda x: x[::-1, :, :])\n .debug_window(\"flip it\")\n .keep_each_frame_in(1, 3)\n .debug_window(\"stuttered\")\n .draw_bboxes(\n lambda x: [\n (\n (\n randint(0, 50),\n randint(0, 50),\n randint(100, 200),\n randint(100, 200),\n \"change\",\n 0.5,\n ),\n (randint(0, 255), 25, 245),\n )\n ]\n )\n .debug_window(\"bboxed\")\n )\n\n p.wait_for_completion()\n\n```\n\n## /!\\ To use Huggingface Models, you must install this package with [hf] extras\n```bash\npoetry add olympict[hf]\nor\npip install olympict[hf]\n```\n\n### Use with Huggingface image classification models\n```python\n\nfrom olympict import ImagePipeline\nfrom olympict.files.o_image import OlympImage\n\ndef print_metas(x: OlympImage):\n print(x.metadata)\n return x\n\nif __name__ == \"__main__\":\n # very important, without this processes will get stuck\n from torch.multiprocessing import set_start_method\n set_start_method(\"spawn\")\n\n (\n ImagePipeline.load_folder(\"./classif\")\n .classify(\"google/mobilenet_v2_1.0_224\")\n .task(print_metas)\n ).wait_for_completion()\n\n```\n\nThis project is still an early version, feedback is very helpful.",
"bugtrack_url": null,
"license": "MIT",
"summary": "A powerful parallel pipelining tool for image processing",
"version": "1.4.0",
"project_urls": {
"Documentation": "https://gitlab.com/gabraken/olympict/-/blob/master/README.md",
"Homepage": "https://gitlab.com/gabraken/olympict",
"Repository": "https://gitlab.com/gabraken/olympict"
},
"split_keywords": [
"image",
" parallel",
" multiprocessing",
" pipeline"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "87cdd79a1b3fe31283739191a69475de76261348014b7c13638f7b73601a4fa1",
"md5": "7dbe0b2b6ce1504d486301d939332282",
"sha256": "2a03fa3755eb174c8328c7ac881ce354f4f473cb6a17267e0619225d127b7892"
},
"downloads": -1,
"filename": "olympict-1.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7dbe0b2b6ce1504d486301d939332282",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<3.13,>=3.9",
"size": 26516,
"upload_time": "2024-09-15T09:09:05",
"upload_time_iso_8601": "2024-09-15T09:09:05.905888Z",
"url": "https://files.pythonhosted.org/packages/87/cd/d79a1b3fe31283739191a69475de76261348014b7c13638f7b73601a4fa1/olympict-1.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "72f9d98a6d6864127c82cb26c2b50bf4dac03ed3506ef502ef3f24a9142c18fc",
"md5": "a3978c00b4c54578837d2c74ab7b667b",
"sha256": "cff45078eb9736858b7b0d0d8961c92cf30fba048db673816ad91345cc43e041"
},
"downloads": -1,
"filename": "olympict-1.4.0.tar.gz",
"has_sig": false,
"md5_digest": "a3978c00b4c54578837d2c74ab7b667b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<3.13,>=3.9",
"size": 17253,
"upload_time": "2024-09-15T09:09:07",
"upload_time_iso_8601": "2024-09-15T09:09:07.522595Z",
"url": "https://files.pythonhosted.org/packages/72/f9/d98a6d6864127c82cb26c2b50bf4dac03ed3506ef502ef3f24a9142c18fc/olympict-1.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-15 09:09:07",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "gabraken",
"gitlab_project": "olympict",
"lcname": "olympict"
}