qtdecomp.m

来自「有关matlab的电子书籍有一定的帮助希望有用」· M 代码 · 共 221 行

M
221
字号
function S = qtdecomp(varargin)
%QTDECOMP Perform quadtree decomposition.
%   QTDECOMP divides a square image into four equal-sized square
%   blocks, and then tests each block to see if meets some
%   criterion of homogeneity. If a block meets the criterion, it
%   is not divided any further. If it does not meet the
%   criterion, it is subdivided again into four blocks, and the
%   test criterion is applied to those blocks. This process is
%   repeated iteratively until each block meets the
%   criterion. The result may have blocks of several different
%   sizes.
%
%   S = QTDECOMP(I) performs a quadtree decomposition on the
%   intensity image I, and returns the quadtree structure in the
%   sparse matrix S. If S(k,m) is nonzero, then (k,m) is the
%   upper-left corder of a block in the decomposition, and the
%   size of the block is given by S(k,m). By default, QTDECOMP
%   splits a block unless all elements in the block are equal.
%
%   S = QTDECOMP(I,THRESHOLD) splits a block if the maximum value
%   of the block elements minus the minimum value of the block
%   elements is greater than THRESHOLD. THRESHOLD is specified as
%   a value between 0 and 1, even if I is of class uint8. If I is
%   uint8, the threshold value you supply is multiplied by 255 to
%   determine the actual threshold to use.
%
%   S = QTDECOMP(I,THRESHOLD,MINDIM) will not produce blocks
%   smaller than MINDIM, even if the resulting blocks do not meet
%   the threshold condition.
%
%   S = QTDECOMP(I,THRESHOLD,[MINDIM MAXDIM]) will not produce
%   blocks smaller than MINDIM or larger than MAXDIM. Blocks
%   larger than MAXDIM are split even if they meet the threshold
%   condition. MAXDIM/MINDIM must be a power of 2.
%
%   S = QTDECOMP(I,FUN) uses the function FUN to determine
%   whether to split a block. QTDECOMP calls FUN with all the
%   current blocks of size M-by-M stacked into M-by-M-by-K array,
%   where K is the number of M-by-M blocks. FUN should return a
%   K-element vector whose values are 1 if the corresponding
%   block should be split, and 0 otherwise. FUN can be a string
%   containing the name of a function, a string containing an
%   expression, or an inline function.
%
%   S = QTDECOMP(I,FUN,P1,P2,...) passes P1,P2,..., as additional
%   arguments to FUN.
%
%   Class Support
%   -------------
%   For the syntaxes that do not include a function, the input
%   image can be of class uint8 or double. For the syntaxes that
%   include a function, the input image can be of any class
%   supported by the function. The output matrix is always of
%   class sparse.
%
%   Example
%   -------
%       I = [1    1    1    1    2    3    6    6
%            1    1    2    1    4    5    6    8
%            1    1    1    1   10   15    7    7
%            1    1    1    1   20   25    7    7
%           20   22   20   22    1    2    3    4
%           20   22   22   20    5    6    7    8
%           20   22   20   20    9   10   11   12
%           22   22   20   20   13   14   15   16];
%       S = qtdecomp(I,5);
%       full(S)
%
%   See also QTSETBLK, QTGETBLK.

%   Steven L. Eddins, March 1995
%   Copyright 1993-1998 The MathWorks, Inc.  All Rights Reserved.
%   $Revision: 1.11 $  $Date: 1997/11/24 15:36:08 $

[A, func, params, minDim, maxDim, msg] = ParseInputs(varargin{:});
if (~isempty(msg))
    error(msg);
end

[M,N] = size(A);
S = zeros(M,N);

% Initialize blocks
S(1:maxDim:M, 1:maxDim:N) = maxDim;

dim = maxDim;
while (dim > minDim)
    % Find all the blocks at the current size.
    [blockValues, Sind] = qtgetblk(A, S, dim);
    if (isempty(Sind))
        % Done!
        break;
    end
    doSplit = feval(func, blockValues, params{:});
    
    % Record results in output matrix.
    dim = dim/2;
    Sind = Sind(doSplit);
    Sind = [Sind ; Sind+dim ; (Sind+M*dim) ; (Sind+(M+1)*dim)];
    S(Sind) = dim;
end

S = sparse(S);

%%%
%%% Subfunction QTDECOMP_Split - the default split tester
%%%
function dosplit = QTDECOMP_Split(A, threshold, dims)

maxVals = max(max(A,[],1),[],2);
minVals = min(min(A,[],1),[],2);
dosplit = (double(maxVals) - double(minVals)) > threshold;

dosplit = (dosplit & (size(A,1) > dims(1))) | (size(A,2) > dims(2));

%%%
%%% Subfunction ParseInputs
%%%
function [A, func, params, minDim, maxDim, msg] = ParseInputs(varargin)

A = [];
func = '';
params = {};
msg = '';

if (nargin == 0)
    msg = 'Too few input arguments';
    return;
end

A = varargin{1};
if (ndims(A) > 2)
    msg = 'A must be two-dimensional';
    return;
end
minDim = 1;
maxDim = min(size(A));

if (nargin == 1)
    % qtdecomp(A)

    func = 'QTDECOMP_Split';
    threshold = 0;
    minDim = 1;
    maxDim = min(size(A));
    params = {threshold [minDim maxDim]};
    
else
    if (ischar(varargin{2}) | isa(varargin{2},'inline'))
        % qtdecomp(A,fun,...)

        params = varargin(3:end);
        func = fcnchk(varargin{2}, length(params));
        
    else
        if (nargin == 2)
            % qtdecomp(A,threshold)
            
            func = 'QTDECOMP_Split';
            threshold = varargin{2};
            minDim = 1;
            maxDim = min(size(A));
            params = {threshold [minDim maxDim]};
            
        elseif (nargin == 3) 
            if (length(varargin{3}) == 1)
                % qtdecomp(A,threshold,mindim)
            
                func = 'QTDECOMP_Split';
                threshold = varargin{2};
                minDim = varargin{3};
                maxDim = min(size(A));
                params = {threshold [minDim maxDim]};
                
            else
                % qtdecomp(A,threshold,[mindim maxdim])
                
                func = 'QTDECOMP_Split';
                threshold = varargin{2};
                minDim = min(varargin{3});
                maxDim = max(varargin{3});
                params = {threshold [minDim maxDim]};
            end
            
        else
            msg = 'Too many input arguments';
            return;
        end
    end
end

if (isequal(func, 'QTDECOMP_Split'))
    % Do some error checking on the parameters
    
    if (threshold < 0)
        msg = 'THRESHOLD must be nonnegative';
        return;
    end
    
    if (any(fix(size(A)./minDim) ~= (size(A)./minDim)))
        msg = 'Size of A is not a multiple of the minimum block dimension';
        return;
    end
    
    if (any(fix(size(A)./maxDim) ~= (size(A)./maxDim)))
        msg = 'Size of A is not a multiple of the maximum block dimension';
        return;
    end
    
    [f, numLevels] = log2(maxDim / minDim);
    if (f ~= 0.5)
        msg = 'MAXDIM / MINDIM is not a power of 2';
        return;
    end
    
    % If the input is uint8, scale the threshold parameter.
    if (isa(A, 'uint8'))
        params{1} = round(255 * params{1});
    end

end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?