{ "metadata": { "name": "", "signature": "sha256:e5a520e0a31d4f941a410d0b7811dcd690a8d1c10b752a07d39911a550dcb83a" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#HW4 Problem 4: Touchscreen Readings#\n", "\n", "In this problem, we will simulate the post-processing of our noisy signal readings in a touchscreen system. First we will set up the python environment." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pylab inline\n", "import numpy as np\n", "from scipy.stats import multivariate_normal\n", "from math import log10, floor\n", "rcParams['figure.figsize'] = 20,10" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following code creates a sample reading from our touchscreen. You do not need to understand the code, but if you're curious we are modelling the finger as a 2D Gaussian distribution. We then place this Gaussian into our `readings` matrix based on `x_offset` and `y_offset`. Next we add some noise using `numpy.random.rand` to each of the pixel and plot our noisy readings." ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Create 2D Gaussian to simulate finger\n", "gaus_size = 20\n", "X,Y = np.meshgrid(np.linspace(-1,1,gaus_size), np.linspace(-1,1,gaus_size))\n", "D = np.sqrt(X*X+Y*Y)\n", "sigma, mu = 0.25, 0.0\n", "G = np.exp(-((D-mu)**2 / (2.0*sigma**2)))\n", "\n", "# Place finger in reading matrix\n", "reading_size = 35;\n", "readings = np.zeros((reading_size, reading_size))\n", "x_offset = 15\n", "y_offset = 20\n", "readings[y_offset-gaus_size/2:y_offset+gaus_size/2, x_offset-gaus_size/2:x_offset+gaus_size/2] = G\n", "\n", "# Add noise to readings\n", "r = np.random.rand(reading_size, reading_size)\n", "readings = readings + r\n", "plt.figure(figsize=(4,4))\n", "plt.imshow(readings, interpolation='none')\n", "title('Noisy Reading')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One way to get deal with the noise is by averaging across a square. The code below uses different window sizes to average. For `window_size = 4`, it takes a 4 by 4 block and averages the values. There are some housekeeping to be done around the edges because we cannot take large window sizes. To solve this, we only produce averages over pixels with valid windows. The edges are patched with a single value that is taken from the outermost values of the averages. (the details aren't important here - make sure you understand the high level idea)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "plt.subplot(241)\n", "plt.imshow(readings, interpolation='none')\n", "title('Noisy Reading')\n", "\n", "# Filter using different window sizes\n", "window_sizes = [2,4,6,8,10]\n", "filtered_results = np.zeros((len(window_sizes), reading_size, reading_size))\n", "for s in range(len(window_sizes)):\n", " window_size = window_sizes[s]\n", " output = np.zeros((reading_size-(window_size-1), reading_size-(window_size-1)))\n", " \n", " # Build output readings (the readings we care about)\n", " for i in range(reading_size-(window_size-1)):\n", " for j in range(reading_size-(window_size-1)):\n", " # Take the average of a window_size by window_size block\n", " temp = np.sum(readings[i:i+window_size-1, j:j+window_size-1])\n", " output[i,j] = temp / (window_size*window_size) if (temp >= 0) else 0\n", " \n", " # Take care of the edges by using a single value\n", " avg_frame = 1./(4*len(output[0]))*(sum(output[0,:])\n", " +sum(output[reading_size-window_size,:])\n", " +sum(output[:,0])\n", " +sum(output[:,reading_size-window_size]))\n", " filtered = np.ones((reading_size, reading_size))*avg_frame\n", " filtered[window_size/2:window_size/2+len(output), window_size/2:window_size/2+len(output[0])] = output\n", " filtered_results[s,:,:] = filtered\n", "\n", " plt.subplot(\"24{}\".format(s+2))\n", " imshow(filtered, interpolation='none')\n", " title('Filtered window={}'.format(window_size))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See how nice the averaging plays out? At around `window_size = 8`, we already have a very clean output.\n", "\n", "##4(a): Vertical averaging##\n", "\n", "Now we will implement a simpler version of the averaging filter using ideas we have learned in the imaging module. The basic structure of the code below should be familiar since it is similar to the imaging lab mask creation.\n", "\n", "Suppose we have a touchscreen of size `reading_size` by `reading_size`. The idea is, for each pixel, grab a couple pixels above, a couple pixels below, and itself, and take the average of these values. For corner cases where there are not enough pixels above or below, use the pixels of the column before or after it (i.e. don't worry about the corner cases, just make sure it works for the pixels around the center of the image). Just as the imaging lab, create `mtx_temp`, a `reading_size*reading_size`-by-1 column matrix that contains the mask for the first pixel. The for loop will copy this over to the next columns, shifting the mask down by 1 pixel for each column.\n", "\n", "We can do this for different \"window sizes\". To see the effect of the window size, the code below runs a loop through different window sizes in the variable `window_sizes`. For a window size `n`, take `n` pixels above it, `n` pixels below it and itself to average.\n", "\n", "Hints:\n", "