matlab boundaries和fchcode函数无法执行的解决办法 未定义与 'double' 类型的输入参数相对应的函数 'boundaries'

在测试代码时发现,自己的matlab无法执行Freeman链码函数:

boundaries和fchcode函数都无法正常运行:

需要在自己的工作目录中添加如下函数:

boundaries   fchcode     minmag     codediff

代码如下:


function B=boundaries(BW,conn,dir) 

%BOUNDARIES Trace object boundaries.

%B=BOUNDARIES(BW) traces the exterior boundaries of objects in the binary

%image BW.B is a p_by_1 cell array,where p is the number of objects in the

%image.Each cell contains a Q_by_2 matrix,each row of which contains the

%row and column coordinates of a boundary pixel.Q is the number of boundary

%pixels for the corresponding object.Object boundaries are traced in the

%clockwise direction.

%

%B=BOUNDARIES(BW,CONN) specifies the connectivity to use when tracing 

%boundaries.CONN may be either 8 or 4.The default value for CONN is 8.

%

%B=BOUNDARIES(BW,CONN,DIR) specifies the direction used for tracing 

%boundaries.DIR should be either 'cw'(trace boundaries clockwise) or 

%'ccw'(trace boundaries counterclockwise).If DIR is omitted BOUNDARIES

%traces in the clockwise direction.

if nargin<3  %nargin定义在用户自定义函数体内,nargin返回

              %用来调用函数的变量的个数。

    dir='cw';

end

if nargin<2

    conn=8;

end

L=bwlabel(BW,conn); %返回值是矩阵L,大小同BW,包含了BW中的连通部分的标记

%The number of objects is the maximum value of L.Initialize the cell

%array(元包数组)B so that each cell initially contains a 0_by_2 matrix.

numObjects=max(L(:));%寻找L中所作标记中的最大值,这个最大值实际上就对应着L中

% 包含的最多的连通部分的数目。

if numObjects>0

    B={zeros(0,2)};%元包数组中仅包含一个元素。

    B=repmat(B,numObjects,1);%将B进行numObjects*1个复制构成新的B。

else

    B={};

end

%Pad label matrix with zeros.This lets us write the boundary_following loop

%without worrying about going off the edge of the image.

Lp=padarray(L,[1 1],0,'both');

%Compute the linear indexing offsets to take us from a pixel to its

%neighbors.

M=size(Lp,1);%SIZE(X,1) returns the number of rows. 

if conn==8

    %Order is N NE E SE S SW W NW.

    offsets=[-1,M-1,M,M+1,1,-M+1,-M,-M-1];

else

    %Order is N E S W.

    offsets=[-1,M,1,-M];

end

%next_search_direction_lut is a lookup table.Given the direction from pixel

%k to pixel k+1,what is the direction to start with when examining the

%neighborhood of pixel k+1?

if conn==8

    next_search_direction_lut=[8 8 2 2 4 4 6 6];

else

    next_search_direction_lut=[4 1 2 3];

end

%next_direction_lut is a lookup table.Given that we just looked at neighbor

%in a given direction,which neighbor do we look at next?

if conn==8

  next_direction_lut=[2 3 4 5 6 7 8 1];

else

  next_direction_lut=[2 3 4 1];

end

%Values used for marking the starting and boundary pixels.

START=-1;

BOUNDARY=-2;

%Initialize scratch space in which to record the boundary pixels as well as

%follow the boundary.

scratch=zeros(100,1);

%Find candidate starting locations for boundaries.

[rr,cc]=find((Lp(2:end-1,:)>0)&(Lp(1:end-2,:)==0));

rr=rr+1;

for k=1:length(rr)

    r=rr(k);

    c=cc(k);

    if (Lp(r,c)>0)&(Lp(r-1,c)==0)&isempty(B{Lp(r,c)})

        %We've found the start of the next boundary.Compute its linear

        %offset,record which boundary it is,mark it,and initialize the

        %counter for the number of boundary pixels.

        idx=(c-1)*size(Lp,1)+r;

        which=Lp(idx);

        scratch(1)=idx;

        Lp(idx)=START;

        numpixels=1;

        currentpixel=idx;

        initial_departure_direction=[];

        done=0;

        next_search_direction=2;

        while ~done

            %Find the next boundary pixel.

            direction=next_search_direction;

            found_next_pixel=0;

            for k=1:length(offsets)

                neighbor=currentpixel+offsets(direction);

                if Lp(neighbor)~=0

                    %Found the next boundary pixel.

                    if (Lp(currentpixel)==START)&...

                        isempty(initial_departure_direction)

                    %We are making the initial departure from the starting

                    %pixel.

                    initial_departure_direction=direction;

                    elseif (Lp(currentpixel)==START)&...

                            (initial_departure_direction==direction)

                      % We are about to retrace our path.

                      %That means we're done.

                      done=1;

                      found_next_pixel=1;

                      break;

                    end

                    %Take the next step along the boundary.

                    next_search_direction=...

                        next_search_direction_lut(direction);

                    found_next_pixel=1;

                    numpixels=numpixels+1;

                    if numpixels>size(scratch,1)

                        %Double the scratch space.

                        scratch(2*size(scratch,1))=0;

                    end

                    scratch(numpixels)=neighbor;

                    if Lp(neighbor)~=START

                      Lp(neighbor)=BOUNDARY;

                    end

                    currentpixel=neighbor;

                    break;

                end

                direction=next_direction_lut(direction);

            end

            if ~found_next_pixel

                %If there is no next neighbor,the object must just have a

                %single pixel.

                numpixels=2;

                scratch(2)=scratch(1);

                done=1;

            end

        end

        %Convert linear indices to row_column coordinates and save in the

        %output cell array.

        [row,col]=ind2sub(size(Lp),scratch(1:numpixels));

        B{which}=[row-1,col-1];

    end

end

if strcmp(dir,'ccw')

    for k=1:length(B)

        B{k}=B{k}(end:-1:1,:);

    end

end



function c = fchcode(b, conn, dir)

%FCHCODE Computes the Freeman chain code of a boundary.

%  C = FCHCODE(B) computes the 8-connected Freeman chain code of a

%  set of 2-D coordinate pairs contained in B, an np-by-2 array. C

%  is a structure with the following fields:

%

%    c.fcc    = Freeman chain code (1-by-np)

%    c.diff  = First difference of code c.fcc (1-by-np)

%    c.mm    = Integer of minimum magnitude from c.fcc (1-by-np)

%    c.diffmm = First difference of code c.mm (1-by-np)

%    c.x0y0  = Coordinates where the code starts (1-by-2)

%

%  C = FCHCODE(B, CONN) produces the same outputs as above, but

%  with the code connectivity specified in CONN. CONN can be 8 for

%  an 8-connected chain code, or CONN can be 4 for a 4-connected

%  chain code. Specifying CONN=4 is valid only if the input

%  sequence, B, contains transitions with values 0, 2, 4, and 6,

%  exclusively.

%     

%  C = FHCODE(B, CONN, DIR) produces the same outputs as above, but,

%  in addition, the desired code direction is specified. Values for

%  DIR can be:

%

%    'same'      Same as the order of the sequence of points in b.

%                This is the default.

%

%    'reverse'  Outputs the code in the direction opposite to the

%                direction of the points in B.  The starting point

%                for each DIR is the same.

%

%  The elements of B are assumed to correspond to a 1-pixel-thick,

%  fully-connected, closed boundary. B cannot contain duplicate

%  coordinate pairs, except in the first and last positions, which

%  is a common feature of boundary tracing programs.

%  FREEMAN CHAIN CODE REPRESENTATION

%  The table on the left shows the 8-connected Freeman chain codes

%  corresponding to allowed deltax, deltay pairs. An 8-chain is

%  converted to a 4-chain if (1) if conn = 4; and (2) only

%  transitions 0, 2, 4, and 6 occur in the 8-code.  Note that

%  dividing 0, 2, 4, and 6 by 2 produce the 4-code.

%

%      -----------------------  ----------------

%      deltax | deltay | 8-code  corresp 4-code

%      -----------------------  ----------------

%        0        1      0            0

%        -1        1      1

%        -1        0      2            1

%        -1      -1      3

%        0      -1      4            2

%        1      -1      5

%        1        0      6            3

%        1        1      7

%      -----------------------  ----------------

%

%  The formula z = 4*(deltax + 2) + (deltay + 2) gives the following

%  sequence corresponding to rows 1-8 in the preceding table: z =

%  11,7,6,5,9,13,14,15. These values can be used as indices into the

%  table, improving the speed of computing the chain code. The

%  preceding formula is not unique, but it is based on the smallest

%  integers (4 and 2) that are powers of 2.

%  Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins

%  Digital Image Processing Using MATLAB, Prentice-Hall, 2004

%  $Revision: 1.6 $  $Date: 2003/11/21 14:34:49 $

% Preliminaries.

if nargin == 1

  dir = 'same';

  conn = 8;

elseif nargin == 2

  dir = 'same';

elseif nargin == 3 

  % Nothing to do here.

else

  error('Incorrect number of inputs.')

end

[np, nc] = size(b);

if np < nc

  error('B must be of size np-by-2.');

end

% Some boundary tracing programs, such as boundaries.m, output a

% sequence in which the coordinates of the first and last points are

% the same. If this is the case, eliminate the last point.

if isequal(b(1, :), b(np, :))

  np = np - 1;

  b = b(1:np, :);

end

% Build the code table using the single indices from the formula

% for z given above:

C(11)=0; C(7)=1; C(6)=2; C(5)=3; C(9)=4;

C(13)=5; C(14)=6; C(15)=7;

% End of Preliminaries.

% Begin processing.

x0 = b(1, 1);

y0 = b(1, 2);

c.x0y0 = [x0, y0];

% Make sure the coordinates are organized sequentially:

% Get the deltax and deltay between successive points in b. The

% last row of a is the first row of b.

a = circshift(b, [-1, 0]);

% DEL = a - b is an nr-by-2 matrix in which the rows contain the

% deltax and deltay between successive points in b. The two

% components in the kth row of matrix DEL are deltax and deltay

% between point (xk, yk) and (xk+1, yk+1).  The last row of DEL

% contains the deltax and deltay between (xnr, ynr) and (x1, y1),

% (i.e., between the last and first points in b).

DEL = a - b;

% If the abs value of either (or both) components of a pair

% (deltax, deltay) is greater than 1, then by definition the curve

% is broken (or the points are out of order), and the program

% terminates.

if any(abs(DEL(:, 1)) > 1) | any(abs(DEL(:, 2)) > 1);

  error('The input curve is broken or points are out of order.')

end

% Create a single index vector using the formula described above.

z = 4*(DEL(:, 1) + 2) + (DEL(:, 2) + 2);

% Use the index to map into the table. The following are

% the Freeman 8-chain codes, organized in a 1-by-np array.

fcc = C(z);

% Check if direction of code sequence needs to be reversed.

if strcmp(dir, 'reverse')

  fcc = coderev(fcc); % See below for function coderev.

end

% If 4-connectivity is specified, check that all components

% of fcc are 0, 2, 4, or 6.

if conn == 4

  val = find(fcc == 1 | fcc == 3 | fcc == 5 | fcc ==7 );

  if isempty(val)

      fcc = fcc./2;

  else

      warning('The specified 4-connected code cannot be satisfied.')

  end

end

% Freeman chain code for structure output.

c.fcc = fcc;

% Obtain the first difference of fcc.

c.diff = codediff(fcc,conn); % See below for function codediff.

% Obtain code of the integer of minimum magnitude.

c.mm = minmag(fcc); % See below for function minmag.

% Obtain the first difference of fcc

c.diffmm = codediff(c.mm, conn);



function z = minmag(c)

%MINMAG Finds the integer of minimum magnitude in a chain code.

%  Z = MINMAG(C) finds the integer of minimum magnitude in a given

%  4- or 8-connected Freeman chain code, C. The code is assumed to

%  be a 1-by-np array.

% The integer of minimum magnitude starts with min(c), but there

% may be more than one such value. Find them all,

I = find(c == min(c));

% and shift each one left so that it starts with min(c).

J = 0;

A = zeros(length(I), length(c));

for k = I;

  J = J + 1;

  A(J, :) = circshift(c,[0 -(k-1)]);

end

% Matrix A contains all the possible candidates for the integer of

% minimum magnitude. Starting with the 2nd column, succesively find

% the minima in each column of A. The number of candidates decreases

% as the seach moves to the right on A.  This is reflected in the

% elements of J.  When length(J)=1, one candidate remains.  This is

% the integer of minimum magnitude. 

[M, N] = size(A);

J = (1:M)';

for k = 2:N

  D(1:M, 1) = Inf;

  D(J, 1) = A(J, k);

  amin = min(A(J, k));

  J = find(D(:, 1) == amin);

  if length(J)==1

      z = A(J, :);

      return

  end

end



function d = codediff(fcc, conn)

%CODEDIFF Computes the first difference of a chain code.

%  D = CODEDIFF(FCC) computes the first difference of code, FCC. The

%  code FCC is treated as a circular sequence, so the last element

%  of D is the difference between the last and first elements of

%  FCC.  The input code is a 1-by-np vector.

%

%  The first difference is found by counting the number of direction

%  changes (in a counter-clockwise direction) that separate two

%  adjacent elements of the code.

sr = circshift(fcc, [0, -1]); % Shift input left by 1 location.

delta = sr - fcc;

d = delta;

I = find(delta < 0);

type = conn;

switch type

case 4 % Code is 4-connected

  d(I) = d(I) + 4;

case 8 % Code is 8-connected

  d(I) = d(I) + 8;

end


添加完以上函数后,测试代码可以顺利运行:

close all;clear all;clc;

I = [1 1 1 1;1 1 0 1;0 1 0 1;0 1 1 1];

g = boundaries(I,4);  %追踪4连接目标边界

c = fchcode(g{:},4);  %求4方向freeman链码

c

output:

c = 

      x0y0: [1 1]  %c.x0y0显示代码开始处的坐标(1×2)

      fcc: [0 0 0 3 3 3 2 2 1 1 2 1]     %c.fcc表示Freeman链码(1×n),边界点集大小为 (n×2)

      diff: [0 0 3 0 0 3 0 3 0 1 3 3]      % c.diff 代码 c.fcc的一阶差分(1×n)

        mm: [0 0 0 3 3 3 2 2 1 1 2 1]   %c.mm表示最小幅度的整数

    diffmm: [0 0 3 0 0 3 0 3 0 1 3 3]   %c.diffmm表示代码c.mm的一阶差分(1×n)

posted on 2019-08-31 20:13  我坚信阳光灿烂  阅读(1625)  评论(0编辑  收藏  举报

导航