Skip to content

Commit

Permalink
Reduce number of color space conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
linusmossberg committed Mar 27, 2020
1 parent f9d0ba9 commit 7c85dc8
Show file tree
Hide file tree
Showing 13 changed files with 71 additions and 64 deletions.
6 changes: 3 additions & 3 deletions source/button-matching/createButtonMosaic.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
% button_history, similarity_threshold, min_dominant_radius,
% unique_button_limit, scale, AA

function [mosaic, corrected] = createButtonMosaic(circles, image, S)
function [mosaic, corrected] = createButtonMosaic(circles, image_lab, S)

search_settings.num_matches = S.button_history;
search_settings.similarity_threshold = S.similarity_threshold;
Expand All @@ -11,7 +11,7 @@

clear findMatchingButtons;
if(search_settings.use_subset)
createLimitedDatabase(image, S.unique_button_limit);
createLimitedDatabase(image_lab, S.unique_button_limit);
end

if nargin < 3 || ~isPowerOfTwo(S.scale)
Expand All @@ -22,7 +22,7 @@
S.AA = 1;
end

dims = size(image, 1:2);
dims = size(image_lab, 1:2);
mosaic = zeros([dims * S.AA * S.scale, 3]);

produce_corrected = nargout > 1;
Expand Down
18 changes: 9 additions & 9 deletions source/buttonMosaic.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
addpath(genpath('.'));
warning('off','images:bwfilt:tie');

image = im2double(image);
image_lab = rgb2lab(im2double(image));

if nargin < 3
[circle_packing_settings, mosaic_settings] = estSettings(image);
[circle_packing_settings, mosaic_settings] = estSettings(image_lab);
end

label_image = segmentImage(image, circle_packing_settings);
circles = createPackedCircles(image, label_image, circle_packing_settings);
label_image = segmentImage(image_lab, circle_packing_settings);
circles = createPackedCircles(image_lab, label_image, circle_packing_settings);

if nargout > 1
[mosaic, corrected] = createButtonMosaic(circles, image, mosaic_settings);
[mosaic, corrected] = createButtonMosaic(circles, image_lab, mosaic_settings);
else
mosaic = createButtonMosaic(circles, image, mosaic_settings);
mosaic = createButtonMosaic(circles, image_lab, mosaic_settings);
end
end

function [circle_packing_settings, mosaic_settings] = estSettings(image)
width = size(image, 2);
function [circle_packing_settings, mosaic_settings] = estSettings(image_lab)
width = size(image_lab, 2);
est_factor = width/1024;
[num_clusters, low_unique] = findNumClusters(image);
[num_clusters, low_unique] = findNumClusters(image_lab);

disp(['Number of clusters: ' num2str(num_clusters)])

Expand Down
20 changes: 10 additions & 10 deletions source/circle-packing/createPackedCircles.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
% S requires the fields:
% min_radius, max_radius, radius_reduction_start

function circles = createPackedCircles(image, label_image, S)
function circles = createPackedCircles(image_lab, label_image, S)
num_regions = max(label_image(:));

circles = [];
Expand Down Expand Up @@ -29,10 +29,10 @@
BB(2) = clamp(BB(2) - 1, 1, h);

small_mask = mask(BB(2):BB(2)+BB(4)-1, BB(1):BB(1)+BB(3)-1);
small_image = image(BB(2):BB(2)+BB(4)-1, BB(1):BB(1)+BB(3)-1, :);
small_image_lab = image_lab(BB(2):BB(2)+BB(4)-1, BB(1):BB(1)+BB(3)-1, :);
offset = [BB(1) - 1, BB(2) - 1];
else
small_image = image;
small_image_lab = image_lab;
small_mask = remaining;
offset = [0, 0];
end
Expand Down Expand Up @@ -61,7 +61,7 @@

radius = floor(radius);

[small_mask, circles] = createCircle(small_image, circles, centroid, radius, small_mask, offset);
[small_mask, circles] = createCircle(small_image_lab, circles, centroid, radius, small_mask, offset);
end

if(i <= (num_regions - 1))
Expand All @@ -85,7 +85,7 @@
close(f)
end

function [L, circles] = createCircle(image, circles, centroid, radius, L, offset)
function [L, circles] = createCircle(image_lab, circles, centroid, radius, L, offset)

new_circle = struct;

Expand All @@ -102,15 +102,15 @@
region(circle) = false;
L(x_range, y_range) = region;

rgb_region = image(x_range, y_range, :);
lab_region = image_lab(x_range, y_range, :);

new_circle.dominant_colors = kDominantColors(rgb_region, circle, 3, 20000, 3);
new_circle.dominant_colors = kDominantColors(lab_region, circle, 3, 20000, 3);
new_circle.radius = radius;
new_circle.position = offset + centroid;

colors = reshape(rgb_region, [], 3);
colors = colors(circle(:), :);
new_circle.mean_color_lab = mean(rgb2lab(colors));
colors_lab = reshape(lab_region, [], 3);
colors_lab = colors_lab(circle(:), :);
new_circle.mean_color_lab = mean(colors_lab);

circles = [circles new_circle];
end
14 changes: 6 additions & 8 deletions source/circle-packing/findNumClusters.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
function [num_clusters, low_unique] = findNumClusters(image)
function [num_clusters, low_unique] = findNumClusters(image_lab)

max_clusters = 16;

num_unique_colors = size(unique(reshape(im2uint8(image), [], 3), 'rows'), 1);
num_unique_colors = size(unique(reshape(im2uint8(lab2rgb(image_lab)), [], 3), 'rows'), 1);

low_unique = false;
if num_unique_colors <= max_clusters
Expand All @@ -11,22 +11,20 @@
return;
end

num_colors = prod(size(image, 1:2));
num_colors = prod(size(image_lab, 1:2));
max_colors = 256*256;

if(num_colors > max_colors)
image = imresize(image, sqrt(max_colors/num_colors), 'bilinear');
image_lab = imresize(image_lab, sqrt(max_colors/num_colors), 'bilinear');
end

image = rgb2lab(image);

image_vec = reshape(image, [], 3);
colors_lab = reshape(image_lab, [], 3);

kmeans_func = @(X,K)(kmeans(X, K, 'MaxIter', 10000, ...
'Options', statset('UseParallel',1), ...
'Replicates', 3));

evaluation = evalclusters(image_vec, kmeans_func, 'CalinskiHarabasz', 'KList', 1:max_clusters);
evaluation = evalclusters(colors_lab, kmeans_func, 'CalinskiHarabasz', 'KList', 1:max_clusters);

num_clusters = evaluation.OptimalK;
end
6 changes: 3 additions & 3 deletions source/circle-packing/segmentImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
% smooth_est_scale, num_clusters, label_min_area,
% label_close_radius, min_radius

function label_image = segmentImage(image, S)
function label_image = segmentImage(image_lab, S)

lab_image = rgb2lab(smoothColor(image, S.smooth_est_scale));
lab_image = smoothColor(image_lab, S.smooth_est_scale);
colors_lab = reshape(lab_image, [], 3);

rng(1);
Expand All @@ -14,7 +14,7 @@
'Options', statset('UseParallel',1), ...
'Replicates', 5);

label_image = reshape(label_vec, size(image, 1:2));
label_image = reshape(label_vec, size(image_lab, 1:2));

for i = 1:max(label_image(:))
mask = label_image == i;
Expand Down
7 changes: 6 additions & 1 deletion source/circle-packing/smoothColor.m
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
function image = smoothColor(image, scale)
function image_lab = smoothColor(image_lab, scale)

if scale <= 0 || scale > 1
return;
end

image = lab2rgb(image_lab);

f = waitbar(0, 'Smoothing image colors');
for i = 1:3
image(:,:,i) = diffuseWithEst(image(:,:,i), scale);
waitbar(i/3, f, 'Smoothing image colors');
end

image_lab = rgb2lab(image);

close(f)
end

Expand Down
12 changes: 6 additions & 6 deletions source/database/createButtonDatabase.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,16 @@ function saveImage(image, alpha, prefix, folder)
db_info_filename = strcat(folder, '\buttons.mat');

mask = alpha > 128;
image = im2double(image);
image_lab = rgb2lab(im2double(image));

entry.dominant_colors = kDominantColors(image, mask, 3, 20000, 5);
entry.dominant_colors = kDominantColors(image_lab, mask, 3, Inf, 5);

colors = reshape(image, [], 3);
colors = colors(mask(:), :);
entry.mean_color_lab = mean(rgb2lab(colors));
colors_lab = reshape(image_lab, [], 3);
colors_lab = colors_lab(mask(:), :);
entry.mean_color_lab = mean(colors_lab);

entry.filename = filename;
entry.diameter = size(image, 1);
entry.diameter = size(image_lab, 1);

if ~isfile(db_info_filename)
data = entry;
Expand Down
8 changes: 4 additions & 4 deletions source/database/createLimitedDatabase.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function createLimitedDatabase(image, num_buttons)
colors_lab = reshape(rgb2lab(image), [], 3);
function createLimitedDatabase(image_lab, num_buttons)
colors_lab = reshape(image_lab, [], 3);

[label_vec, ~] = kmeans(colors_lab, num_buttons, ...
'MaxIter', 10000);
Expand All @@ -8,8 +8,8 @@ function createLimitedDatabase(image, num_buttons)

buttons_subset = struct;
for i = 1:max(label_vec)
mask = reshape(label_vec == i, size(image, 1:2));
dominant_colors = kDominantColors(image, mask, 3, Inf, 5);
mask = reshape(label_vec == i, size(image_lab, 1:2));
dominant_colors = kDominantColors(image_lab, mask, 3, Inf, 5);
buttons_subset.data(i) = findBestButton(dominant_colors);
end
data = buttons_subset.data;
Expand Down
10 changes: 5 additions & 5 deletions source/database/recomputeColorInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ function recomputeColorInfo()
entry = buttons.data(i);
[image, ~, alpha] = imread(sprintf('../buttons/%s', entry.filename));
mask = alpha > 128;
image = im2double(image);
image_lab = rgb2lab(im2double(image));

entry.dominant_colors = kDominantColors(image, mask, 3, Inf, 5);
entry.dominant_colors = kDominantColors(image_lab, mask, 3, Inf, 5);

colors = reshape(image, [], 3);
colors = colors(mask(:), :);
entry.mean_color_lab = mean(rgb2lab(colors));
colors_lab = reshape(image_lab, [], 3);
colors_lab = colors_lab(mask(:), :);
entry.mean_color_lab = mean(colors_lab);

buttons.data(i) = entry;

Expand Down
6 changes: 3 additions & 3 deletions source/lib/scielab/deltaLab.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
% delta E, using the numbers in k94 as the k parameter (see
% deltaE94). If k94 is only one number, use the default k=[1 1 1].
%
% Functions called: xyz2lab, deltaE94.
% Functions called: xyz2lab_cie, deltaE94.
%
% Xuemei Zhang 10/26/95
% Last modified 4/15/98
Expand All @@ -34,8 +34,8 @@
xyz2 = reshape(xyz2, prod(m)/3, 3);
end

lab1 = xyz2lab(xyz1, whitepoint, exp);
lab2 = xyz2lab(xyz2, whitepoint, exp);
lab1 = xyz2lab_cie(xyz1, whitepoint, exp);
lab2 = xyz2lab_cie(xyz2, whitepoint, exp);

if (nargin>4)
if (length(k94)<3)
Expand Down
2 changes: 1 addition & 1 deletion source/lib/scielab/scielab.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
% Functions called: changeColorSpace, cmatrix,
% getPlanes, pad4conv, resize, deltaLab,
% separableFilters, separableConv.
% (implicit: gauss, gauss2, sumGauss, xyz2lab).
% (implicit: gauss, gauss2, sumGauss, xyz2lab_cie).
%
% Xuemei Zhang 1/28/96
% Last Modified 4/15/98
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function lab = xyz2lab(xyz, whitepoint, exp)
% xyz2lab(xyz,whitepoint,exp)
function lab = xyz2lab_cie(xyz, whitepoint, exp)
% xyz2lab_cie(xyz,whitepoint,exp)
%
% Converts colors in XYZ coordinates into CIEL*a*b* coordinates.
%
Expand Down
22 changes: 13 additions & 9 deletions source/util/kDominantColors.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function result = kDominantColors(image, mask, k, max_colors, replicates, should_plot)
function result = kDominantColors(image_lab, mask, k, max_colors, replicates, should_plot)

if nargin < 6
should_plot = false;
Expand All @@ -17,29 +17,33 @@
% It does however become trivial to determine dominant colors in such
% cases.

color_samples = reshape(imresize(image, resize_scale, 'nearest'), [], 3);
color_samples = color_samples(mask(:), :);
unique_colors = uniquetol(color_samples, 1e-3, 'ByRows', true);
colors_lab = reshape(imresize(image_lab, resize_scale, 'nearest'), [], 3);
colors_lab = colors_lab(mask(:), :);
unique_colors = uniquetol(colors_lab, 1e-3, 'ByRows', true);
num_unique_colors = size(unique_colors, 1);

if(num_unique_colors <= k)
result.dominance = zeros(1, k);
result.colors_lab = zeros(k, 3);
for i = 1:num_unique_colors
c = unique_colors(i, :);
result.dominance(i) = sum(sum(abs(color_samples - c), 2) <= 1e-3);
result.colors_lab(i, :) = rgb2lab(c);
result.dominance(i) = sum(sum(abs(colors_lab - c), 2) <= 1e-3);
result.colors_lab(i, :) = c;
end
result.dominance = result.dominance / sum(result.dominance);

[~,idx] = sort(result.dominance, 'descend');
result.dominance = result.dominance(idx);
result.colors_lab = result.colors_lab(idx, :);
else
interpolated_color_samples = reshape(imresize(image, resize_scale, 'bilinear'), [], 3);
interpolated_color_samples = interpolated_color_samples(mask(:), :);

colors_lab = rgb2lab(interpolated_color_samples);
if resize_scale ~= 1
image_lab = imresize(image_lab, resize_scale, 'bilinear');
end

colors_lab = reshape(image_lab, [], 3);
colors_lab = colors_lab(mask(:), :);

[L, dominant_colors] = kmeans(colors_lab, k, 'MaxIter', 10000, ...
'Options', statset('UseParallel',1), ...
'Replicates', replicates);
Expand Down

0 comments on commit 7c85dc8

Please sign in to comment.