Use Neighborhood, Reduction, and Iterator Patterns with a Frame-Based Model or Function for HDL Code Generation
In this example, you use frame-based modeling to model an image processing algorithm that rectifies fog in an image. You then generate synthesizable HDL code by using the HDL Coder™ frame-to-sample conversion optimization to generate pixel-based code from the frame-based model.
The fog rectification model uses neighborhood, reduction, and iterator patterns. You can model neighborhood patterns by using the hdl.npufun
function in a MATLAB® Function block or the Neighborhood Processing Subsystem block. You can implement reduction and iterator patterns by using hdl.iteratorfun
in a MATLAB Function block.
Additionally, as an alternative from generating HDL code from a Simulink® model, you can use a MATLAB function to generate HDL code that contains the frame-based fog rectification algorithm.
Model Algorithm by Using a MATLAB Function Block
In the hdlFrame_FogRectification_2D_MLFB
model, the device under test (DUT) contains a MATLAB Function block that includes the neighborhood processing, reduction, and iterator operations needed for fog rectification. To generate synthesizable HDL code from the frame-based model, the neighborhood processing algorithm uses the frame-to-sample conversion supported function hdl.npufun
. The iterator and reduction algorithms use the frame-to-sample conversion supported function hdl.iteratorfun
. For more information, see hdl.npufun
and hdl.iteratorfun
. Using these two functions in a frame-based model enables you to contain an entire fog rectification algorithm in a single MATLAB Function block.
Open the hdlFrame_FogRectification_2D_MLFB/DUT/MATLAB Function
subsystem to see the fog rectification algorithm.
load_system("hdlFrame_FogRectification_2D_MLFB"); open_system("hdlFrame_FogRectification_2D_MLFB/DUT/MATLAB Function");
function [r_out,g_out,b_out] = fog_rectification(Ru, Gu, Bu) [im_gray, restoreR, restoreG, restoreB] = fog_stage1(Ru, Gu, Bu); [r_out,g_out,b_out] = fog_rectification_m(im_gray, restoreR, restoreG, restoreB); end function [im_gray, restoreR, restoreG, restoreB] = fog_stage1(Ru, Gu, Bu) coder.inline('never') %% Dark channel Estimation from input darkChannel = hdl.npufun(@min_kernel, [1 1], Ru, Gu, Bu); % diff_im is used as input and output variable for anisotropic diffusion diff_im = fi(fi(0.9,0,16,14)*darkChannel, 1, 32, 16); %% Refine dark channel using Anisotropic diffusion. diff_im(:) = hdl.npufun(@filter_kernel, [3 3], diff_im); diff_im(:) = hdl.npufun(@filter_kernel, [3 3], diff_im); diff_im(:) = hdl.npufun(@filter_kernel, [3 3], diff_im); %% Reduction with min % diff_im = min(darkChannel,diff_im); diff_im(:) = hdl.npufun(@min_kernel2, [1 1], darkChannel, diff_im); diff_im(:) = cast(fi(0.6,0,16,14)*diff_im, 'like', diff_im); %% Parallel element-wise math to compute % Restoration with inverse Koschmieder's law factor = hdl.npufun(@calc_restoration_factor, [1 1], diff_im); restoreRf = (Ru-diff_im).*factor; restoreGf = (Gu-diff_im).*factor; restoreBf = (Bu-diff_im).*factor; % Convert to integer restoreR = uint8(restoreRf); restoreG = uint8(restoreGf); restoreB = uint8(restoreBf); %% % Stretching performs the histogram stretching of the image. % im is the input color image and p is cdf limit. % out is the contrast stretched image and cdf is the cumulative prob. % density function and T is the stretching function. % RGB to grayscale conversion im_gray = hdl.npufun(@convert_gray, [1 1], restoreR, restoreG, restoreB); % [restoreR, restoreG, restoreB] = hdl.npufun(@zero_to_one, [1 1], restoreR, restoreG, restoreB); % restoreR(restoreR == 0) = 1; % restoreG(restoreG == 0) = 1; % restoreB(restoreB == 0) = 1; % Rewriting 0-1 setting to avoid reshape zeros_to_one = (restoreR == 0); restoreR = restoreR + uint8(zeros_to_one); zeros_to_one = (restoreG == 0); restoreG = restoreG + uint8(zeros_to_one); zeros_to_one = (restoreB == 0); restoreB = restoreB + uint8(zeros_to_one); end function out = filter_kernel(in) hN = fi([0.0625 0.1250 0.0625; 0.1250 0.2500 0.1250; 0.0625 0.1250 0.0625], 0, 16, 15); out = cast(sum(in(:).*hN(:)),'like',in); end function out = min_kernel(R, G, B) out = min([R, G, B]); end function out = convert_gray(R, G, B) out = uint8(round(fi(0.2989,1,16,15) * R + fi(0.5870,1,16,15) * G + fi(0.1140,1,16,15) * B)); end function out = min_kernel2(A, B) out = min(A, B); end function factor = calc_restoration_factor(diff_im) ds = bitshift(diff_im, -8); % divide by 256 to make value < 1 % compute factor with taylor series expansion % 1/(1-x) = 1 + x + x^2 + x^3 + x^4 + x^5; ds2 = fi(ds*ds,1,32,16); ds3 = fi(ds2*ds,1,32,16); ds4 = fi(ds3*ds,1,32,16); ds5 = fi(ds4*ds,1,32,16); factor = fi(1 + ds + ds2 + ds3 + ds4 + ds5,1,32,24); end function [r_out,g_out,b_out] = fog_rectification_m(im_gray, r, g, b) coder.inline('never') %FOG_RECTIFICATION_HDL_3_STAGE2 % histogram computation % Find cdf % Find breakpoints of table % Compute table % Use table on input image to create output image % histogram calculation hist = zeros(1, 256, 'uint32'); hist = hdl.iteratorfun(@hist_kernel_fcn, im_gray, hist); cdf_init = zeros(256,1,'uint32'); cdf = hdl.iteratorfun(@cdf_compute, hist, cdf_init); N = numel(im_gray); p1 = fi(5*N/100); p2 = fi(N-(5*N/100)); i1i2 = zeros(1,2,'uint8'); i1i2 = hdl.iteratorfun(@find_break_points, cdf, i1i2, p1, p2); i1 = i1i2(1); i2 = 255-i1i2(2); o1 = fi(255*0.10,1,32,16,'RoundingMethod','Zero','OverflowAction','Saturate'); o2 = fi(255*0.90,1,32,16,'RoundingMethod','Zero','OverflowAction','Saturate'); t1 = o1/fi(i1,'RoundingMethod','Zero','OverflowAction','Saturate'); t2 = (o2-o1)/fi(i2-i1,'RoundingMethod','Zero','OverflowAction','Saturate'); t3 = (255-o2)/fi(255-i2,'RoundingMethod','Zero','OverflowAction','Saturate'); t1f = fi(t1, 0, 32, 24); t2f = fi(t2, 0, 32, 24); t3f = fi(t3, 0, 32, 24); T = zeros(1,256, 'uint8'); T = hdl.iteratorfun(@createTable, T, T, i1, i2, t1f, t2f, t3f, o1, o2); [r_out, g_out, b_out] = hdl.npufun(@table_lookup, [1,1], r, g, b, 'KernelArg', T); end function count = hist_kernel_fcn(pix, count, idx) %#ok<*INUSD> count(pix+1) = count(pix+1) +1; end function cdf = cdf_compute(hist, cdf, idx) if idx > 1 cdf(idx) = cdf(idx-cast(1,'like',idx)) + hist; else cdf(1) = hist; end end function i1i2 = find_break_points(cdf, i1i2, idx, p1, p2) if (cdf <= p1) i1i2(1) = i1i2(1) + 1; end if (cdf >= p2) i1i2(2) = i1i2(2) + 1; end end function T = createTable(unused, T, idx, i1, i2, t1f, t2f, t3f, o1, o2) is = uint16(idx); if is <= i1+1 T(idx) = uint8(t1f*(is-1)); elseif is >= i1+2 && is <= i2+1 T(idx) = uint8(((t2f)*(is-1))-((t2f)*i1)+o1); else T(idx) = uint8(((t3f)*(is-1))-((t3f)*i2)+o2); end end function [r_out, g_out, b_out] = table_lookup(r, g, b, T) out1=T(r); out2=T(g); out3=T(b); r_out = uint8(out1); g_out = uint8(out2); b_out = uint8(out3); end
Run the Model
The model uses 2-D matrices as inputs to the DUT. These inputs signals are the separated R, G, and B components of the input image. Each input signal is a frame input matrix composed of 240x320 pixels. Simulate the model to see the frame size and simulation results.
sim("hdlFrame_FogRectification_2D_MLFB");
Generate HDL Code
Generate synthesizable HDL code by using the frame-to-sample conversion. Set the HDL block property ConvertToSamples
on the Inport blocks of the DUT that connect to the R, G, B input signals to convert the input signals from frame-based to sample-based inputs.
hdlset_param('hdlFrame_FogRectification_2D_MLFB/DUT/r_in', 'ConvertToSamples', 'on'); hdlset_param('hdlFrame_FogRectification_2D_MLFB/DUT/g_in', 'ConvertToSamples', 'on'); hdlset_param('hdlFrame_FogRectification_2D_MLFB/DUT/b_in', 'ConvertToSamples', 'on');
For the MATLAB Function block that contains the fog rectification algorithm, set the HDL block property Architecture
to MATLAB Datapath
. Enable the frame-to-sample conversion optimization and generate HDL code using the makehdl
command. For more information on the frame-to-sample conversion optimization, see HDL Code Generation from Frame-Based Algorithms.
hdlset_param('hdlFrame_FogRectification_2D_MLFB/DUT/MATLAB Function', 'Architecture', 'MATLAB Datapath') hdlset_param('hdlFrame_FogRectification_2D_MLFB', 'FrameToSampleConversion', 'on')
makehdl('hdlFrame_FogRectification_2D_MLFB/DUT')
The frame-to-sample conversion separates the frame-based inputs into sample, valid, and ready signals for a sample-based hardware-targeted interface.
Model Algorithm by Using Neighborhood Processing Subsystem and MATLAB Function Blocks
In the hdlFrame_FogRectification_2D_SLBlock
model, the DUT models the fog rectification algorithm using multiple Neighborhood Processing Subsystem and MATLAB Function blocks that use the hdl.npufun
function. The MATLAB Function block fogStage2
and the hdl.iteratorfun
function model the reduction and iterator functions. Separating the fog rectification algorithm into various Simulink blocks enables you to visualize and model the different aspects of the fog rectification in a more modular way than with a single MATLAB Function block.
Open the hdlFrame_FogRectification_2D_SLBlock/DUT
subsystem to see the fog rectification algorithm.
load_system("hdlFrame_FogRectification_2D_SLBlock"); open_system("hdlFrame_FogRectification_2D_SLBlock/DUT");
Run the Model
The model uses 2-D matrices as inputs to the DUT. These inputs signals are the separated R, G, and B components of the input image. Each input signal is a frame input matrix composed of 240x320 pixels. Simulate the model to see the frame size and simulation results.
sim("hdlFrame_FogRectification_2D_SLBlock");
Although the hdlFrame_FogRectification_2D_SLBlock
and hdlFrame_FogRectification_2D_MLFB
models differ in design, the output is the same. Both models can also generate synthesizable HDL code for sample-based hardware.
Generate HDL Code
Generate synthesizable HDL code by using the frame-to-sample conversion. Set the HDL block property ConvertToSamples
on the Inport blocks of the DUT that connect to the R, G, B input signals to convert the input signals from frame-based to sample-based inputs.
hdlset_param('hdlFrame_FogRectification_2D_SLBlock/DUT/R_in', 'ConvertToSamples', 'on'); hdlset_param('hdlFrame_FogRectification_2D_SLBlock/DUT/G_in', 'ConvertToSamples', 'on'); hdlset_param('hdlFrame_FogRectification_2D_SLBlock/DUT/B_in', 'ConvertToSamples', 'on');
Enable the frame-to-sample conversion optimization and generate HDL code using the makehdl
command.
hdlset_param('hdlFrame_FogRectification_2D_SLBlock', 'FrameToSampleConversion', 'on')
makehdl('hdlFrame_FogRectification_2D_SLBlock/DUT')
The frame-to-sample conversion separates the frame-based inputs into sample, valid, and ready signals for a sample-based hardware-targeted interface.
Model Algorithm and Generate HDL Code by Using a MATLAB Function
You can also generate HDL code directly from MATLAB functions by using the MATLAB-to-HDL workflow. For more information on the MATLAB-to-HDL workflow, see Generate HDL Code from MATLAB Code Using the Command Line Interface. In this example, the MATLAB function fog_rectification
contains the MATLAB code from the MATLAB Function block in the hdlFrame_FogRectification_2D_MLFB/DUT
subsystem.
open("fog_rectification");
Open the test bench function, fog_rectification_tb
, to see the input fog rectification image separated into the R,G, and B components.
open("fog_rectification_tb");
The fog_rectification_tb
script tests the function by inputting the original fog rectification image and splitting the input signal into the R, G, and B frame-based components of the image.
The test bench uses code generation to run the algorithm faster. To specify the input types and generate HDL code quickly without running the test bench, use the -args
option.
To generate HDL code from a MATLAB function, create a coder.HdlConfig
object, hdlcfg
. Set the DesignFunctionName
property to the fog_rectification
function.
hdlcfg = coder.config('hdl'); hdlcfg.DesignFunctionName = 'fog_rectification';
To enable frame-to-sample conversion, first enable AggressiveDataflowConversion
. This property transforms the control flow algorithm of the MATLAB code in the MATLAB function to a dataflow representation that is used for the frame-to-sample conversion optimization.
hdlcfg.AggressiveDataflowConversion = true;
Enable frame-to-sample conversion for the coder.HdlConfig
object.
hdlcfg.FrameToSampleConversion = true;
Specify the input image and separate the image into its R, G, and B frame-based input components.
I = imread('inputFogRectification.png');
R = I(:,:,1);
G = I(:,:,2);
B = I(:,:,3);
Generate HDL code by using the codegen
function. Specify the input arguments in the codegen
command by using the -args
option.
codegen -config hdlcfg -args { R,G,B }
See Also
Related Examples
- Generate IP Core for Frame-Based Model with AXI4 Stream Interfaces
- Generate HDL Code from Frame-Based Models by Using Neighborhood Modeling Methods
- Use Sample-Based Inputs and Frame-Based Inputs in an Algorithm