Skip to content

Commit

Permalink
Removed thresholding during colour classification.
Browse files Browse the repository at this point in the history
- Also integrated classifier construction function into probe detection.
  • Loading branch information
bllanos committed Jun 19, 2017
1 parent f980178 commit 0f794c3
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 85 deletions.
14 changes: 7 additions & 7 deletions DetectProbe.m
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
request_bounding_region = false;

% Determination of the probe's bounding region
detectBoundingBoxesParams.noise_threshold = []; % If empty, select automatically using Otsu's method
erosion_radius_initial = 5;
detectBoundingBoxesParams.erosion_radius = erosion_radius_initial;
detectBoundingBoxesParams.radius_adj = 2 * erosion_radius_initial + 10;
Expand All @@ -155,7 +154,6 @@
detectBoundingBoxesParams.region_expansion_factor_width = 1.5;

% Determination of refined probe colour regions
detectWithinBoundingBoxParams.noise_threshold = []; % If empty, select automatically using Otsu's method
erosion_radius_final = 2;
detectWithinBoundingBoxParams.erosion_radius = erosion_radius_final;
detectWithinBoundingBoxParams.radius_adj = 2 * erosion_radius_final + 4;
Expand Down Expand Up @@ -183,15 +181,17 @@
detectBoundingBoxesVerbose.display_original_image = false;
detectBoundingBoxesVerbose.display_hue_image = false;
detectBoundingBoxesVerbose.plot_hue_estimator = true;
detectBoundingBoxesVerbose.display_distribution_backprojections = false;
detectBoundingBoxesVerbose.display_binary_images = false;
detectBoundingBoxesVerbose.plot_hue_classifier = true;
detectBoundingBoxesVerbose.display_distribution_backprojections = true;
detectBoundingBoxesVerbose.display_binary_images = true;
detectBoundingBoxesVerbose.verbose_region_filtering = false;
detectBoundingBoxesVerbose.display_region_expansion = false;
detectBoundingBoxesVerbose.display_region_expansion = true;

detectWithinBoundingBoxVerbose.display_hue_image = false;
detectWithinBoundingBoxVerbose.plot_hue_estimator = true;
detectWithinBoundingBoxVerbose.display_distribution_backprojections = false;
detectWithinBoundingBoxVerbose.display_binary_images = false;
detectWithinBoundingBoxVerbose.plot_hue_classifier = true;
detectWithinBoundingBoxVerbose.display_distribution_backprojections = true;
detectWithinBoundingBoxVerbose.display_binary_images = true;
detectWithinBoundingBoxVerbose.verbose_region_filtering = false;
detectWithinBoundingBoxVerbose.display_regions_colored = false;
detectWithinBoundingBoxVerbose.display_band_edge_extraction = false;
Expand Down
7 changes: 3 additions & 4 deletions detectBoundingBoxes.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@
% params -- Fixed parameters
% Parameters that should be stable across a variety of input images and
% probe models. `params` is a structure containing the following fields:
% - noise_threshold: Threshold for identifying noise pixels in
% histogram backprojections. If empty (`[]`), a threshold will be
% selected automatically using Otsu's method.
% - erosion_radius: Radius for morphological erosion of the binary images
% describing the probe colour regions. The `radius` parameter of
% 'extractBinaryRegions()'
Expand Down Expand Up @@ -116,6 +113,7 @@
display_original_image = verbose.display_original_image;
extractBinaryRegionsVerbose.display_hue_image = verbose.display_hue_image;
extractBinaryRegionsVerbose.plot_hue_estimator = verbose.plot_hue_estimator;
extractBinaryRegionsVerbose.plot_hue_classifier = verbose.plot_hue_classifier;
extractBinaryRegionsVerbose.display_distribution_backprojections = verbose.display_distribution_backprojections;
extractBinaryRegionsVerbose.display_binary_images = verbose.display_binary_images;
verbose_region_filtering = verbose.verbose_region_filtering;
Expand All @@ -124,6 +122,7 @@
display_original_image = false;
extractBinaryRegionsVerbose.display_hue_image = false;
extractBinaryRegionsVerbose.plot_hue_estimator = false;
extractBinaryRegionsVerbose.plot_hue_classifier = false;
extractBinaryRegionsVerbose.display_distribution_backprojections = false;
extractBinaryRegionsVerbose.display_binary_images = false;
verbose_region_filtering = false;
Expand All @@ -146,7 +145,7 @@

[ probe_regions_initial, probe_regions_bw_initial] = extractBinaryRegions(...
I, probe_color_distributions, probe_color_distribution_resolution,...
rgb_sigma_polyfit, params.noise_threshold,...
rgb_sigma_polyfit,...
params.erosion_radius,...
[],...
extractBinaryRegionsVerbose...
Expand Down
6 changes: 2 additions & 4 deletions detectWithinBoundingBox.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@
% params -- Fixed parameters
% Parameters that should be stable across a variety of input images and
% probe models. `params` is a structure containing the following fields:
% - noise_threshold: Threshold for identifying noise pixels in
% histogram backprojections. If empty (`[]`), a threshold will be
% selected automatically using Otsu's method.
% - erosion_radius: Radius for morphological erosion of the binary images
% describing the probe colour regions. The `radius` parameter of
% 'extractBinaryRegions()'
Expand Down Expand Up @@ -147,6 +144,7 @@
verbose = varargin{1};
extractBinaryRegionsVerbose.display_hue_image = verbose.display_hue_image;
extractBinaryRegionsVerbose.plot_hue_estimator = verbose.plot_hue_estimator;
extractBinaryRegionsVerbose.plot_hue_classifier = verbose.plot_hue_classifier;
extractBinaryRegionsVerbose.display_distribution_backprojections = verbose.display_distribution_backprojections;
extractBinaryRegionsVerbose.display_binary_images = verbose.display_binary_images;
verbose_region_filtering = verbose.verbose_region_filtering;
Expand All @@ -156,6 +154,7 @@
else
extractBinaryRegionsVerbose.display_hue_image = false;
extractBinaryRegionsVerbose.plot_hue_estimator = false;
extractBinaryRegionsVerbose.plot_hue_classifier = false;
extractBinaryRegionsVerbose.display_distribution_backprojections = false;
extractBinaryRegionsVerbose.display_binary_images = false;
verbose_region_filtering = false;
Expand All @@ -176,7 +175,6 @@
[ probe_regions_final, probe_regions_bw_final] = extractBinaryRegions(...
I, probe_color_distributions, probe_color_distribution_resolution,...
rgb_sigma_polyfit,...
params.noise_threshold,...
params.erosion_radius,...
mask,...
extractBinaryRegionsVerbose...
Expand Down
113 changes: 44 additions & 69 deletions extractBinaryRegions.m
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
function [ regions, bw ] = extractBinaryRegions(...
I, color_distributions, color_distribution_resolution,...
rgb_sigma_polyfit, threshold, radius, varargin...
rgb_sigma_polyfit, radius, varargin...
)
% EXTRACTBINARYREGIONS Threshold and refine binary regions
%
% ## Syntax
% regions = extractBinaryRegions(...
% I, color_distributions, color_distribution_resolution,...
% rgb_sigma_polyfit, threshold, radius [, mask, verbose]...
% rgb_sigma_polyfit, radius [, mask, verbose]...
% )
% [ regions, bw ] = extractBinaryRegions(...
% I, color_distributions, color_distribution_resolution,...
% rgb_sigma_polyfit, threshold, radius [, mask, verbose]...
% rgb_sigma_polyfit, radius [, mask, verbose]...
% )
%
% ## Description
% regions = extractBinaryRegions(...
% I, color_distributions, color_distribution_resolution,...
% rgb_sigma_polyfit, threshold, radius [, mask, verbose]...
% rgb_sigma_polyfit, radius [, mask, verbose]...
% )
% Returns binary regions corresponding to each colour probability
% distribution.
%
% [ regions, bw ] = extractBinaryRegions(...
% I, color_distributions, color_distribution_resolution,...
% rgb_sigma_polyfit, threshold, radius [, mask, verbose]...
% rgb_sigma_polyfit, radius [, mask, verbose]...
% )
% Additionally returns binary images corresponding to the binary regions.
%
% ## Input Arguments
%
% I -- Image
% An RGB image in which the colours described by `color_distributions`
% An RGB image, in which the colours described by `color_distributions`
% are to be detected.
%
% color_distributions -- Colour estimators
Expand All @@ -53,16 +53,6 @@
% Refer to the documentation of './EstimateRGBStandardDeviations.m' for
% details.
%
% threshold -- Threshold identifying poorly-distinguished pixels
% The threshold applied to the probabilities assigned to pixels in `I`
% from the distributions in `color_distributions` which eliminates pixels
% which are not strongly selected by any distribution.
%
% If empty, Otsu's method will be used to select the threshold
% automatically.
%
% Refer the discussion of the algorithm below for details.
%
% radius -- Radius of disk structuring element
% The radius passed in `strel('disk', radius)` when creating a
% structuring element to erode the final binary images prior to extraction
Expand Down Expand Up @@ -93,20 +83,6 @@
% the binary image consisting of the connected components in
% `regions(i)`.
%
% ## Algorithm
%
% To extract the regions which appear to correspond to a given colour
% class, as dictated by a probability distribution, it is sufficient to
% threshold the greyscale image formed by backprojecting the probability
% distribution. This function does so, optionally choosing the threshold
% using Otsu's method.
%
% For this application, there are multiple colour classes. Therefore, the
% thresholding is performed on the colour class which gives the given pixel
% the highest probability. This is a simple approximation to a
% multi-labelling optimization problem (which could be solved with
% alpha-expansion, for example).
%
% See also bwconncomp, otsuthresh, imbinarize, imerode, mlDiscreteClassifier

% Bernard Llanos
Expand All @@ -131,11 +107,13 @@
verbose = varargin{2};
display_hue_image = verbose.display_hue_image;
plot_hue_estimator = verbose.plot_hue_estimator;
plot_hue_classifier = verbose.plot_hue_classifier;
display_distribution_backprojections = verbose.display_distribution_backprojections;
display_binary_images = verbose.display_binary_images;
else
display_hue_image = false;
plot_hue_estimator = false;
plot_hue_classifier = false;
display_distribution_backprojections = false;
display_binary_images = false;
end
Expand Down Expand Up @@ -181,56 +159,53 @@
title('Hue density estimators')
end

% Transform the image using histogram backprojection
n_colors_plus_background = n_colors + 1;
distributions_backprojected = zeros(image_height, image_width, n_colors_plus_background);
for i = 1:n_colors
distributions_backprojected(:, :, i) = queryDiscretized1DFunction(...
H, color_distributions(:, i), I_color_distribution_increment...
);
end
distributions_backprojected(:, :, n_colors_plus_background) = queryDiscretized1DFunction(...
H, I_color_distribution, I_color_distribution_increment...
);

if display_distribution_backprojections
for i = 1:n_colors
figure
imshow(distributions_backprojected(:, :, i));
title(sprintf('Distribution backprojection for probe colour %d', i))
end
figure
imshow(...
distributions_backprojected(:, :, n_colors_plus_background) /...
max(max(distributions_backprojected(:, :, n_colors_plus_background)))...
);
title('Distribution backprojection for the background')
[color_classifier, color_classification_likelihood] = mlDiscreteClassifier(...
color_distributions, I_color_distribution_increment, I_color_distribution...
);
else
color_classifier = mlDiscreteClassifier(...
color_distributions, I_color_distribution_increment, I_color_distribution...
);
end

use_otsu = isempty(threshold);
if plot_hue_classifier
plotHueClassifier(...
I_color_distribution_increment, color_classifier,...
n_colors...
);
title('Hue classifier for colors on the probe vs. the interest area')
end

% Find the most likely colour class for each pixel
[~, max_ind] = max(distributions_backprojected, [], 3);
H_masked = H(mask);
max_ind_masked = queryDiscretized1DFunction(...
H_masked, color_classifier, I_color_distribution_increment...
);
max_ind = zeros(image_height, image_width);
max_ind(mask) = max_ind_masked;
foreground_mask = (max_ind ~= 0);
x = 0:(image_width - 1);
y = 1:image_height;
[X,Y] = meshgrid(x,y);
max_ind_linear = Y + X .* image_height + (max_ind - 1) .* (image_width * image_height);
bw = false(image_height, image_width, n_colors_plus_background);
bw(max_ind_linear) = true;
bw = bw(:, :, 1:(end - 1));
max_ind_linear_masked = max_ind_linear(foreground_mask);
bw = false(image_height, image_width, n_colors);
bw(max_ind_linear_masked) = true;

% Threshold probabilities for each colour
for i = 1:n_colors
distributions_backprojected_i = distributions_backprojected(:, :, i);
if use_otsu
counts_i = imhist(distributions_backprojected_i(mask));
threshold_i = otsuthresh(counts_i);
bw(:, :, i) = bw(:, :, i) & imbinarize(distributions_backprojected_i, threshold_i);
else
bw(:, :, i) = bw(:, :, i) & imbinarize(distributions_backprojected_i, threshold);
% Transform the image using histogram backprojection
if display_distribution_backprojections
max_probability_masked = queryDiscretized1DFunction(...
H_masked, color_classification_likelihood, I_color_distribution_increment...
);
max_probability_masked = max_probability_masked(max_ind_masked ~= 0);
distributions_backprojected = zeros(image_height, image_width, n_colors);
distributions_backprojected(max_ind_linear_masked) = max_probability_masked;
for i = 1:n_colors
figure
imshow(distributions_backprojected(:, :, i));
title(sprintf('Distribution backprojection for probe colour %d', i))
end
% Apply the mask
bw(:, :, i) = bw(:, :, i) & mask;
end

% Obtain binary regions.
Expand Down
2 changes: 1 addition & 1 deletion mlDiscreteClassifier.m
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
% University of Alberta, Department of Computing Science
% File created May 26, 2017

nargoutchk(1, 1);
nargoutchk(1, 2);
narginchk(2, 3);

periodic = false;
Expand Down

0 comments on commit 0f794c3

Please sign in to comment.