blob: 1139c34d193ad3e61f547ff917fd5e2c47ebf571 [file]
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {},
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Copyright 2020 The IREE Authors"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Licensed under the Apache License v2.0 with LLVM Exceptions.\n",
"# See https://llvm.org/LICENSE.txt for license information.\n",
"# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Image edge detection module"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup"
]
},
{
"cell_type": "code",
"source": [
"%%capture\n",
"!python -m pip install --upgrade tensorflow"
],
"metadata": {},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"!python -m pip install --pre iree-base-compiler iree-base-runtime iree-tools-tf -f https://iree.dev/pip-release-links.html"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Imports\n",
"\n",
"import os\n",
"import tempfile\n",
"\n",
"from matplotlib import pyplot as plt\n",
"import numpy as np\n",
"import tensorflow as tf\n",
"\n",
"from iree import runtime as ireert\n",
"from iree.tf.support import module_utils\n",
"from iree.compiler import compile_str\n",
"from iree.compiler import tf as tfc\n",
"\n",
"# Print version information for future notebook users to reference.\n",
"print(\"TensorFlow version: \", tf.__version__)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Setup Artifacts Directory\n",
"\n",
"# Used in the low-level compilation section.\n",
"ARTIFACTS_DIR = os.path.join(tempfile.gettempdir(), \"iree\", \"colab_artifacts\")\n",
"os.makedirs(ARTIFACTS_DIR, exist_ok=True)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Define the EdgeDetectionModule\n",
"class EdgeDetectionModule(tf.Module):\n",
"\n",
" @tf.function(input_signature=[tf.TensorSpec([1, 128, 128, 1], tf.float32)])\n",
" def edge_detect_sobel_operator(self, image):\n",
" # https://en.wikipedia.org/wiki/Sobel_operator\n",
" sobel_x = tf.constant([[-1.0, 0.0, 1.0],\n",
" [-2.0, 0.0, 2.0],\n",
" [-1.0, 0.0, 1.0]],\n",
" dtype=tf.float32, shape=[3, 3, 1, 1])\n",
" sobel_y = tf.constant([[ 1.0, 2.0, 1.0],\n",
" [ 0.0, 0.0, 0.0],\n",
" [-1.0, -2.0, -1.0]],\n",
" dtype=tf.float32, shape=[3, 3, 1, 1])\n",
" gx = tf.nn.conv2d(image, sobel_x, 1, \"SAME\")\n",
" gy = tf.nn.conv2d(image, sobel_y, 1, \"SAME\")\n",
" return tf.math.sqrt(gx * gx + gy * gy)\n",
"\n",
"tf_module = EdgeDetectionModule()"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Load a test image of a [labrador](https://commons.wikimedia.org/wiki/File:YellowLabradorLooking_new.jpg) and run the module with TF\n",
"def load_image(path_to_image):\n",
" image = tf.io.read_file(path_to_image)\n",
" image = tf.image.decode_image(image, channels=1)\n",
" image = tf.image.convert_image_dtype(image, tf.float32)\n",
" image = tf.image.resize(image, (128, 128))\n",
" image = image[tf.newaxis, :]\n",
" return image\n",
"\n",
"content_path = tf.keras.utils.get_file(\n",
" 'YellowLabradorLooking_new.jpg',\n",
" 'https://storage.googleapis.com/download.tensorflow.org/example_images/YellowLabradorLooking_new.jpg')\n",
"image = load_image(content_path).numpy()\n",
"\n",
"def show_images(image, edges):\n",
" fig, axs = plt.subplots(1, 2)\n",
"\n",
" axs[0].imshow(image.reshape(128, 128), cmap=\"gray\")\n",
" axs[0].set_title(\"Input image\")\n",
" axs[1].imshow(edges.reshape(128, 128), cmap=\"gray\")\n",
" axs[1].set_title(\"Output image\")\n",
"\n",
" axs[0].axis(\"off\")\n",
" axs[1].axis(\"off\")\n",
" fig.tight_layout()\n",
" fig.show()\n",
"\n",
"# Invoke the function with the image as an argument\n",
"tf_edges = tf_module.edge_detect_sobel_operator(image).numpy()\n",
"\n",
"# Plot the input and output images\n",
"show_images(image, tf_edges)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## High Level Compilation With IREE"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@markdown ### Backend Configuration\n",
"\n",
"backend_choice = \"iree_vmvx (CPU)\" #@param [ \"iree_vmvx (CPU)\", \"iree_llvmcpu (CPU)\", \"iree_vulkan (GPU/SwiftShader)\" ]\n",
"backend_choice = backend_choice.split(\" \")[0]\n",
"backend = module_utils.BackendInfo(backend_choice)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Compile and Run the EdgeDetectionModule with IREE.\n",
"module = backend.compile_from_class(EdgeDetectionModule)\n",
"\n",
"# Compute the edges using the compiled module and display the result.\n",
"iree_edges = module.edge_detect_sobel_operator(image)\n",
"show_images(image, iree_edges)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Low-Level Compilation\n",
"\n",
"Overview:\n",
"\n",
"1. Convert the `tf.Module` into an IREE compiler module (using `stablehlo`)\n",
"2. Save the MLIR assembly from the module into a file (can stop here to use it from another application)\n",
"3. Compile the `stablehlo` MLIR into a VM module for IREE to execute\n",
"4. Run the VM module through IREE's runtime to test the edge detection function"
]
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Construct a module containing the edge detection function\n",
"\n",
"# Do *not* further compile to a bytecode module for a particular backend.\n",
"#\n",
"# By stopping at stablehlo, we can more easily take advantage of future\n",
"# compiler improvements within IREE. For a production application, we would\n",
"# probably want to freeze the version of IREE used and compile as completely as\n",
"# possible ahead of time, then use some other scheme to load the module into\n",
"# the application at runtime.\n",
"compiler_module = tfc.compile_module(\n",
" EdgeDetectionModule(), import_only=True)\n",
"\n",
"# Save the imported MLIR to disk.\n",
"imported_mlirbc_path = os.path.join(ARTIFACTS_DIR, \"edge_detection.mlirbc\")\n",
"with open(imported_mlirbc_path, \"wb\") as output_file:\n",
" output_file.write(compiler_module)\n",
"print(f\"Wrote MLIR to path '{imported_mlirbc_path}'\")\n",
"\n",
"# Copy MLIR bytecode to MLIR text and see how the compiler views this program.\n",
"imported_mlir_path = os.path.join(ARTIFACTS_DIR, \"edge_detection.mlir\")\n",
"!iree-ir-tool copy {imported_mlirbc_path} -o {imported_mlir_path}\n",
"print(\"Edge Detection MLIR:\")\n",
"!cat {imported_mlir_path}"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"#@title Compile and prepare to test the edge detection module\n",
"\n",
"flatbuffer_blob = compile_str(compiler_module, target_backends=[\"vmvx\"], input_type=\"stablehlo\")\n",
"\n",
"# Register the module with a runtime context.\n",
"config = ireert.Config(backend.driver)\n",
"ctx = ireert.SystemContext(config=config)\n",
"vm_module = ireert.VmModule.from_flatbuffer(ctx.instance, flatbuffer_blob)\n",
"ctx.add_vm_module(vm_module)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {},
"source": [
"edge_detect_sobel_operator_f = ctx.modules.module[\"edge_detect_sobel_operator\"]\n",
"\n",
"low_level_iree_edges = edge_detect_sobel_operator_f(image)\n",
"\n",
"show_images(image, low_level_iree_edges)"
],
"execution_count": null,
"outputs": []
}
]
}