{ "cells": [ { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "******************************************\n", "Image Preprocessing and Feature Extraction\n", "******************************************\n", "\n", "Local Binary Patterns\n", "=====================\n", "\n", "A local binary pattern (LBP) operator computes a value at each pixel that is\n", "partially invariant to luminance changes.\n", "\n", "Histograms\n", "==========\n", "\n", "Histogram descriptors are useful for tasks with plenty of spatial resolution.\n", "They are largely unsuitable when an object's spatial layout is important for\n", "identification." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.1\n", "=============\n", "\n", "It will be the diagonal line in Figure 13.2 where the gray level intensity is\n", "between :math:`[0, 127]` and the cumulative proportion is between\n", ":math:`[0, 1]`. Starting at the gray level intensity :math:`128`, the diagonal\n", "line switches to horizontal line. Applying histogram equalization changes the\n", "ordinate scale i.e. changes the range of the pixel intensities to\n", ":math:`[0, 255]`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy\n", "\n", "I = J = 512\n", "K = 255\n", "_ = numpy.random.randint(0, K / 2, I * J)\n", "\n", "X = numpy.sort(_)\n", "F = numpy.arange(I * J) / (I * J)\n", "\n", "plt.plot(X, F)\n", "\n", "h, X1 = numpy.histogram(_, bins=(K + 1), range=(0, K), density=True)\n", "dx = X1[1] - X1[0]\n", "F1 = numpy.cumsum(h) * dx\n", "plt.plot(X1[1:], F1)\n", "\n", "plt.tight_layout()\n", "plt.title('CDF')\n", "plt.xlabel('Pixel Intensity')\n", "plt.ylabel('Fraction')\n", "plt.xlim([0, 255])\n", "plt.ylim([-0.05, 1.05])\n", "plt.show();" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.2\n", "=============\n", "\n", "Define images :math:`a` and :math:`b` as\n", "\n", ".. math::\n", "\n", " a[i, j] =\n", " [f \\otimes p](i, j) =\n", " \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty\n", " p[i - m, j - n] f[m, n] dm dn\\\\\\\\\n", " b[m', n'] =\n", " [g \\otimes f](m', n') =\n", " \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty\n", " f[m' - m, n' - n] g[m, n] dm dn\n", "\n", "where\n", "\n", ".. math::\n", "\n", " \\left[ (g \\otimes f) \\otimes p \\right](k, l)\n", " &= [b \\otimes p](k, l)\\\\\n", " &= \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty\n", " p[k - i, l - j] b[i, j] di dj\\\\\n", " &= \\iiiint_{-\\infty}^\\infty\n", " p[k - i, l - j] f[i - m, j - n] g[m, n] dm dn di dj\\\\\n", " &= \\iiiint_{-\\infty}^\\infty\n", " p[k - m - m', l - n - n'] f[m', n'] g[m, n] dm dn dm' dn'\n", " & \\quad & \\text{change of variables where }\n", " i = m' + m \\text{ and } j = n' + n\\\\\n", " &= \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty g[m, n]\n", " \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty\n", " p[k - m - m', l - n - n'] f[m', n'] dm' dn' dm dn\n", " & \\quad & \\text{Fubini-Tonelli Theorem}\\\\\n", " &= \\int_{-\\infty}^\\infty \\int_{-\\infty}^\\infty\n", " a[k - m, l - n] g[m, n] dm dn\\\\\n", " &= [g \\otimes a](k, l)\\\\\n", " &= [g \\otimes (f \\otimes p)](k, l).\n", "\n", "The result extends to infinite discrete images. For finite sized images, the\n", "boundary pixels may have different results depending on the padding." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.3\n", "=============\n", "\n", "(a, b)\n", "------\n", "\n", "The two-rectangle feature requires six operations.\n", "\n", "(c)\n", "---\n", "\n", "The three-rectangle feature requires eight operations.\n", "\n", "(d)\n", "---\n", "\n", "The four-rectangle feature requires nine operations." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.4\n", "=============\n", "\n", "Bilateral filters preserve sharp edges." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.5\n", "=============\n", "\n", ".. math::\n", "\n", " \\begin{bmatrix}\n", " 0 & -1 & -2\\\\\n", " 1 & 0 & -1\\\\\n", " 2 & 1 & 0\n", " \\end{bmatrix}" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.6\n", "=============\n", "\n", "The coefficients of the Sobel :math:`F_x` can be modified to satisfy these\n", "requirements (e.g. Scharr operator). Taking a page out of bilateral filters,\n", "each coefficient can be weighted according to their spatial distance from\n", "the kernel's center." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.7\n", "=============\n", "\n", ":doc:`LBPs `\n", "have been crafted to be invariant to gray scale and rotation. What's left in a\n", "natural image are primitive microfeatures (e.g. edges, lines, corners, spots,\n", "and flat areas)." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.8\n", "=============\n", "\n", "K-means `assumes`_ the clusters will have spherical variance and gives more\n", "weight to larger clusters. Data with uneven clusters will cause k-means to fail\n", "while GMM succeeds.\n", "\n", ".. _assumes: http://www.r-bloggers.com/k-means-clustering-is-not-a-free-lunch" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.9\n", "=============\n", "\n", "The single outlier will drag one of the two cluster means into the empty region.\n", "One surefire approach is to use a GMM using two t-distributions; another\n", "approach could be to weigh the contributions of data points depending on\n", "distance." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Exercise 13.10\n", "==============\n", "\n", "These peaks correspond typically to the number of data clusters.\n", ":cite:`zelnik2005self` computes the affinity matrix and analyze the gaps between\n", "eigenvalues as well as the eigenvectors' to estimate the number of clusters." ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. rubric:: References\n", "\n", ".. bibliography:: chapter-13.bib" ] } ], "metadata": { "anaconda-cloud": {}, "celltoolbar": "Raw Cell Format", "kernelspec": { "display_name": "Python [default]", "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.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }