Code covered by the BSD License  

Highlights from
fillgaps in an array/matrix/image

image thumbnail

fillgaps in an array/matrix/image

by

 

Fill gaps in a cell-array/vector/matrix or image based on an alternative cell/vector/matrix/image

fillgaps(target,refarray,fields2fill,varargin)
function [combined_data,data] = fillgaps(target,refarray,fields2fill,varargin)

% Objective: This code is useful when there is two or more versions of data
% for the same dates or spatial points or images where each version has
% some gaps in certain fields that are crucial for the analysis. The
% objective is to fill the gaps in the best version (or any version if no
% preferance), using corresponding values in the alternative versions.
%
% The function accepts a cell-array (or matrix), and replaces NaN values 
% of certain fields of it with available values of the second or more given
% reference cell-arrays (or matrixes). Both cell-arrays and matrixes are
% accepted as target and reference(s). 
% The first two arguments are the target and reference
% cell-arrays/matrices, the third argument provides index(es) of fields
% where NaNs should be replaced (target and reference cell-arrays/matrices
% should have similar fields). More reference cell-arrays/matrices/images
% can be given as arbitrary arguments. If the values to be replaced in
% target cell-array/matrix are NaNs in the first refenece, the extra
% references (if available) will also be checked. If non of the references
% have valid value for a NaN record in the target, the returned
% cell-array/matrix will be still NaN (no change) for that record. As a
% rule, NaNs will be replcaed with the available non-NaN values from the
% first reference cell-array(s)/matrices.
% For images where NaNs or missing data are spread all over the image, all
% columns (1:length(cols)) can be given so that the entire image is
% repaired based on the available reference image(s). Note that if the
% function works with doubles, so if the input image is in a bit-scale
% (such as 8-bit or any unint), the input first should be turned to double.
% If the missing data in the image are, for example, 0, they can be turned
% to NaN before calling the function because the function is designed only
% to replace NaNs.
%
% Inputs: 
%   target: target cell-array (or matirx)
%   refarray: reference cell-array (or matirx)
%   fields2fill: index or indexes of fields where NaNs should be replaced;
%   it can be only single index or a set of indices.
%   varargin: one or more extra reference cell-array(s)/matrices.
% Outputs:
%   combined_data: same as target input cell-array/matrix with gaps for the
%   requested field(s) filled using corresponding field(s) in the reference
%   cell-arrays/matrices (refarray and extra references if available).
%   data: a cell-array where the input target and reference cell-arrays
%   or matrices are stored (can be used to compare data before and after  
%   filling the gaps).
% If the input target was cell-array, the output result (combined_data)
% will be also cell-array, if the target was a matrix, the result will be
% also a matrix. The second output will always be a cell-array of
% cell-array elements.
%
% Example:
% target=[3 4 NaN 4; 2.4 5 6.1 7; 10 11 1.1 NaN; 0.1 3 2 8];
% refarray=[4 2 30 4; 8 7 9 2; 4 5 12 24; 9 8 2 23];
% fields2fill=[3 4];
% [combined_data,data] = fillgaps(target,refarray,fields2fill)
% combined_data =
% 
%           3              4              30               4
%         2.4              5             6.1               7
%          10             11             1.1              24
%         0.1              3               2               8
% 
% data = 
%     {4x4 cell}    {4x4 cell}
% 
% Example for image input:
%
% im=imread('NZ.jpg'); %or any 3-band image
% b1=double(im(:,:,1)); %single out band 1 (red)
% b2=double(im(:,:,2)); %single out band 2 (green)
% b1=b1-min(b1(:)); b2=b2-min(b2(:)); %enhance contract by removing bg haze
% xidx=randi(400,12); %propogate random noise along lines
% yidx=randi(250,12); %propogate random noise along columns
% b1(xidx,yidx)=NaN;  %assign NaN to random points of b1
% % call func to fill NaNs of b1 using b2 as reference:
% [b_repaired,data] = fillgaps(b1,b2,1:300);
% % compare the results:
% subplot(1,2,1), imshow(b1,[min(b1(:)) max(b1(:))]);
% title('band1 with holes'), set(gca,'FontWeight','bold','FontSize',16);
% subplot(1,2,2), imshow(b_repaired,[min(b1(:)) max(b1(:))]); 
% title('band1 with holes filled');
% set(gca,'FontWeight','bold','FontSize',16);
%
% First version: 04 June 2012
% Updated: 09 June 2012 and 12 Jul 2012
% Email: sohrabinia.m@gmail.com
%--------------------------------------------------------------------------

%tic;
% target
% refarray
% fields2fill
if nargin <3
   %[status] = errors(3,'fill_gaps',3) 
   error(['Error! at least three inputs: target array/matrix, reference '...
       'array/matrix and vector of field indexes gaps of which needs to '...
       'be filled']);
end

data=cell(1,nargin-1);
data{1,1}=target;
data{1,2}=refarray;
for i=1:length(varargin)
   data{1,i+2}=varargin{i}; 
end

% check if all input cell have equal number of rows:
for i=1:nargin-1
    if size(target,1)~= size(data{1,i},1)
        [status] = errors(4,'fill gaps')
        return;
    end
end


% check if the inputs are not cell-array, transform them to cell-array:
typ=zeros(nargin-1,1);
for i=1:nargin-1
    tmp1=data{1,i};
    %t=whos('tmp1');
    if  ~iscell(tmp1)% strcmp(t.class,'cell')~=1
        typ(i)=1;        
        for i2=1:size(tmp1,1)
            for j=1:size(tmp1,2)
                tmp2{i2,j}=tmp1(i2,j);
            end
        end        
        data{1,i}=tmp2;
    end
end
target=data{1,1};

rows=size(target,1);

% Now loop whole rows of fields2fill fields, and check if there is non-NaN
% available for NaN records of fields2fill, do it for all rows, in case
% the input was cell and first row was Column-Headers, it still works, and
% will not cause a problem:
for i=1:rows %start from 1st row  
    for i2=1:length(fields2fill)
        % if isnan(target{i,fields2fill(i2)})==1
        for j=2:length(data) %1st data is the matrix/cell itself
            if isnan(target{i,fields2fill(i2)})
                if  ~isnan(data{1,j}{i,fields2fill(i2)})
                    target{i,fields2fill(i2)}=data{1,j}{i,fields2fill(i2)};
                end
            end
        end
        %end
    end
end

if typ(1)==1
    target=cell2mat(target(:,:));    
end
combined_data=target;
%t=toc
end %end of fillgaps function

Contact us