Algorithms for Reconstruction of Undersampled Atomic Force Microscopy Images Extra Figures

Copyright (c) 2017, Christian Schou Oxvig
All rights reserved.

This notebook shows various figures detailing results from reconstructions of undersampled AFM images. The reconstructions were obtained using a variety of interpolation and reconstruction methods.

Parts of the dataset "Algorithms for Reconstruction of Undersampled Atomic Force Microscopy Images Dataset" by Christian Schou Oxvig, Thomas Arildsen, and Torben Larsen licensed under CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/) is used in this notebook. The full dataset along with its license conditions is available at http://dx.doi.org/10.5281/zenodo.375833. Both some of the original images as well as adapted images are shown in this notebook.

The above mentioned dataset and the images displayed in this notebook are derived from "Atomic Force Microscopy Images of Cell Specimens" and "Atomic Force Microscopy Images of Various Specimens" by Christian Rankl licensed under CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/). The original images are available at http://dx.doi.org/10.5281/zenodo.17573 and http://dx.doi.org/10.5281/zenodo.60434. The images are provided as-is without warranty of any kind. Both some of the original images as well as adapted images are shown in this notebook.

Refer to the corresponding code below and the above dataset for details about how the images have been adapted.

In [1]:
%matplotlib inline

import collections
import json
import os
import sys

import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import pandas as pd
import tables as tb

import magni  # Requires Magni 1.7.0 from http://dx.doi.org/10.5278/VBN/MISC/Magni
import utils as rg_utils  # Requires the utils.py from http://dx.doi.org/10.5281/zenodo.375833

Data Paths

In [2]:
# Set these paths as needed
img_folder = './'  # Path to images from http://dx.doi.org/10.5281/zenodo.17573
#                    as well as http://dx.doi.org/10.5281/zenodo.60434
#  IMAGE       MD5SUM                             SHA256SUM
#  image_0.mi  cbdad52d68b2c3d294fa79f1c1f5b289   17be078f0cd8c0af212508295d776325c7a609ff14a442d958447a9f38e78112
#  image_1.mi  0bad0a8617677de8316a69c3d4250859   371f55ea437c852e0195b8e5025e385ebce80e75752a4937ed795f841318e577
#  image_2.mi  04bb426527fe09fb089559b98e5ea69d   1c578e632bb1fd101fce0a11546f04d9e198ad325238b7eafb518ea05f02ef43
#  image_3.mi  3b335afa6fc331d3b6dcc1a3827e72f7   6b0a0faa87772240a986f87feec52e88584a225a156aa963703f3c0de4b6809b
#  image_4.mi  58dd5ec753463a0b8027553b6aa5a1d1   e6ec20f9e9c94323ce83e1ee8aab9f2d5b944e28bc23f04f978be49d8909dc84
#  image_5.mi  95fd0548021cc51518082a2eeb962b49   29bf989526aa1f31cb88fa9637b96d1562605ea14eeab661c1f6965962f2d8d6
#  image_6.mi  038574a2050ab73e8fc88ecf770bfe1a   82f7b2e214579bd7694e7a0c0ef06cbf60418e28c95336247adea71510791400
#  image_7.mi  d20175f3de3732e217f6c8000e8e105a   d38514378efe521c97361f81ca440900ff56073b0cace6c88f6d23f30b633c4d
#  image_8.mi  f2567c28dbd2561a064f3b5b5faf31a1   2b5b129deb5e13084c8bb57856204bf4d882d04b8bfd98aac1235916131b4131
#  image_9.mi  dc07f9619b5b954e2b0a0baa874216ff   1b3d9b09057e1b8421c5db7c16fc0d068f6b39aede41cc85f19c0e1a04b3460b
#  image_10.mi 28721367516a20ea31e75c00f3b5ce0c   c891c6763158bea335dc57900629c84179cde657af96c0b896ad4e38268a80e2
#  image_11.mi 7ebc8f25cf4ba4f6bf722dce27622360   aa8d20b5719eb1e07f84eb9c963aa9c38cf4cdb88afaffc3f187d38f8a637c5c
#  image_12.mi bd01764ed7ae0169cc543fc399c762cf   83a890f10bdc5a561a4a63af9a0242ffefa87832b9f77b0fb024d150158d4082
#  image_13.mi 0aa8b4488c5db7fd391128b82c5b3f54   c05b285abd7ba2b0f182025c25567db9aea6a4cc6e794196c49b76e6fcdca8e5
#  image_14.mi 2062bf84fcad3b0ee7d0b04b1d7064ab   2fd8b0cb71c7185aa1a45dcbd9a55e23c30f7e97ff7a0d4b1dd84f50483764c1
#  image_15.mi fdd16e5c54a147c457af6568ce602698   a2c842021b7942573ac02706e1a52bd5485e9a1a3f7320ffaaab85a354266a43
#  image_16.mi 12c71a620bd18638bb590ee782bf15ab   6720ffea925d039251b6cdb8467350f99b038684b01f1381a650c14bf53c73ae

database_path = 'reconstruction_goblet_ID_0_of_1.hdf5'  # Path to database from http://dx.doi.org/10.5281/zenodo.375833
# DATABASE: reconstruction_goblet_ID_0_of_1.hdf5
# MD5SUM: 21d2c0f87868b8ee807dbd451e17470c
# SHA256SUM: 2990d97eb4ff9ae566f08d2b932a7ee526b99c99ddac2c53089fe4e954cf6bc7

Common Setup

In [3]:
# Settings
img_size = 256
pretty_reconstruction_algorithms = collections.OrderedDict([
        ('linear_interp', 'Linear Interpolation'),
        ('cubic_interp', 'Cubic Interpolation'),
        ('nearestn_interp', 'Nearest Neighbour Interpolation'),
        ('tv_optim', 'Total Variation LS'),
        ('w_ell_1_optim', 'Weighted $\\ell_1$ LS'),
        ('ell_1_optim', '$\\ell_1$ LS'),
        ('w_ist_resmeasrat', 'w-IST (Res/Meas)'),
        ('ist_fixed_resmeasrat', 'IST (Res/Meas)'),
        ('w_iht_resmeasrat', 'w-IHT (Res/Meas)'),
        ('awgn_wbl_gamp_em_resmeasrat', 'AWGN wBL GAMP EM (Res/Meas)'),
        ('awgn_iidbl_gamp_em_resmeasrat', 'AWGN iidBL GAMP EM (Res/Meas)'),
        ('minimax_amp_m_resmeasrat', 'DMM AMP M (Res/Meas)')
    ])
it_reconstruction_algorithms = [
    algorithm for algorithm in pretty_reconstruction_algorithms if 'ist' or 'iht' in algorithm]

pretty_sampling_patterns = collections.OrderedDict([
        ('uniform_lines', 'Uniform Lines'),
        ('uniform_rotated_lines', 'Rotated Uniform Lines'),
        ('random_pixels', 'Random Pixels'),
        ('rect_spiral', 'Spiral (including corners)')
    ])
GROUPBY = ['sampling_pattern', 'reconstruction_parameter', 'reconstruction_algorithm', 'delta']


# Task setup details
with tb.File(database_path) as h5_file:
    task_setup_summary = json.loads(h5_file.root.annotations.task_setup.task_setup_summary.read().decode())

undersampling_ratios = task_setup_summary['undersampling_ratios']
reconstruction_parameters = task_setup_summary['reconstruction_parameters']
sampling_patterns = task_setup_summary['sampling_patterns']
reconstruction_algorithms = task_setup_summary['reconstruction_algorithms']
images = task_setup_summary['all_images']

display_sampling_patterns = list(pretty_sampling_patterns.keys())
display_images = [images[k] for k in [0, 1, 2, 10]]
display_undersampling_ratios = [undersampling_ratios[k] for k in [4, 8, 12]]
display_reconstruction_algorithms = list(pretty_reconstruction_algorithms.keys())

for reconstruction_algorithm in reconstruction_algorithms:
    assert reconstruction_algorithm in pretty_reconstruction_algorithms
    
for sampling_pattern in sampling_patterns:
    assert sampling_pattern in pretty_sampling_patterns
    
gg_color = '#333333'

Load Ground Truth Images

In [4]:
all_imgs = [magni.afm.io.read_mi_file(os.path.join(img_folder, image)).get_buffer('Topography')[0].data 
            for image in images]
display_imgs = []
for img in all_imgs:
    downsampling = int(img.shape[0] / img_size)
    display_img = magni.imaging.visualisation.stretch_image(
        magni.imaging.preprocessing.detilt(img[::downsampling, ::downsampling]), 1.0)
    assert display_img.shape == (img_size, img_size)
    display_imgs.append(display_img)

Load Reconstruction Metrics

In [5]:
hdf_store = pd.HDFStore(database_path)
reconstruction_metrics = hdf_store.select('/simulation_results/metrics')
hdf_store.close()
reconstruction_metrics.head()
Out[5]:
image sampling_pattern dictionary delta reconstruction_algorithm reconstruction_parameter pre_randomization ssim psnr time stop_criterion iota
0 image_0.mi uniform_rotated_lines DCT 0.0500 cubic_interp 1.0 none 0.682783 20.592487 0.175235 N/A 0.131332
1 image_0.mi rect_spiral DCT 0.1000 cubic_interp 1.0 none 0.808926 28.187925 0.211942 N/A 0.160782
2 image_0.mi rect_spiral DCT 0.1125 cubic_interp 1.0 none 0.840155 24.063163 0.243998 N/A 0.180969
3 image_0.mi random_pixels DCT 0.1125 cubic_interp 1.0 none 0.928472 35.803496 0.304727 N/A 0.224991
4 image_0.mi uniform_lines DCT 0.1125 cubic_interp 1.0 none 0.908411 35.902075 0.384760 N/A 0.221802

Structure in DCT Coefficients (for all 17 AFM images)

In [6]:
dct_coefs_images = range(17)

with plt.style.context(('ggplot')):
    magni.utils.plotting.setup_matplotlib({'figure': {'figsize': (14, 90)}, 'axes': {'grid': False}}, cmap='coolwarm')
    fig, axes = plt.subplots(len(dct_coefs_images), 3)
    
    for k, img_num in enumerate(dct_coefs_images):
        img = display_imgs[img_num]
        
        # Get 10 % DCT coefficients reconstruction of image
        DCT_coefficients, DCT_reconstructions = magni.imaging.dictionaries.analysis.get_reconstructions(
            img, 'DCT', [0.10, 1.00])
        normalised_DCT_reconstruction = magni.imaging.visualisation.stretch_image(DCT_reconstructions[0], 1)

        # Show image, DCT coefficients, and reconstruction from 10% DCT coefficients
        im_0 = magni.imaging.visualisation.imshow(img, ax=axes[k, 0], show_axis='top')
        c_bar_ax_0 = make_axes_locatable(axes[k, 0]).append_axes('bottom', '5%', pad='3%')
        cbar_0 = plt.colorbar(mappable=im_0, cax=c_bar_ax_0, orientation='horizontal')
        cbar_0.solids.set_edgecolor("face")

        im_1 = magni.imaging.visualisation.imshow(normalised_DCT_reconstruction, ax=axes[k, 1], show_axis='top')
        c_bar_ax_1 = make_axes_locatable(axes[k, 1]).append_axes('bottom', '5%', pad='3%')
        cbar_1 = plt.colorbar(mappable=im_1, cax=c_bar_ax_1, orientation='horizontal')
        cbar_1.solids.set_edgecolor("face")

        magni.imaging.dictionaries.analysis.show_transform_quantiles(img, 'DCT', fraction=0.1, ax=axes[k, 2])

plt.show()
<matplotlib.figure.Figure at 0x7fac900accf8>