Kikuchi Band Detection using the Hough Transform

Motivation

The detection of Kikuchi bands is a first step towards the extraction of quantitative crystallographic information form a measured Kikuchi pattern.

Initialization code

[1]:
%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib import cm

import numpy as np

import skimage.io
from skimage import exposure
from skimage.morphology import disk
from skimage.filters import rank
from skimage.filters import threshold_otsu
from skimage.transform import (hough_line, hough_line_peaks,
    probabilistic_hough_line)
from scipy.ndimage.filters import correlate

from aloe.plots import plot_image
from aloe.image.kikufilter import img_to_uint
from aloe.image.downsample import downsample

Loading the Filtered Data

From the previous pattern processing step, we can load a single binned pattern, in 8bit range:

[2]:
pattern=skimage.io.imread('./data/Si/Si_img8_binned.tif',
                          plugin='tifffile')
print(pattern.shape, pattern.dtype)
plot_image(pattern, title='EBSD pattern processed \
           for line detection')
(60, 80) uint8
../_images/pattern_processing_line_detection_hough_6_1.png
[3]:
n, bins, patches = plt.hist(np.ravel(pattern), bins=100)
plt.title('histogram of input pattern for line detection')
plt.show()
../_images/pattern_processing_line_detection_hough_7_0.png

8bit pattern, 255 gray scales, relatively low contrast, large background offset camera: gain + offset settings, cannot be optimized for each pattern in the map, compromise for whole map with possibly strongly varying signal

Hough Transform Band Detection

[4]:
def otsu(img, factor=1.15):
    """ return True/False array
        from thresholding the image
    """
    thresh = factor*threshold_otsu(img)
    binary = img > thresh
    return binary

binary=otsu(pattern).astype(int)
plot_image(binary)

#skimage.io.imsave('./results/img8_binary.png', 255*binary)
../_images/pattern_processing_line_detection_hough_10_0.png
[5]:
# Classic straight-line Hough transform from binary data.
image=np.flipud(binary)
background=np.ones_like(image)

ang=np.deg2rad(np.linspace(-90,90,150))
h, theta, d = hough_line(image, theta=ang)
h_masked = np.ma.masked_equal(h ,0)
h_masked=h_masked/np.max(h_masked)

# butterfly mask convolution
# 9x9 mask Krieger-Lassen
k = np.array([[-10, -15, -22, -22, -22, -22, -22, -15, -10],
              [  1,  -6, -13, -22, -22, -22, -13,  -6,   1],
              [  3,   6,   4,  -3, -22,  -3,   4,   6,   3],
              [  3,  11,  19,  28,  42,  28,  19,  11,   3],
              [  3,  11,  27,  42,  42,  42,  27,  11,   3],
              [  3,  11,  19,  28,  42,  28,  19,  11,   3],
              [  3,   6,   4,  -3, -22,  -3,   4,   6,   3],
              [  1,  -6, -13, -22, -22, -22, -13,  -6,   1],
              [-10, -15, -22, -22, -22, -22, -22, -15, -10] ])

h = correlate(h_masked, k, mode='nearest') #.astype(np.int64)
a=(h-np.min(h))/(np.max(h)-np.min(h))

hpeaks=hough_line_peaks(a, theta, d,
        min_distance=10, min_angle=15,
        threshold=0.5*np.max(a), num_peaks=12)
[6]:
# Generating figure 1.
fig, (ax0, ax1, ax2) = plt.subplots(3, 1, figsize=(6, 13))

ax0.imshow(image, cmap=cm.gray)
ax0.set_title('Processed Input Data')
ax0.set_axis_off()

#ax1.imshow(np.log(1 + h), extent=[np.rad2deg(theta[-1]),
#            np.rad2deg(theta[0]),
#           d[-1], d[0]], cmap=cm.gray, aspect=1)
ax1.imshow(a,cmap=cm.gray)
ax1.set_title('Hough transform')
ax1.set_xlabel('Angles (degrees)')
ax1.set_ylabel('Distance (pixels)')
ax1.axis('image')

ax2.imshow(np.flipud(pattern), cmap=cm.gray)
row1, col1 = pattern.shape
linecount=1
houghkl=[]
houghlines=[]
for _, angle, dist in zip(*hpeaks):
    y0 = (dist - 0 * np.cos(angle)) / np.sin(angle)
    y1 = (dist - col1 * np.cos(angle)) / np.sin(angle)
    ax2.plot((0, col1), (y0, y1), '-r')
    houghlines.append([linecount, dist, np.degrees(angle),
                       0, y0, col1,y1 ])
    #print(linecount, dist, np.rad2deg(angle),gpc)
    linecount=linecount+1
ax2.axis((0, col1, row1, 0))
ax2.set_title('detected lines')
ax2.set_axis_off()
plt.tight_layout()
plt.show()
#plt.savefig('hough_simple.png')
../_images/pattern_processing_line_detection_hough_12_0.png