Sharpen Image

#### Import packages and find all the *.nid files.¶

In [34]:

    from NSFopen.read import read as afmreader

    import os
    from os import listdir
    from os.path import isfile, join

    import numpy as np
    import math
    import collections

    import cv2 as cv
    from PIL import Image

    import matplotlib
    import matplotlib.pyplot as plt
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    from mpl_toolkits.axes_grid1.colorbar import colorbar
    %matplotlib inline

    font = {'size': 12}
    matplotlib.rc('font', **font)

    dirpath = os.getcwd()
    onlyfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f)) and f.split(".")[-1] == "nid"]
    print(dirpath, "with", len(onlyfiles), "*.nid files")
    print(onlyfiles)

    Q:\Marketing\Projects\Jupyter Notebooks\Sharpen Image with 1 *.nid files
    ['grid1.nid']

#### Define functions¶

In [35]:

    def fittingFunc(matrix, xaxis, order):
        newmatrix = np.zeros(np.shape(matrix))
        for i in range(len(matrix)):
            p = np.polyfit(xaxis, matrix[i,:], order)
            f = np.poly1d(p)
            fit_array = f(xaxis)
            newmatrix[i, :] = matrix[i, :] - fit_array
        return newmatrix

    def unsharp_mask(image, kernel_size=5, sigma=1.0, amount=1.0, threshold=0):
        if kernel_size%2 != 1:
            kernel_size += 1
        blurred = cv.GaussianBlur(image, (kernel_size, kernel_size), sigma)
        sharpened = float(amount + 1) * image - float(amount) * blurred
        sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
        sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
        sharpened = sharpened.round().astype(np.uint8)
        if threshold > 0:
            low_contrast_mask = np.absolute(image - blurred) < threshold
            np.copyto(sharpened, image, where=low_contrast_mask)
        return sharpened

    def laplacian_sharp(image, ddepth = cv.CV_16S, kernel_size=3, amount = 0.5):
        edges = cv.Laplacian(image, ddepth, ksize=kernel_size)
        sharpened = (1-amount)*image - amount*edges
        armax = np.max(sharpened)
        armin = np.min(sharpened)
        sharpened = (sharpened - armin)/(armax-armin)*255
        return sharpened

#### Define what to plot¶

In [36]:

    filename = 'grid1.nid'
    signal_to_plot = 'Z-Axis' # 'Phase', 'Amplitude', 'Z-Axis', 'Z-Axis Sensor' there could be more, i.e. 2nd lock-in signal, etc.
    scan_direction = 'Forward' # 'Forward', 'Backward', '2nd Forward', '2nd Backward'
    what_to_plot = 'Image' # 'Image', 'Spec' or 'Sweep'
    fitting_order = 1 # order of the fitting polynom
    fitting = True # Fit or not

#### Build X, Y axes and read data¶

In [37]:

    alldata = afmreader(filename, verbose = False).data
    rawdata0 = alldata[what_to_plot][scan_direction][signal_to_plot]*1e9 # nm
    rawdata = np.array(rawdata0, dtype = 'float')

    param = afmreader(filename, verbose = False).param
    xrange = param['X']['range'][0]
    yrange = param['Y']['range'][0]

    dict_key = filename.split(".nid")[0]

    xaxis = np.linspace(0, xrange*1E6, len(rawdata[0]))

    yaxis = np.linspace(0, yrange*1E6, len(rawdata))

    if fitting:
        data = fittingFunc(rawdata, xaxis, fitting_order)
    else:
        data = rawdata

#### Prepare the figure and plot¶

In [52]:

    force_limits = True # in case of glitches and spikes in the plots, make it False in the beginning

    xlbl = 'X (um)'
    ylbl = 'Y (um)'
    fig, axarr = plt.subplots(1, 1, figsize=(7.5,7))

    vmin = -40
    vmax = 40
    cmap = plt.get_cmap('copper')

    im = axarr.pcolormesh(xaxis, yaxis, data, cmap = cmap, shading='auto')
    if force_limits:
        im.set_clim(vmin = vmin, vmax = vmax)

    axarr.set_title(filename.split(".nid")[0])
    axarr.set(xlabel=xlbl, ylabel=ylbl)
    ax_divider = make_axes_locatable(axarr)
    cax = ax_divider.append_axes("right", size="5%", pad="2%")
    p = colorbar(im, cax=cax)
    p.ax.set_ylabel("Z (nm)")
    plt.show()

#### Change data to 0 - 255¶

In [39]:

    for i in range(len(data)):
        for j in range(len(data[0])):
            if data[i,j] < vmin:
                data[i,j] = vmin
            if data[i,j] > vmax:
                data[i,j] = vmax

    spread = 1/(vmax - vmin)
    imdata = (data-vmin)*spread*255
    imdata_new = np.uint8(imdata)

#### Sharpen¶

In [42]:

    img = Image.fromarray(imdata_new, 'L')
    img.save('img.jpg')

    img = cv.imread('img.jpg', cv.IMREAD_GRAYSCALE) # Save and read img file, because cv2.imdecode is producing an error

    img_sharp_g = unsharp_mask(img, kernel_size=7, sigma=1.0, amount=25.0, threshold=0.5)
    img_sharp_l = laplacian_sharp(img, ddepth = cv.CV_16S, kernel_size=3, amount = 0.6)

    img_sharp_g = img_sharp_g/spread/255 + vmin # Bring back to the physical range
    img_sharp_l = img_sharp_l/spread/255 + vmin # Bring back to the physical range

#### Plot original and sharpened together¶

In [51]:

    im_im = collections.OrderedDict()
    axnum = 0
    fig, axarr = plt.subplots(1, 3, figsize=(14,5))
    fig.tight_layout(pad=5.0)

    for ax in axarr:
        index = str(axnum)
        if axnum == 0:
            im_im[str(axnum)] = ax.pcolormesh(xaxis, yaxis, data, cmap = cmap, shading = 'auto')
            ax.set_title(filename.split(".nid")[0])
            ax.set(xlabel=xlbl, ylabel=ylbl)
            im_im[str(axnum)].set_clim(vmin = vmin, vmax = vmax)
        elif axnum == 1:
            im_im[str(axnum)] = ax.pcolormesh(xaxis, yaxis, img_sharp_g, cmap = cmap, shading = 'auto')
            ax.set_title(filename.split(".nid")[0] + " unsharp")
            ax.set(xlabel=xlbl, ylabel='')
            im_im[str(axnum)].set_clim(vmin = vmin, vmax = vmax)
        else:
            im_im[str(axnum)] = ax.pcolormesh(xaxis, yaxis, img_sharp_l, cmap = cmap, shading = 'auto')
            ax.set_title(filename.split(".nid")[0] + " laplacian")
            ax.set(xlabel=xlbl, ylabel='')
            im_im[str(axnum)].set_clim(vmin = vmin/3, vmax = vmax/3)

        ax_divider = make_axes_locatable(ax)
        cax = ax_divider.append_axes("right", size="5%", pad="2%")
        p = colorbar(im_im[str(axnum)], cax=cax)
        if axnum == 2:
            p.ax.set_ylabel("Z (nm)")
        axnum += 1