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.html7/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
Top Related