<repo_name>ahndroo/CVPython<file_sep>/Chapter1/Ex7.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import measurements, morphology
from imtools import *

""" Experiment with successive morphological operations on a thresholded image of
your choice.  When you have found some settings that produce good results, try the
function center_of_mass in measurements to find the center coordinates of each objects
and plot them in the image. """

pil_im = Image.open('SimpleObjects.gif')
im = np.array(pil_im.convert('L'))
im,cdf = histeq(im)
im = 1*(im<128)

labels, nbr_obj = measurements.label(im)
im_open = morphology.binary_opening(im,np.ones((4,4)), iterations=2)

com = measurements.center_of_mass(im,labels,np.arange(nbr_obj)+1)
com = np.asarray(com)

plt.imshow(im)
plt.plot(com[:,1],com[:,0],'*') # flip plot arounds
plt.show()
<file_sep>/Chapter1/Ex3.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
from PIL import Image
from imtools import *

""" An alternative image normalization to histogram equalization is a quotient image.
A quotient image is obtained by dividing the image with a blurred version I/I*G.
Implement this and try it on some sample images. """

pil_im = Image.open("FD_rx7.jpg")
imGray = np.array(pil_im.convert("L"))

imGrayBlur = filters.gaussian_filter(imGray,1)
prod = (imGray * imGrayBlur) + 1 # add 1 to avoid div by 0
imQuot = imGray + imGray/prod
<file_sep>/Chapter2/harris.py
from scipy.ndimage import filters
import matplotlib.pyplot as plt
import numpy as np

def compute_harris_response(im, sigma=3):
    """ Compute the Harris corner detector response function for each pixel
        in a graylevel image. """

    # derivatives
    imx = np.zeros(im.shape)
    filters.gaussian_filter(im, (sigma, sigma), (0,1), imx)
    imy = np.zeros(im.shape)
    filters.gaussian_filter(im, (sigma, sigma), (1,0), imy)

    # compute components of the Harris matrix
    Wxx = filters.gaussian_filter(imx*imx, sigma)
    Wyy = filters.gaussian_filter(imy*imy, sigma)
    Wxy = filters.gaussian_filter(imx*imy, sigma)

    # determinant and trace
    Wdet = Wxx*Wxx - Wyy*Wyy
    Wtr =  Wxx + Wyy

    return Wdet / Wtr

def get_harris_points(harrisim, min_dist=10, threshold=0.1):
    """ Return corners from a Harris response image
        min_dist is the minimum number of pixels separating corners
        and image boundary. """

    # find top corner candidates about threshold
    corner_threshold = harrisim.max() * threshold
    harrisim_t = (harrisim > corner_threshold) * 1 # values greater than threshold go to one

    # get coordinates of candidates and their values
    coords = np.array(harrisim_t.nonzero()).T
    candidate_values = [harrisim[c[0], c[1]] for c in coords]

    # sort candidates
    index = np.argsort(candidate_values)

    # store allowed point locations in array
    allowed_locations = np.zeros(harrisim.shape)
    allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1

    # select the best points taking min_dstance into account
    filtered_coords = []
    for i in index:
        if allowed_locations[coords[i,0], coords[i, 1]] == 1:
            filtered_coords.append(coords[i])
            allowed_locations[(coords[i,0]-min_dist):(coords[i,0]+min_dist),
                                (coords[i,1]-min_dist):(coords[i,1]+min_dist)] = 0
    return filtered_coords

def plot_harris_points(image, filtered_coords):
    """ Plots corners found in image """

    plt.figure()
    plt.gray()
    plt.imshow(image)
    plt.plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
    plt.axis('off'); plt.show()
<file_sep>/Chapter1/ch1Examples.py
from PIL import Image
import os
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import imtools as imtools
from scipy.ndimage import filters, measurements, morphology

def createThumbnail(im, size=(128,128)):
    # Input:
        # im = PIL image
        # size = tuple indicating thumbnail size
    thumbnail = im.thumbnail(size)
    return thumbnail

def crop(im, box=(100,100,400,400)):
    # Input:
        # im = PIL Image
        # box = 4-tuple indicating crop region (left, upper, right, lower)
            # PIL uses coord. sys with (0,0) in upper left corner
    cropRegion = im.crop(box)
    # take cropped region and paste upsidedown
    # cropRegion = cropRegion.transpose(Image.ROTATE_180)
    # im.paste(cropRegion, box)
    return cropRegion

def resize(im, size=(128,128)):
    # Input:
        # im = PIL Image
        # size = tuple indicating image resize dimensions
    im2 = im.resize(size)
    return im2

def imContour(pil_im):
    # Input:
        # pil_im = PIL image
    im = array(pil_im.convert('L'))

    plt.figure(); plt.gray()
    plt.contour(im, origin = 'image')
    plt.axis('equal'); plt.axis('off')
    plt.show()

def imHist(pil_im):
    # Input:
        # pil_im = PIL image
    im = array(pil_im.convert('L'))

    plt.figure()
    plt.hist(im.flatten(),128)
    plt.show()

def userInput(pil_im):
    # Input:
        # pil_im = PIL image
    im = np.array(pil_im.convert('L'))
    plt.imshow(im)
    print("Please click 3 points...")
    x = plt.ginput(3)
    print("You clicked {}".format(x))
    plt.show()

def graylevelTrans(pil_im):
    # Input:
        # pil_im = PIL image
    im = np.array(pil_im.convert('L'))
    im2 = 255 - im # invert uint8 image
    im3 = (100.0/255) * im + 100 # clamp image on interval 100:200
    im4 = 255.0*(im/255.0)**2 # square image
    # display images
    plt.figure()
    plt.subplot(2,2,1)
    plt.imshow(im);plt.title('Original Image')
    plt.subplot(2,2,2)
    plt.imshow(im2);plt.title('Inverted Image')
    plt.subplot(2,2,3)
    plt.imshow(im3);plt.title('Clamped image')
    plt.subplot(2,2,4)
    plt.imshow(im4);plt.title('Squared Image')
    plt.show()

def imresize(im,sz):
    # Input:
        # im = numpy image array
        # sz = size of output image
    pil_im = Image.fromarray(uint8(im)) # convert to PIL image
    return array(pil_im.resize(sz))

def afonts():
    """ Perform PCA on various images of letter 'a'"""

    im = np.array(Image.open(imlist[0])) # open one image to get size
    m, n = im.shape[0:2] # get the size of images
    imnbr = len(imlist) # get the number of images
    # create matrix to store all flattened images
    immatrix = np.array([np.array(Image.open(im)).flatten() for im in imlist], 'f')
    # perform PCA
    V, S, immean = pca.pca(immatrix)
    # show some images
    plt.figure(); plt.gray()
    plt.subplot(2, 4, 1); plt.imshow(immean.reshape(m,n))
    for i in range(7):
        plt.subplot(2,4,i+2); plt.imshow(V[i].reshape(m,n))
    plt.show()

def usingWith():
    # open file and save
    with open('font_pca_modes.pkl','wb') as f:
        pickle.dump(immean, f)
        pickle.dump(V, f)

    # open file and load
    with open('font_pca_modes',''rb') as f:
        immean = pickle.load(f)
        V = pickle.load(f)

def blurringImages(pil_im):
    # application of different blur effects and filters
    im = np.array(pil_im.convert('L'))
    im2 = filters.gaussian_filter(im,5) # 5 is standard deviation, larger values give more blurring
    # for color images, blur each color channel
    for i in range(3):
        im2[:,:,i] = filters.gaussian_filter(im[:,:,i],5)
    im2 = uint8(im2) # forces im2 to be uint8

    # Filters (interchange between Sobel-Prewitt)
        # calculates gradient magnitude |grad(V)| = sqrt(Ix**2 + Iy**2)
        # calculates gradient angle ang = arctan2(Ix,Iy)
            # numpy arctan2 returns signed angle in rad from -pi:pi
    imx = np.zeros(im.shape); filters.prewitt(im,1,imx)
    imy = np.zeros(im.shape); filters.prewitt(im,0,imy)
    magnitude = np.sqrt(imx**2 + imy**2)
    ang = np.arctan2(imx,imy)

    # gaussian filter
    sigma = 5
    imx = np.zeros(im.shape); filters.gaussian_filter(im,(sigma,sigma), (0,1), imx)
    imy = np.zeros(im.shape); filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)

def morphology(pil_im):
    # count objects in image---idk
    im = np.array(pil_im.convert('L'))
    im = 1*(im<128)

    labels, nbr_objects = measurements.label(im)
    print("Number of objects: {}".format(nbr_objects))
    # morphology - opening to separate objects better
    im_open = morphology.binary_opening(im, ones((9,5)), iterations=2)
    labels, nbr_objects = measurements.label(im_open)
    print("Number of objects: {}".format(nbr_objects))
<file_sep>/Chapter1/Ex5.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
from PIL import Image
from imtools import *

""" Use gradient direction and magnitude to detect lines in an image.  Estimate
the extent of the lines and their parameters.  Plot the lines overlaid on the image."""

pil_im = Image.open('SimpleObjects.gif')
im = np.array(pil_im.convert('L'))
im = im[:100, :100]

imxSob = np.zeros(im.shape); imySob = np.zeros(im.shape)
filters.sobel(im,1,imxSob); filters.sobel(im,0,imySob)
sobMag = np.sqrt(imxSob**2 + imySob**2)
sobDir = np.arctan2(imxSob, imySob)

imxPre = np.zeros(im.shape); imyPre = np.zeros(im.shape)
filters.prewitt(im,1,imxPre); filters.prewitt(im,0,imyPre)
preMag = np.sqrt(imxPre**2 + imyPre**2)
preDir = np.arctan2(imxPre, imyPre)

# not sure what the ques is asking
<file_sep>/Chapter1/Ex6.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import measurements, morphology
from imtools import *

""" Apply the label() function to a thresholded image of your choice.  Use
histograms and the resulting label image to plot the distribution of object sizes
in the image. """

labelList = labels.flatten()
plt.hist(labelList,nbr_obj);plt.show()

sortIdx = np.argsort(imhist)
imhist = imhist[sortIdx] # sort in ascending order
bins = bins[sortIdx] # sort in ascending order

plt.plot(imhist[:-3]);plt.title('Objects increasing in size');plt.show()
<file_sep>/Chapter1/imtools.py
from PIL import Image
import os
import matplotlib.pyplot as plt
import numpy as np

def saveJPG():
    for infile in filelist:
        outfile = os.path.splittext(infile[0] + ".jpg")
        if infile != outfile:
            try:
                Image.open(infile).save(outfile)
            except IOError:
                print("Cannot convert {}".format(infile))

def get_imlist(path):
    # Return a list of filenames for jpg images in directory
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]

def histeq(im, nbr_bins=256):
    """ Histogram Equalization of grayscale iamge """

    # get image Histogram
    imhist, bins = np.histogram(im.flatten(), nbr_bins, normed=True)
    cdf = imhist.cumsum() # cumulative dist. function
    cdf = 255 * cdf / cdf[-1] # normalize

    # use linear interpolation of cdf to find new pixel values
    im2 = np.interp(im.flatten(), bins[:-1],cdf)
    # REVIEW THIS
    return im2.reshape(im.shape), cdf

def compute_average(imlist):
    """ Compute the average of a list of images """
    # open first image and make into array of type float
    averageim = np.array(Image.open(imlist[0]), 'f')

    for imname in imlist[1:]:
        try:
            averageim += np.array(Image.open(imname))
        except:
            print("{} ...skipped".format(imname))
        averageim /= len(imlist)
    # return average as uint8
    return array(averageim, 'uint8')

def pca(X):
    """ Principal Component Analysis
    input: X, matrix with training data stored as flattened arrays in rows
    return: projection matrix (with important dimensions first), variance
    and mean. """

    # get dims
    N, D = X.shape

    # center data
    mean_X = X.mean(axis=0)
    X = X-mean_X

    if D < N:
        # PCA- compact trick used
        M = np.dot(X, X.T) # covariance matrix
        e, EV = np.linalg.eigh(M) # eigenvalues and eigenvectors
        tmp = np.dot(X.T, EV).T # compact trick
        V = tmp[::-1] # reverse since last eigenvectors are the ones we want
        S = np.sqrt(e)[::-1] # reverse since eigenvalues are in increasing order
        for i in range(V.shape[1]):
            V[:,i] /= S
        else:
            # PCA- SVD used
            U, S, V = np.linalg.svd(X)
            V - V[:N] # only make sense to return the first N
        # return projection matrix, variance and mean
        return V, S, mean_X

def denoise(im, U_init, tolerance=0.1, tau=0.125, tv_weight=100):
    """ An implementation of the Rudin-Osher-Fatemi (ROF) denoising model
    using the numerical procedure presented in eq(11) <NAME> (2005).

    Input: noisy input image (grayscale), initial guess for U, weight of
    the TV-regularizing term, steplength, tolerance for stop criterion.

    Output: denoised and detextured image, texture residual. """

    m,n = im.shape # size of noisy image

    # initialize
    U = U_init
    Px = im # x-component to dual field
    Py = im # y-component to dual field
    error = 1

    while (error > tolerance):
        Uold = U

        # gradient of primal var
        GradUx = roll(U, -1, axis=1)-U # x-component of U's gradient
        GradUy = roll(U, -1, axis=0)-U # y-component of U's gradient

        # update dual var
        PxNew = Px + (tau/tv_weight)*GradUx
        PyNew = Py + (tau/tv_weight)*GradUy
        NormNew = maximum(1,sqrt(PxNew**2 + PyNew**2))

        Px = PxNew/NormNew # update of x-component (dual)
        Py = PyNew/NormNew # update of y-component (dual)

        # update of primal variable
        RxPx = roll(Px, 1, axis=1) # right x-translation of x-component
        RyPy = roll(Py, 1, axis=0) # right y-translatino of y-component

        DivP = (Px-RxPx)+(Py-RyPy) # divergence of dual field
        U = im + tv_weight*DivP # update of primal var
        # update of error
        error = np.linalg.norm(U-Uold)/sqrt(n*m)

    return U,im-U # return denoised image and texture residual
<file_sep>/Chapter1/Ex4.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
from PIL import Image
from imtools import *

""" Write a function that finds the outline of simple objects in images (for example
a square against a white background) using image gradients. """

pil_im = Image.open('SimpleObjects.gif')
im = np.array(pil_im.convert('L'))

imxSob = np.zeros(im.shape); imySob = np.zeros(im.shape)
filters.sobel(im,1,imxSob); filters.sobel(im,0,imySob)
sobMag = np.sqrt(imxSob**2 + imySob**2)
sobDir = np.arctan2(imxSob, imySob)

imxPre = np.zeros(im.shape); imyPre = np.zeros(im.shape)
filters.prewitt(im,1,imxPre); filters.prewitt(im,0,imyPre)
preMag = np.sqrt(imxPre**2 + imyPre**2)
preDir = np.arctan2(imxPre, imyPre)

plt.subplot(2,2,1);plt.imshow(sobMag,cmap='gray');plt.title('Sobel Magnitude')
plt.subplot(2,2,2);plt.imshow(sobDir,cmap='gray');plt.title('Sobel Direction')
plt.subplot(2,2,3);plt.imshow(preDir,cmap='gray');plt.title('PreWitt Magnitude')
plt.subplot(2,2,4);plt.imshow(preDir,cmap='gray');plt.title('PreWitt Direction')
plt.show()
<file_sep>/Chapter1/Ex1.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters

pil_im = Image.open("FD_rx7.jpg")
im = np.array(pil_im.convert("L"))

sig = np.array([2, 5, 10, 20])

plt.subplot(5,2,1); plt.imshow(im); plt.title("Original")
plt.subplot(5,2,2); plt.contour(im, origin='image')
for i,s in enumerate(sig):
    imBlur = filters.gaussian_filter(im,s)
    gaussInd = (i+2)*2-1
    contInd = (i+2)*2
    plt.subplot(5,2,gaussInd);plt.imshow(imBlur);plt.title("Blur with Sigma= {}".format(sig[i]))
    plt.subplot(5,2,contInd);plt.contour(imBlur, origin='image')

""" With increasing blur, the countour begins to lose its shape.  Since blur tends
to remove edge detail, the countour has a hard time finding definitive edges. """
<file_sep>/README.md
# CVPython
Practice code and examples for 'Programming Computer Vision with Python' - <NAME>
<file_sep>/Chapter1/Ex2.py
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
from PIL import Image

""" Implement an unsharp masking operation.  (http://en.wikipedia.org/wiki/Unsharp_masking)
by blurring an image and then subtracting the blurred version from the original.
This gives a sharpening effect to the image.  Try on both color and grayscale images """

pil_im = Image.open("FD_rx7.jpg")
imGray = np.array(pil_im.convert("L"))
imColor = np.array(pil_im)

amt = .5 # percentage, controls magnitude of contrast at edges
imGrayBlur = filters.gaussian_filter(imGray,1)
imGrayUnsharp = imGray - imGrayBlur # unsharpening mask
imGraySharp = imGray + (imGrayUnsharp) *amt

imColorBlur = np.zeros(imColor.shape)
for i in range(3):
    imColorBlur[:,:,i] = filters.gaussian_filter(imColor[:,:,i],1)
    imColorBlur = np.uint8(imColorBlur)
    imColorUM[:,:,i] = imColor[:,:,i] - imColorBlur[:,:,i]
imColorUM = np.uint8(imColorUM)
# imColorUM = imColor - imColorBlur
imColorSharp = imColor + (imColorUM)
