*Resources*
online book: http://programmingcomputervision.com/
scikit-image tutorial page: http://scikit-image.org/docs/dev/
!ls data/python-cv/
%pylab inline
alcatraz1.jpg climbing_2_small.jpg sf_view1.jpg alcatraz2.jpg crans_1_small.jpg sf_view2.jpg AquaTermi_lowcontrast.JPG crans_2_small.jpg sudoku_images.zip a_selected_thumbs C-uniform03.ppm sunsets.zip a_thumbs empire.jpg sunset_tree.jpg book_frontal.JPG fisherman.jpg turningtorso1.jpg book_perspective.bmp flower32_t0.png turningtorso1_points.txt book_perspective.JPG fontimages.zip Univ1.jpg boy_on_hill.jpg houses.png Univ2.jpg calibration.JPG jkfaces.xml Univ3.jpg calibration_setup.JPG jkfaces.zip Univ4.jpg ceramic-houses_t0.png LICENSE.txt Univ5.jpg climbing_1_small.jpg selectedfontimages.zip Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. For more information, type 'help(pylab)'.
## PIL is good at loading, writing, color-changing
## and other basic image processing manipulations
from PIL import Image
## load data
im = Image.open('data/python-cv/empire.jpg')
print type(im), im
## convert to gray_scale
im = im.convert('L')
im.show()
## FOR THE REASON that PIL uses a different represntation of images than
## np.array, the manipulations that it supports is NOT that useful in practice
## but the two formats can always be converted back and forth from each other
## 1. from PIL.Image to np.array -> just call np.array(Image.open(...))
## 2. from np.array to PIL.Image -> just call Image.fromarray(PIL.Image)
## PIL.Image works in an object-oriented way
## some useful operations from PIL.Image packages -- it is quite like windows Paint app
## im.crop
## im.paste
## im.thumbnail
## im.rotate
## im.resize
## im.rotate
<type 'instance'> <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=569x800 at 0x3E73638>
## matplotlib is good at drawing and advanced plotting of images
## NOTE: like scipy and a lot of other python libraries, images in matplotlib
## are represented as numpy.array. HOWEVER, the PIL library loads the image data
## as a special class, which need to be converted to np.array before used with
## other libraries
import numpy as np
## show images
print np.array(Image.open('data/python-cv/empire.jpg')).shape
print np.array(Image.open('data/python-cv/empire.jpg').convert('L')).shape
im = array(Image.open('data/python-cv/empire.jpg').convert('L'))
gray() ## make matplotlib to show gray scale images
imshow(im)
## draw lines/dots as normal
## NOTE THE COORDINATES IN THE IMAGE OF MATPLOTLIB
x = [100, 100, 400, 400]
y = [200, 500, 200, 500]
plot(x, y, 'r*')
## contours
figure()
contour(im, origin = 'image')
axis('equal')
#axis('off')
(800, 569, 3) (800, 569)
(0.0, 600.0, 0.0, 800.0)
## SO use PIL.Image loading and matplotlib plotting together
## CONVERTION BETWEEN PIL IMAGE REPRESENTATION AND MATPLOTLIB IMAGE REPRESENTATION (NP.ARRAY)
## 1. from PIL image to np.array
im_pil = Image.open('data/python-cv/empire.jpg')
im_arr = np.array(im_pil)
## 2. from np.array to PIL image
im_pil_back = Image.fromarray(im_arr)
print type(im_pil), type(im_arr), type(im_pil_back)
## original images converted to gray scale
im = np.array(Image.open('data/python-cv/empire.jpg').convert('L'))
figure()
imshow(im)
## draw contours by pylab
## NOTE: origin set to 'image'
## axis set to 'equal'
figure()
contour(im, origin = 'image')
axis('equal')
## draw histogram by pylab
figure()
ns, bins, patches = hist(im.flatten(), bins = 128) ## pylab.hist
#print ns
#print bins
#print patches[0]
## interactive gui
"""
figure()
imshow(im)
print 'Please click on 3 points'
x = ginput(3)
print 'you clicked', x
show()
"""
<type 'instance'> <type 'numpy.ndarray'> <type 'instance'>
"\nfigure()\nimshow(im)\nprint 'Please click on 3 points'\nx = ginput(3)\nprint 'you clicked', x\nshow()\n"
## skimage, scipy.ndimage and other libraries are good at advanced image processings
## such as filtering and etc
*Histogram equalization*
skimage.exposure
* packageWhile histogram equalization has the advantage that it requires no parameters, it sometimes yields unnatural looking images. An alternative method is contrast stretching, where the image is rescaled to include all intensities that fall within the 2nd and 98th percentiles
Applications
The method is useful in images with backgrounds and foregrounds that are both bright or both dark. In particular, the method can lead to better views of bone structure in x-ray images, and to better detail in photographs that are over or under-exposed.
from skimage import io, exposure, color
## original image
img = io.imread('data/python-cv/empire.jpg')
print type(img), img.dtype, img.shape
img = color.rgb2gray(img)
print img.shape, img.dtype, np.max(img), np.min(img)
figure(figsize = (16, 8))
subplot(1, 3, 1)
imshow(img)
subplot(1, 3, 2)
img_hist, bins = exposure.histogram(img, nbins = 256)
plot(bins, img_hist)
subplot(1, 3, 3)
img_cdf, bins = exposure.cumulative_distribution(img, nbins=256)
plot(bins, img_cdf)
## histogram equalizier
img_eq = exposure.equalize(img)
figure(figsize = (16, 8))
subplot(1, 3, 1)
imshow(img_eq)
subplot(1, 3, 2)
img_hist, bins = exposure.histogram(img_eq, nbins = 256)
plot(bins, img_hist)
subplot(1, 3, 3)
img_cdf, bins = exposure.cumulative_distribution(img_eq, nbins=256)
plot(bins, img_cdf)
## contrast stretching
p2, p98 = np.percentile(img, 2), np.percentile(img, 98)
img_eq = exposure.rescale_intensity(img, in_range = (p2, p98))
figure(figsize = (16, 8))
subplot(1, 3, 1)
imshow(img_eq)
subplot(1, 3, 2)
img_hist, bins = exposure.histogram(img_eq, nbins = 256)
plot(bins, img_hist)
subplot(1, 3, 3)
img_cdf, bins = exposure.cumulative_distribution(img_eq, nbins=256)
plot(bins, img_cdf)
## adaptive equalization
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
figure(figsize = (16, 8))
subplot(1, 3, 1)
imshow(img_adapteq)
subplot(1, 3, 2)
img_hist, bins = exposure.histogram(img_adapteq, nbins = 256)
plot(bins, img_hist)
subplot(1, 3, 3)
img_cdf, bins = exposure.cumulative_distribution(img_adapteq, nbins=256)
plot(bins, img_cdf)
<class 'skimage.io._io.Image'> uint8 (800, 569, 3) (800, 569) float64 1.0 0.0100901960784 skimage.dtype_converter: WARNING: Possible precision loss when converting from float64 to uint16
[<matplotlib.lines.Line2D at 0x4ca8f10>]
*PCA of Images*
## load images
from os import path
import os
img_folder = 'data/python-cv/a_selected_thumbs/'
images = [io.imread(path.join(img_folder, f))
for f in os.listdir('data/python-cv/a_selected_thumbs/')]
print len(images)
X = np.vstack([img.flatten() for img in images])
print X.shape
## PCA using sklearn
from sklearn import decomposition
pca = decomposition.PCA(whiten=True)
pca.fit_transform(X)
X_pca = pca.components_
print X_pca.shape
images_pca = [arr.reshape((25, 25)) for arr in X_pca]
## plot images and pca
for i in xrange(4):
for j in xrange(3):
#print i, j
subplot(4, 3, i*3+j+1)
imshow(images_pca[i*3+j])
66 (66, 625) (66, 625)
*Gaussian Blurring*
from scipy.ndimage import filters
img = np.array(Image.open('data/python-cv/empire.jpg').convert('L'))
figure(figsize = (16, 8))
subplot(1, 4, 1)
imshow(img)
for (i, std) in enumerate([2, 5, 10], 2):
blur_img = filters.gaussian_filter(img, std)
subplot(1, 4, i)
imshow(blur_img)
title('Gaussian-blurred std=%d' % std)
*Image Derivatives (Sobel filters)*
skimage.filter
pacakage as hsobel
(horizontal edges), vsobel
(vertical edges), and sobel
(edge magnitude)from skimage import filter
img = np.array(Image.open('data/python-cv/empire.jpg').convert('L'))
figure(figsize=(16, 16))
gray()
subplot(2, 2, 1)
imshow(img)
title('original')
## horizontal edges
img_hedges = filter.hsobel(img)
subplot(2, 2, 2)
imshow(img_hedges)
title('horizontal edges')
## vertical edges
img_vedges = filter.vsobel(img, )
subplot(2, 2, 3)
imshow(img_vedges)
title('vertical edges')
## magnitude of edges
img_edges = filter.sobel(img)
subplot(2, 2, 4)
imshow(img_edges)
title('edge magnitudes')
<matplotlib.text.Text at 0x534ad90>
*Morphology - counting objects*
Basic Operators
Erosion
Dilation
Opening
Closing
from skimage import morphology, measure, io, color
## load image and threshold to make sure it is binary
img = color.rgb2gray(io.imread('data/python-cv/houses.png'))
figure()
imshow(img)
bin_img = img < .5
bin_img = bin_img.astype('uint8')
figure()
imshow(bin_img)
labeled_img = morphology.label(bin_img)
labels = np.unique(labeled_img)
figure()
#imshow(labeled_img)
contour(labeled_img, linewidth=3, origin='image')
axis('equal')
axis('off')
## morphology - opening to separate objects better
## The second argument of binary_opening() specifies the structuring element , an array
## that indicates what neighbors to use when centered around a pixel. In this case we
## used 9 pixels (4 above, the pixel itself, and 4 below) in the y direction and 5 in the x direction.
## the non-zeros in the matrix will determine the neighbors
open_img = morphology.binary_opening(img, np.ones((9, 5)), )
figure()
imshow(open_img)
labeled_open_img = morphology.label(open_img)
figure()
contour(labeled_open_img, origin='image')
axis('equal')
axis('off')
(0.0, 600.0, 0.0, 600.0)
## doing the same thing in skimage way
from skimage import filter
from skimage import segmentation
from skimage import morphology
from skimage import measure
from skimage import color
from skimage import io
## original image
img = color.rgb2gray(io.imread('data/python-cv/houses.png'))
figure()
imshow(img)
## binarization by thresholding
thr = filter.threshold_otsu(img)
bw = img < thr
figure()
imshow(bw)
label_img = morphology.label(bw, )
figure()
imshow(label_img, cmap='jet')
<matplotlib.image.AxesImage at 0x5d7ce90>
*Rudin-Osher-Fatemi (ROF) Denoising*
denoise_tv_chambolle
and denoise_tv_bregman
Examples from skimage page http://scikit-image.org/docs/dev/auto_examples/plot_denoise.html
## Load original image
from skimage import color, filter, io
from scipy.ndimage import filters
img = color.rgb2gray(io.imread('data/python-cv/empire.jpg'))
## Gaussian blur
gassian_img = filters.gaussian_filter(img, sigma = 5)
## chambolle-implementation tv denoising
chamolle_img = filter.denoise_tv_chambolle(img, weight = 0.1, multichannel=False)
## bregman-implmentation tv denoising - CANNOT BE USED FOR MULTICHANNEL COLOR IMAGES
bregman_img = filter.denoise_tv_bregman(img, weight=0.1)
## bilateral filtering
bilateral_img = filter.denoise_bilateral(img, sigma_range=0.05, sigma_spatial=15)
## Plot images
fig, axes = subplots(nrows = 2, ncols = 3, figsize=(8, 8))
gray()
axes[0, 0].imshow(img)
axes[0, 0].set_title('original')
axes[0, 1].imshow(gassian_img)
axes[0, 1].set_title('gaussian blur $\sigma=5$')
axes[0, 2].imshow(bilateral_img)
axes[0, 2].set_title('bilateral blur $\sigma (range,spatial)=(0.05, 15)$')
axes[1, 0].imshow(chamolle_img)
axes[1, 0].set_title('chamolle tv $weight=0.1$')
axes[1, 1].imshow(bregman_img)
axes[1, 1].set_title('bregman tv $weight=0.1$')
<matplotlib.text.Text at 0x16cd22d0>