This README describes code developed for my EE367 final project:

Analysis of Richardson-Lucy Deconvolution with a TV Prior
Jerald R. Evans
March 19, 2021

For any  questions, contact:
Jerry Evans
jerald.r.evans@gmail.com


Code developed for this project
===============================

RL_TV_reg_term_test.py
    a command line program - see usage below

RL_TV_joint_plots.py
    a command line program - see usage below

RLTV.py
    contains a function to execute the RL+TV algorithm

RLTV_utils.py
    contains helper functions used by above programs


Code provided by others
=======================

first_diff.py
    provided by EE367 TA Mark Nishimura
    contains functions implementing the image gradient operator and its 
    transpose 

fspecial.py
    provided by EE367 staff
    contains the function fspecial_gaussian_2d


Image directory
===============

test_images
    directory containing all test images used for the project
    also used to store run-time results of per image random number
    calculations in order to compute random quantities only once
    across multiple runs of the programs when desirable



RL_TV_reg_term_test.py usage
============================

This program runs one of two versions of RL+TV, referred to as A and B as
described in my project report.  One of the images in the test_images directory
is used.  The program contains a list (called "lams") of values for the lambda
parameter for the regularization term.  This list must be edited manually to
change it.

The program creates an output directory in the current directory for all the
output files from a single run.  The name is based on the test image name and
will be the same name for an image across multiple runs, unless the list called
"image_names" in the code is updated.

New test images can be added by putting them in the test_images directory and
updating the image_names list in the program.

Several image and graph files are produced automatically and are given
descriptive names.

In addition three different kinds of files can be produced per iteration through
the RL+TV algorithm by uncommenting out the appropriate directory name definition
in the code: grad_mag_dirname to produce per iteration gradient magnitude images,
grad_hist_dirname to produce per iteration gradient histogram images, and
update_rule_dirname to produce per iteration x update rule denominator histogram
images.  The project report describes how these images were used in the project.

Here is an annotated directory listing of an output directory after running
the program:

$ ls coffee_RL+TV_B
 b_Gradient_Histogram_000.png   bluured, noisy image gradient histogram
 b_gradient_magnitude.png       bluured, noisy image gradient magnitude image
 coffee_b.png                   bluured, noisy image
 coffee_gt.png                  ground truth image
 coffee_RL+TV_B_0.0.png         reconstructed image, lambda=0.00
 coffee_RL+TV_B_0.01.png        reconstructed image, lambda=0.01
 coffee_RL+TV_B_0.02.png        reconstructed image, lambda=0.02
 coffee_RL+TV_B_0.03.png        reconstructed image, lambda=0.03
 coffee_RL+TV_B_0.04.png        reconstructed image, lambda=0.04
 coffee_RL+TV_B_0.05.png        reconstructed image, lambda=0.05
 grad_hist_dir                  directory to hold per iteration gradient histograms
 grad_mag_dir                   directory to hold per iteration gradient magnitude images
 RL+TV_B_0.0.png                side-by-side comparison input/noise/output, lambda=0.00
 RL+TV_B_0.01.png               side-by-side comparison input/noise/output, lambda=0.01
 RL+TV_B_0.02.png               side-by-side comparison input/noise/output, lambda=0.02
 RL+TV_B_0.03.png               side-by-side comparison input/noise/output, lambda=0.03
 RL+TV_B_0.04.png               side-by-side comparison input/noise/output, lambda=0.04
 RL+TV_B_0.05.png               side-by-side comparison input/noise/output, lambda=0.05
 RL+TV_B_dxyl1norm.png          graph of L1 norm vs iteration for all lambda selected
 RL+TV_B_grad_std_dev.png       graph of gradient std dev vs iteration for all lambda
 RL+TV_B_log_likelihood.png     graph of log-likelihood vs iteration for all lambda
 RL+TV_B_mse.png                graph of MSE vs iteration for all lambda
 RL+TV_B_pct_grad_mag_threshold.png  grapf of percent under threshold vs. iteration 
 update_rule_dir                directory to hold per iteration update rule histograms
 x_gt_Gradient_Histogram_000.png ground truth gradient histogram
 x_gt_gradient_magnitude.png    ground truth gradient magnitude image
 'x_RL+TV_B_λ=0.0_gradient_magnitude.png'  reconstructed gradient magnitude, lambda=0.00
 'x_RL+TV_B_λ=0.01_gradient_magnitude.png' reconstructed gradient magnitude, lambda=0.01
 'x_RL+TV_B_λ=0.02_gradient_magnitude.png' reconstructed gradient magnitude, lambda=0.02
 'x_RL+TV_B_λ=0.03_gradient_magnitude.png' reconstructed gradient magnitude, lambda=0.03
 'x_RL+TV_B_λ=0.04_gradient_magnitude.png' reconstructed gradient magnitude, lambda=0.04
 'x_RL+TV_B_λ=0.05_gradient_magnitude.png' reconstructed gradient magnitude, lambda=0.05


The number of iterations to run RL+TV is controlled by the variable nIters which
is set manually. 

The RL_TV_reg_term_test command takes 0, 1, or 2 arguments.  With no arguments
it runs the B algorithm on image 1, the FluorescentCells.jpg image.  The A
algorithm and other image files are selected by command line arguments, e.g.:

RL_TV_reg_term_test A        # run algorithm A on image 1

RL_TV_reg_term_test 2        # run algorithm B on image 2

RL_TV_reg_term_test 3 A      # run algorithm A on image 3

RL_TV_reg_term_test A 4      # run algorithm A on image 4

RL_TV_reg_term_test B 5      # # run algorithm B on image 5

There are 7 images in the test_images directory, whose names are in
the image_names list.  Thge image numbers above (minus 1) index into
that list.



RL_TV_joint_plots.py usage
==========================

The previous program produces data for one algorithm (A or B) at a time.
If you want to plot data on the same graph from runs of both algorithms,
use RL_TV_joint_plots.py.  

The program takes 0 or 1 argument.  If an argument is supplied, it indicates
which test image to use, as above.  If no argument is supplied, the
FluorescentCells.jpg image is used.

As above, the number of iterations to run RL+TV is controlled by the variable
nIters which is set manually.

The code defines a list named param_list.

Specify in param_list each set of parameters to jointly plot:
    1) the regularization term for the RL+TV prior x update rule, either
       RL+TV_A or RL+TV_B
    2) the value of lambda, typically between 0.01 and 0.05

as a tuple.  param_list may hold one or more tuples.

Example:
param_list = [("RL+TV_A", 0.04), ("RL+TV_B, 0.02)]

Also, a plot_id string may be provided in the code
Example:
plot_id = "joint_plot_1"

The program will create an output directory named RL_TV_test_joint_plots in the
current directory.  The plot_id will be a part of the filename for all generated
files.  The program will generate five files containing five graphs of the 
following quantities vs. iteration number: L1 gradient norm, gradient standard
deviation, percent of pixels under threshold, log-likelihood, and mean squared
error.

Here is a directory listing of the output directory after running the program:

$ ls RL_TV_test_joint_plots
joint_plot_4_dxyl1norm.png
joint_plot_4_grad_std_dev.png
joint_plot_4_log_likelihood.png
joint_plot_4_mse.png
joint_plot_4_pct_grad_mag_threshold.png




