{ "cells": [ { "cell_type": "markdown", "id": "9464d148", "metadata": {}, "source": [ "# Interoperability with cupy\n", "[cupy](https://cupy.dev) is another GPU-acceleration library that allows processing images. To make the best out of GPUs, we demonstrate here how cupy and clesperanto can be combined." ] }, { "cell_type": "code", "execution_count": 1, "id": "eedee89f", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import cupy as cp\n", "import cupyx.scipy.ndimage as ndi\n", "import pyclesperanto_prototype as cle\n", "from skimage.io import imread" ] }, { "cell_type": "markdown", "id": "528ec468", "metadata": {}, "source": [ "Let's start with a numpy-array and send it to cupy." ] }, { "cell_type": "code", "execution_count": 2, "id": "844d14cc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(120, 160, 160)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np_data = imread('../../data/Haase_MRT_tfl3d1.tif')\n", "np_data.shape" ] }, { "cell_type": "code", "execution_count": 3, "id": "5688550c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(120, 160, 160)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cp_data = cp.asarray(np_data)\n", "cp_data.shape" ] }, { "cell_type": "markdown", "id": "6bbceaca", "metadata": {}, "source": [ "Next, we can apply a filter to the image in cupy." ] }, { "cell_type": "code", "execution_count": 4, "id": "c86d249a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(120, 160, 160)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cp_filtered = ndi.gaussian_filter(cp_data, sigma=5)\n", "cp_filtered.shape" ] }, { "cell_type": "markdown", "id": "02c35f2b", "metadata": {}, "source": [ "Just as an example, we can now threshold the image using `threshold_otsu` which is provided by clesperanto but not by cupy." ] }, { "cell_type": "code", "execution_count": 5, "id": "8faa5574", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(120, 160, 160)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cl_binary = cle.threshold_otsu(cp_filtered)\n", "cl_binary.shape" ] }, { "cell_type": "markdown", "id": "c7f2af3b", "metadata": {}, "source": [ "clesperanto also comes with a function for visualizing data" ] }, { "cell_type": "code", "execution_count": 6, "id": "ab453d2c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0\n", "1.0\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQEAAAD8CAYAAAB3lxGOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAAQm0lEQVR4nO3de4xc9XnG8e8TG5tCQoyBur41NolLRaPWWBa4SoqiuI3BoWyqRsgoCiRxZVUlLZRUYILU5M/QtKFBaolIIIWKQCkBxapIjXGhUaXawZAFA+aymJuNLyThphABTt7+cX5uxsuu1zNnzmXm93yk1c6cuZx3zsw88zuXmVcRgZnl611NF2BmzXIImGXOIWCWOYeAWeYcAmaZcwiYZa6yEJB0lqQnJI1JWl/VfMysHFVxnICkacCTwB8Bu4D7gfMj4rG+z8zMSqlqJHA6MBYROyPiLeBWYKSieZlZCdMrut/5wAsd53cBZ0x25RmaGUdzbEWlmBnA67z844g4afz0qkJgSpLWAesAjuYYztDKpkoxy8I9cftzE02vanVgN7Cw4/yCNO3/RcR1EbE8IpYfxcyKyjCzqVQVAvcDSyQtljQDWANsqGheZlZCJasDEXFA0ueBjcA04IaIeLSKeZlZOZVtE4iIu4C7qrp/M+sPHzFoljmHgFnmHAJmmXMImGWusYOFrB02vjg65XVWzVtaeR3WHIfAEDuSN3id99Mth089HAJDoKk3adX68bgcJFPzNgGzzHkkMICG9ZO/CodbVh4lFBwCA8Rv/v4avzxzDQWHQMv5jV+fXEPB2wTMMueRQAv5078dOp+HYR4VOARawm/8dhvmQPDqQAs4AAbLxhdHh+o5cwiYZc6rAw0Zpk+SXB18Dgd99cAjgQY4AIbLoK8e9BwCkhZKulfSY5IelXRxmj5b0iZJT6X/x/evXDPrtzIjgQPAFyLiVGAFcJGkU4H1wOaIWAJsTuctGeRPDDu8QR0R9LxNICL2AHvS6dcl7aDoPDQCfCRd7UbgPuDyUlUOuEF8YVjvBm13Yl+2CUhaBJwGbAXmpIAA2AvM6cc8BtGgfjJY/wzC8186BCS9G/gucElEvNZ5WRQtjydseyxpnaRtkra9zZtlyzCzHpUKAUlHUQTAzRFxR5q8T9LcdPlcYP9Etx32NmSD8Alg9Wj7a6HM3gEB1wM7IuJrHRdtAC5Mpy8Evtd7eYOp7U+61a/Nq4ZlDhb6EPBpYLuk0TTti8BXgNskrQWeA84rVeEAaeuTbO2x8cXR1m0sLLN34H8ATXKx+4ybDQgfMWhWs7aNGB0CfdK2J9barU3bCBwCfdCWJ9MGTxteOw4Bs8w5BMwy5xAooU3rdTa4mn4NOQTMMucQMGuBJkeVDoEeNT2EM+sXh4BZizTx4eIQMMucQ6AHXhWwYeIQMGuZujcSuu9AFzwCsGHkkYBZ5hwCZi1V18jTIWCWOYfAEfL2AGtCHa87h4BZ5vrRd2CapB9J+o90frGkrZLGJP2bpBnlyzSzqvRjJHAxsKPj/FXA1RHxAeBlYG0f5mFmFSnbfGQB8HHgW+m8gI8Ct6er3Ah8osw82sDbA6xJVR88VHYk8I/AZcAv0/kTgFci4kA6v4uiSek7uA2ZWTuU6UB0DrA/Ih7o5fbD3obMbFCU7UB0rqTVwNHAccDXgVmSpqfRwAJgd/kyzawqPY8EIuKKiFgQEYuANcB/RcSngHuBT6arZdmL0GyQVHGcwOXApZLGKLYRXF/BPMysT/ryLcKIuA+4L53eCZzej/s1s1+pqpmpv0p8GN41aDnwYcNmmXMIHMaqeUtb10verN8cAmaZcwiYZc4hYJY5h4BZ5hwCR8AbB22YOQTMMucQMMucQ8Ascw6BI+TtAjasHAJmmXMImGXOIWCWOYeAWeYcAmaZcwiYZa5s85FZkm6X9LikHZJ+X9JsSZskPZX+H9+vYs2s/8qOBL4O/GdE/DbwexTtyNYDmyNiCbA5nR94/qkxG1Zlmo+8FziT9GvCEfFWRLwCjFC0H4MhaUNmNszKjAQWAy8B305dib8l6VhgTkTsSdfZC8wpW6SZVadMCEwHlgHXRsRpwM8YN/SPiABiohu7F6FZO5QJgV3ArojYms7fThEK+yTNBUj/909040HqRejtATbMyrQh2wu8IOmUNGkl8BiwgaL9GLgNmVnrlW0+8pfAzZJmADuBz1IEy22S1gLPAeeVnIeZVahUCETEKLB8gotWlrnftvBqgOXARwyaZc4hYJY5h4BZ5hwCZplzCJhlziFgljmHgNkAqWK3tUPALHMOAbPMOQTMMucQMMucQ8Ascw4Bs8w5BMwy5xCYhL9GbLlwCJhlruwvCw0Vf/pbjjwSSBwAlqtSIwFJfw38GcXPim+n+I3BucCtwAnAA8CnI+KtknVWwm98s3IdiOYDfwUsj4gPAtOANcBVwNUR8QHgZWBtPwo1s2qUXR2YDvyapOnAMcAe4KMUPQigxW3IPAowK/S8OhARuyX9PfA88HPgborh/ysRcSBdbRcwv3SVfeQ3vw2yVfOW9v0+y6wOHE/RfHQxMA84Fjiri9vX3obMAWD2TmVWB/4QeCYiXoqIt4E7gA8Bs9LqAcACYPdENx6kNmRmw6zM3oHngRWSjqFYHVgJbAPuBT5JsYeg8TZk/vQ3O7wyvQi3UmwAfJBi9+C7gOuAy4FLJY1R7Ca8vg919sQBYDa1sm3IvgR8adzkncDpZe63LL/5zY6cjxg0y9zQhYBHAWbdGaoQcACYdW+oQsDMujcUXyX2CMCsdx4JmGVu4EPAowDLRRXfG4AhCAEzK8chYJa5gQ4BrwqYlTfQIWBm5TkEzDLnEDDLnEPALHMOAbPMOQTMMjcU3x0wG2ZVHSl40ECPBKpeOGY5mDIEJN0gab+kRzqmzZa0SdJT6f/xabokXSNpTNLDkpZVWbyZlXckI4F/4Z39BNYDmyNiCbA5nQc4G1iS/tYB1/anzMl5NGBWzpQhEBE/AH46bvIIRYsxOLTV2AhwUxS2UPQgmNunWs2sAr1uE5gTEXvS6b3AnHR6PvBCx/VqaUO2at5SjwjMelR6w2BEBEVr8q400YbMzN6p1xDYd3CYn/7vT9N3Aws7ruc2ZGYl1DHC7TUENlC0GINDW41tAC5IewlWAK92rDZUzqsEZt2b8mAhSbcAHwFOlLSLouPQV4DbJK0FngPOS1e/C1gNjAFvAJ+toGYz66MpQyAizp/kopUTXDeAi8oWZWb1GegjBifiVQIbFnW9locuBMysO/4CkVnL1D2a9UjALHNDGQI+gtDsyA1lCJgNqiY+vBwCZplzCJhlznsHzFqgyW1YHgmYZc4hYJY5h4BZw5rene0QMMucQ8CsQU2PAsAhYJY9h4BZ5oY6BNow1DKbSJu+3zLUIWBmU+u1DdlXJT2eWo3dKWlWx2VXpDZkT0haVVHdZtYnvbYh2wR8MCJ+F3gSuAJA0qnAGuB30m3+WdK0vlVrNgTashpwUE9tyCLi7og4kM5uoegvAEUbslsj4s2IeIbiV4dP72O9XWvTupdZG/Vjm8DngO+n0420ITOz3pX6FqGkK4EDwM093HYdRedijuaYMmWYWQk9h4CkzwDnACtTvwHosg0ZcB3AcZrddS9DM+uPnlYHJJ0FXAacGxFvdFy0AVgjaaakxcAS4IflyyzP2wWsDdr4Ouy1DdkVwExgkySALRHx5xHxqKTbgMcoVhMuiohfVFW8mZWnX43km3OcZscZekdXs0psfHG0lvmYTaTJkcA9cfsDEbF8/HQfMWiWuexCwMcNmB0quxAws0NlGwIeDZgVsg0BMytkHQIeDZhlHgJm5hAwy172IeBdhpa77EPALHcOAbPMOQTMMucQSLxdwHLlEDDLnEPALHMOAbPMOQQ6eLuA5cghYJa5ntqQdVz2BUkh6cR0XpKuSW3IHpa0rIqizax/em1DhqSFwMeA5zsmn03xC8NLKHoKXFu+xHr5MGLLTU9tyJKrKX52vPOXSkeAm6KwBZglaW5fKjWzSvTad2AE2B0RD427yG3IzAZM1yEg6Rjgi8DflpmxpHWStkna9jZvlrmrSniVwHLRy0jg/cBi4CFJz1K0GntQ0m/QZRuyiFgeEcuPYmYPZVTP2wcsB12HQERsj4hfj4hFEbGIYsi/LCL2UrQhuyDtJVgBvBoRe/pbcv0cBFZWmz9QjmQX4S3A/wKnSNolae1hrn4XsBMYA74J/EVfqjSzykzZizAizp/i8kUdpwO4qHxZ7bNq3lK3MLOh5CMGu9DmIZ1ZrxwCZplzCPTAowEbJg6BHjkIbFhMuWHQJtcZBN5oaIPKIwGzzDkE+sSrBzaoHAJ95F2INogcAhVwGNh4G18cbe12I4eAWeYcAhXyiMAGgUOgBg4CazMfJ1ATH1NgbeWRgFnmHAIN8OqBtYlDoCHeaGht4RAwy5xDoGEeDVjTHAIt4CCwJjkEWsLbCKwpDgGzzDkEzDKn4lfCGy5Cegn4GfDjpmsBTsR1dHIdhxrkOt4XESeNn9iKEACQtC0ilrsO1+E66q3DqwNmmXMImGWuTSFwXdMFJK7jUK7jUENXR2u2CZhZM9o0EjCzBjQeApLOkvSEpDFJ62uc70JJ90p6TNKjki5O078sabek0fS3uoZanpW0Pc1vW5o2W9ImSU+l/8dXXMMpHY95VNJrki6pY3lIukHSfkmPdEyb8PGrcE16vTwsaVnFdXxV0uNpXndKmpWmL5L0847l8o2K65j0eZB0RVoeT0ha1fUMI6KxP2Aa8DRwMjADeAg4taZ5zwWWpdPvAZ4ETgW+DPxNzcvhWeDEcdP+DlifTq8Hrqr5edkLvK+O5QGcCSwDHpnq8QOrge8DAlYAWyuu42PA9HT6qo46FnVer4blMeHzkF6zDwEzgcXp/TStm/k1PRI4HRiLiJ0R8RZwKzBSx4wjYk9EPJhOvw7sAObXMe8jNALcmE7fCHyixnmvBJ6OiOfqmFlE/AD46bjJkz3+EeCmKGwBZkmaW1UdEXF3RBxIZ7cAC/oxr27rOIwR4NaIeDMingHGKN5XR6zpEJgPvNBxfhcNvBElLQJOA7amSZ9Pw78bqh6GJwHcLekBSevStDkRsSed3gvMqaGOg9YAt3Scr3t5wOSPv8nXzOcoRiEHLZb0I0n/LekPapj/RM9D6eXRdAg0TtK7ge8Cl0TEa8C1wPuBpcAe4B9qKOPDEbEMOBu4SNKZnRdGMe6rZTeOpBnAucC/p0lNLI9D1Pn4JyPpSuAAcHOatAf4zYg4DbgU+I6k4yosobLnoekQ2A0s7Di/IE2rhaSjKALg5oi4AyAi9kXELyLil8A36XJo1YuI2J3+7wfuTPPcd3CYm/7vr7qO5GzgwYjYl2qqfXkkkz3+2l8zkj4DnAN8KgUSafj9k3T6AYp18d+qqobDPA+ll0fTIXA/sETS4vQJtAbYUMeMJQm4HtgREV/rmN65fvknwCPjb9vnOo6V9J6Dpyk2RD1CsRwuTFe7EPhelXV0OJ+OVYG6l0eHyR7/BuCCtJdgBfBqx2pD30k6C7gMODci3uiYfpKkaen0ycASYGeFdUz2PGwA1kiaKWlxquOHXd15FVs3u9wSuppiy/zTwJU1zvfDFEPMh4HR9Lca+Fdge5q+AZhbcR0nU2zdfQh49OAyAE4ANgNPAfcAs2tYJscCPwHe2zGt8uVBETp7gLcp1mnXTvb4KfYK/FN6vWwHlldcxxjFOvfB18g30nX/ND1fo8CDwB9XXMekzwNwZVoeTwBndzs/HzFolrmmVwfMrGEOAbPMOQTMMucQMMucQ8Ascw4Bs8w5BMwy5xAwy9z/AVGavTakl3dVAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "print(cl_binary.min())\n", "print(cl_binary.max())\n", "cle.imshow(cl_binary)" ] }, { "cell_type": "markdown", "id": "1f1c63e5", "metadata": {}, "source": [ "In order to get the image back to cupy, we need to do this:" ] }, { "cell_type": "code", "execution_count": 7, "id": "dd128dba", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(120, 160, 160)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cu_binary = cp.asarray(cl_binary)\n", "cu_edges = ndi.sobel(cu_binary, output=float)\n", "cu_edges.shape" ] }, { "cell_type": "markdown", "id": "21e34a79", "metadata": {}, "source": [ "A cupy-image can also be visualized using clesperantos imshow:" ] }, { "cell_type": "code", "execution_count": 8, "id": "d6e52357", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "cle.imshow(cu_edges)" ] }, { "cell_type": "markdown", "id": "d9ad3a83", "metadata": {}, "source": [ "## Final remark\n", "Keep in mind that when using clesperanto and cupy in combination, data is transferred multiple times between GPU and CPU. Try to minimize data transfer and run as many operations as possible in a row using the same library." ] }, { "cell_type": "code", "execution_count": null, "id": "850494cd", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 5 }