## Copyright (C) 2004 Josep Mones i Teixidor ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## -*- texinfo -*- ## @deftypefn {Function File} {@var{S} = } qtdecomp (@var{I}) ## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold}) ## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{mindim}) ## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{[mindim maxdim]}) ## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun}) ## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun},@var{P1},@var{P2},...) ## Performs quadtree decomposition ## ## qtdecomp decomposes a square image @var{I} into four equal-sized ## blocks. Then it performs some kind of test on each block to decide if ## it should decompose them further. This process is repeated ## iteratively until there's no block left to be decomposed. ## ## Note that blocks are not decomposed if their dimensions are not even. ## ## The output is a sparse matrix whose non-zero elements determine the ## position of the block (the element is at top-left position in the ## block) and size of each block (the value of the element determines ## length of a side of the square-shaped block). ## ## S = qtdecomp(I) decomposes an intensity image @var{I} as described ## above. By default it doesn't split a block if all elements are equal. ## ## S = qtdecomp(I, threshold) decomposes an image as decribed, but only ## splits a block if the maximum value in the block minus the minimum ## value is greater than @var{threshold}, which is a value between 0 and ## 1. If @var{I} is of class uint8, @var{threshold} is multiplied by 255 ## before use. Also, if@var{I} is of class uint16, @var{threshold} is ## multiplied by 65535. ## ## S = qtdecomp(I, threshold, mindim) decomposes an image using the ## @var{threshold} as just described, but doesn't produce blocks smaller ## than mindim. ## ## S = qtdecomp(I, threshold, [mindim maxdim]) decomposes an image as ## described, but produces blocks that can't be bigger than maxdim. It ## decomposes to maxdim even if it isn't needed if only @var{threshold} ## was considered. ## ## S = qtdecomp(I, fun) decomposes an image @var{I} and uses function ## @var{fun} to decide if a block should be splitted or not. @var{fun} ## is called with a m-by-m-by-k array of m-by-m blocks to be ## considered, and should return a vector of size k, whose elements ## represent each block in the stacked array. @var{fun} sets the ## corresponding value to 1 if the block should be split, and 0 ## otherwise. ## ## S = qtdecomp(I, fun, ...) behaves as qtdecomp(I, fun) but passes ## extra parameters to @var{fun}. ## ## @end deftypefn ## @seealso qtgetblk, qtsetblk ## Author: Josep Mones i Teixidor function S = qtdecomp(I, p1, varargin) if (nargin<1) usage("S=qtdecomp(I)"); endif if (!ismatrix(I) || size(I,1)!=size(I,2)) error("qtdecomp: I should be a square matrix."); endif ## current size (assumed to be square) curr_size=size(I,1); ## initial mindim to a sensible value mindim=1; ## sensible default maxdim value maxdim=curr_size; if (nargin<2) ## Initialize decision method variable ## We could have implemented threshold as a function and use an ## uniform interface (function handle) to decide whether to split or ## not blocks. We have decided not to do so because block ## rearrangement that is needed as a parameter to functions is ## expensive. decision_method=0; elseif (isreal(p1)) ## p1 is threshold threshold=p1; decision_method=1; if(strcmp(typeinfo(I), 'uint8 matrix')) threshold*=255; elseif(strcmp(typeinfo(I), 'uint16 matrix')) threshold*=65535; endif if (nargin>3) usage("S=qtdecomp(I,threshold,mindim), \ S=qtdecomp(I,threshold,[mindim maxdim])"); elseif (nargin==3) dims=varargin{1}; if (isvector(dims)&&length(dims)==2) mindim=dims(1); maxdim=dims(2); elseif (isreal(dims)) mindim=dims; else error("qtdecomp: third parameter must be 'mindim' or '[mindim maxdim]'"); endif ## we won't check if mindim or maxdim are powers of 2. It's too ## restrictive and don't need it at all. endif elseif strcmp(typeinfo(p1),"function handle") ... || strcmp(typeinfo(p1),"inline function") ## function handles seem to return true to isscalar fun=p1; decision_method=2; else error("qtdecomp: second parameter must be a integer (threshold) or a function handle (fun)."); endif ## initialize results matrices res=[]; ## bool to flag end finished=false; ## array of offsets to blocks to evaluate offsets=[1,1]; if (maxdim0) divs=2^initial_splits; if (rem(curr_size,divs)!=0) error("qtdecomp: Can't decompose I enough times to fulfill maxdim requirement."); endif ## update curr_size curr_size/=divs; if(curr_size0) ## check other ending conditions: ## is size is odd? ## is splitted size < than mindim? if ((rem(curr_size,2)!=0)||((curr_size/2) varargin{:}. Now works on 2.1.58 % % Revision 1.5 2004/09/08 14:07:22 pkienzle % Fix test for 'inline function' % % Revision 1.4 2004/08/11 19:52:41 jmones % qtsetblk added % % Revision 1.3 2004/08/11 00:05:21 jmones % seealso qtgetblk added to doc % % Revision 1.2 2004/08/10 00:19:42 jmones % Corrected misleading comment. % % Revision 1.1 2004/08/09 01:48:54 jmones % Added qtdecomp: quadtree decomposition % %