%% Code Generation for Denoising Deep Neural Network
% This example shows how to generate CUDA® MEX from MATLAB® code and denoise grayscale images by using the denoising convolutional neural network (DnCNN [1]). You can use the denoising network to estimate noise in a noisy image, and then remove it to obtain a denoised image.
%% Third-Party Prerequisites
% Required
% This example generates CUDA MEX and has the following third-party requirements.
% CUDA® enabled NVIDIA® GPU and compatible driver.
% Optional
% For non-MEX builds such as static, dynamic libraries or executables, this example has the following additional requirements.
% NVIDIA toolkit.
% NVIDIA cuDNN library.
% Environment variables for the compilers and libraries. For more information, see Third-party Products and Environment Variables.
%% Verify GPU Environment
% Use the coder.checkGpuInstall function to verify that the compilers and libraries necessary for running this example are set up correctly.

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

%
%% Load Noisy Image
% Load a noisy grayscale image into the workspace and display the image.

noisyI = imread('noisy_cameraman.png');
figure
imshow(noisyI);
title('Noisy Image');

%
%% Get Pretrained Denoising Network
% Call the getDenoisingNetwork helper function to get a pretrained image denoising deep neural network.

net = getDenoisingNetwork;

%
% The getDenoisingNetwork function returns a pretrained DnCNN [1] that you can use to detect additive white Gaussian noise (AWGN) that has unknown levels. The network is a feed-forward denoising convolutional network that implements a residual learning technique to predict a residual image. In other words, DnCNN [1] computes the difference between a noisy image and the latent clean image.
% The network contains 59 layers including convolution, batch normalization, and regression output layers. To display an interactive visualization of the deep learning network architecture, use the  analyzeNetwork function.
% analyzeNetwork(net);
%% The denoisenet_predict Function
% The denoisenet_predict entry-point function takes a noisy image input and returns a denoised image by using a pretrained denoising network.
% The function loads the network object returned by getDenoisingNetwork into a persistent variable mynet and reuses the persistent object on subsequent prediction calls.

type denoisenet_predict

%
% Here, the activations method is called with the layer numeric index as 59 to extract the activations from the final layer of the network. The 'OutputAs'  'channels' name-value pair argument computes activations on images larger than the imageInputLayer.InputSize of the network.
% The activations method returns an estimate of the noise in the input image by using the pretrained denoising image.
% Once the noise is estimated, subtract the noise from the original image to obtain a denoised image.
%% Run MEX Code Generation
% To generate CUDA code for the denoisenet_predict.m entry-point function, create a GPU code configuration object for a MEX target and set the target language to C++. Use the coder.DeepLearningConfig function to create a CuDNN deep learning configuration object and assign it to the DeepLearningConfig property of the GPU code configuration object. Run the codegen command specifying an input size of [256,256]. This value corresponds to the size of the noisy image that you intend to denoise.

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg denoisenet_predict -args {ones(256,256,'single')} -report

%
%% Run Generated MEX
% The DnCNN [1] is trained on input images having an input range [0,1]. Call the docid:images_ref#f4-480694 function on noisyI to rescale the values from [0,255] to [0,1].
% Call denoisenet_predict_predict on the rescaled input image.

denoisedI = denoisenet_predict_mex(im2single(noisyI));

%
%% View Denoised Image

figure
imshowpair(noisyI,denoisedI,'montage');
title('Noisy Image (left) and Denoised Image (right)');

%
%% References
% [1] Zhang, K., W. Zuo, Y. Chen, D. Meng, and L. Zhang. "Beyond a Gaussian Denoiser: Residual Learning of Deep CNN for Image Denoising." IEEE Transactions on Image Processing. Vol. 26, Number 7, Feb. 2017, pp. 3142-3155.
% Copyright 2018-2021 The MathWorks, Inc.