function slide=ipss001
%IPSS001 Region labeling of steel grains.
%
%   This demo illustrates the use of double thresholding, feature based
%   logic, binary morphology, and connected components labeling to 
%   locate grain boundaries and label the grains in a microscope image
%   of steel.  
%
%   See also BWLABEL, BWSELECT, BWMORPH.

%   Chris Griffin, Feb. 1997
%   $Revision: 1.6 $  $Date: 1998/02/19 16:29:33 $ 
%   Copyright 1993-1998 The MathWorks, Inc.  All Rights Reserved.

if nargout<1,
   playshow ipss001
else
   %========== Slide 1 ==========
   
   slide(1).code={
      'FigHandle = gcf;',
      'set(FigHandle, ''DoubleBuffer'', ''on'');', 
      'set(FigHandle, ''Colormap'', gray(128));',
      'set(FigHandle, ''Name'', ''Region Labeling of Steel Grains'');',
      'pos = get(FigHandle, ''Position'');',
      '',
      '% Adjust the size of the figure window',
      'pos(3:4) = [560 420];',
      'horizDecorations = 10;  % resize controls, etc. ',
      'vertDecorations = 45;   % title bar, etc.',
      'screenSize = get(0,''ScreenSize'');',
      'if (screenSize(3) <= 1)',
      '   screenSize(3:4) = [100000 100000];',
      'end',
      'if (((pos(3) + horizDecorations) > screenSize(3)) | ((pos(4) + vertDecorations) > screenSize(4)))',
      '   delete(fig);',
      '   error([''Screen resolution is too low (or text fonts are too big) to run this demo'']);',
      'end',
      'dx = screenSize(3) - pos(1) - pos(3) - horizDecorations;',
      'dy = screenSize(4) - pos(2) - pos(4) - vertDecorations;',
      'if (dx < 0)',
      '    pos(1) = max(5,pos(1) + dx);',
      'end',
      'if (dy < 0)',
      '    pos(2) = max(5,pos(2) + dy);',
      'end',
      'set(FigHandle, ''Position'', pos)',
      'set(FigHandle, ''Resize'', ''off'');',
      'if ~isfield(slideData, ''Images''),',
      '   slideData.Images = [];',
      'end',
      'if isempty(slideData.Images) | ~isfield(slideData.Images,''steel''),',
      '   steel = [];',
      '   load imdemos steel;',
      '   slideData.Images.steel = steel;',
      'end',
      'ax = findobj(FigHandle, ''type'', ''axes'');',
      'delete(ax);',
      'ax1left = (pos(3)*.78)/2-64;',
      'ax1bot = .39*pos(4)+(pos(4)*(1-.39))/2-64;',
      'wid = 128; ht = 128;',
      'frameLeft = .78;',
      'ax1 = axes( ''Units'', ''Pixels''',
      ' ''Parent'', FigHandle',
      ' ''ydir'', ''reverse''',
      ' ''XLim'', [.5 128.5]',
      ' ''YLim'', [.5 128.5]',
      ' ''CLim'', [0 255]',
      ' ''Position'',[ax1left ax1bot wid ht]',
      ' ''Tag'', ''axis1''',
      ' ''XTick'',[],''YTick'',[]);',
      'set(get(ax1, ''title''), ''string'', ''Steel grains'');',
      'img1 = image(''CData'', slideData.Images.steel',
      ' ''CDataMapping'', ''scaled''',
      ' ''Parent'',ax1',
      ' ''Xdata'', [1 128]',
      ' ''Ydata'', [1 128]',
      ' ''Tag'', ''image1''',
      ' ''EraseMode'', ''none'');',
      'ax2left = (pos(3)*.78)/3-80;',
      'ax2 = axes( ''Units'', ''Pixels''',
      ' ''Parent'', FigHandle',
      ' ''ydir'', ''reverse''',
      ' ''XLim'', [.5 128.5]',
      ' ''YLim'', [.5 128.5]',
      ' ''CLim'', [0 1]',
      ' ''Position'',[ax2left ax1bot wid ht]',
      ' ''Tag'', ''axis2''',
      ' ''Visible'', ''off''',
      ' ''XTick'',[],''YTick'',[]);',
      'img2 = image(''CData'', []',
      ' ''CDataMapping'', ''scaled''',
      ' ''Parent'',ax2',
      ' ''Xdata'', [1 128]',
      ' ''Ydata'', [1 128]',
      ' ''Tag'', ''image2''',
      ' ''EraseMode'', ''none'');',
      'ax3left = (2*pos(3)*.78)/3-48;',
      'ax3 = axes( ''Units'', ''Pixels''',
      ' ''Parent'', FigHandle',
      ' ''ydir'', ''reverse''',
      ' ''XLim'', [.5 128.5]',
      ' ''YLim'', [.5 128.5]',
      ' ''CLim'', [0 1]',
      ' ''Position'',[ax3left ax1bot wid ht]',
      ' ''Tag'', ''axis3''',
      ' ''Visible'', ''off''',
      ' ''XTick'',[],''YTick'',[]);',
      'img3 = image(''CData'', []',
      ' ''CDataMapping'', ''scaled''',
      ' ''Parent'',ax3',
      ' ''Xdata'', [1 128]',
      ' ''Ydata'', [1 128]',
      ' ''Tag'', ''image3''',
      ' ''EraseMode'', ''none'');',
      '' };
   slide(1).text={
      'This slideshow illustrates the use of double thresholding, ',
      'feature based logic, binary morphology and connected  ',
      'components labeling to locate grain boundaries and label '
      'different grains in a microscope image of steel.',
      '',    
      '» load imdemos steel;',
      '» imshow(steel);',
      ''};
   
   %========== Slide 2 ==========
   
   slide(2).code={
      'set([ax1 ax2 ax3 img1 img2 img3], ''Visible'', ''off'')',
      'drawnow',
      't1 = 70;',
      'if ~isfield(slideData.Images,''thresh1''),',
      '   slideData.Images.thresh1 = slideData.Images.steel > t1;',
      'end',
      '',
      't2 = 210;',
      'if ~isfield(slideData.Images,''thresh2''),',
      '   slideData.Images.thresh2 = slideData.Images.steel > t2;',
      'end',
      '',
      'set(img2, ''Cdata'', slideData.Images.thresh1)',
      'set(get(ax2, ''title''), ''string'', [''Threshold=''num2str(t1)])',
      'set(img3, ''Cdata'', slideData.Images.thresh2)',
      'set(get(ax3, ''title''), ''string'', [''Threshold=''num2str(t2)])',
      'set([ax2 ax3 img2 img3], ''Visible'', ''on'')',
      '' };
   slide(2).text={
      'The steel image is thresholded at two different threshold ',
      'values, yielding the images displayed above.',
      '',
      '» bw_70 = steel > 70;',
      '» bw_210 = steel > 210;',
      '» imshow(bw_70);',
      '» imshow(bw_210);',
      ''};
   
   %========== Slide 3 ==========
   
   slide(3).code={
      'set([ax1 ax2 ax3 img1 img2 img3], ''Visible'', ''off'')',
      'drawnow',
      'if ~isfield(slideData.Images,''ro''),',
      '   [slideData.Images.ro,slideData.Images.co] = find(slideData.Images.thresh1==0);',
      'end',
      'if ~isfield(slideData.Images,''clean''),',
      '   slideData.Images.clean = bwselect(~slideData.Images.thresh2, slideData.Images.co, slideData.Images.ro, 8);',
      'end',
      'set(ax1, ''CLim'', [0 1], ''Visible'', ''on'')',
      'set(img1, ''Cdata'', slideData.Images.clean, ''Visible'', ''on'')',
      'set(get(ax1, ''title''), ''string'', ''Minor region removal'')',
      '' };
   slide(3).text={
      'Points which were black in the image with the low threshold are',
      'used to select white objects in the negative of the image with',
      'the high threshold.  This effectively removes the minor regions',
      'which appeared in the second thresholded image.',
      '',
      '» [r,c] = find(bw_70 == 0);',
      '» bw_clean = bwselect(~bw_210, c, r, 8);',
      '» imshow(bw_clean);',
      ''};
   
   %========== Slide 4 ==========
   
   slide(4).code={
      'set([ax1 ax2 ax3 img1 img2 img3], ''Visible'', ''off'')',
      'drawnow',
      'if ~isfield(slideData.Images,''skinny''),',
      '   slideData.Images.skinny = bwmorph(slideData.Images.clean, ''skel'', 6);',
      'end',
      'if ~isfield(slideData.Images,''pruned''),',
      '   slideData.Images.pruned  = bwmorph(slideData.Images.skinny, ''spur'', 8);',
      'end',
      'set(img2, ''CData'', slideData.Images.skinny)',
      'set(img3, ''CData'', slideData.Images.pruned)',
      'set(ax2, ''CLim'', [0 1])',
      'set(get(ax2, ''title''), ''string'', ''Skeletonized'')',
      'set(get(ax3, ''title''), ''string'', ''Spur points removed'')',
      'set([ax2 ax3 img2 img3], ''Visible'', ''on'')',
      '' };
   slide(4).text={
      'The BWMORPH function is used to skeletonize the result of the',
      'minor region removal.  BWMORPH is applied again to prune the',
      'spur pixels from the skeletonized image.',
      '',
      '» bw_skel = bwmorph(bw_clean, ''skel'', 6);',
      '» imshow(bw_skel);',
      '» bw_pruned  = bwmorph(bw_skel, ''spur'', 8);',
      '» imshow(bw_pruned);',
      ''};
   
   %========== Slide 5 ==========
   
   slide(5).code={
      'set([ax1 ax2 ax3 img1 img2 img3], ''Visible'', ''off'')',
      'drawnow',
      'if ~isfield(slideData.Images,''result''),',
      '   slideData.Images.result = ~slideData.Images.pruned;',
      'end',
      'set(img2, ''CData'', slideData.Images.steel)',
      'set(ax2, ''CLim'', [0 255])',
      'set(img3, ''CData'', slideData.Images.result)',
      'set(get(ax2, ''title''), ''string'', ''Original image'')',
      'set(get(ax3, ''title''), ''string'', ''Boundary map'')',
      'set([ax2 ax3 img2 img3], ''Visible'', ''on'')',
      '' };
   slide(5).text={
      'The grain boundary map is the logical NOT of the pruned image.',
      '',
      '» grain_boundaries = ~bw_pruned;',
      '» imshow(steel);',
      '» imshow(grain_boundaries);',
      ''};
   
   %========== Slide 6 ==========
   
   slide(6).code={
      'set([ax1 ax2 ax3 img1 img2 img3], ''Visible'', ''off'')',
      'drawnow',
      'if ~isfield(slideData.Images,''rgb''),',
      '   [labeled,Num] = bwlabel(slideData.Images.result,4);',
      '   slideData.Images.rgb = ind2rgb(labeled+1, [0 0 0; jet(Num)]);',
      'end',
      'set(img3, ''CData'', slideData.Images.rgb);',
      'set(get(ax3, ''title''), ''string'', ''Labeled steel grains'')',
      'set([ax2 ax3 img2 img3], ''Visible'', ''on'')',
      '' };
   slide(6).text={
      'The BWLABEL command is used to label different objects in',
      'the binary result.  The objects are displayed with different', 
      'colors from a jet colormap.',
      '',
      '» [labeled,N] = bwlabel(grain_boundaries,4);',
      '» colored = ind2rgb(labeled+1, [0 0 0; jet(N)]);',
      '» imshow(steel);',
      '» imshow(colored);'};
end
