]> Creatis software - CreaPhase.git/blob - octave_packages/image-1.0.15/blkproc.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / image-1.0.15 / blkproc.m
1 ## Copyright (C) 2004 Josep Mones i Teixidor
2 ##
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published by
5 ## the Free Software Foundation; either version 2 of the License, or
6 ## (at your option) any later version.
7 ##
8 ## This program is distributed in the hope that it will be useful,
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 ## GNU General Public License for more details.
12 ##
13 ## You should have received a copy of the GNU General Public License
14 ## along with this program; If not, see <http://www.gnu.org/licenses/>.
15
16 ## -*- texinfo -*-
17 ## @deftypefn {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun})
18 ## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun}, ...)
19 ## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], [@var{mborder},@var{nborder}], @var{fun}, @var{...})
20 ## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, 'indexed', ...)
21 ## Processes image in blocks using user-supplied function.
22 ##
23 ## @code{B=blkproc(A,[m,n],fun)} divides image @var{A} in
24 ## @var{m}-by-@var{n} blocks, and passes them to user-supplied function
25 ## @var{fun}, which result is concatenated to build returning matrix
26 ## @var{B}. If padding is needed to build @var{m}-by-@var{n}, it is added
27 ## at the bottom and right borders of the image.  0 is used as a padding
28 ## value.
29 ##
30 ## @code{B=blkproc(A,[m,n],fun,...)} behaves as described above but
31 ## passes extra parameters to function @var{fun}.
32 ##
33 ## @code{B=blkproc(A,[m,n],[mborder,nborder],fun,...)} behaves as
34 ## described but uses blocks which overlap with neighbour blocks.
35 ## Overlapping dimensions are @var{mborder} vertically and @var{nborder}
36 ## horizontally. This doesn't change the number of blocks in an image
37 ## (which depends only on size(@var{A}) and [@var{m},@var{n}]). Adding a
38 ## border requires extra padding on all edges of the image. 0 is used as
39 ## a padding value.
40 ##
41 ## @code{B=blkproc(A,'indexed',...)} assumes that @var{A} is an indexed
42 ## image, so it pads the image using proper value: 0 for uint8 and
43 ## uint16 images and 1 for double images. Keep in mind that if 'indexed'
44 ## is not specified padding is always done using 0.
45 ##
46 ## @seealso{colfilt,inline,bestblk}
47 ## @end deftypefn
48
49 ## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
50
51 function B = blkproc(A, varargin)
52   if(nargin<3)
53     error("blkproc: invalid number of parameters.");
54   endif
55   
56   ## check 'indexed' presence
57   indexed=false;
58   p=1;
59   if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
60     indexed=true;
61     p+=1;
62     if(isa(A,"uint8") || isa(A,"uint16"))
63         padval=0;
64     else
65       padval=1; 
66     endif
67   else
68     padval=0;
69   endif
70
71   ## check [m,n]
72   if(!isvector(varargin{p}))
73     error("blkproc: expected [m,n] but param is not a vector.");
74   endif
75   if(length(varargin{p})!=2)
76     error("blkproc: expected [m,n] but param has wrong length.");
77   endif
78   sblk=varargin{p}(:);
79   p+=1;
80
81   ## check [mborder,nborder]
82   if(nargin<p)
83     error("blkproc: required parameters haven't been supplied.");
84   endif
85
86   if(isvector(varargin{p}) && isnumeric(varargin{p})) 
87     if(length(varargin{p})!=2)
88       error("blkproc: expected [mborder,nborder] but param has wrong length.");
89     endif
90     sborder=varargin{p}(:);
91     p+=1;
92   else
93     sborder=[0;0];
94   endif
95
96   ## check fun
97   ## TODO: add proper checks for this one
98   if(nargin<p)
99     error("blkproc: required parameters haven't been supplied.");
100   endif
101
102   fun=varargin{p};
103   if(!isa(fun,"function_handle") &&
104      !isa(fun,"inline function") &&
105      !ischar(fun))
106     error("blkproc: invalid fun parameter.");
107   endif
108   
109   ## remaining params are params to fun
110   ## extra params are p+1:nargin-1
111
112   ## First of all we calc needed padding which will be applied on bottom
113   ## and right borders
114   ## The "-" makes the function output needed elements to fill another
115   ## block directly
116   sp=mod(-size(A)',sblk);
117
118   if(any(sp))
119     A=padarray(A,sp,padval,'post');
120   endif
121
122   ## we store A size without border padding to iterate later
123   soa=size(A);
124   
125   ## If we have borders then we need more padding
126   if(any(sborder))
127     A=padarray(A,sborder,padval);
128   endif
129
130   ## calculate end of block
131   eblk=sblk+sborder*2-1;
132
133   ## now we can process by blocks
134   ## we try to preserve fun return type by concatenating everything
135   for i=1:sblk(1):soa(1)
136     ## This assures r has the same class as returned by fun
137     r=feval(fun,A(i:i+eblk(1),1:1+eblk(2)),varargin{p+1:nargin-1});
138     for j=1+sblk(2):sblk(2):soa(2)
139       r=horzcat(r,feval(fun,A(i:i+eblk(1),j:j+eblk(2)),varargin{p+1:nargin-1}));
140     endfor
141     if(i==1) ## this assures B has the same class as A
142       B=r;
143     else
144       B=vertcat(B,r);
145     endif
146   endfor
147 endfunction
148
149 %!demo
150 %! blkproc(eye(6),[2,2],inline("any(x(:))","x"))
151 %! # Returns a 3-by-3 diagonal
152
153
154 %!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],@sum));
155 %!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],inline("sum(x)","x")));
156 %!assert(blkproc(eye(6),[1,2],@sum),kron(eye(3),[1;1]));
157 %!assert(blkproc(eye(6),[2,2],inline("any(x(:))","x")),eye(3)!=0);
158 %!assert(blkproc(eye(6),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
159 %!assert(blkproc(eye(6),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[8,5,6;6,2,3;5,3,4;4,3,5;3,2,6;6,5,8]);
160 %!assert(blkproc(eye(6),[2,3],[4,3],inline("sum(x(:))","x")),ones(3,2)*6);
161
162 % Some int* and uint* tests
163 %!assert(blkproc(eye(6),[2,2],inline("int8(sum(x(:)))","x")),eye(3,"int8")*2);
164
165 % Padding is 0 even for indexed
166 %!assert(blkproc(uint8(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
167 %!assert(blkproc(uint8(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
168 %!assert(blkproc(uint16(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
169 %!assert(blkproc(uint16(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
170
171
172 %
173 % $Log$
174 % Revision 1.5  2007/03/23 16:14:36  adb014
175 % Update the FSF address
176 %
177 % Revision 1.4  2007/01/04 23:44:22  hauberg
178 % Minor changes in help text
179 %
180 % Revision 1.3  2007/01/04 23:37:54  hauberg
181 % Minor changes in help text
182 %
183 % Revision 1.2  2006/10/08 21:41:04  adb014
184 % check isnumeric for vector and 'function_handle' not 'function handle' in isa test
185 %
186 % Revision 1.1  2006/08/20 12:59:31  hauberg
187 % Changed the structure to match the package system
188 %
189 % Revision 1.5  2005/09/08 02:00:17  pkienzle
190 % [for Bill Denney] isstr -> ischar
191 %
192 % Revision 1.4  2004/11/15 16:04:20  pkienzle
193 % Fix tests for functions which return boolean matrices
194 %
195 % Revision 1.3  2004/09/03 17:49:37  jmones
196 % Improved uint8 and uint16 padding expections
197 %
198 % Revision 1.2  2004/09/03 13:40:13  jmones
199 % Check result has same class as function result, and improved fun param checking
200 %
201 % Revision 1.1  2004/08/15 19:27:46  jmones
202 % blkproc: block process an image using user-supplied function
203 %
204 %