diff --git a/Assignment_2/Image2Graph.m b/Assignment_2/Image2Graph.m index 7d4e27e..9dc90ee 100644 --- a/Assignment_2/Image2Graph.m +++ b/Assignment_2/Image2Graph.m @@ -11,9 +11,12 @@ function myAffinityMat = Image2Graph (imIn) imageHeight = size(imIn, 1); imageChannels = size(imIn, 3); + % Produces the matrix singleLineTransform = reshape(imIn, 1, [], imageChannels); - diff = repmat(singleLineTransform, imageWidth * imageHeight, 1, 1) - ... - permute(singleLineTransform, [2 1 3]); - dist = sum(diff .^ 2, 3) .^ 0.5; - myAffinityMat = 1 ./ exp(dist); + myAffinityMat = 1 ./ exp( ... + sum(( ... + repmat(singleLineTransform, imageWidth * imageHeight, 1, 1) - ... + permute(singleLineTransform, [2 1 3])) ... + .^ 2, 3) ... + .^ 0.5); end diff --git a/Assignment_2/calculateNcut.m b/Assignment_2/calculateNcut.m index 1a88340..c3fc676 100644 --- a/Assignment_2/calculateNcut.m +++ b/Assignment_2/calculateNcut.m @@ -1,8 +1,8 @@ function nCutValue = calculateNcut (anAffinityMat , clusterIdx) -%Implementation the NCut metric calculation +%Calculation of the NCut metric % Usage nCutValue = calculateNcut (anAffinityMat , clusterIdx), where: % Inputs -% - anAffinityMat is a rectagular, symmetrical affinity matrix +% - anAffinityMat is a rectangular, symmetrical affinity matrix % representation of an image % - clusterIdx is a vector storing the cluster Id of each node % Output @@ -11,15 +11,17 @@ function nCutValue = calculateNcut (anAffinityMat , clusterIdx) % Gets the unique cluster IDs clusterIds = unique(clusterIdx); if size(clusterIds, 1) ~= 2 - error('Too many different clusters! Number of clusters should be two'); + error('Too many different clusters! Number of clusters must be two'); end + % Finds the indices of the samples of each cluster clusterOneIndices = (clusterIdx == clusterIds(1)); clusterTwoIndices = (clusterIdx == clusterIds(2)); + % Calculates the N-Cut metric nCutValue = 2 - ... - (sum(sum(anAffinityMat(clusterOneIndices, clusterOneIndices'))) / ... + (sum(sum(anAffinityMat(clusterOneIndices, clusterOneIndices))) / ... sum(sum(anAffinityMat(clusterOneIndices, :))) + ... - sum(sum(anAffinityMat(clusterTwoIndices, clusterTwoIndices'))) / ... + sum(sum(anAffinityMat(clusterTwoIndices, clusterTwoIndices))) / ... sum(sum(anAffinityMat(clusterTwoIndices, :)))); end diff --git a/Assignment_2/demo1.m b/Assignment_2/demo1.m index e31e291..e03336c 100644 --- a/Assignment_2/demo1.m +++ b/Assignment_2/demo1.m @@ -1,3 +1,4 @@ +%% Initialization clear clear all @@ -6,20 +7,27 @@ rng(1); load('dip_hw_2.mat'); +%% Executes experiments for the affinity matrix +% Clustering into two clusters clusters = mySpectralClustering(d1a, 2); + +% Presents results clusters = clusters ./ 2; -%clusters = reshape(clusters, 4, []); figure(); -imshow(clusters); +imshow(clusters'); +% Clustering into three clusters clusters = mySpectralClustering(d1a, 3); + +% Presents results clusters = clusters ./ 3; -%clusters = reshape(clusters, 4, []); figure(); -imshow(clusters); +imshow(clusters'); +% Clustering into four clusters clusters = mySpectralClustering(d1a, 4); + +% Presents results clusters = clusters ./ 4; -%clusters = reshape(clusters, 4, []); figure(); -imshow(clusters); +imshow(clusters'); diff --git a/Assignment_2/demo2.m b/Assignment_2/demo2.m index 445153a..036d74e 100644 --- a/Assignment_2/demo2.m +++ b/Assignment_2/demo2.m @@ -1,3 +1,4 @@ +%% Initialization clear clear all @@ -14,19 +15,28 @@ graph2 = Image2Graph(d2b); figure(); imshow(d2a); +% Clustering into two clusters clusters = mySpectralClustering(graph1, 2); + +% Presents results clusters = clusters ./ 2; clusters = reshape(clusters, size(d2a, 1), []); figure(); imshow(clusters); +% Clustering into three clusters clusters = mySpectralClustering(graph1, 3); + +% Presents results clusters = clusters ./ 3; clusters = reshape(clusters, size(d2a, 1), []); figure(); imshow(clusters); +% Clustering into four clusters clusters = mySpectralClustering(graph1, 4); + +% Presents results clusters = clusters ./ 4; clusters = reshape(clusters, size(d2a, 1), []); figure(); @@ -36,26 +46,35 @@ imshow(clusters); figure(); imshow(d2b); +% Clustering into two clusters clusters = mySpectralClustering(graph2, 2); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 2; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 2; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); +% Clustering into three clusters clusters = mySpectralClustering(graph2, 3); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 3; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 3; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); +% Clustering into four clusters clusters = mySpectralClustering(graph2, 4); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 4; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 4; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); diff --git a/Assignment_2/demo3a.m b/Assignment_2/demo3a.m index 0e2f9be..63c7e9b 100644 --- a/Assignment_2/demo3a.m +++ b/Assignment_2/demo3a.m @@ -1,3 +1,4 @@ +%% Initialization clear clear all @@ -14,19 +15,28 @@ graph2 = Image2Graph(d2b); figure(); imshow(d2a); +% Clustering into two clusters clusters = myNCuts(graph1, 2); + +% Presents results clusters = clusters ./ 2; clusters = reshape(clusters, size(d2a, 1), []); figure(); imshow(clusters); +% Clustering into three clusters clusters = myNCuts(graph1, 3); + +% Presents results clusters = clusters ./ 3; clusters = reshape(clusters, size(d2a, 1), []); figure(); imshow(clusters); +% Clustering into four clusters clusters = myNCuts(graph1, 4); + +% Presents results clusters = clusters ./ 4; clusters = reshape(clusters, size(d2a, 1), []); figure(); @@ -36,26 +46,35 @@ imshow(clusters); figure(); imshow(d2b); +% Clustering into two clusters clusters = myNCuts(graph2, 2); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 2; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 2; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); +% Clustering into three clusters clusters = myNCuts(graph2, 3); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 3; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 3; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); +% Clustering into four clusters clusters = myNCuts(graph2, 4); + +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 4; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +clusters = clusters ./ 4; +clusters = reshape(clusters, size(d2a, 1), []); +figure(); +imshow(clusters); diff --git a/Assignment_2/demo3b.m b/Assignment_2/demo3b.m index 11da403..309ee23 100644 --- a/Assignment_2/demo3b.m +++ b/Assignment_2/demo3b.m @@ -1,3 +1,4 @@ +%% Initialization clear clear all @@ -17,6 +18,7 @@ imshow(d2a); clusters = myNCuts(graph1, 2); NCut1 = calculateNcut(graph1, clusters); +% Presents results clusters = clusters - 1; clusters = reshape(clusters, size(d2a, 1), []); figure(); @@ -29,6 +31,7 @@ imshow(d2b); clusters = myNCuts(graph2, 2); NCut2 = calculateNcut(graph2, clusters); +% Presents results figure(); imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); diff --git a/Assignment_2/demo3c.m b/Assignment_2/demo3c.m index db02198..823c948 100644 --- a/Assignment_2/demo3c.m +++ b/Assignment_2/demo3c.m @@ -1,3 +1,4 @@ +%% Initialization clear clear all @@ -15,19 +16,52 @@ figure(); imshow(d2a); clusters = recursiveNCuts(graph1); -clusters = clusters ./ 2; + +% Presents results clusters = reshape(clusters, size(d2a, 1), []); +clustersR = clusters; +clustersG = clusters; +clustersB = clusters; + +for cluster = 1:size(unique(clusters), 1) + clustersR(clusters == cluster) = rand; + clustersG(clusters == cluster) = rand; + clustersB(clusters == cluster) = rand; +end +clusters(:, :, 1) = clustersR; +clusters(:, :, 2) = clustersG; +clusters(:, :, 3) = clustersB; + figure(); imshow(clusters); +clearvars clustersR clustersG clustersB cluster + %% Executes recursive experiments for the second image figure(); imshow(d2b); clusters = recursiveNCuts(graph2); + +% Presents results +clusters = reshape(clusters, size(d2b, 1), []); figure(); -imshow(meanClustersColorRGB(d2b, reshape(clusters, size(d2b, 1), []))); -% clusters = clusters ./ 2; -% clusters = reshape(clusters, size(d2a, 1), []); -% figure(); -% imshow(clusters); +imshow(meanClustersColorRGB(d2b, clusters)); + +clustersR = clusters; +clustersG = clusters; +clustersB = clusters; + +for cluster = 1:size(unique(clusters), 1) + clustersR(clusters == cluster) = rand; + clustersG(clusters == cluster) = rand; + clustersB(clusters == cluster) = rand; +end +clusters(:, :, 1) = clustersR; +clusters(:, :, 2) = clustersG; +clusters(:, :, 3) = clustersB; + +figure(); +imshow(clusters); + +clearvars clustersR clustersG clustersB cluster \ No newline at end of file diff --git a/Assignment_2/meanClustersColorRGB.m b/Assignment_2/meanClustersColorRGB.m index e46d055..4e7922b 100644 --- a/Assignment_2/meanClustersColorRGB.m +++ b/Assignment_2/meanClustersColorRGB.m @@ -1,28 +1,37 @@ -function segIm = meanClustersColorRGB(image, clusters) -%MEANCLUSTERSCOLOR Summary of this function goes here -% Detailed explanation goes here +function coloredIm = meanClustersColorRGB(image, clusters) +%meanClustersColorRGB assigns the mean color of each cluster to the cluster +% Usage coloredIm = meanClustersColorRGB (image, clusters), where: +% Inputs +% - image is the original image +% - clusters is a matrix of the same dimensions as the image that +% holds the cluster ID of each pixel +% Output +% - coloredIm is the image produced by assigning the mean color of +% each cluster to the cluster's pixels + % Initializes helper variables redChannel = image(:, :, 1); greenChannel = image(:, :, 2); blueChannel = image(:, :, 3); - segImR = clusters; - segImG = clusters; - segImB = clusters; + coloredImR = clusters; + coloredImG = clusters; + coloredImB = clusters; + % Assigns the mean color to each cluster for cluster = 1:max(max(clusters)) meanR = mean(redChannel(clusters == cluster)); meanG = mean(greenChannel(clusters == cluster)); meanB = mean(blueChannel(clusters == cluster)); - segImR(clusters == cluster) = meanR; - segImG(clusters == cluster) = meanG; - segImB(clusters == cluster) = meanB; + coloredImR(clusters == cluster) = meanR; + coloredImG(clusters == cluster) = meanG; + coloredImB(clusters == cluster) = meanB; end - segIm = zeros(size(image, 1), size(image, 2), 3); - segIm(:, :, 1) = segImR; - segIm(:, :, 2) = segImG; - segIm(:, :, 3) = segImB; + coloredIm = zeros(size(image, 1), size(image, 2), 3); + coloredIm(:, :, 1) = coloredImR; + coloredIm(:, :, 2) = coloredImG; + coloredIm(:, :, 3) = coloredImB; end diff --git a/Assignment_2/myNCuts.m b/Assignment_2/myNCuts.m index 9e2a6cf..78dd3a4 100644 --- a/Assignment_2/myNCuts.m +++ b/Assignment_2/myNCuts.m @@ -2,18 +2,25 @@ function clusterIdx = myNCuts (anAffinityMat, k) %Implementation of the N-cuts algorithm % Usage clusterIdx = myNCuts (anAffinityMat, k), where: % Inputs -% - anAffinityMat is a rectagular, symmetrical affinity matrix +% - anAffinityMat is a rectangular, symmetrical affinity matrix % representation of an image % - k is the desired number of clusters % Output % - clusterIdx is a vector storing the cluster Id of each node + % Makes sure preconditions are met if ~issymmetric(anAffinityMat) error('The affinity matrix provided is not symmetric.'); end + if k < 2 + error('The number of clusters must be greater than two.'); + end + % Calculates the eigenvectors D = diag(sum(anAffinityMat, 2)); - L = D - anAffinityMat; - [eigenvectorsMatrix, ~] = eigs(double(L), double(D), k, 'sm'); + [eigenvectorsMatrix, ~] = eigs(double(D - anAffinityMat), double(D), ... + k, 'sm'); + + % Does the clustering using K-Means clusterIdx = kmeans(eigenvectorsMatrix, k); end diff --git a/Assignment_2/mySpectralClustering.m b/Assignment_2/mySpectralClustering.m index de999f5..ec43376 100644 --- a/Assignment_2/mySpectralClustering.m +++ b/Assignment_2/mySpectralClustering.m @@ -2,17 +2,24 @@ function clusterIdx = mySpectralClustering (anAffinityMat, k) %Implementation of spectral clustering % Usage clusterIdx = mySpectralClustering (anAffinityMat, k), where: % Inputs -% - anAffinityMat is a rectagular, symmetrical affinity matrix +% - anAffinityMat is a rectangular, symmetrical affinity matrix % representation of an image % - k is the desired number of clusters % Output % - clusterIdx is a vector storing the cluster Id of each node + % Makes sure preconditions are met if ~issymmetric(anAffinityMat) error('The affinity matrix provided is not symmetric.'); end + if k < 2 + error('The number of clusters must be greater than two.'); + end - L = diag(sum(anAffinityMat, 2)) - anAffinityMat; - [eigenvectorsMatrix, ~] = eigs(double(L), k, 'sm'); + % Calculates the eigenvectors + [eigenvectorsMatrix, ~] = eigs(double( ... + diag(sum(anAffinityMat, 2)) - anAffinityMat), k, 'sm'); + + % Does the clustering using K-Means clusterIdx = kmeans(eigenvectorsMatrix, k); end diff --git a/Assignment_2/recursiveNCuts.m b/Assignment_2/recursiveNCuts.m index 6d78641..69df448 100644 --- a/Assignment_2/recursiveNCuts.m +++ b/Assignment_2/recursiveNCuts.m @@ -1,26 +1,43 @@ -function clusters = recursiveNCuts(graph) -%RECURSIVENCUTS Summary of this function goes here -% Detailed explanation goes here +function clusterIdx = recursiveNCuts(anAffinityMat) +%Implementation of the recursive N-cuts algorithm +% Usage clusters = recursiveNCuts (anAffinityMat), where: +% Inputs +% - anAffinityMat is a rectangular, symmetrical affinity matrix +% representation of an image +% Output +% - clusterIdx is a vector storing the cluster Id of each node - clusters = myNCuts(graph, 2); + % Makes sure preconditions are met + if ~issymmetric(anAffinityMat) + error('The affinity matrix provided is not symmetric.'); + end + + % Executes clustering using N-Cuts algorithm + clusterIdx = myNCuts(anAffinityMat, 2); - if (nnz(clusters == 1) < 5 || nnz(clusters == 2) < 5) + % Checks stop conditions + if (nnz(clusterIdx == 1) < 5 || nnz(clusterIdx == 2) < 5) return; end - - NCut = calculateNcut(graph, clusters); + NCut = calculateNcut(anAffinityMat, clusterIdx); if (NCut > 0.85) return; end - clusterOneIndices = (clusters == 1); - clusterTwoIndices = (clusters == 2); + % Finds indices of each cluster + clusterOneIndices = (clusterIdx == 1); + clusterTwoIndices = (clusterIdx == 2); - firstSubClusters = recursiveNCuts(graph(clusterOneIndices, clusterOneIndices')); - secondSubClusters = recursiveNCuts(graph(clusterTwoIndices, clusterTwoIndices')); + % Recursively calls itself for each part of the matrix + firstSubClusters = recursiveNCuts(anAffinityMat(clusterOneIndices, ... + clusterOneIndices)); + secondSubClusters = recursiveNCuts(anAffinityMat(clusterTwoIndices, ... + clusterTwoIndices)); + % Makes sure the IDs of the clusters of each half are unique secondSubClusters = secondSubClusters + size(unique(firstSubClusters), 1); - clusters(clusterOneIndices) = firstSubClusters; - clusters(clusterTwoIndices) = secondSubClusters; + % Re-merges the sub-cluster arrays + clusterIdx(clusterOneIndices) = firstSubClusters; + clusterIdx(clusterTwoIndices) = secondSubClusters; end