Professional Documents
Culture Documents
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.
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;
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;
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;
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;
end type(testbench_name); clear mlhdlc_2DFIR; TOL = 1e-6; % Read the image image_in = double(imread('mlhdlc_cameraman.tif')); H = fspecial('unsharp');
% Pad the image [rows pixels] = size(image_in); pad_vert_im = [ zeros(1,pixels);zeros(1,pixels);image_in;... zeros(1,pixels);zeros(1,pixels)]; pad_horiz_im = [ zeros(rows+4,2) pad_vert_im zeros(rows+4,2)];
% Reshape the image as a vector [rows pixels] = size(pad_horiz_im); image_vector_length = rows*pixels; image_in_vector = reshape(pad_horiz_im',1,image_vector_length);
for i = 1:length(image_in_vector)
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');
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 ProjectRun Fixed-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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% 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);
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 bm = make_buffer_matrix_gv(gv) 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, gv); b2p = step(b2, b1p); b3p = step(b3, b2p); b4p = step(b4, b3p);
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
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);
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);
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)
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, ...
'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);
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';
testbench_name = 'mlhdlc_image_scale_tb.m';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % 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 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 SF
= 8;
NR_OF_BINS MAX_DF
= 1; = 1;
= 1; = NR_OF_BINS; = 0; = 0; = 0; = (2^14/DR_PER_BIN) - 1;
if y_in < height frame_valid = 1; if x_in < width line_valid = 1; else line_valid = 0; end else frame_valid = 0;
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
%************************************************************************** %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
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;
%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
%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;
min_hist_weighted = (min_hist_weighted_old + ... min_hist_weighted_new)/256; min_hist_damped = max(0, min_hist_weighted); max_hist_weighted_old = damping_factor_in*max_hist_damped; max_hist_weighted_new = (MAX_DF-damping_factor_in+1)*tail_high; max_hist_weighted = (max_hist_weighted_old + ... max_hist_weighted_new)/256; max_hist_damped = min(NR_OF_BINS, max_hist_weighted); damping_done = 1; hist_ind = 1; %********************************************************************** %Reset all bins to zero. More than one bin can be reset per function %call if blanking time is too short. %********************************************************************** elseif ~reset_hist_done histWriteIndex1 = hist_ind; histWriteValue1 = 0; histWriteIndex2 = hist_ind; histWriteValue2 = 0; hist_ind = hist_ind+1; if hist_ind == NR_OF_BINS reset_hist_done = 1; end %********************************************************************** %The gain factor is determined by comparing the measured damped actual
%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;
type(testbench_name);
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));
[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
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
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 Coder ProjectRun 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)
type(design_name);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% % heq.m % Histogram Equalization Algorithm %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%% function [x_out y_out pixel_out] = ... mlhdlc_heq(x_in, y_in, pixel_in, width, height)
if isempty(histogram) histogram = zeros(1, 2^14); transferFunc = zeros(1, 2^14); histInd = 0; cumSum = 0; end
% Figure out indexes based on where we are in the frame if y_in < height && x_in < width % valid pixel data
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
%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
type(testbench_name);
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
if x_out < width && y_out < height imgOut(y_out+1,x_out+1) = pixel_out; end end end
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
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 FixedPoint Conversion and HDL Code GenerationClean up the Generated Files
MATLAB Design
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
D = [.299 .587 .144; -.147 -.289 .436; .615 -.515 -.1]; C = [0; 128; 128];
type(testbench_name);
vidData = double(imread('mlhdlc_img_yuv.tif'));
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
if yOut >= 0 && yOut < HEIGHT && xOut >= 0 && xOut < WIDTH vidOut(yOut+1,xOut+1,:) = [yData vData uData]; end end end
end
Executing the following lines of code copies the necessary example files into a temporary folder mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
% 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);
% 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