{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "> **作者**: Emmanuelle Gouillart\n", "\n", "[scikit-image](http://scikit-image.org/)是专注于图像处理的Python包,并且使用原生的Numpy数组作为图像对象。本章描述如何在不同图像处理任务上使用`scikit-image`,并且保留了其他科学Python模块比如Numpy和Scipy的链接。\n", "\n", "---\n", "**也可以看一下:**对于基本图像处理,比如图像剪切或者简单过滤,大量简单操作可以用Numpy和SciPy来实现。看一下[使用Numpy和Scipy图像操作和处理部分](http://www.scipy-lectures.org/advanced/image_processing/index.html#basic-image)。\n", "\n", "注意,在阅读本章之前你应该熟悉前面章节的内容,比如基础操作,比如面具和标签作为先决条件。\n", "\n", "---\n", "\n", "---\n", "**章节内容**\n", "- **介绍和观点**\n", " - `scikit-image` 和 `SciPy`生态系统\n", " - `scikit-image`能发现什么\n", "- **输入/输出, 数据类型和 颜色空间**\n", " - 数据类型\n", " - 颜色空间\n", "- **图像预处理/增强**\n", " - 本地过滤器\n", " - 非-本地过滤器\n", " - 数学形态学\n", "- **图像细分**\n", " - 二元细分: 前景 + 背景\n", " - 基于标记的方法\n", "- **测量区域的属性**\n", "- **数据可视化和交互**\n", "\n", "## 3.3.1 介绍和观点\n", "\n", "图像是NumPy的数组`np.ndarray`\n", "\n", "|图像:\t|np.ndarray|\n", "|--|--|\n", "|像素:|array values: a[2, 3]|\n", "|渠道:|array dimensions|\n", "|图像编码:|dtype (np.uint8, np.uint16, np.float)|\n", "|过滤器:|functions (numpy, skimage, scipy)|" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import numpy as np\n", "check = np.zeros((9, 9))\n", "check[::2, 1::2] = 1\n", "check[1::2, ::2] = 1\n", "import matplotlib.pyplot as plt\n", "plt.imshow(check, cmap='gray', interpolation='nearest') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.3.1.1 scikit-image 和 SciPy 生态系统\n", "\n", "最新版的`scikit-image`包含在大多数的科学Python发行版中,比如,Anaconda或Enthought Canopy。它也包含在 Ubuntu/Debian。" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import skimage\n", "from skimage import data # 大多数函数在子包中" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "大多数`scikit-image`函数用NumPy ndarrays作为参数" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dtype('uint8')" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "camera = data.camera()\n", "camera.dtype" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(512, 512)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "camera.shape" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "numpy.ndarray" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from skimage import restoration\n", "filtered_camera = restoration.denoise_bilateral(camera)\n", "type(filtered_camera) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "其他Python包也可以用于图像处理,并且使用Numpy数组:\n", "- [scipy.ndimage](http://docs.scipy.org/doc/scipy/reference/ndimage.html#module-scipy.ndimage) : 对于 nd-arrays。基础过滤、数学形态学和区域属性\n", "- [Mahotas](http://luispedro.org/software/mahotas)\n", "同时,强大的图形处理库有Python封装:\n", "- [OpenCV](https://opencv-python-tutroals.readthedocs.org/en/latest/) (计算机视觉)\n", "- [ITK](http://www.itk.org/itkindex.html) (3D图像和注册)\n", "- 其他\n", "(但是,他们没有那么Pythonic也没有Numpy友好,在一定范围)。\n", "\n", "### 3.3.1.2 scikit-image能发现什么\n", "\n", "- 网站: http://scikit-image.org/\n", "- 例子库 (就像在 [matplotlib](http://matplotlib.org/gallery.html) 或 [scikit-learn](http://scikit-learn.org/)): http://scikit-image.org/docs/stable/auto_examples/ 不同类的函数,从基本的使用函数到高级最新算法。\n", "\n", "- 过滤器: 函数将图像转化为其他图像。\n", " - NumPy组件\n", " - 通用过滤器算法\n", "- 数据简化函数: 计算图像直方图、局部极值位置、角。\n", "- 其他动作: I/O, 可视化,等。\n", "\n", "## 3.3.2 输入/输出, 数据类型和颜色空间\n", "\n", "I/O: [skimage.io](http://scikit-image.org/docs/stable/api/skimage.io.html#module-skimage.io)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from skimage import io" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "读取文件: [skimage.io.imread()](http://scikit-image.org/docs/stable/api/skimage.io.html#skimage.io.imread)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import os\n", "filename = os.path.join(skimage.data_dir, 'camera.png')\n", "camera = io.imread(filename)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](http://www.scipy-lectures.org/_images/plot_camera_1.png)\n", "\n", "支持所有被Python Imaging Library(或者`imread` `plugin`关键词提供的任何I/O插件)的数据格式。\n", "也支持URL图片路径:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "logo = io.imread('http://scikit-image.org/_static/img/logo.png')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "存储文件:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "io.imsave('local_logo.png', logo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(`imsave`也用外部插件比如PIL)\n", "\n", "### 3.3.2.1 数据类型\n", "\n", "![](http://www.scipy-lectures.org/_images/plot_camera_uint_1.png)\n", "\n", "图像ndarrays可以用整数(有符号或无符号)或浮点来代表。\n", "\n", "小心整数类型的溢出" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dtype('uint8')" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "camera = data.camera()\n", "camera.dtype" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "camera_multiply = 3 * camera" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "可用不同的整型大小: 8-, 16- 或 32-字节, 有符号或无符号。\n", "\n", "---\n", "一个重要的 (如果有疑问的话) `skimage` **惯例**: 图像浮点支持在[-1, 1] (与所以浮点图像相对)\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(255, 1.0)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from skimage import img_as_float\n", "camera_float = img_as_float(camera)\n", "camera.max(), camera_float.max()" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "一些图像处理程序需要应用在浮点数组上,因此,输出的数组可能类型和数据范围都与输入数组不同" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.5915023652179584" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "try:\n", " from skimage import filters\n", "except ImportError:\n", " from skimage import filter as filters\n", "camera_sobel = filters.sobel(camera)\n", "camera_sobel.max() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "在上面的例子中,我们使用`scikit-image`的子模块`filters`,在0.11到0.10版本间,`filter`被重命名为`filters`,为了避免与Python内置的`filter`冲突。\n", "\n", "---\n", "\n", "在[skimage](http://scikit-image.org/docs/stable/api/skimage.html#module-skimage)提供了下列skimage实用的函数来转化dtype和data range: `util.img_as_float`、 `util.img_as_ubyte`等。\n", "\n", "看一下[用户手册](http://scikit-image.org/docs/stable/user_guide/data_types.html)来了解细节。\n", "\n", "### 3.3.2.2 颜色空间\n", "\n", "颜色图像是 (N, M, 3) 或 (N, M, 4) 形状 (当alpha渠道编码为透明度)\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(768, 1024, 3)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import scipy\n", "face = scipy.misc.face()\n", "face.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[skimage.color](http://scikit-image.org/docs/stable/api/skimage.color.html#module-skimage.color)中包含转换不同颜色空间(RGB、HSV、LAB 等)的程序: `color.rgb2hsv`、color.lab2rgb等。检查一下文档字符串了解一下输入图像期望的dtype。\n", "\n", "---\n", "3D 图像\n", "`skimage`的大多数函数可以接受3D图像作为参数。看一些文档字符串确认一下函数是否可以被用于3D图像(例如MRI或CT图像)。\n", "---\n", "\n", "---\n", "练习\n", "\n", "在硬盘上打开一个颜色图像作为Numpy数组。\n", "\n", "找一个图像函数计算图像的直方图,并且打印每个颜色通道的直方图。\n", "\n", "将图像转换为灰度图,打印直方图。\n", "---\n", "\n", "## 3.3.3 图像预处理 / 增强\n", "\n", "目的: 降噪、特征 (边缘) 抽取 ...\n", "\n", "### 3.3.3.1 本地过滤器\n", "\n", "本地过滤器用一个函数替换像素临近像素的值。这个函数可以是线性或非线性的。\n", "\n", "临近: 方块 (选择大小)、磁盘、或更复杂的结构化元素。\n", "\n", "![](http://www.scipy-lectures.org/_images/kernels1.png)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "An important (if questionable) skimage convention: float images are supposed to lie in [-1, 1] (in order to have comparable contrast for all float images)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "3.3.1. Introduction and concepts\n", "\n", "Images are NumPy’s arrays np.ndarray" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.11" } }, "nbformat": 4, "nbformat_minor": 0 }