Может быть, это может помочь:
imdata = double(imread('test.jpg'));
tic
[m,n,~] = size(imdata);
pixels = m*n;
x = imdata(:,:,1)*1000000+imdata(:,:,2)*1000+imdata(:,:,3);
keys = unique(x);
n_keys = length(keys);
map = containers.Map(keys,zeros(n_keys,1));
for i = 1:pixels
map(x(i)) = map(x(i)) +1;
end
toc
%here comes post-processing
tic
b = rem(keys, 1000);
g = floor((rem(keys, 1000000) - b)/1000);
r = floor(keys/1000000);
v = map.values;
result = [r g b [v{:}]'];
toc
Я совершенно уверен, что это не самое быстрое и не самое элегантное решение. Что я пытался сделать:
Mare обратимое единственное значение для каждого существующего цвета
Использование уникальных значений в качестве ключей в объекте карты
Подсчет количества появлений для каждого значения
Последняя часть - необязательная - преобразование карты в массив с первыми 3 столбцами для цветовых компонентов и последним для числа внешности.
Я проверил это на простом изображении, как прикрепленное
Вы можете использовать его для тестов, оно 500x500 и имеет только 4 цвета. На моем P C прошло менее 7 секунд. И я попробовал это на реальном изображении 1080x1920 пикселей - это заняло 57 секунд. Я полагаю, довольно медленно. Итак, я попробовал другой подход - я заменил l oop на другой:
for i = 1:n_keys
map(keys(i)) = sum(sum(x==keys(i)));
end
Для маленького изображения это работало менее 0,05 секунды (воу!) - в этом случае у нас мало ключей, Итак, мы делаем несколько итераций. Но для большого - он имеет 271833 уникальных цвета - это заняло несколько минут, что делает этот подход неприемлемым. Если мы сможем сгруппировать закрывающие цвета в одну корзину - это будет работать быстрее.
Итак, я бы придерживался первого подхода.