1 ## Copyright (C) 2004 Josep Mones i Teixidor
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.
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.
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/>.
17 ## @deftypefn {Function File} {@var{B} = } im2col (@var{A}, [@var{m},@var{n}], @var{block_type})
18 ## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, [@var{m},@var{n}])
19 ## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, 'indexed', ...)
20 ## Rearranges image blocks into columns.
22 ## @code{B=im2col(A, [m, n], blocktype)} rearranges blocks in @var{A}
23 ## into columns in a way that's determined by @var{block_type}, which
24 ## can take the following values:
28 ## Rearranges each distinct @var{m}-by-@var{n} block in image @var{A}
29 ## into a column of @var{B}. Blocks are scanned from left to right and
30 ## the up to bottom in @var{A}, and columns are added to @var{B} from
31 ## left to right. If @var{A}'s size is not multiple @var{m}-by-@var{n}
34 ## Rearranges any @var{m}-by-@var{n} sliding block of @var{A} in a
35 ## column of @var{B}, without any padding, so only sliding blocks which
36 ## can be built using a full @var{m}-by-@var{n} neighbourhood are taken.
37 ## In consequence, @var{B} has @var{m}*@var{n} rows and
38 ## (@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) columns (where @var{mm} and
39 ## @var{nn} are the size of @var{A}).
41 ## This case is thought to be used applying operations on columns of
42 ## @var{B} (for instance using sum(:)), so that result is a
43 ## 1-by-(@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) vector, that is what
44 ## the complementary function @code{col2im} expects.
47 ## @code{B=im2col(A,[m,n])} takes @code{distinct} as a default value for
50 ## @code{B=im2col(A,'indexed',...)} will treat @var{A} as an indexed
51 ## image, so it will pad using 1 if @var{A} is double. All other cases
52 ## (incluing indexed matrices with uint8 and uint16 types and
53 ## non-indexed images) will use 0 as padding value.
55 ## Any padding needed in 'distinct' processing will be added at right
56 ## and bottom edges of the image.
61 ## Author: Josep Mones i Teixidor <jmones@puntbarra.com>
63 function B = im2col(A, varargin)
64 if(nargin<2 || nargin>4)
65 usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
68 ## check 'indexed' presence
71 if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
73 usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
77 if(isa(A,"uint8") || isa(A,"uint16"))
87 if(!isvector(varargin{p}))
88 error("im2col: expected [m,n] but param is not a vector.");
90 if(length(varargin{p})!=2)
91 error("im2col: expected [m,n] but param has wrong length.");
99 ## we have block_type param
100 if(!ischar(varargin{p}))
101 error("im2col: invalid parameter block_type.");
103 block_type=varargin{p};
107 ## if we didn't have 'indexed' but had 4 parameters there's an error
109 usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
115 error("im2col: A should be a matrix (or vector).");
120 ## calc needed padding
121 sp=mod(-size(A)',[m;n]);
124 A=padarray(A,sp,padval,'post');
127 ## iterate through all blocks
129 for i=1:m:size(A,1) ## up to bottom
130 for j=1:n:size(A,2) ## left to right
131 ## TODO: check if we can horzcat([],uint8([10;11])) in a
132 ## future Octave version > 2.1.58
134 B=A(i:i+m-1,j:j+n-1)(:);
136 B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
143 disp("WARNING: 'indexed' has no sense when using sliding.");
145 if(m>size(A,1) || n>size(A,2))
146 error("im2col: block size can't be greater than image size in sliding");
148 ## TODO: check if matlab uses top-down and left-right order
150 for j=1:1:size(A,2)-n+1 ## left to right
151 for i=1:1:size(A,1)-m+1 ## up to bottom
152 ## TODO: check if we can horzcat([],uint8([10;11])) in a
153 ## future Octave version > 2.1.58
155 B=A(i:i+m-1,j:j+n-1)(:);
157 B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
163 error("im2col: invalid block_type.");
169 %! A=[1:10;11:20;21:30;31:40]
170 %! B=im2col(A,[2,5],'distinct')
171 %! C=col2im(B,[2,5],[4,10],'distinct')
172 %! # Divide A using distinct blocks and reverse operation
174 %!shared B, A, Bs, As, Ap, Bp0, Bp1
177 %! B=[v, v+10, v+20, v+30, v+40, v+50];
178 %! A=[r, r+10; r+20, r+30; r+40, r+50];
179 %! As=[1,2,3,4,5;6,7,8,9,10;11,12,13,14,15];
180 %! b1=As(1:2,1:4)(:);
181 %! b2=As(2:3,1:4)(:);
182 %! b3=As(1:2,2:5)(:);
183 %! b4=As(2:3,2:5)(:);
187 %! Bp0([9:10],[2,4,6])=0;
188 %! Bp1([9:10],[2,4,6])=1;
191 %!error(im2col(A,[2,5],'wrong_block_type'));
194 %!assert(im2col(A,[2,5],'distinct'), B);
197 %!assert(im2col(Ap,[2,5],'distinct'), Bp0);
198 %!assert(im2col(Ap,'indexed',[2,5],'distinct'), Bp1);
201 %!assert(im2col(As,[2,4]), Bs);
202 %!assert(im2col(As,[2,4],'sliding'), Bs);
203 %!assert(im2col(As,[3,5],'sliding'), As(:));
205 %!# disctint uint8 & uint16
206 %!assert(im2col(uint8(A),[2,5],'distinct'), uint8(B));
207 %!assert(im2col(uint16(A),[2,5],'distinct'), uint16(B));
209 %!# padding uint8 & uint16 (to 0 even in indexed case)
210 %!assert(im2col(uint8(Ap),[2,5],'distinct'), uint8(Bp0));
211 %!assert(im2col(uint8(Ap),'indexed',[2,5],'distinct'), uint8(Bp0));
212 %!assert(im2col(uint16(Ap),[2,5],'distinct'), uint16(Bp0));
213 %!assert(im2col(uint16(Ap),'indexed',[2,5],'distinct'), uint16(Bp0));
215 %!# now sliding uint8 & uint16
216 %!assert(im2col(uint8(As),[2,4],'sliding'), uint8(Bs));
217 %!assert(im2col(uint16(As),[2,4],'sliding'), uint16(Bs));
224 % Revision 1.4 2007/03/23 16:14:36 adb014
225 % Update the FSF address
227 % Revision 1.3 2007/01/04 23:47:43 hauberg
228 % Put seealso before end deftypefn
230 % Revision 1.2 2007/01/04 23:37:54 hauberg
231 % Minor changes in help text
233 % Revision 1.1 2006/08/20 12:59:33 hauberg
234 % Changed the structure to match the package system
236 % Revision 1.3 2005/09/08 02:00:17 pkienzle
237 % [for Bill Denney] isstr -> ischar
239 % Revision 1.2 2004/09/03 17:37:08 jmones
240 % Added support for int* and uint* types
242 % Revision 1.1 2004/08/18 14:39:07 jmones
243 % im2col and col2im added