%kvlabel 'Perform Labeling on Multiband or Cluster Image (K1)'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros vlabel.pane file
%
% Parameters: 
% Integer: w 'Border Width ', default: 0: 'Specify the border width in pixels'
% MultiChoice: m 'Type of Distance Metric (Choose One): ', default: 1: 'Distance Metric: 1 = Euclidean distance, 2 = city block'
%    Choices are:
%   1: 'Euclidean '
%   2: 'City Block'
% MultiChoice: c 'Type of Connectivity (Choose One): ', default: 1: 'Connectivity: 1 = 4-connectivity, 2 = 8-connectivity'
%    Choices are:
%   1: '4 Connectivity'
%   2: '8 Connectivity'
% Double: s 'Minimum Region Size in % ', default: 1: 'Minimum number of pixel to keep in label region'
% OutputFile: o 'Output Labeled Image', required: 'output image after the labeling process'
% OutputFile: asc 'Output ASCII File', optional: 'Output ASCII file for vlabel result display'
% InputFile: i1 'Initial Image ', optional: 'input image'
% InputFile: i2 'Cluster Center Image', optional: 'input image for cluster centers'
% InputFile: i3 'Cluster Number Image', optional: 'input image for cluster numbers'
% Integer: n 'Approximate Number of Regions Expected ', default: 10: 'Number of region to get from labeling process'
% Double: f 'Split and Merge Factor', default: 0.07: 'Split & Merge Factor: higher values result in finer regions'
%
% Example: [o, asc] = kvlabel({i1, i2, i3}, {'w',0;'m',1;'c',1;'s',1;'o','';'asc','';'i1','';'i2','';'i3','';'n',10;'f',0.07})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% vlabel - Perform Labeling on Multiband or Cluster Image  (K1)
%
%  DESCRIPTION
% .I vlabel
% performs a labeling on a multiband image or a cluster image by
% attempting to merge connected pixels.
% 
% The principal of the algorithm is as follows: A pixel receives the same 
% label as its neighbor if the likelihood distance between the two pixels 
% is acceptable.  The label process is propagated for a given region number
% until it is no longer possible to find a candidate.
% 
% \fBThree different types of labeling choices exist":
% 
%  1
% .I First choice:
% uses a single or multi band image, where the data storage can be
% any of the following types: VFF_TYP_1_BYTE, VFF_TYP_2_BYTE, 
% VFF_TYP_4_BYTE, or VFF_TYP_FLOAT.
% The input image corresponds to the -i1 argument.
% The distance is computed using all the bands of the image.
% 
%  2.
% .I Second choice:
% uses a cluster number and cluster center
% image obtained from an algorithm like vkmeans or vquant.
% For this case, the cluster center represents the value of a
% class of pixels that have been grouped together.
% Therefore, the distance between two neighbors will be the
% distance between their clusters.
% This case will require less computation time because the algorithm
% will only compute the inter-class distance, instead of computing
% the distance of two neighbors for the entire image.
% An additional advantage with this choice, is that the output from
% algorithms such as vkmeans or vquant may be utilized, which may lead
% to better results.
% The cluster center image corresponds to -i2 argument
% The cluster number image corresponds to -i3 argument in the
% command line.
% 
%  3.
% .I The final possibility
% is to use a single or multiband input image 
% (argument -i1) associated with a cluster number image (argument -i3).
% The advantage of this choice is that the results of a clustering 
% algorithm are used to keep the neighbor pixels that have the same cluster 
% number in the same class, and to rely on the distance in the single or 
% multi band image to group two neighbors that do not belong to the same 
% cluster.
% 
% In summary, the three possible choices are:
% 
% 
% -i1 image.xv
% 
% 
% -i2 cluster_center.xv -i3 cluster_number.xv
% 
% 
% -i1 image.xv -i3 cluster_number.xv
% 
% .I The algorithm also requires
% the following parameters:
% \fBMetric distance:"
% There are 2 different metric distances that can be used.
% 
% 
% -d 1 uses  Euclidean distance: sqrt[(x-s)^2 + (y-t)^2].
% 
% 
% -d 2 uses  City Block distance: |x-s| + |y-t|.
% 
% \fBConnectivity:"
% There are two possible neighborhoods:
% 
% 
% -c 1  uses the 4 connectivity to link pixels together.
% 
% 
% -c 2  uses the 8 connectivity.
% 
% \fBMinimum size of a region:"
% 
% 
% -s  (float_value)  determines the number of pixels required for a region
% to be retained.
% The minimum number of pixels is equal to: 
% Total number of pixels in image * float_value / 100.0 (-s corresponds to 
% a percentage of the total number of pixels in the image).
% 
% \fBBorder Size:"
% Each pixel in the image is updated except those outside of the border.
% The size of the border is specified by the -w argument.
% 
% \fBMerging Process:"
% When the labeling process is computed, the user can expect that the small
% rejected region will be merged together in a bigger acceptable region or 
% will be included inside another connected region.
% This choice is selected by setting the logical argument -merge to TRUE.
% If -merge is set to FALSE, the small regions will be ignored and labeled as
% an UNDEFINED REGION (label number 0), the same as the border.
% 
% "The AUTOMATIC or MANUAL OPTION:\fP
% This option allows the user either to fix a threshold, or to give
% an approximate number of regions. 
% If the AUTOMATIC option is used, the algorithm will iterate on the threshold
% until the number of regions labeled by the process is comparable to the number
% of expected regions.
% In fact, if the expected number is not reached after 30 iterations, 
% the threshold that gives the closest number of regions is used for 
% the final labeling.
% 
% Although this option is easy to use, the function:
% 
% 
% number of regions = F(Threshold)  is not a monotonically increasing function, 
% and the convergence toward a solution may not exist.
% 
% 
% -n  int_value   (AUTOMATIC OPTION) determines the approximate final number of
% regions expected.
% -f  float_value (MANUAL OPTION) determines the threshold used by the labeling
% process.
% THESE TWO OPTIONS ARE MUTUALLY EXCLUSIVE
% The default threshold value is 0.07. This value generally gives good results
% on noiseless images with large uniform regions. 
% Decreasing this value will increase the number of regions found during the
% labeling process, but these regions will get smaller and could be rejected
% by the minimum size threshold.
% Increasing this value will decrease the number of regions found during the
% labeling process. At the same time, the number of small regions will decrease
% which means that this area of the curve, \fBnumber of regions = F(Threshold)",
% is more stable than the other one.
% Once the user becomes accustomed to this routine, good results are generally
% obtained.  One way to become familiar with the routine, is to use the
% automatic option and analyze the output ASCII file (Statistics on the 
% iteration process). This file contains the number of regions labeled for 
% each iteration, allowing the user to see how the number of regions changes 
% as the THRESHOLD is changed.
% 
% \fBOutput Files"
% 
%  1
% \fBOutput image:"
% The resulting image, which corresponds to the -o1 argument, contains the 
% labeled image in which every pixel has a region number as its value. This 
% image is of data storage type VFF_TYP_4_BYTE.
% The region label numbers are 1 to N.  The region number 0 is reserved
% as an UNDEFINED label or for the border.
% 
%  2
% \fBOutput Statistic ASCII File:"
% This file contains all the information relative to the labeling process.
% 
%
%  
%
%  EXAMPLES
% 
% vlabel -i1 image.xv -d 1 c 1 -merge 0 -f 0.07 -s 0.7 -w 2 -o image1.xv -asc stats
% This command will label image.xv using the Euclidean distance, the
% 4 connectivity, a split and merge factor equal to 0.07, a minimum
% size for the regions equal to 0.7 percent of the total number of pixels
% in image.xv, and a border size of 2. The merge option is not used which 
% means that the small regions will not be labeled. 
% The labeled image will be stored in image1.xv and the statistics will be
% written in the ASCII file, stats.
%
%  "SEE ALSO"
% lvkmeans(3), lvquant(3), vkmeans(1), vquant(1).
%
%  RESTRICTIONS 
% vlabel works only with cluster number and cluster center images conforming 
% to the convention established by the set of clustering algorithms.
%
%  REFERENCES 
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
% 


function varargout = kvlabel(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kvlabel(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'w', 0;'m', 1;'c', 1;'s', 1;'o', '__output';'asc', '__output';'i1', '__input';'i2', '__input';'i3', '__input';'n', 10;'f', 0.07};
maxval={16,0,0,100,0,1,1,1,1,2500,1};
minval={0,0,0,0,0,1,1,1,1,2,0};
istoggle=[1,0,0,1,0,1,1,1,1,1,1];
was_set=istoggle * 0;
paramtype={'Integer','MultiChoice','MultiChoice','Double','OutputFile','OutputFile','InputFile','InputFile','InputFile','Integer','Double'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs)) 
        error(['Input ' narglist{jj,1} ' has no corresponding input!']); 
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout) 
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']); 
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)  
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in') 
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = ''; 
        end;
        narglist{jj,2} = ''; 
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = ''; 
          narglist{jj,2} = ''; 
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs)) 
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']); 
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs)) 
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else 
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else 
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1) 
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']); 
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs) 
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else 
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'vlabel"  '],Inputs,narglist);
