diff --git a/notebooks/image_CUDA_demo/threshold_test.ipynb b/notebooks/image_CUDA_demo/threshold_test.ipynb index 9e59283c..bb750bb1 100644 --- a/notebooks/image_CUDA_demo/threshold_test.ipynb +++ b/notebooks/image_CUDA_demo/threshold_test.ipynb @@ -1,5 +1,29 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "45fd5ee6-9514-4fc2-8561-ec3aaec330a0", + "metadata": {}, + "source": [ + "## Parallel Image thresholding using CUDA C++ and Python PIL" + ] + }, + { + "cell_type": "markdown", + "id": "4947f8aa-ba7b-4755-9373-5bc23cc013fd", + "metadata": {}, + "source": [ + "### We aim to threshold this image of CERN, to enhance focus on the Alps and white text" + ] + }, + { + "cell_type": "markdown", + "id": "f1ac7a20-ddc1-408f-a42b-599f724c295b", + "metadata": {}, + "source": [ + "" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -10,7 +34,15 @@ "#include \n", "#include \n", "#include \n", - "#include\n" + "#include" + ] + }, + { + "cell_type": "markdown", + "id": "482eb964-0d48-422d-8f67-fcd9fb785f89", + "metadata": {}, + "source": [ + "### We define a CUDA kernel that brightens or underexposes pixels based on a threshold value:" ] }, { @@ -65,7 +97,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: Pillow in /opt/conda/envs/.venv/lib/python3.10/site-packages (10.0.1)\n" + "Collecting Pillow\n", + " Obtaining dependency information for Pillow from https://files.pythonhosted.org/packages/7a/07/e896b096a77375e78e02ce222ae4fd6014928cd76c691d312060a1645dfa/Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl.metadata\n", + " Downloading Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl.metadata (9.5 kB)\n", + "Downloading Pillow-10.0.1-cp310-cp310-manylinux_2_28_x86_64.whl (3.6 MB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.6/3.6 MB 2.2 MB/s eta 0:00:00\n", + "Installing collected packages: Pillow\n", + "Successfully installed Pillow-10.0.1\n" ] } ], @@ -83,7 +121,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: numpy in /opt/conda/envs/.venv/lib/python3.10/site-packages (1.26.0)\n" + "Collecting numpy\n", + " Obtaining dependency information for numpy from https://files.pythonhosted.org/packages/9b/5a/f265a1ba3641d16b5480a217a6aed08cceef09cd173b568cd5351053472a/numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", + " Downloading numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (58 kB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 58.5/58.5 kB 1.0 MB/s eta 0:00:00\n", + "Downloading numpy-1.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 18.2/18.2 MB 2.6 MB/s eta 0:00:00\n", + "Installing collected packages: numpy\n", + "Successfully installed numpy-1.26.0\n" ] } ], @@ -101,17 +146,43 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: matplotlib in /opt/conda/envs/.venv/lib/python3.10/site-packages (3.8.0)\n", - "Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (1.1.1)\n", - "Requirement already satisfied: cycler>=0.10 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (0.11.0)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (4.42.1)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (1.4.5)\n", + "Collecting matplotlib\n", + " Obtaining dependency information for matplotlib from https://files.pythonhosted.org/packages/b5/24/aaccf324ce862bb82277e8814d2aebbb2a2c160d04e95aa2b8c9dc3137a9/matplotlib-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", + " Downloading matplotlib-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.8 kB)\n", + "Collecting contourpy>=1.0.1 (from matplotlib)\n", + " Obtaining dependency information for contourpy>=1.0.1 from https://files.pythonhosted.org/packages/f1/6b/e4b0f8708f22dd7c321f87eadbb98708975e115ac6582eb46d1f32197ce6/contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", + " Downloading contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.9 kB)\n", + "Collecting cycler>=0.10 (from matplotlib)\n", + " Obtaining dependency information for cycler>=0.10 from https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl.metadata\n", + " Downloading cycler-0.12.1-py3-none-any.whl.metadata (3.8 kB)\n", + "Collecting fonttools>=4.22.0 (from matplotlib)\n", + " Obtaining dependency information for fonttools>=4.22.0 from https://files.pythonhosted.org/packages/ac/ed/9a33eca5e2cc35dc1fea0a968509c653db9a99a5979656ae57c6c019d66b/fonttools-4.43.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n", + " Downloading fonttools-4.43.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (152 kB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 152.4/152.4 kB 1.4 MB/s eta 0:00:00\n", + "Collecting kiwisolver>=1.0.1 (from matplotlib)\n", + " Obtaining dependency information for kiwisolver>=1.0.1 from https://files.pythonhosted.org/packages/6f/40/4ab1fdb57fced80ce5903f04ae1aed7c1d5939dda4fd0c0aa526c12fe28a/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl.metadata\n", + " Downloading kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl.metadata (6.4 kB)\n", "Requirement already satisfied: numpy<2,>=1.21 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (1.26.0)\n", - "Requirement already satisfied: packaging>=20.0 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (23.1)\n", + "Requirement already satisfied: packaging>=20.0 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (23.2)\n", "Requirement already satisfied: pillow>=6.2.0 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (10.0.1)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (3.1.1)\n", + "Collecting pyparsing>=2.3.1 (from matplotlib)\n", + " Obtaining dependency information for pyparsing>=2.3.1 from https://files.pythonhosted.org/packages/39/92/8486ede85fcc088f1b3dba4ce92dd29d126fd96b0008ea213167940a2475/pyparsing-3.1.1-py3-none-any.whl.metadata\n", + " Downloading pyparsing-3.1.1-py3-none-any.whl.metadata (5.1 kB)\n", "Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from matplotlib) (2.8.2)\n", - "Requirement already satisfied: six>=1.5 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n" + "Requirement already satisfied: six>=1.5 in /opt/conda/envs/.venv/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n", + "Downloading matplotlib-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.6 MB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.6/11.6 MB 1.8 MB/s eta 0:00:00\n", + "Downloading contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (301 kB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 301.7/301.7 kB 1.8 MB/s eta 0:00:00\n", + "Downloading cycler-0.12.1-py3-none-any.whl (8.3 kB)\n", + "Downloading fonttools-4.43.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.5/4.5 MB 2.4 MB/s eta 0:00:00\n", + "Downloading kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.6 MB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 2.7 MB/s eta 0:00:00\n", + "Downloading pyparsing-3.1.1-py3-none-any.whl (103 kB)\n", + " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 103.1/103.1 kB 3.4 MB/s eta 0:00:00\n", + "Installing collected packages: pyparsing, kiwisolver, fonttools, cycler, contourpy, matplotlib\n", + "Successfully installed contourpy-1.1.1 cycler-0.12.1 fonttools-4.43.1 kiwisolver-1.4.5 matplotlib-3.8.0 pyparsing-3.1.1\n" ] } ], @@ -119,6 +190,14 @@ "!pip install matplotlib" ] }, + { + "cell_type": "markdown", + "id": "6d6a53e4-c2a1-49ad-9f76-90a86bf022b8", + "metadata": {}, + "source": [ + "### Read the image in Python using PIL and convert to grayscale" + ] + }, { "cell_type": "code", "execution_count": 8, @@ -143,32 +222,6 @@ { "cell_type": "code", "execution_count": 9, - "id": "6a1cd914-db44-4e34-a9fb-5d2100b298b8", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[126 126 125 ... 84 84 84]\n", - " [126 126 125 ... 84 84 84]\n", - " [127 126 126 ... 84 84 84]\n", - " ...\n", - " [ 58 55 63 ... 19 15 8]\n", - " [ 57 56 53 ... 23 17 16]\n", - " [ 55 50 58 ... 5 16 16]]\n" - ] - } - ], - "source": [ - "%%python\n", - "\n", - "print(image_array)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, "id": "7545b5c9-c901-4599-abde-3ae5ac17e160", "metadata": {}, "outputs": [], @@ -186,9 +239,17 @@ "}" ] }, + { + "cell_type": "markdown", + "id": "6eb60938-dbd8-49f4-8e3b-23a975f36143", + "metadata": {}, + "source": [ + "### Converting the python image into a std::vector using Cppyy:" + ] + }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "id": "a3c74a47-399e-4454-89f6-f4e8b0376a68", "metadata": {}, "outputs": [], @@ -201,9 +262,17 @@ "img_vector = cppyy.gbl.std.vector['float'](img_list)" ] }, + { + "cell_type": "markdown", + "id": "cd6d8d32-6175-4af3-a0eb-7d563e142f1e", + "metadata": {}, + "source": [ + "### C++ function that recives the std::vector and passes it to the CUDA function host input:" + ] + }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "id": "ab6c16bd-c44a-4e4e-985a-12c5ca3256a8", "metadata": {}, "outputs": [], @@ -222,9 +291,17 @@ "}\n" ] }, + { + "cell_type": "markdown", + "id": "75a21ae2-cffa-4f34-9404-c59577d9b67f", + "metadata": {}, + "source": [ + "### C++ function to return the host output to the Python side:" + ] + }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "id": "a168bbab-fc67-41f5-85c1-f9980d75a00b", "metadata": {}, "outputs": [], @@ -240,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "id": "2eec8b62-5500-45e4-9c02-9bc587288206", "metadata": {}, "outputs": [], @@ -252,7 +329,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "id": "fd1bef06-d14e-4c82-8fa5-da14df696fe5", "metadata": {}, "outputs": [ @@ -268,9 +345,17 @@ "displayImgArray(h_input);" ] }, + { + "cell_type": "markdown", + "id": "fa4fb49f-ea0f-40c0-bf4d-92ad469e0426", + "metadata": {}, + "source": [ + "### Allocating CUDA memory and calling the kernel" + ] + }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "id": "ea90464f-ed8f-44f1-9336-99aa3dc85149", "metadata": {}, "outputs": [], @@ -294,9 +379,17 @@ "cudaFree(d_output)" ] }, + { + "cell_type": "markdown", + "id": "1edf472e-fe51-4fd1-a0e5-e30a2d092739", + "metadata": {}, + "source": [ + "### Verifying host output" + ] + }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "id": "7bf09ac1-ac6b-45e9-93c2-d4ae50897c2d", "metadata": {}, "outputs": [ @@ -314,7 +407,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "id": "3a97a53f-c2b7-4e24-a299-a6c0ec81b16e", "metadata": {}, "outputs": [], @@ -322,9 +415,17 @@ "std::vector blurredRes = getOutput();" ] }, + { + "cell_type": "markdown", + "id": "e22c59e0-019f-479f-8fa0-63e00b680702", + "metadata": {}, + "source": [ + "### Access the CUDA filter result on the Python side:" + ] + }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 18, "id": "2586f437-295d-4b33-b18e-6f28628a7f81", "metadata": {}, "outputs": [], @@ -337,7 +438,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "id": "a8104074-7398-4653-a81a-827dd81a16b3", "metadata": {}, "outputs": [], @@ -352,16 +453,23 @@ "id": "d0d2e15b-5a5f-4ed8-8f17-3fd1f3fc4daf", "metadata": {}, "source": [ - "\n", - "" + "\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0969406d-0bab-4022-bbeb-0e2581035ef4", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "CUDA (C++17)", + "display_name": "CppInterOp (C++17)", "language": "CUDA", - "name": "cuda-xcpp17" + "name": "cppinterop-xcpp17" }, "language_info": { "codemirror_mode": "text/x-c++src",