# Images¶

Play with some images. I want to make a point about the meaning of 'resolution'.

• In digital photography, resolution usually means sample interval (or, equivalently, sample rate). In reflection seismic, this is usually 250 to 1000 Hz, giving a half-Nyquist of 125 Hz to 500 Hz, which is usually plenty for our signals.
• In signal analysis, we talk a lot about localization, which is the smearedness of things. This is akin to 'focus' in photography, but that's not quite it, because something can be fuzzy in the physical world not just because we took a poor photo. On other words, something canbe inherently unlocalized (see the M32 galaxy example, below).
• In audio signals, 'resolution' usually means bit depth.

Let's say that these properties are the 3 horsemen of resolution.

## Prelims¶

In [2]:
import numpy as np
#from numpy.fft import fft, fftfreq
from scipy.fftpack import fft, rfft, irfft, fftfreq, rfftfreq
import scipy.signal
import matplotlib.pyplot as plt
%matplotlib inline


## Image analogies¶

In [3]:
import scipy.ndimage

In [4]:
im = np.zeros((20, 20))
im[5:-5, 5:-5] = 1
im = scipy.ndimage.distance_transform_bf(im)
im_noise = im + 0.2 * np.random.randn(*im.shape)
im_med = scipy.ndimage.median_filter(im_noise, 3)
plt.imshow(im_med, interpolation="none", cmap="Greys")
plt.show()


## Unlocalized object¶

Start by reading the red channel of an astronomical photograph from a file.

In [5]:
m32 = scipy.ndimage.imread("m32.jpg")[...,0]

In [7]:
m32.shape

Out[7]:
(866, 866)
In [8]:
plt.imshow(m32, interpolation="none", cmap="gray")

Out[8]:
<matplotlib.image.AxesImage at 0x111f19050>
In [9]:
m32_med = scipy.ndimage.median_filter(m32, 5)
plt.imshow(m32_med, interpolation="none", cmap="Greys")
plt.show()

In [10]:
m32_gss = scipy.ndimage.gaussian_filter(m32, 5)
plt.imshow(m32_gss, interpolation="none", cmap="Greys")
plt.show()

In [11]:
m32.shape

Out[11]:
(866, 866)
In [12]:
m32

Out[12]:
array([[ 7,  6,  5, ..., 24, 25, 24],
[ 9,  5,  2, ..., 31, 27, 28],
[10,  8,  4, ..., 28, 21, 26],
...,
[16, 15, 17, ..., 40, 49, 49],
[17, 23, 33, ..., 41, 46, 46],
[17, 24, 34, ..., 43, 46, 46]], dtype=uint8)

Let's look for another image

In [13]:
import requests
from StringIO import StringIO
from PIL import Image

In [14]:
a = requests.get("http://svs.gsfc.nasa.gov/vis/a010000/a010400/a010485/M31_Wide.jpg")

In [15]:
m31 = np.array(Image.open(StringIO(a.content))) # ndimage can't work with this object

In [16]:
plt.imshow(m31)

Out[16]:
<matplotlib.image.AxesImage at 0x11629afd0>
In [17]:
m32 = m31[5200:6000,3700:4500,0]

In [18]:
plt.imshow(m32, interpolation="none", cmap="gray")

Out[18]:
<matplotlib.image.AxesImage at 0x1163ec390>
In [19]:
plt.plot(m32[400,:])

Out[19]:
[<matplotlib.lines.Line2D at 0x116426810>]

## Quantize image values¶

In [6]:
def index(a, colours=8):
b = a.reshape(a.size)
b = float(colours) * b / np.amax(b)
bins = np.linspace(0, colours-1, colours)
c = np.digitize(b, bins)
return c.reshape(a.shape)

In [7]:
quantized = index(m32, 8)

plt.figure(figsize=(12,5))
plt.subplot(121)
plt.imshow(quantized)
plt.hlines(400,0,880,'red')
plt.subplot(122)
plt.plot(quantized[400,:], 'red')
plt.show()


We can attack it in the signal:noise space:

In [8]:
noise = np.random.random_integers(0, 255, m32.shape) # The image is 8-bit int.
m32_nse = m32 + noise

plt.figure(figsize=(15,8))
plt.subplot(121)
plt.imshow(m32, cmap="gray", interpolation="none")
plt.subplot(122)
plt.imshow(m32_nse, cmap="gray", interpolation="none")
plt.show()