%% Design a Hardware-Targeted Image Filter in MATLAB
% This example shows how to design a hardware-targeted image filter using 
% Vision HDL Toolbox(TM) objects.
%
% The key features of a model for hardware-targeted video processing in MATLAB(R) are:
%
% * *Streaming pixel interface*: System objects in Vision HDL Toolbox use a
% streaming pixel interface. Serial processing is efficient for hardware designs,
% because less memory is required to store pixel data. The serial interface
% enables the object to operate independently of image size and format and
% makes the design more resilient to video timing errors. For further information,
% see <docid:visionhdl_ug.budgsr5-1>.
% * *Function targeted for HDL code generation*: Once the data is converted
% to a pixel stream, you can design a hardware model by selecting System objects
% from the Vision HDL Toolbox libraries. The part of the design targeted for
% HDL code generation must be in a separate function.
% * *Conversion to frame-based video*: For verification, you can display 
% frame-based video, or you can compare the result of your hardware-compatible
% design with the output of a MATLAB frame-based behavioral model. Vision 
% HDL Toolbox provides a System object(TM) that enables you to deserialize 
% the output of your design.
%
% Copyright 2015 The MathWorks, Inc.
%% Import Data
% Read an image file into the workspace. This sample image contains 256&times;256
% pixels. Each pixel is a single |uint8| value representing intensity. To
% reduce simulation speed while testing, select a thumbnail portion of the image. 
% 
% Simulating serial video in the MATLAB interpreted language can be time-consuming.
% Once you have debugged the design with a small image size, use MEX code
% generation to accelerate testing with larger images. See <docid:visionhdl_gs.example-ex64676005>.

origIm = imread('rice.png');
origImSize = size(origIm)
imActivePixels = 64;
imActiveLines = 48;
inputIm = origIm(1:imActiveLines,1:imActivePixels);
figure
imshow(inputIm,'InitialMagnification',300)
title 'Input Image'

%% Serialize Data
% The <docid:visionhdl_ref.bumli6o-1> System object converts framed video to
% a pixel stream and control structure. This object provides input for a 
% function targeted for HDL code generation, but it does not itself support
% HDL code generation.
%
% To simulate with a standard video format, choose a predefined video padding
% format to match your input source. To simulate with a custom-sized image,
% choose dimensions of inactive regions to surround the image. This tutorial
% uses a custom image. The properties of the |visionhdl.FrameToPixels| object
% correspond to the dimensions in the diagram. 
%
% <<../frametopixels_parameters.png>>
%
% Create a |visionhdl.FrameToPixels| object and set the image properties. 
% The image is an intensity image with a scalar value representing each pixel,
% therefore set |NumComponents| property to 1. This tutorial pads the thumbnail
% image with 5 inactive lines above and below, and 10 inactive pixels on the
% front and back of each line. 
% 
% Use the <docid:visionhdl_ref.buuame6> function to get useful image dimensions
% from the serializer object. This syntax discards the first two returned 
% values, and keeps only the total number of pixels in the padded frame.
% Call the object to convert the image into a vector of pixels and a vector
% of control signals. 
%
% *Note:* This syntax runs only in R2016b or later. If you are using an 
% earlier release, replace each call of an object with the equivalent |step|
% syntax. For example, replace |myObject(x)| with |step(myObject,x)|.

frm2pix = visionhdl.FrameToPixels(...
         'NumComponents',1,...
         'VideoFormat','custom',...
         'ActivePixelsPerLine',imActivePixels,...
         'ActiveVideoLines',imActiveLines,...
         'TotalPixelsPerLine',imActivePixels+20,...
         'TotalVideoLines',imActiveLines+10,...
         'StartingActiveLine',6,...     
         'FrontPorch',10); 

[~,~,numPixelsPerFrame] = getparamfromfrm2pix(frm2pix);
[pixel,ctrl] = frm2pix(inputIm);

%% Design HDL-Compatible Model
% Select an image processing object from the |visionhdl| library. This tutorial
% uses <docid:visionhdl_ref.bt42xpl>.
%
% Construct a function containing a persistent instance of this object. The
% function processes a single pixel by executing one call to the object.
% 
% The |ctrlIn| and |ctrlOut| arguments of the object are structures that contain
% five control signals. The signals indicate the validity of each pixel and
% the location of each pixel in the frame.
%
% Set the filter coefficients of the |visionhdl.ImageFilter| to perform a
% 2&times;2 blur operation.
%
% For this tutorial, you do not need to change the |LineBufferSize| property
% of the filter object. This parameter does not affect simulation speed, so
% it does not need to be modified when simulating with a small test image. 
% When choosing |LineBufferSize|, select a power of two that accommodates the
% active line size of the largest required frame format. The default value,
% 2048, accommodates 1080p video format.
%
% <include>HDLTargetedDesign.m</include> 
%
% Preallocate the output vectors for a more efficient simulation. Then, call
% the function once for each pixel in the padded frame, which is represented
% by the |pixel| vector.
pixelOut = zeros(numPixelsPerFrame,1,'uint8');
ctrlOut  = repmat(pixelcontrolstruct,numPixelsPerFrame,1);
 for p = 1:numPixelsPerFrame
    [pixelOut(p),ctrlOut(p)] = HDLTargetedDesign(pixel(p),ctrl(p));
 end
%% Deserialize Filtered Pixel Stream
% The <docid:visionhdl_ref.bumqceg-1> System object converts a pixel stream
% to frame-based video. Use this object to deserialize the filtered data from
% |visionhdl.ImageFilter|. Set the image dimension properties to match the 
% test image. Call the object to convert the output of the HDL-targeted function
% to a matrix.
pix2frm = visionhdl.PixelsToFrame(...
         'NumComponents',1,...
         'VideoFormat','custom',...
         'ActivePixelsPerLine',imActivePixels,...
         'ActiveVideoLines',imActiveLines);

[outputIm,validIm] = pix2frm(pixelOut,ctrlOut);
%% Display Results
% Use the |imshow| function to display the result of the operation.
if validIm
    figure
    imshow(outputIm,'InitialMagnification',300)
    title 'Output Image'
end
%% Compare to Behavioral Model
% If you have a behavioral model of the design, you can compare the output 
% frames visually or mathematically. For filtering, you can compare |visionhdl.ImageFilter|
% with the <docid:images_ref.btsmcj2-1> function in Image Processing Toolbox(TM).
% The |imfilter| function operates on the frame as a matrix and return a 
% modified frame as a matrix. You can compare this matrix with the matrix 
% output of the |pix2frm| object.
% 
% To avoid dependency on a Image Processing Toolbox license, this tutorial 
% does not perform a compare.
%% HDL Code Generation
% Once your design is working in simulation, use HDL Coder(TM) to generate 
% HDL code for the |HDLTargetedDesign| function. See <docid:visionhdl_ug.buqqz1a-1>.