function slide=ipss002
%IPSS002 Feature-based logic.
%
%   This slideshow illustrates the use of BWSELECT to accomplish
%   a feature-based AND operation.  In feature-based AND, ON pixels
%   in one binary image are used to select objects (connected 
%   groups of ON pixels) in another object.  
%
%   The first example shows two binary images, one containing dots 
%   and another containing a box.  The intersection of the ON 
%   pixels in the two images is used to select objects from the 
%   dots image.
%
%   In the second example we want to select bacteria cells which
%   have bright granules in them.  The image is thresholded once
%   to segment the cells, and then it is filtered and thresholded 
%   again to segment the granules.  BWSELECT is then used to 
%   select cells which contain the bright granules.
%
%   See also BWSELECT.

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


if nargout<1,
   playshow ipss002
else
   %========== Slide 1 ==========
   
   slide(1).code={
      'FigHandle = gcf;',
      'if ~isfield(slideData, ''Initialized'')',
      '   set(FigHandle, ''DoubleBuffer'', ''on'');', 
      '   slideData.Initialized = 1;',
      '   set(FigHandle, ''Colormap'', gray(128));',
      '   set(FigHandle, ''Name'', ''Feature-Based Logic'');',
      '   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,''dots'') & ~isfield(slideData.Images,''box'')),',
      '      dots = []; box = [];',
      '      load imdemos dots box',
      '      slideData.Images.dots = dots;',
      '      slideData.Images.box = box;',
      '   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;',
      '   slideData.ax1 = axes( ''Units'', ''Pixels''',
      '    ''Parent'', FigHandle',
      '    ''ydir'', ''reverse''',
      '    ''XLim'', [.5 128.5]',
      '    ''YLim'', [.5 128.5]',
      '    ''CLim'', [0 1]',
      '    ''Position'',[ax1left ax1bot wid ht]',
      '    ''Tag'', ''axis1''',
      '    ''XTick'',[],''YTick'',[]);',
      '   slideData.img1 = image(''CData'', []',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax1',
      '    ''Xdata'', [1 128]',
      '    ''Ydata'', [1 128]',
      '    ''Tag'', ''image1''',
      '    ''EraseMode'', ''none'');',
      '   ax2left = (pos(3)*.78)/3-80;',
      '   slideData.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''',
      '    ''XTick'',[],''YTick'',[]);',
      '   set(get(slideData.ax2, ''title''), ''string'', ''dots'');',
      '   slideData.img2 = image(''CData'', slideData.Images.dots',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax2',
      '    ''Xdata'', [1 128]',
      '    ''Ydata'', [1 128]',
      '    ''Tag'', ''image2''',
      '    ''EraseMode'', ''none'');',
      '   ax3left = (2*pos(3)*.78)/3-48;',
      '   slideData.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''',
      '    ''XTick'',[],''YTick'',[]);',
      '   set(get(slideData.ax3, ''title''), ''string'', ''box'');',
      '   slideData.img3 = image(''CData'', slideData.Images.box',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax3',
      '    ''Xdata'', [1 128]',
      '    ''Ydata'', [1 128]',
      '    ''Tag'', ''image3''',
      '    ''EraseMode'', ''none'');',
      '',
      '   ax4left = (pos(3)*.78)/2-89;',
      '   ax4bot = .39*pos(4)+(pos(4)*(1-.39))/2-89;',
      '   wid = 178; ht = 178;',
      '   frameLeft = .78;',
      '   slideData.ax4 = axes( ''Units'', ''Pixels''',
      '    ''Parent'', FigHandle',
      '    ''ydir'', ''reverse''',
      '    ''XLim'', [.5 178.5]',
      '    ''YLim'', [.5 178.5]',
      '    ''CLim'', [0 1]',
      '    ''Position'',[ax4left ax4bot wid ht]',
      '    ''Tag'', ''axis4''',
      '    ''XTick'',[],''YTick'',[]);',
      '   slideData.img4 = image(''CData'', []',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax4',
      '    ''Xdata'', [1 178]',
      '    ''Ydata'', [1 178]',
      '    ''Tag'', ''image4''',
      '    ''EraseMode'', ''none'');',
      '   ax5left = (pos(3)*.78)/3-105;',
      '   slideData.ax5 = axes( ''Units'', ''Pixels''',
      '    ''Parent'', FigHandle',
      '    ''ydir'', ''reverse''',
      '    ''XLim'', [.5 178.5]',
      '    ''YLim'', [.5 178.5]',
      '    ''CLim'', [0 255]',
      '    ''Position'',[ax5left ax4bot wid ht]',
      '    ''Tag'', ''axis5''',
      '    ''XTick'',[],''YTick'',[]);',
      '   slideData.img5 = image(''CData'', []',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax5',
      '    ''Xdata'', [1 178]',
      '    ''Ydata'', [1 178]',
      '    ''Tag'', ''image2''',
      '    ''EraseMode'', ''none'');',
      '   ax6left = (2*pos(3)*.78)/3-48;',
      '   slideData.ax6 = axes( ''Units'', ''Pixels''',
      '    ''Parent'', FigHandle',
      '    ''ydir'', ''reverse''',
      '    ''XLim'', [.5 178.5]',
      '    ''YLim'', [.5 178.5]',
      '    ''CLim'', [0 1]',
      '    ''Position'',[ax6left ax4bot wid ht]',
      '    ''Tag'', ''axis3''',
      '    ''XTick'',[],''YTick'',[]);',
      '   slideData.img6 = image(''CData'', slideData.Images.box',
      '    ''CDataMapping'', ''scaled''',
      '    ''Parent'',slideData.ax6',
      '    ''Xdata'', [1 178]',
      '    ''Ydata'', [1 178]',
      '    ''Tag'', ''image6''',
      '    ''EraseMode'', ''none'');',
      'end',
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2], ''Visible'', ''on'');',
      'set([slideData.ax4 slideData.ax5 slideData.img4 slideData.img5], ''Visible'', ''off'');',
      'set([slideData.ax1 slideData.ax6 slideData.img1 slideData.img6], ''Visible'', ''off'');',
      '' };
   slide(1).text={
      'This slideshow illustrates the use of feature-based logic on both',
      'synthetic binary images and a microscope image of bacteria.  ',
      'In the two images above, we want to find features in the ',
      'dots image which overlap features in the box image.',
      '',
      '» load imdemos dots box         % Load the data from a mat-file',
      '» imshow(box); imshow(dots);      % Display the images',
      ''};
   
   %========== Slide 2 ==========
   
   slide(2).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''logical_and'')',
      '   slideData.Images.logical_and = slideData.Images.dots & slideData.Images.box;',
      'end',
      'set(slideData.img1, ''Cdata'',slideData.Images.logical_and)',
      'set(get(slideData.ax1, ''title''), ''string'', ''Logical AND of dots and box'');',
      'set([slideData.ax1 slideData.img1], ''visible'', ''on'')',
      '' };
   slide(2).text={
      'The first step is to identify pixels that are ON (value = 1) in ',
      'both images.  This is accomplished by doing the logical  ',
      'AND of the two images.'
      '',
      '» logical_and = box & dots;',
      '» imshow(logical_and);'};
   
   %========== Slide 3 ==========
   
   slide(3).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''feature_and'')',
      '   [r,c] = find(slideData.Images.logical_and);',
      '   slideData.Images.feature_and = bwselect(dots, c, r);',
      'end',
      'set(slideData.img1, ''Cdata'',slideData.Images.feature_and)',
      'set(get(slideData.ax1, ''title''), ''string'', ''Feature-based AND of dots and box'');',
      'set([slideData.ax1 slideData.img1], ''visible'', ''on'')',
      '' };
   slide(3).text={
      'The feature-based AND is computed by using the ON pixels from ',
      'the logical AND as inputs to the BWSELECT function.',
      '',
      '» [r,c] = find(logical_and);',
      '» feature_and = bwselect(dots, c, r);',
      '» imshow(feature_and);'};
   
   %========== Slide 4 ==========
   
   slide(4).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''bacteria'')',
      '   bacteria = [];',
      '   load imdemos bacteria',
      '   slideData.Images.bacteria = bacteria;',
      'end',
      'set([slideData.ax4], ''CLim'', [0 255]);',
      'set(slideData.img4, ''Cdata'',slideData.Images.bacteria)',
      'set(get(slideData.ax4, ''title''), ''string'', ''Bacteria'');',
      'set([slideData.ax4 slideData.img4], ''visible'', ''on'')',
      '' };
   slide(4).text={
      'In this second example we want to identify which of the bacteria ',
      'in the image above contain one or more bright granules.  We want ',
      'to determine the number of granule-containing bacteria, not the ',
      'total number of granules, as some bacteria may contain more than ',
      'one granule.',
      '',
      '» load imdemos bacteria;',
      '» imshow(bacteria);'};
   
   %========== Slide 5 ==========
   
   slide(5).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''bact_bw'')',
      '   slideData.Images.bact_bw = ~(slideData.Images.bacteria>100);',
      'end',
      'set(slideData.ax4, ''CLim'', [0 1]);',
      'set(slideData.img4, ''Cdata'',slideData.Images.bact_bw)',
      'set(get(slideData.ax4, ''title''), ''string'', ''Thresholded bacteria'');',
      'set([slideData.ax4 slideData.img4], ''visible'', ''on'')',
      '' };
   slide(5).text={
      'The image is thresholded and complemented to segment the ',
      'bacteria.  The binary segmentation mask is displayed above.',
      '',
      '» bact_bw = ~(bacteria>100);',
      '» imshow(bact_bw);'};
   
   %========== Slide 6 ==========
   
   slide(6).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''bact_filtered'')',
      '   slideData.Images.bact_filtered = filter2(fspecial(''laplacian''),slideData.Images.bacteria);',
      '   slideData.Images.bact_granules = (slideData.Images.bact_filtered > -4) & slideData.Images.bact_bw;',
      'end',
      'fmin=min(slideData.Images.bact_filtered(:));',
      'fmax=max(slideData.Images.bact_filtered(:));',
      'set(slideData.ax5, ''CLim'', [fmin fmax]);',
      'set(slideData.ax6, ''CLim'', [0 1]);',
      'set(slideData.img5, ''Cdata'',slideData.Images.bact_filtered)',
      'set(slideData.img6, ''Cdata'',slideData.Images.bact_granules)',
      'set(get(slideData.ax5, ''title''), ''string'', ''Output of Laplacian filter'');',
      'set(get(slideData.ax6, ''title''), ''string'', ''Bacteria with granules'');',
      'set([slideData.ax5 slideData.img5 slideData.ax6 slideData.img6], ''visible'', ''on'')',
      '' };
   slide(6).text={
      'A Laplacian filter is applied to the original image and the result is',
      'thresholded and then logically combined with the binary ',
      'segmentation mask.  The resulting image shows the granules',
      'in the bacteria cells.',
      '',
      '» filtered = filter2(fspecial(''laplacian''), bacteria);',
      '» bact_granules = (filtered > -4) & bact_bw;',
      '» imshow(filtered, [ ]);  imshow(bact_granules);'};
    
   %========== Slide 7 ==========
   
   slide(7).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''granules'')',
      '   slideData.Images.granules = erode(slideData.Images.bact_bw) & (slideData.Images.bact_granules==0);',
      'end',
      'set(slideData.ax4, ''CLim'', [0 1]);',
      'set(slideData.img4, ''Cdata'',slideData.Images.granules)',
      'set(get(slideData.ax4, ''title''), ''string'', ''Segmented granules'');',
      'set([slideData.ax4 slideData.img4], ''visible'', ''on'')',
      '' };
   
   slide(7).text={
      'The granules are isolated by eroding the segmentation',
      'mask and selecting areas in the result where bact_granules',
      'is zero.  The erosion prevents detection of points',
      'along the edges of the cells. ',
      '',
      '» granules = erode(bact_bw) & (bact_granules==0);',
      '» imshow(granules);'};
   
   %========== Slide 8 ==========
   
   slide(8).code={
      'set([slideData.ax3 slideData.ax2 slideData.img3 slideData.img2 slideData.ax1 slideData.img1], ''visible'', ''off''), drawnow',
      'set([slideData.ax4 slideData.ax5 slideData.ax6 slideData.img4 slideData.img5 slideData.img6], ''visible'', ''off''), drawnow',
      'if ~isfield(slideData.Images, ''result'')',
      '   [r,c] = find(slideData.Images.granules);',
      '   slideData.Images.result =bwselect(slideData.Images.bact_bw, c, r);',
      'end',
      'set([slideData.ax5], ''CLim'', [0 255]);',
      'set(slideData.img6, ''Cdata'',slideData.Images.result)',
      'set(slideData.img5, ''Cdata'',slideData.Images.bacteria)',
      'set(get(slideData.ax5, ''title''), ''string'', ''Original image'');',
      'set(get(slideData.ax6, ''title''), ''string'', ''Bacteria with granules'');',
      'set([slideData.ax6 slideData.img6 slideData.ax5 slideData.img5], ''visible'', ''on'')',
      '' };
   
   slide(8).text={
      'BWSELECT is used to identify objects in the simple thresholded ',
      'image that have granules in them.'
      '',
      '» [r,c] = find(granules);',
      '» result = bwselect(bact_bw, c, r);',
      '» imshow(bacteria); imshow(result);'};
end
