Basic image processing: Part II

Note: This notebook assumes that all definitions in ipcv_definitions.nb have been evaluated first. It also assumes that the directory in the Set image directory points to an image directory with the following images: texture1.gif, texture2.gif, texture3.gif and texture4.gif

Local definitions

Vector clustering

Distance measure between two vectors

dist1[a_,  b_] :=  Sqrt[(a - b) . (a - b)];

dist = 
        Compile[{{a, _Real, 1}, {b, _Real, 1}}, 
          Sqrt[(a - b) . (a - b)]];

Assign class-centroid labels to single datum

AssignClass[
          x_,  μs_] := 
Module[{tmp}, 
tmp = dist[
                  x,  #] &  /@  μs; 
Position[
                tmp,  Min[tmp]]  //  Flatten  //  
            First
];

One step of the k-means algorithm

KMeansOne[
          data_,  μs_] := 
Module[{k, 
            cl}, 
k = 
            Length[μs]; 
cl  =  AssignClass[#,  μs] &  /@  
              data; 
Mean  /@  (Part[data, 
                    Flatten[Position[cl, #]]] &  /@  
                Range[k])
];

Complete k-means algorithm

KMeansAll1[data_, μs_,  
          tst_:  .01] := 
NestWhile[
          KMeansOne[data, #] &, μs,  (conv[#1, #2] > tst) &,  
          2];

KMeansAll[data_,  n_, 
          tst_:  .01] := 
Module[{tmp, μs}, 
tmp = {}; 
While[
            Length[tmp]  ≠  n, 
tmp = 
              Union[Table[
                  Random[Integer, {1, 
                      Length[data]}], {n}]]
]; 
μs = (data[[#]]) &  /@  
              tmp; 
KMeansAll1[data, μs, 
            tst]
];

Set image directory

If[StringQ[$ImagePath], $path = $ImagePath,  $path = "."]; 
    SetDirectory[$path];

2D convolution: simple texture segmentation (example #1)

Load two texture images

tmp1 = ReadImage["texture3.gif"];
tmp2 = ReadImage["texture4.gif"];
img = BlockMatrix[{{tmp1, tmp2}}];
scale = 1;

Display combined texture image

ShowImage[img, scale];

Compute nine texture energy images

"Edge-Level" texture energy image (1)

tmp = Mask[img,  EL[]  //  N];
tex1  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex1, scale, Max[tex1]];

"Ridge-Level" texture energy image (2)

tmp = Mask[img,  RL[]  //  N];
tex2  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex2, scale, Max[tex2]];

"Edge-Spot" texture energy image (3)

tmp = Mask[img,  ES[]  //  N];
tex3  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex3, scale, Max[tex3]];

"Ridge-Ridge" texture energy image (4)

tmp = Mask[img,  RR[]  //  N];
tex4  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex4, scale, Max[tex4]];

"Spot-Level" texture energy image (5)

tmp = Mask[img,  SL[]  //  N];
tex5  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex5, scale, Max[tex5]];

"Edge-Edge" texture energy image (6)

tmp = Mask[img,  EE[]  //  N];
tex6  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex6, scale, Max[tex6]];

"Edge-Ridge" texture energy image (7)

tmp = Mask[img,  ER[]  //  N];
tex7  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex7, scale, Max[tex7]];

"Spot-Spot" texture energy image (8)

tmp = Mask[img,  SS[]  //  N];
tex8  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex8, scale, Max[tex8]];

"Spot-Ridge" texture energy image (9)

tmp = Mask[img,  SR[]  //  N];
tex9  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex9, scale, Max[tex9]];

Cluster nine-dimensional texture data

Generate 9d texture data

texdat = 
        Partition[
            Flatten[Transpose  /@  ({tex1, tex2, tex3, tex4, tex5, tex6, 
                      tex7, tex8, tex9}  //  Transpose)], 9]  //  
          N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[centroids = KMeansAll[texdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, centroids] &  /@  
            texdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[centroids] + 1];

Compare to intensity-based clustering

Generate 1d intensity data

intdat = {#} & /@  Flatten[img]  //  N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[c2 = KMeansAll[intdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, c2] &  /@  
            intdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[c2] + 1];

2D convolution: simple texture segmentation (example #2)

Load two texture images

tmp1 = ReadImage["texture1.gif"];
tmp2 = ReadImage["texture4.gif"];
img = BlockMatrix[{{tmp1, tmp2}}];
scale = 1;

Display combined texture image

ShowImage[img, scale];

Compute nine texture energy images

"Edge-Level" texture energy image (1)

tmp = Mask[img,  EL[]  //  N];
tex1  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex1, scale, Max[tex1]];

"Ridge-Level" texture energy image (2)

tmp = Mask[img,  RL[]  //  N];
tex2  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex2, scale, Max[tex2]];

"Edge-Spot" texture energy image (3)

tmp = Mask[img,  ES[]  //  N];
tex3  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex3, scale, Max[tex3]];

"Ridge-Ridge" texture energy image (4)

tmp = Mask[img,  RR[]  //  N];
tex4  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex4, scale, Max[tex4]];

"Spot-Level" texture energy image (5)

tmp = Mask[img,  SL[]  //  N];
tex5  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex5, scale, Max[tex5]];

"Edge-Edge" texture energy image (6)

tmp = Mask[img,  EE[]  //  N];
tex6  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex6, scale, Max[tex6]];

"Edge-Ridge" texture energy image (7)

tmp = Mask[img,  ER[]  //  N];
tex7  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex7, scale, Max[tex7]];

"Spot-Spot" texture energy image (8)

tmp = Mask[img,  SS[]  //  N];
tex8  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex8, scale, Max[tex8]];

"Spot-Ridge" texture energy image (9)

tmp = Mask[img,  SR[]  //  N];
tex9  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex9, scale, Max[tex9]];

Cluster nine-dimensional texture data

Generate 9d texture data

texdat = 
        Partition[
            Flatten[Transpose  /@  ({tex1, tex2, tex3, tex4, tex5, tex6, 
                      tex7, tex8, tex9}  //  Transpose)], 9]  //  
          N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[centroids = KMeansAll[texdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, centroids] &  /@  
            texdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[centroids] + 1];

Compare to intensity-based clustering

Generate 1d intensity data

intdat = {#} & /@  Flatten[img]  //  N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[c2 = KMeansAll[intdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, c2] &  /@  
            intdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[c2] + 1];

2D convolution: simple texture segmentation (example #3)

Load two texture images

tmp1 = ReadImage["texture1.gif"];
tmp2 = ReadImage["texture2.gif"];
img = BlockMatrix[{{tmp1, tmp2}}];
scale = 1;

Display combined texture image

ShowImage[img, scale];

Compute nine texture energy images

"Edge-Level" texture energy image (1)

tmp = Mask[img,  EL[]  //  N];
tex1  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex1, scale, Max[tex1]];

"Ridge-Level" texture energy image (2)

tmp = Mask[img,  RL[]  //  N];
tex2  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex2, scale, Max[tex2]];

"Edge-Spot" texture energy image (3)

tmp = Mask[img,  ES[]  //  N];
tex3  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex3, scale, Max[tex3]];

"Ridge-Ridge" texture energy image (4)

tmp = Mask[img,  RR[]  //  N];
tex4  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex4, scale, Max[tex4]];

"Spot-Level" texture energy image (5)

tmp = Mask[img,  SL[]  //  N];
tex5  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex5, scale, Max[tex5]];

"Edge-Edge" texture energy image (6)

tmp = Mask[img,  EE[]  //  N];
tex6  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex6, scale, Max[tex6]];

"Edge-Ridge" texture energy image (7)

tmp = Mask[img,  ER[]  //  N];
tex7  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex7, scale, Max[tex7]];

"Spot-Spot" texture energy image (8)

tmp = Mask[img,  SS[]  //  N];
tex8  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex8, scale, Max[tex8]];

"Spot-Ridge" texture energy image (9)

tmp = Mask[img,  SR[]  //  N];
tex9  = 
        Mask[tmp, MeanFilter[15]  //  N];
ShowImage[tex9, scale, Max[tex9]];

Cluster nine-dimensional texture data

Generate 9d texture data

texdat = 
        Partition[
            Flatten[Transpose  /@  ({tex1, tex2, tex3, tex4, tex5, tex6, 
                      tex7, tex8, tex9}  //  Transpose)], 9]  //  
          N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[centroids = KMeansAll[texdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, centroids] &  /@  
            texdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[centroids] + 1];

Compare to intensity-based clustering

Generate 1d intensity data

intdat = {#} & /@  Flatten[img]  //  N;

Perform 2-cluster k-means algorithm

This step may take a while...

Timing[c2 = KMeansAll[intdat, 2,  .001];]

Assign class labels

This step may take a while...

Timing[classes = AssignClass[#, c2] &  /@  
            intdat;]

Display segmentation results

segmented = 
        Partition[classes, Dimensions[img]  //  Last];
ShowImage[segmented, scale, Length[c2] + 1];