2D FIR Filter

Embed Size (px)

Citation preview

  • 7/22/2019 2D FIR Filter

    1/38

    2D FIR Filter

    This example shows how to generate HDL code from a MATLAB design that unsharps an image using 2D FIR filtering.

    Algorithm

    The image unsharp technique filters images with a 2D unsharp kernel so the contrast of the image is enhanced. The following MATLAB code shows

    the effects of unsharping.

    image_in = imread('mlhdlc_cameraman.tif');

    H = fspecial('unsharp');

    filt_image = imfilter(image_in,H);

    figure;

    subplot(1,2,1);

    imshow(image_in);

    title('Original');

    subplot(1,2,2);

    imshow(filt_image);

    title('Sharpened');

    MATLAB Design

    The following example shows how to implement the image processing algorithm for HDL code generation.

    design_name = 'mlhdlc_2DFIR.m';

    testbench_name = 'mlhdlc_2DFIR_tb.m';

    Let us take a look at the MATLAB design

    type(design_name);

    %#codegen

    function [pixel_out] = mlhdlc_2DFIR(pixel_in)

    % The 2D FIR algorithm maintains three line buffers. Each iteration the

    % input pixel is pushed into the current line buffer that is being written to.

    % The control logic rotates between these three buffers when it reaches the

    % column boundary.

    % Each buffer is followed by a shift register and data at the current

    % column index is pushed into the shift register.

    % At each iteration a 3x3 kernel of pixels is formed from the pixel input, shift

    % registers and line buffer outputs.

    % The kernel is multiplied by a 3x3 filter coefficient mask and the sum of

    % the resultant values is computed as the pixel output.

    nRows = 260;

    nCols = 260;

    mask = [-0.1667 -0.6667 -0.1667 -0.6667 4.3333 -0.6667 -0.1667 -0.6667 -0.1667];

    persistent row_count;

    persistent col_count;

    persistent t_minus_1_pixel;

    persistent t_minus_2_pixel;

    persistent t_minus_1_memrow1;

  • 7/22/2019 2D FIR Filter

    2/38

    persistent t_minus_2_memrow1;

    persistent t_minus_1_memrow2;

    persistent t_minus_2_memrow2;

    persistent t_minus_1_memrow3;

    persistent t_minus_2_memrow3;

    persistent mem_row_idx;

    persistent mem_row1;

    persistent mem_row2;

    persistent mem_row3;

    if isempty(t_minus_1_memrow3)

    t_minus_1_memrow3 = 0;

    t_minus_2_memrow3 = 0;

    t_minus_1_memrow2 = 0;

    t_minus_2_memrow2 = 0;

    t_minus_1_memrow1 = 0;

    t_minus_2_memrow1 = 0;

    row_count = 1;

    col_count = 1;

    t_minus_1_pixel = 0;

    t_minus_2_pixel = 0;

    mem_row_idx = 1;

    mem_row1 = zeros(1,nCols);

    mem_row2 = zeros(1,nCols);

    mem_row3 = zeros(1,nCols);

    end

    row_count_r=row_count;

    col_count_r=col_count;

    t_minus_1_pixel_r=t_minus_1_pixel;

    t_minus_2_pixel_r=t_minus_2_pixel;

    t_minus_1_memrow1_r=t_minus_1_memrow1;

    t_minus_2_memrow1_r=t_minus_2_memrow1;

    t_minus_1_memrow2_r=t_minus_1_memrow2;

    t_minus_2_memrow2_r=t_minus_2_memrow2;

    t_minus_1_memrow3_r=t_minus_1_memrow3;

    t_minus_2_memrow3_r=t_minus_2_memrow3;

    mem_row_idx_r = mem_row_idx;

  • 7/22/2019 2D FIR Filter

    3/38

    write_col_idx = col_count_r;

    current_mem_row1_data = mem_row1(write_col_idx);

    current_mem_row2_data = mem_row2(write_col_idx);

    current_mem_row3_data = mem_row3(write_col_idx);

    if mem_row_idx_r==1

    top_row= [t_minus_2_memrow2_r t_minus_1_memrow2_r current_mem_row2_data];

    middle_row= [t_minus_2_memrow3_r t_minus_1_memrow3_r current_mem_row3_data];

    elseif mem_row_idx_r==2

    top_row= [t_minus_2_memrow3_r t_minus_1_memrow3_r current_mem_row3_data];

    middle_row= [t_minus_2_memrow1_r t_minus_1_memrow1_r current_mem_row1_data];

    else

    top_row= [t_minus_2_memrow1_r t_minus_1_memrow1_r current_mem_row1_data];

    middle_row= [t_minus_2_memrow2_r t_minus_1_memrow2_r current_mem_row2_data];

    end

    bottom_row = [ t_minus_2_pixel_r t_minus_1_pixel_r pixel_in];

    kernel = [top_row middle_row bottom_row];

    if col_count_r>=3 && row_count_r>=3

    %pixel_out=sum(operand.*mask);

    m1 = kernel(1) * mask(1);

    m2 = kernel(2) * mask(2);

    m3 = kernel(3) * mask(3);

    m4 = kernel(4) * mask(4);

    m5 = kernel(5) * mask(5);

    m6 = kernel(6) * mask(6);

    m7 = kernel(7) * mask(7);

    m8 = kernel(8) * mask(8);

    m9 = kernel(9) * mask(9);

    % tree of adders

    s1 = m1 + m2;

    s2 = m3 + m4;

    s3 = m5 + m6;

    s4 = m7 + m8;

    s21 = s1 + s2;

    s22 = s3 + s4;

    s31 = s21 + s22;

    pixel_out = s31 + m9;

  • 7/22/2019 2D FIR Filter

    4/38

    else

    pixel_out=0;

    end

    if mem_row_idx_r==1

    mem_row1_write_data = pixel_in;

    mem_row2_write_data = current_mem_row2_data;

    mem_row3_write_data = current_mem_row3_data;

    elseif mem_row_idx_r==2

    mem_row1_write_data = current_mem_row1_data;

    mem_row2_write_data = pixel_in;

    mem_row3_write_data = current_mem_row3_data;

    else

    mem_row1_write_data = current_mem_row1_data;

    mem_row2_write_data = current_mem_row2_data;

    mem_row3_write_data = pixel_in;

    end

    mem_row1(write_col_idx)=mem_row1_write_data;

    mem_row2(write_col_idx)=mem_row2_write_data;

    mem_row3(write_col_idx)=mem_row3_write_data;

    if col_count_r==nCols

    %toggle memrow

    if mem_row_idx_r ==1;

    mem_row_idx=2;

    elseif mem_row_idx_r ==2;

    mem_row_idx=3;

    else

    mem_row_idx=1;

    end

    end

    t_minus_1_pixel = pixel_in;

    t_minus_2_pixel = t_minus_1_pixel_r;

    t_minus_1_memrow1=current_mem_row1_data;

    t_minus_2_memrow1=t_minus_1_memrow1_r;

    t_minus_1_memrow2=current_mem_row2_data;

    t_minus_2_memrow2=t_minus_1_memrow2_r;t_minus_1_memrow3=current_mem_row3_data;

  • 7/22/2019 2D FIR Filter

    5/38

    t_minus_2_memrow3=t_minus_1_memrow3_r;

    if col_count_r+1

  • 7/22/2019 2D FIR Filter

    6/38

    for i = 1:length(image_in_vector)

    y(i) = mlhdlc_2DFIR(image_in_vector(i));

    end

    % Reshape the output back to a 2D matrix

    image_out = reshape(y,pixels,rows)';

    filt_image = imfilter(image_in,H,0);

    err = filt_image-image_out(4:end-1,4:end-1);

    err = (err > TOL) .* err;

    figure('Name', [mfilename, '_plot']);

    subplot(1,2,1);

    imshow(int8(image_out(4:end-1,4:end-1)));title('HDL Output');

    subplot(1,2,2);

    imshow(err);title('Difference');

    Create a New HDL CoderProject

    coder -hdlcoder-newmlhdlc_2dfir_prj

    Next, add the file 'mlhdlc_2DFIR.m' to the project as the MATLAB Function and 'mlhdlc_2DFIR_tb.m' as the MATLAB Test Bench.

    You can refer toGetting Started with MATLAB to HDL Workflowtutorial for a more complete tutorial on creating and populating MATLAB HDL Coder

    projects.

    Run Fixed-Point Conversion and HDL Code Generation

    Launch HDL Advisor and right click on the 'Code Generation' step and choose the option 'Run to selected task' to run all the steps from the beginning

    through the HDL code generation.

    Examine the generated HDL code by clicking on the hyperlinks in the Code Generation Log window.

    Enable Distributed Pipelining Option

    To improve clock frequency of the synthesized circuit you can use the distributed pipelining option to pipeline the multipliers inferred in the design.

    1. Choose the option 'Output Pipeline: 10'

    2. Enable the option 'Distribute Pipeline Registers'

    3. Reset the 'Code Generation' task

    4. Rerun the code generation and synthesis steps and examine the synthesis results.

    Clean up the Generated Files

    You can run the following commands to clean up the temporary project folder.

    mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');

    mlhdlc_temp_dir = [tempdir 'mlhdlc_sobel'];

    clear mex;cd (mlhdlc_demo_dir);

    rmdir(mlhdlc_temp_dir, 's');

    http://www.mathworks.in/help/hdlcoder/examples/getting-started-with-matlab-r-to-hdl-workflow.htmlhttp://www.mathworks.in/help/hdlcoder/examples/getting-started-with-matlab-r-to-hdl-workflow.htmlhttp://www.mathworks.in/help/hdlcoder/examples/getting-started-with-matlab-r-to-hdl-workflow.htmlhttp://www.mathworks.in/help/hdlcoder/examples/getting-started-with-matlab-r-to-hdl-workflow.html
  • 7/22/2019 2D FIR Filter

    7/38

    Corner Detection

    This example shows how to generate HDL code from design implementing the Harris Stephens Corner

    Detector in MATLAB.

    Contents

    IntroductionSetup for the ExampleSimulate the DesignCreate a New HDL Coder ProjectRunFixed-Point

    Conversion and HDL Code GenerationClean up the Generated Files

    Introduction

    Corner Detection is used in many Image processing applications like mosaicking, tracking and

    recognition. Corner detectors are robust to image rotation, translation and variation in lighting

    The algorithm applies an edge filter to find horizontal and vertical gradients; applies square & gaussian

    low pass filter on the two gradients. the results are then multiplied and further low pass filtered before

    computing the corner metric.

    The testbench takes the corner metric to find the threshold and local maxima to compute corners. The

    valid pixel information from the design is used to super impose the corners onto the original image

    design_name = 'mlhdlc_corner_detection.m';

    testbench_name = 'mlhdlc_corner_detection_tb.m';

    Let us take a look at the MATLAB design

    type(design_name);

    %#codegen

    function [cm] = mlhdlc_corner_detection(data_in)

    persistent h1

    if isempty(h1)

    h1 = dsp.Delay('FrameBasedProcessing', false);

    end

    [xfo, yfo] = sobel_filt(data_in);

    cm = compute_corner_metric(xfo, yfo);

    end

  • 7/22/2019 2D FIR Filter

    8/38

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function bm = compute_corner_metric(gh, gv)

    cmh = make_buffer_matrix_gh(gh);

    cmv = make_buffer_matrix_gv(gv);

    bm = compute_harris_metric(cmh, cmv);

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function bm = make_buffer_matrix_gh(gh)

    persistent b1 b2 b3 b4;

    if isempty(b1)

    b1 = dsp.Delay('FrameBasedProcessing', false, 'Length', 80);

    b2 = dsp.Delay('FrameBasedProcessing', false, 'Length', 80);

    b3 = dsp.Delay('FrameBasedProcessing', false, 'Length', 80);

    b4 = dsp.Delay('FrameBasedProcessing', false, 'Length', 80);

    end

    b1p = step(b1, gh);

    b2p = step(b2, b1p);

    b3p = step(b3, b2p);

    b4p = step(b4, b3p);

    cc = [b4p; b3p; b2p; b1p; gh];

    persistent h1 h2 h3 h4;

    if isempty(h1)

    h1 = dsp.Delay('FrameBasedProcessing', false);

  • 7/22/2019 2D FIR Filter

    9/38

  • 7/22/2019 2D FIR Filter

    10/38

    cc = [b4p; b3p; b2p; b1p; gv];

    persistent h1 h2 h3 h4;

    if isempty(h1)

    h1 = dsp.Delay('FrameBasedProcessing', false);

    h2 = dsp.Delay('FrameBasedProcessing', false);

    h3 = dsp.Delay('FrameBasedProcessing', false);

    h4 = dsp.Delay('FrameBasedProcessing', false);

    end

    h1p = step(h1, cc);

    h2p = step(h2, h1p);

    h3p = step(h3, h2p);

    h4p = step(h4, h3p);

    bm = [h4p; h3p; h2p; h1p; cc];

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function cm = compute_harris_metric(gh, gv)

    [g1, g2, g3] = gaussian_filter(gh, gv);

    [s1, s2, s3] = reduce_matrix(g1, g2, g3);

    cm = (((s1*s3) - (s2*s2)) - (((s1+s3) * (s1+s3)) * 0.04));

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function [g1, g2, g3] = gaussian_filter(gh, gv)

  • 7/22/2019 2D FIR Filter

    11/38

    g=fspecial('gaussian',[5 5],1.5);

    g1 = (gh .* gh) .* g(:);

    g2 = (gh .* gv) .* g(:);

    g3 = (gv .* gv) .* g(:);

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function [s1, s2, s3] = reduce_matrix(g1, g2, g3)

    s1 = sum(g1);

    s2 = sum(g2);

    s3 = sum(g3);

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%

    function [xfo, yfo, e] = sobel_filt(u)

    % Pipelined Sobel Edge Detection algorithm on serialized image.

    numCols=80;

    thresh=uint8(157);

    [xfo, yfo] = s_filter(u, numCols);

    persistent h1

    if isempty(h1)

    h1 = dsp.Delay('FrameBasedProcessing', false);

    end

    ax = abs(xfo);

    ay = abs(yfo);

    t = (ax + ay >= thresh);

  • 7/22/2019 2D FIR Filter

    12/38

    e = step(h1, t);

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    % Compute convolution of serialized image data with sobel masks

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    function [xfo, yfo] = s_filter(u, numCols)

    persistent buf1 buf2;

    if isempty(buf1)

    buf1 = dsp.Delay('FrameBasedProcessing', false, 'Length', numCols);

    buf2 = dsp.Delay('FrameBasedProcessing', false, 'Length', numCols);

    end

    lb1 = step(buf1, u);

    lb2 = step(buf2, lb1);

    persistent h1 h2 h3 h4 h5 h6;

    if isempty(h1)

    h1 = dsp.Delay('FrameBasedProcessing', false);

    h2 = dsp.Delay('FrameBasedProcessing', false);

    h3 = dsp.Delay('FrameBasedProcessing', false);

    h4 = dsp.Delay('FrameBasedProcessing', false);

    h5 = dsp.Delay('FrameBasedProcessing', false);

    h6 = dsp.Delay('FrameBasedProcessing', false);

    end

    ud1 = step(h1, u);

    ud2 = step(h2, ud1);

  • 7/22/2019 2D FIR Filter

    13/38

    lb1d1 = step(h3, lb1);

    lb1d2 = step(h4, lb1d1);

    lb2d1 = step(h5, lb2);

    lb2d2 = step(h6, lb2d1);

    xfo = xf(u, ud1, ud2, lb2, lb2d1, lb2d2);

    yfo = yf(ud2, u, lb1d2, lb1, lb2d2, lb2);

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    % Compute x gradient

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    function xf_out = xf(u, xd1, xd2, lb2, zd1, zd2)

    c2 = 2;

    t1 = xd1 * c2;

    a1 = u + t1 + xd2;

    t1 = zd1 * c2;

    a2 = lb2 + t1 + zd2;

    xf_out = a1 - a2;

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    % Compute y gradient

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    function yf_out = yf(xd2, u, yd2, lb1, zd2, lb2)

  • 7/22/2019 2D FIR Filter

    14/38

    a1 = xd2 - u;

    t = yd2 - lb1;

    c2 = 2;

    a2 = c2 * t;

    a3 = zd2 - lb2;

    yf_out = a1 + a2 + a3;

    end

    type(testbench_name);

    clear all;

    image_in = checkerboard(10);

    [rows pixels] = size(image_in);

    image_vector_length = rows*pixels;

    image_in_vector = reshape(image_in',1,image_vector_length);

    % Pre-allocating y for simulation performance

    y = zeros(1,length(image_in_vector));

    dataValidOut = y;

    for i = 1:length(image_in_vector)

    y(i) = mlhdlc_corner_detection(image_in_vector(i));

    end

    % Reshape output back to 2D array

    image_out = reshape(y,pixels,rows)';

    image_out_crop = image_out(7:end, 7:end);

    padImage = zeros(size(image_out_crop)+6);

    padImage(4:end-3,4:end-3) = image_out_crop;

    findLocalMaxima = vision.LocalMaximaFinder('MaximumNumLocalMaxima', 50, ...

  • 7/22/2019 2D FIR Filter

    15/38

    'NeighborhoodSize', [11 11], ...

    'Threshold', 0.0005);

    Corners = step(findLocalMaxima, padImage);

    drawMarkers = vision.MarkerInserter('Size', 2); % Draw marker circles at corners

    ImageCornersMarked = step(drawMarkers, image_in, Corners);

    % Display results

    figure('Name', 'Corners');

    imagesc(image_out), colormap('gray')

    figure('Name', 'Corners Marked on Original');

    imagesc(ImageCornersMarked), colormap('gray')

    Setup for the Example

    Executing the following lines of code copies the necessary example files into a temporary folder

    mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');

    mlhdlc_temp_dir = [tempdir 'mlhdlc_cdetect'];

    % create a temporary folder and copy the MATLAB files

    cd(tempdir);

    [~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');

    mkdir(mlhdlc_temp_dir);

    cd(mlhdlc_temp_dir);

    % copy the design files to the temporary directory

    copyfile(fullfile(mlhdlc_demo_dir, design_name), mlhdlc_temp_dir);

    copyfile(fullfile(mlhdlc_demo_dir, testbench_name), mlhdlc_temp_dir);

  • 7/22/2019 2D FIR Filter

    16/38

    Simulate the Design

    It is a good practice to simulate the design with the testbench prior to code generation to make sure

    there are no runtime errors.

    mlhdlc_corner_detection_tb

    Warning: The Computer Vision System Toolbox coordinate system changed. You

    invoked a function, System object, or block affected by the change. See

    R2011b Release Notes for details.

    Contrast Adjustment

    This example shows how to generate HDL code from MATLAB design that adjusts image contrast by

    linearly scaling pixel values.

    Contents

    IntroductionAlgorithmSimulate the DesignCreate a New Folder and Copy Relevant FilesCreate a New

    HDL Coder ProjectRun Fixed-Point Conversion and HDL Code GenerationClean up the Generated Files

    Introduction

    design_name = 'mlhdlc_image_scale.m';

  • 7/22/2019 2D FIR Filter

    17/38

    testbench_name = 'mlhdlc_image_scale_tb.m';

    Let us take a look at the MATLAB design

    type(design_name);

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    % scale.m

    %

    % Adjust image contrast by linearly scaling pixel values.

    %

    % The input pixel value range has 14bits and output pixel value range is

    % 8bits.

    %

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%

    function [x_out y_out pixel_out] = ...

    mlhdlc_image_scale(x_in, y_in, pixel_in, ...

    damping_factor_in, dynamic_range_in, ...

    tail_size_in, max_gain_in, ...

    width, height)

    persistent histogram1 histogram2

  • 7/22/2019 2D FIR Filter

    18/38

    persistent low_count

    persistent high_count

    persistent offset

    persistent gain

    persistent limits_done

    persistent damping_done

    persistent reset_hist_done

    persistent scaling_done

    persistent hist_ind

    persistent tail_high

    persistent min_hist_damped %Damped lower limit of populated histogram

    persistent max_hist_damped %Damped upper limit of populated histogram

    persistent found_high

    persistent found_low

    DR_PER_BIN = 8;

    SF = 1./(1:(2^14/8)); % be nice to fix this

    NR_OF_BINS = (2^14/DR_PER_BIN) - 1;

    MAX_DF = 255;

    if isempty(offset)

    offset = 1;

    gain = 1;

    limits_done = 1;

    damping_done = 1;

  • 7/22/2019 2D FIR Filter

    19/38

    reset_hist_done = 1;

    scaling_done = 1;

    hist_ind = 1;

    tail_high = NR_OF_BINS;

    low_count = 0;

    high_count = 0;

    min_hist_damped = 0;

    max_hist_damped = (2^14/DR_PER_BIN) - 1;

    found_high = 0;

    found_low = 0;

    end

    if isempty(histogram1)

    histogram1 = zeros(1, NR_OF_BINS+1);

    histogram2 = zeros(1, NR_OF_BINS+1);

    end

    if y_in < height

    frame_valid = 1;

    if x_in < width

    line_valid = 1;

    else

    line_valid = 0;

    end

    else

    frame_valid = 0;

  • 7/22/2019 2D FIR Filter

    20/38

    line_valid = 0;

    end

    % initialize at beginning of frame

    if x_in == 0 && y_in == 0

    limits_done = 0;

    damping_done = 0;

    reset_hist_done = 0;

    scaling_done = 0;

    low_count = 0;

    high_count = 0;

    hist_ind = 1;

    end

    max_gain_frac = max_gain_in/2^4;

    pix11 = floor(pixel_in/DR_PER_BIN);

    pix_out_temp = pixel_in;

    %**************************************************************************

    %Check if valid part of frame. If pixel is valid remap pixel to desired

    %output dynamic range (dynamic_range_in) by subtracting the damped offset

    %(min_hist_damped) and applying the calculated gain calculated from the

    %previous frame histogram statistics.

    %**************************************************************************

    % histogram read

  • 7/22/2019 2D FIR Filter

    21/38

    histReadIndex1 = 1;

    histReadIndex2 = 1;

    if frame_valid && line_valid

    histReadIndex1 = pix11+1;

    histReadIndex2 = pix11+1;

    elseif ~limits_done

    histReadIndex1 = hist_ind;

    histReadIndex2 = NR_OF_BINS - hist_ind;

    end

    histReadValue1 = histogram1(histReadIndex1);

    histReadValue2 = histogram2(histReadIndex2);

    histWriteIndex1 = NR_OF_BINS+1;

    histWriteIndex2 = NR_OF_BINS+1;

    histWriteValue1 = 0;

    histWriteValue2 = 0;

    if frame_valid

    if line_valid

    temp_sum = histReadValue1 + 1;

    ind = min(pix11+1, NR_OF_BINS);

    val = min(temp_sum, tail_size_in);

    histWriteIndex1 = ind;

    histWriteValue1 = val;

    histWriteIndex2 = ind;

    histWriteValue2 = val;

  • 7/22/2019 2D FIR Filter

    22/38

    %Scale pixel

    pix_out_offs_corr = pixel_in - min_hist_damped*DR_PER_BIN;

    pix_out_scaled = pix_out_offs_corr * gain;

    pix_out_clamp = max(min(dynamic_range_in, pix_out_scaled), 0);

    pix_out_temp = pix_out_clamp;

    end

    else

    %**********************************************************************

    %Ignore tail_size_in pixels and find lower and upper limits of the

    %histogram. TODO: Make tail_size_in an input parameter so that we can

    %chose how many outliers to ignore. Typical value 0.3%

    %**********************************************************************

    if ~limits_done

    if hist_ind == 1

    tail_high = NR_OF_BINS-1;

    offset = 1;

    found_high = 0;

    found_low = 0;

    end

    low_count = low_count + histReadValue1;

    hist_ind_high = NR_OF_BINS - hist_ind;

    high_count = high_count + histReadValue2;

    %Found enough high outliers

  • 7/22/2019 2D FIR Filter

    23/38

    if high_count > tail_size_in && ~found_high

    tail_high = hist_ind_high;

    found_high = 1;

    end

    %Found enough low outliers

    if low_count > tail_size_in && ~found_low

    offset = hist_ind;

    found_low = 1;

    end

    hist_ind = hist_ind + 1;

    %All bins checked so limits must already be found

    if hist_ind >= NR_OF_BINS

    hist_ind = 1;

    limits_done = 1;

    end

    %**********************************************************************

    %Damp the limit change to avoid image flickering. Code below equivalent

    %to: max_hist_damped = damping_factor_in*max_hist_dampedOld +

    %(1-damping_factor_in)*max_hist_dampedNew;

    %**********************************************************************

    elseif ~damping_done

    min_hist_weighted_old = damping_factor_in*min_hist_damped;

    min_hist_weighted_new = (MAX_DF-damping_factor_in+1)*offset;

  • 7/22/2019 2D FIR Filter

    24/38

  • 7/22/2019 2D FIR Filter

    25/38

    %dynamic range to the desired user specified dynamic range. Input

    %dynamic range is measured in bins over DR_PER_BIN space. TODO: Add a

    %max gain limit, possibly as an input port. This will prevent over

    %stretching for very low contrast scenes.

    %**********************************************************************

    elseif ~scaling_done

    dr_in = round(max_hist_damped - min_hist_damped);

    gain_temp = dynamic_range_in*SF(dr_in);

    gain_scaled = gain_temp/DR_PER_BIN;

    gain = min(max_gain_frac, gain_scaled);

    scaling_done = 1;

    hist_ind = 1;

    end

    end

    histogram1(histWriteIndex1) = histWriteValue1;

    histogram2(histWriteIndex2) = histWriteValue2;

    x_out = x_in;

    y_out = y_in;

    pixel_out = pix_out_temp;

    type(testbench_name);

  • 7/22/2019 2D FIR Filter

    26/38

    %Test bench for scaling, analogous to automatic gain control (AGC)

    testFile = 'mlhdlc_img_drive1.tif';

    imgOrig = imread(testFile);

    [height width] = size(imgOrig);

    imgOut = zeros(height,width);

    hBlank = 20;

    % make sure we have enough vertical blanking to filter the histogram

    vBlank = ceil(2^14/(width+hBlank));

    %df - Temporal damping factor of rescaling

    %dr - Desired output dynamic range

    df = 0;

    dr = 255;

    nrOfOutliers = 248;

    maxGain = 2*2^4;

    for frame = 1:2

    disp(['frame: ', num2str(frame)]);

    for y_in = 0:height+vBlank-1

    %disp(['frame: ', num2str(frame), ' of 2, row: ', num2str(y_in)]);

    for x_in = 0:width+hBlank-1

    if x_in < width && y_in < height

    pixel_in = double(imgOrig(y_in+1, x_in+1));

  • 7/22/2019 2D FIR Filter

    27/38

    else

    pixel_in = 0;

    end

    [x_out y_out pixel_out] = ...

    mlhdlc_image_scale(x_in, y_in, pixel_in, df, dr, ...

    nrOfOutliers, maxGain, width, height);

    if x_out < width && y_out < height

    imgOut(y_out+1,x_out+1) = pixel_out;

    end

    end

    end

    figure('Name', [mfilename, '_scale_plot']);

    subplot(2,2,1); imshow(imgOrig, []);

    title('Original Image');

    subplot(2,2,2); imshow(imgOut, []);

    title('Scaled Image');

    subplot(2,2,3); hist(double(imgOrig(:)),2^14-1);

    title('Histogram of original Image');

    subplot(2,2,4); hist(double(imgOut(:)),2^14-1);

    title('Histogram of equalized Image');

    end

  • 7/22/2019 2D FIR Filter

    28/38

    Algorithm

    The Contrast Adjustment block adjusts the contrast of an image by linearly scaling the pixel values

    between upper and lower limits. Pixel values that are above or below this range are saturated to the

    upper or lower limit value, respectively.

    Image Enhancement by Histogram Equalization

    This example shows how to generate HDL code from MATLAB design that does image enhancement

    using histogram equalization technique.

    Contents

    MATLAB DesignAlgorithmSimulate the DesignSetup for the ExampleCreate a New HDL CoderProjectRun Fixed-Point Conversion and HDL Code GenerationClean up the Generated Files

    MATLAB Design

    design_name = 'mlhdlc_heq.m';

    testbench_name = 'mlhdlc_heq_tb.m';

    Algorithm

    The Histogram Equalization algorithm enhances the contrast of images by transforming the values in an

    intensity image so that the histogram of the output image is approximately flat.

    I = imread('pout.tif');

    J = histeq(I);

    subplot(2,1,1);

    imhist(I)

    subplot(2,1,2);

    imhist(J)

    Let us take a look at the MATLAB design

  • 7/22/2019 2D FIR Filter

    29/38

  • 7/22/2019 2D FIR Filter

    30/38

    histInd = pixel_in + 1;

    elseif y_in == height && x_in == 0 % first column of height+1

    histInd = 1;

    elseif y_in >= height % vertical blanking period

    histInd = min(histInd + 1, 2^14);

    elseif y_in < height % horizontal blanking - do nothing

    histInd = 1;

    end

    %Read histogram (must be outside conditional logic)

    histValRead = histogram(histInd);

    %Read transfer function (must be outside conditional logic)

    transValRead = transferFunc(histInd);

    %If valid part of frame add one to pixel bin and keep transfer func val

    if y_in < height && x_in < width

    histValWrite = histValRead + 1; %Add pixel to bin

    transValWrite = transValRead; %Write back same value

    cumSum = 0;

    elseif y_in >= height %In blanking time index through all bins and reset to zero

    histValWrite = 0;

    transValWrite = cumSum + histValRead;

    cumSum = transValWrite;

    else

  • 7/22/2019 2D FIR Filter

    31/38

    histValWrite = histValRead;

    transValWrite = transValRead;

    end

    %Write histogram (must be outside conditional logic)

    histogram(histInd) = histValWrite;

    %Write transfer function (must be outside conditional logic)

    transferFunc(histInd) = transValWrite;

    pixel_out = transValRead;

    x_out = x_in;

    y_out = y_in;

    type(testbench_name);

    %Test bench for Histogram Equalization

    testFile = 'mlhdlc_img_drive1.tif';

    imgOrig = imread(testFile);

    [height width] = size(imgOrig);

  • 7/22/2019 2D FIR Filter

    32/38

    imgOut = zeros(height,width);

    hBlank = 20;

    % make sure we have enough vertical blanking to filter the histogram

    vBlank = ceil(2^14/(width+hBlank));

    for frame = 1:2

    disp(['working on frame: ', num2str(frame)]);

    for y_in = 0:height+vBlank-1

    %disp(['frame: ', num2str(frame), ' of 2, row: ', num2str(y_in)]);

    for x_in = 0:width+hBlank-1

    if x_in < width && y_in < height

    pixel_in = double(imgOrig(y_in+1, x_in+1));

    else

    pixel_in = 0;

    end

    [x_out y_out pixel_out] = ...

    mlhdlc_heq(x_in, y_in, pixel_in, width, height);

    if x_out < width && y_out < height

    imgOut(y_out+1,x_out+1) = pixel_out;

    end

    end

    end

  • 7/22/2019 2D FIR Filter

    33/38

    figure(1)

    subplot(2,2,1); imshow(imgOrig, []);

    title('Original Image');

    subplot(2,2,2); imshow(imgOut, []);

    title('Equalized Image');

    subplot(2,2,3); hist(double(imgOrig(:)),2^14-1);

    title('Histogram of original Image');

    subplot(2,2,4); hist(double(imgOut(:)),2^14-1);

    title('Histogram of equalized Image');

    end

    Image Format Conversion: RGB to YUV

    This example shows how to generate HDL code from MATLAB design implementing a RGB2YUV

    conversion

    Contents

    MATLAB DesignSetup for the ExampleSimulate the DesignCreate a New HDL Coder ProjectRun Fixed -

    Point Conversion and HDL Code GenerationClean up the Generated Files

    MATLAB Design

    design_name = 'mlhdlc_rgb2yuv.m';

    testbench_name = 'mlhdlc_rgb2yuv_tb.m';

  • 7/22/2019 2D FIR Filter

    34/38

    Let us take a look at the MATLAB design

    type(design_name);

    function [x_out y_out y_data_out u_data_out v_data_out] = mlhdlc_rgb2yuv(x_in, y_in, r_in, g_in, b_in)

    %#codegen

    persistent RGB_Reg YUV_Reg

    persistent x1 x2 y1 y2

    if isempty(RGB_Reg)

    RGB_Reg = zeros(3,1);

    YUV_Reg = zeros(3,1);

    x1 = 0;

    x2 = 0;

    y1 = 0;

    y2 = 0;

    end

    D = [.299 .587 .144;

    -.147 -.289 .436;

    .615 -.515 -.1];

    C = [0; 128; 128];

  • 7/22/2019 2D FIR Filter

    35/38

    RGB = [r_in; g_in; b_in];

    YUV_1 = D*RGB_Reg;

    YUV_2 = YUV_1 + C;

    RGB_Reg = RGB;

    y_data_out = round(YUV_Reg(1));

    u_data_out = round(YUV_Reg(2));

    v_data_out = round(YUV_Reg(3));

    YUV_Reg = YUV_2;

    x_out = x2;

    x2 = x1;

    x1 = x_in;

    y_out = y2;

    y2 = y1;

    y1 = y_in;

    type(testbench_name);

  • 7/22/2019 2D FIR Filter

    36/38

    FRAMES = 1;

    WIDTH = 752;

    HEIGHT = 480;

    HBLANK = 10;%748;

    VBLANK = 10;%120;

    vidData = double(imread('mlhdlc_img_yuv.tif'));

    for f = 1:FRAMES

    vidOut = zeros(HEIGHT, WIDTH, 3);

    for y = 0:HEIGHT+VBLANK-1

    for x = 0:WIDTH+HBLANK-1

    if y >= 0 && y < HEIGHT && x >= 0 && x < WIDTH

    b = vidData(y+1,x+1,1);

    g = vidData(y+1,x+1,2);

    r = vidData(y+1,x+1,3);

    else

    b = 0;

    g = 0;

    r = 0;

    end

  • 7/22/2019 2D FIR Filter

    37/38

    [xOut yOut yData uData vData] = ...

    mlhdlc_rgb2yuv(x, y, r, g, b);

    if yOut >= 0 && yOut < HEIGHT && xOut >= 0 && xOut < WIDTH

    vidOut(yOut+1,xOut+1,:) = [yData vData uData];

    end

    end

    end

    figure(1);

    subplot(1,2,1);

    imshow(uint8(vidData));

    subplot(1,2,2);

    imshow(ycbcr2rgb(uint8(vidOut)));

    drawnow;

    end

    Setup for the Example

    Executing the following lines of code copies the necessary example files into a temporary folder

    mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');

  • 7/22/2019 2D FIR Filter

    38/38

    mlhdlc_temp_dir = [tempdir 'mlhdlc_rgb2yuv'];

    % create a temporary folder and copy the MATLAB files

    cd(tempdir);

    [~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');

    mkdir(mlhdlc_temp_dir);

    cd(mlhdlc_temp_dir);

    % copy files to the temp dir

    copyfile(fullfile(mlhdlc_demo_dir, design_name), mlhdlc_temp_dir);

    copyfile(fullfile(mlhdlc_demo_dir, testbench_name), mlhdlc_temp_dir);

    Simulate the Design

    % It is always a good practice to simulate the design with the testbench prior to

    % code generation to make sure there are no runtime errors.

    mlhdlc_rgb2yuv_tb