function [c_0,c_1,c_2,c_3,c_4,c_5,c_6,c_7]=nnfilt(x,ParamFN,x_1,x_2,x_3,x_4,x_5,x_6,x_7,x_8,x_9,x_10,x_11,x_12,x_13,x_14,x_15,x_16,x_17,x_18,x_19,x_20,x_21,x_22,x_23,x_24,x_25,x_26,x_27,x_28,x_29,x_30)
% CP_COOC  Comparative texture measure study: Kalle Karus NN Filter
%	c=cp_nnfilt(x,ParamFN,x1,x2,x3,...,'ParamId',Value,'ParamId',Value,...)
%	Legal ParamId's are: 
%	- LearnRate	Learning rate (default 0.01)
%	- Momentum	Training momentum (default 0.5)
%	- NumLayers	Number of layers in NN (default 3)
%	- MaskSize	Filter mask size (default 11)
%	- Steps   	Number of training steps  (default 1e6)
%	- PruneSteps 	Number of node pruning steps (default 1)
%	- Nodes   	Number of nodes in layer 1 and 2 (default [20 20])
%	- RandSeed	Random number generator seed (default 9423)
%	
%	Example:
%	x_1=load_texture( 8,128,128);
%	x_2=load_texture(84,128,128);
%	c=nnfilt([x_1 x_2],[],x_1,x_2);
%	gimage(c,'colorbar','off'); 



LearnRate=0.01;
Momentum=0.5;
NumLayers=3;
Steps=1e6;
PruneSteps=1;
MaskSize=11;
Nodes=[20 20];
RandSeed=9423;

if isempty(ParamFN)
  ParamFN=tempnam;
  DoDeleteParamFile=1;
else
  DoDeleteParamFile=0;
end
TrainFN=tempnam;
TmpTrainFN=tempnam;
TmpFN=tempnam;
ImageFN=tempnam;
ClassFN=tempnam;

[M,N]=size(x);

% Construct a sequence of the training images
TrainImgNo=1;
IsFirstTrainImg=1;
while exist(sprintf('x_%d',TrainImgNo))
  param=eval(sprintf('x_%d',TrainImgNo));
  if isstr(param) % 			The parameter is an identifier
    arg=eval(sprintf('x_%d',TrainImgNo+1));
    TrainImgNo=TrainImgNo+1;
    if strcmp(lower(param),lower('LearnRate'))
      LearnRate = arg;
    elseif strcmp(lower(param),lower('Momentum'))
      Momentum = arg;
    elseif strcmp(lower(param),lower('NumLayers'))
      NumLayers = arg;
    elseif strcmp(lower(param),lower('MaskSize'))
      MaskSize = arg;
    elseif strcmp(lower(param),lower('Steps'))
      Steps = arg;
    elseif strcmp(lower(param),lower('PruneSteps'))
      PruneSteps = arg;
    elseif strcmp(lower(param),lower('RandSeed'))
      RandSeed = arg;
    elseif strcmp(lower(param),lower('Nodes'))
      Nodes = arg;
    end
  else % 				The parameter is a training image
    hipswrite(param,TmpFN);
    if IsFirstTrainImg
      IsFirstTrainImg=0;
      eval(sprintf('!mv %s %s',TmpFN,TmpTrainFN));
    else
      eval(sprintf('!catframes %s %s > %s',TrainFN,TmpFN,TmpTrainFN));
    end
    eval(sprintf('!mv %s %s',TmpTrainFN,TrainFN));
  end
  TrainImgNo=TrainImgNo+1;
end
eval(sprintf('!rm -f %s',TmpFN));

if exist([ParamFN '_0'])~=2
  fprintf(1,'Designing network => %s_*\n',ParamFN);
  % Train the network: nnprd
  eval(sprintf('%s %s',...
    sprintf('!nnprd -n %d -dn %d -l %d -m %d -s %d -r %d -p %s', ...
    LearnRate,Momentum,NumLayers,MaskSize,Steps,PruneSteps,ParamFN),...
    sprintf('-n1 %d -n2 %d -e %d < %s',...
    Nodes(1),Nodes(2),RandSeed,TrainFN)));
end

% Save the image as a file and classify: forwpr
fprintf(1,'Using network in %s_*\n',ParamFN);
hipswrite(x,ImageFN);
for OutputNo=0:nargout-1
  eval(sprintf('!forwpr -p %s_%d < %s > %s',ParamFN,OutputNo,ImageFN,ClassFN));
  c=hipsread(ClassFN);
  % Fix borders
  [M_c,N_c]=size(c);
  c=c(1:M_c-MaskSize+1,1:N_c-MaskSize+1);
  c=symmext(c,(MaskSize-1)/2,(MaskSize-1)/2,(MaskSize-1)/2,(MaskSize-1)/2);
  eval(sprintf('c_%d=c;',OutputNo));
end

% Clean
eval(sprintf('!rm -f %s %s %s %s %s',...
  TrainFN,TmpTrainFN,TmpFN,ImageFN,ClassFN));
if DoDeleteParamFile
  eval(sprintf('!rm -f %s_*',ParamFN));
end  
