## Copyright (C) 2000 Etienne Grossmann ## ## 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 ## [im2,npix,bb] = bwlabel(im, mins, maxs, verbose) ## ## Find the connected regions of an image. ## ## im : RxC 0-1 matrix ## ## im2 : RxC int matrix in which the connected regions of im have been ## numbered. 4-neighborhoods are considered. ## ## npix : 1xQ int number of pixel in each region ## ## bb : 4xQ int bounding boxes of the regions. Rows are minrow, ## maxrow, mincol, maxcol. ## ## Options : ## ## mins : Minimum size of the regions (set to zero for no minimum) ## maxs : Maximum size of the regions (set to zero for no maximum) ## verbose : Level of output comments in range 0 to 2. ## ## Author: Etienne Grossmann ## Last modified: July 2002 ## ## Modified by David Fletcher to avoid artificially ## separate regions which actually touch (as indicated when "prudent" is set) ## through addition of lrow update within loop over touching regions. Also ## removed "sayif" function references, and call to read_options. Enabled ## options, setting of output verbosity. "Prudent" is left in place, but ## should no longer find any errors. function [im2,npix,bb] = bwlabel(im, mins, maxs, verbose) if (nargin == 1) mins = 0; maxs = 0; prudent = 1; verbose = 0; elseif (nargin == 2) maxs = 0; prudent = 1; verbose = 0; elseif (nargin == 3) prudent = 1; verbose = 0; elseif ((nargin == 4) && (verbose >= 0) && (verbose <= 2)) prudent = 1; else usage ("bwlabel2(im, mins, maxs, verbose)"); endif if any(im(:)&im(:)!=1), printf("bwlabel : im is not binary\n"); return end [R,C]=size(im); tr = 0 ; # Loop as little as possible if R= 1) printf("bwlabel : There will be %i loops ... \n%5i ",C,0) ; endif; lrow = zeros(R,1); # Last treated image column for i=1:C, t1 = find(imup(:,i)) ; t2 = find(imdo(:,i)) ; nrow = zeros(R,1); # Next row for j = 1:rows(t1(:)) , # Loop over slices of i'th column rc++ ; # rc = number of current slice. im2(t1(j):t2(j),i) = rc ; # Slices from previous column that touch # this slice. rr = create_set(lrow(t1(j):t2(j))) ; if !isempty(rr) && !rr(1), rr = rr(2:length(rr)) ; end if rc>size(rnum,2), # Get more space (uncertain effect on # speed; avoids resizing rnum and npix) tmp = 2*(ceil(C*rc/i)-rc+1+rows(t1(:))-j) ; if (verbose == 2) printf("bwlabel : (i=%i) Foreseeing %i more regions\n",i,tmp); endif; rnum = [ rnum, ones(1,tmp) ] ; npix = [ npix,zeros(1,tmp) ] ; bb = [ bb,zeros(4,tmp) ] ; end if isempty(rr), # New region if (verbose == 2) printf("bwlabel : creating region %i\n",rc); endif; r0 = rc ; # r0 = number of the region bb(1,r0) = t1(j) ; bb(2,r0) = t2(j) ; bb(3:4,r0) = i ; else # Add to already existing region ##### r0 = rnum(rr(1)) ; [i, j, r0]; bb(1,r0) = min(bb(1,r0),t1(j)) ; bb(2,r0) = max(bb(2,r0),t2(j)) ; bb(4,r0) = i ; # Touches region r0 if (verbose == 2) printf("bwlabel : adding to region %i\n",r0); endif; # Touches other regions too for k = rr(find(rr!=r0)), # Loop over other touching regions, that # should be merged to the first. if (verbose == 2) printf("bwlabel : merging regions %i and %i\n",k,r0); endif; rnum(find(rnum==k)) = r0 ; lrow(find(lrow==k)) = r0 ; ##Update lrow for next comparsion loop npix(r0) = npix(r0) + npix(k) ; bb([1,3],r0) = min(bb([1,3],r0)',bb([1,3],k)')' ; bb([2,4],r0) = max(bb([2,4],r0)',bb([2,4],k)')' ; end end # End of add to already existing region ## if r0==259 && i==39,"r0==259",keyboard;end rnum(rc) = r0 ; npix(r0) = npix(r0) + 1+t2(j)-t1(j) ; nrow(t1(j):t2(j)) = r0 ; end # End of looping over slices lrow = nrow ; if (verbose >= 1) printf("."); if (!rem(i,70) && i= 1) printf("\n"); endif; keep = ones(1,rc) ; if mins, keep = keep & (npix(rnum(1:rc))>=mins) ; end if maxs, keep = keep & (npix(rnum(1:rc))<=maxs) ; end keep(1) = 1 ; keep = find(keep) ; # Indices of slices to be kept foo = create_set(rnum(keep)) ; # Indices of regions to be kept nr = prod(size(foo)) ; # Number of regions (including bg) ## lrow = zeros(1,nr) ; tmp = zeros(1,rc) ; tmp(foo) = 0:nr-1 ; bar = zeros(1,rc) ; bar(keep) = tmp(rnum(keep)) ; ## keyboard im2 = reshape(bar(im2),R,C) ; npix = npix(foo(2:nr)); bb = bb(:,foo(2:nr)); if 0, # Draw bb on the image (will ruin # coherence) for i=1:nr-1, im2([bb(1,i),bb(2,i)] ,bb(3,i):bb(4,i) ) = i ; im2( bb(1,i):bb(2,i) ,[bb(3,i),bb(4,i)]) = i ; end end ## keyboard if prudent, if (verbose >= 1) printf("bwlabel : Checking coherence\n"); endif; hcontact = im2 & im2!=[im2(:,2:C),zeros(R,1)] & [im2(:,2:C),zeros(R,1)] ; vcontact = im2 & im2!=[im2(2:R,:);zeros(1,C)] & [im2(2:R,:);zeros(1,C)] ; ok = 1 ; if (any(hcontact(:))) if (verbose == 2) [x,y] = find(hcontact) endif; ok = 0 ; printf("bwlabel: Whoa! Found horizontally connected separated regions\n"); end if (any(vcontact(:))) if (verbose == 2)[x,y] = find(vcontact) endif; ok = 0 ; printf("bwlabel: Whoa! Found vertically connected separated regions\n"); end if !ok, keyboard ; end end ## Eventually transpose result if tr, im2 = im2' ; bb = bb([3,4,1,2],:); end