Main Content

visionhdl.LineBuffer

Store video lines and return neighborhood pixels

Description

The visionhdl.LineBuffer System object™ selects neighborhood pixels from streaming image data. It handles video control signals and edge padding, and is pipelined for high-speed video designs. The object outputs one column of the neighborhood at a time. To compose a neighborhood for further processing, use the shiftEnable signal to store the output columns, including padding, in a shift register. This object allows you to share the line buffer resources when your design performs multiple operations on the same neighborhood.

The following waveform shows the visionhdl.LineBuffer object returning 5-by-1 pixel columns that make up a 5-by-5 neighborhood. The time frame shown is at the beginning (top-left corner) of an input frame. The output starts after the object has stored two (floor(M/2)) lines and is receiving the start of the third line. The shiftEnable signal is asserted two cycles earlier than the output ctrl.valid signal, which indicates that the first two (floor(M/2)) columns are exclusively padding pixels. Similarly, shiftEnable stays high for two extra cycles at the end of the line.

To extract sliding pixel neighborhoods from a video stream:

  1. Create the visionhdl.LineBuffer object and set its properties.

  2. Call the object with arguments, as if it were a function.

To learn more about how System objects work, see What Are System Objects?

Creation

Description

example

linemem = visionhdl.LineBuffer(Name,Value) returns a line buffer System object. Set properties using name-value pairs. Enclose each property name in single quotes.

Example: linemem = visionhdl.LineBuffer('NeighborhoodSize',[5 5])

Properties

expand all

Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them.

If a property is tunable, you can change its value at any time.

For more information on changing property values, see System Design in MATLAB Using System Objects.

Size of output neighborhood to be formed, specified as a 2-element row vector of integer dimensions [vertical horizontal]. The object returns a column vector of vertical elements. The horizontal dimension is used to determine padding.

Select one of these methods for padding the boundary of the input image.

  • 'Constant' — Interpret pixels outside the image frame as having a constant value.

  • 'Replicate' — Repeat the value of pixels at the edge of the image.

  • 'Symmetric' — Set the value of the padding pixels to mirror the edge of the image.

  • 'Reflection' — Set the value of the padding pixels to reflect around the pixel at the edge of the image.

  • 'None' — Exclude padding logic. The object does not set the pixels outside the image frame to any particular value. This option reduces the hardware resources that are used by the object and reduces the blanking that is required between frames. However, this option affects the accuracy of the output pixels at the edges of the frame. To maintain pixel stream timing, the output frame is the same size as the input frame. However, to avoid using pixels calculated from undefined padding values, mask off the n/2 pixels around the edge of the frame for downstream operations. n is the size of the operation kernel. For more details, see Increase Throughput with Padding None.

For more information about these methods, see Edge Padding.

Value used to pad the boundary of the input image, specified as an integer. The object casts this value to the same data type as the input pixel.

Dependencies

This property is valid when you set PaddingMethod to 'Constant'.

Size of line memory buffer, specified as a positive integer. Choose a power of two that accommodates the number of active pixels in a horizontal line. If you specify a value that is not a power of two, the buffer uses the next largest power of two.

Usage

Description

example

[pixelout,ctrlout,shiftEnable] = lineMem(pixelin,ctrlin) returns a column vector of pixels in the kernel, and accompanying control signals.

This object uses a streaming pixel interface with a structure for frame control signals. This interface enables the object to operate independently of image size and format and to connect with other Vision HDL Toolbox™ objects. The object accepts and returns a scalar pixel value and control signals as a structure containing five signals. The control signals indicate the validity of each pixel and its location in the frame. To convert a pixel matrix into a pixel stream and control signals, use the visionhdl.FrameToPixels object. For a full description of the interface, see Streaming Pixel Interface.

Input Arguments

expand all

You can simulate System objects with a multipixel streaming interface, but System objects that use multipixel streams are not supported for HDL code generation. Use the equivalent blocks to generate HDL code for multipixel algorithms.

Single image pixel in a pixel stream, specified as a scalar value representing intensity.

double and single data types are supported for simulation, but not for HDL code generation.

Data Types: uint8 | uint16 | uint32 | int8 | int16 | int32 | fi | logical | double | single

Control signals accompanying the input pixel stream, specified as a pixelcontrol structure containing five logical data type signals. The signals describe the validity of the pixel and its location in the frame. For more details, see Pixel Control Structure.

Data Types: struct

Output Arguments

expand all

Single column neighborhood pixel values, returned as a of 1-by-M vector, where M is the vertical neighborhood dimension. The output pixel data type is the same as the data type of the input pixels.

To compose a neighborhood for further processing, use the shiftEnable signal to store the output columns, including padding, in a shift register.

Note

HDL code generation is supported for small matrices, but matrix operations can impact hardware performance and resource usage. Therefore, minimize how much your design operates on an N-by-M neighborhood directly. You can :

  • Separate a filter into vertical and horizontal components.

  • Concatenate the neighborhood pixels into a N*M-by-1 vector.

These design suggestions also provide opportunities to add pipelining around each adder or multiplier to increase synthesized clock speed and fit the design to DSP blocks on an FPGA.

Data Types: int8 | int16 | int32 | uint8 | uint16 | uint32 | logical | double | single

Control signals accompanying pixel stream, returned as a structure containing five logical signals. The signals describe the validity of the center pixel of the column, and the location of that pixel within the frame. See Pixel Control Structure.

Columns that contain only padding pixels do not assert ctrl.valid. The shiftEnable signal is asserted for both padding and active columns.

Note

For most of the frame, the object returns the input control signals that arrived with the bottom pixel of the column. However, for the final floor(M/2) lines of each frame, the bottom pixel of the column is a padding pixel, so the object generates output control signals. The object generates a contiguously asserted ctrl.valid signal for the valid pixels in each line.

Object Functions

To use an object function, specify the System object as the first input argument. For example, to release system resources of a System object named obj, use this syntax:

release(obj)

expand all

stepRun System object algorithm
releaseRelease resources and allow changes to System object property values and input characteristics
resetReset internal states of System object

Examples

collapse all

The visionhdl.LineBuffer System object™ stores video lines and returns sliding neighborhoods for kernel-based image operations. This example calculates the average of each neighborhood.

Import image source and set up serializer and deserializer objects.

frmOrig = imread('rice.png');
frmActivePixels = 48;
frmActiveLines = 32;
frmIn = frmOrig(1:frmActiveLines,1:frmActivePixels);
figure
imshow(frmIn,'InitialMagnification',300)
title 'Input Image'

frm2pix = visionhdl.FrameToPixels(...
      'NumComponents',1,...
      'VideoFormat','custom',...
      'ActivePixelsPerLine',frmActivePixels,...
      'ActiveVideoLines',frmActiveLines,...
      'TotalPixelsPerLine',frmActivePixels+10,...
      'TotalVideoLines',frmActiveLines+10,...
      'StartingActiveLine',6,...
      'FrontPorch',5);
[~,~,numPixPerFrm] = getparamfromfrm2pix(frm2pix);

pix2frm = visionhdl.PixelsToFrame(...
      'NumComponents',1,...
      'VideoFormat','custom',...
      'ActivePixelsPerLine',frmActivePixels,...
      'ActiveVideoLines',frmActiveLines);

Write a function that creates and calls the System object™. The object returns one column of the neighborhood at a time. Use a shift register to save the columns. Then, calculate the average of the pixel neighborhood. You can generate HDL from this function.

Note: This object 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).

         
function  [pixOut,ctrlOut] = AvgFilter(pixIn,ctrlIn)
%AvgFilter
% Calculates the average pixel value for each 3x3 kernel
% pixIn and pixOut are scalar uint8 pixel values.
% ctrlIn and ctrlOut are structures that contain control signals associated
% with the pixel.
% You can generate HDL code from this function.

  persistent linemem;
  if isempty(linemem)
     linemem = visionhdl.LineBuffer;
  end
  persistent dataShiftReg; 
  if isempty(dataShiftReg)
      % use typeof(pixIn)?
     dataShiftReg = fi(zeros(3,3),0,8,0);
  end
  % HDL code gen does not support arrays of structs
  persistent controlShiftReg1;
  persistent controlShiftReg2;    
  persistent controlShiftReg3;
  if isempty(controlShiftReg1)
     controlShiftReg1 = pixelcontrolstruct();
     controlShiftReg2 = pixelcontrolstruct();
     controlShiftReg3 = pixelcontrolstruct();
  end
  
  persistent div9;
  if isempty(div9)
      div9 = fi(1/9,0,12,15);
  end

 % Advance shift registers 
 dataShiftReg(:,2:end) = dataShiftReg(:,1:end-1);
 controlShiftReg3 = controlShiftReg2;
 controlShiftReg2 = controlShiftReg1;
 
 % Fetch next column
 [dataShiftReg(:,1),controlShiftReg1] = linemem(fi(pixIn,0,8,0),ctrlIn);
 
 % Calculate the average over the neighborhood
 pixOut = uint8((sum(dataShiftReg(:),'native')).*div9);
 ctrlOut = controlShiftReg3;

end

Process the image by calling the function for each pixel.

pixOutVec = ones(numPixPerFrm,1,'uint8');
ctrlOutVec = repmat(pixelcontrolstruct(false,false,false,false,false),numPixPerFrm,1);

[pixInVec,ctrlInVec] = frm2pix(frmIn);
for p = 1:numPixPerFrm
    [pixOutVec(p),ctrlOutVec(p)] = AvgFilter(pixInVec(p),ctrlInVec(p));
end

Recreate the filtered frame.

[frmOut,frmValid] = step(pix2frm,pixOutVec,ctrlOutVec);

if frmValid
    figure;
    imshow(frmOut,'InitialMagnification',300)
    title 'Output Image'
end

Algorithms

The object stores M – 1 lines of valid pixels, as specified by the neighborhood size. It adds padding bits at the edge of the frame. The object returns the first output column once it can form a complete neighborhood column, which occurs at the start of input line floor(M/2).

Extended Capabilities

Introduced in R2017b