MATLAB: применение прозрачной маски к изображению RGB и смешивание с другим

У меня есть 2 изображения: передний план и фон. Передний план представляет собой матрицу чисел от -50 до 300. Я отображаю ее через imagesc. (То есть это не изображение RGB). Фон представляет собой RGB-изображение.

Я хочу сначала применить маску прозрачности на переднем плане, чтобы изменить ее внешний вид. Это достаточно легко с помощью

altered_foreground = imagesc(foreground, 'AlphaData', Alphamask)

Теперь я хочу наложить altered_foreground поверх фона. Проблема в том, что, поскольку я уже использовал Alphamask на переднем плане, я не могу наложить его через:

imagesc(background)
hold on
bimage = imagesc(altered_foreground)
set(bimage, 'AlphaData', altered_foreground)

(не работает по сравнению с тем, если бы я просто хотел наложить неизмененный передний план на фон, где я бы использовал:

imagesc(background)
hold on
bimage = imagesc(foreground)
set(bimage, 'AlphaData', foreground)

Есть идеи?

ИЗМЕНИТЬ

Вот пример данных:

Передний план:


(источник: gawkerassets.com)

Скачать образ; Введите следующий код для его обработки:

Foreground = im2double(imread('500x_54.jpg'));
Foreground = Foreground + 50*randn(101,1);

Мой измененный передний план может быть чем-то простым, например, сделать первые 100 столбцов изображения полностью прозрачными (на самом деле это немного сложнее, я устанавливаю пороговые значения и тому подобное)

Задний план:

Аналогичным образом загрузите изображение и введите:

Background = imread('2-effect1-500x225.jpg');

person Briandmg    schedule 15.08.2014    source источник
comment
Взгляните на это. stackoverflow.com/q/25011048/3839249 Все еще изучаю вашу проблему.   -  person Yvon    schedule 15.08.2014
comment
Ах, этому парню повезло, что его передний план удерживает значения в фиксированном диапазоне чисел. Мои значения переднего плана являются переменными, не обязательно фиксированными от -50 до 300. Обычно они примерно там, но также могут сходить с ума от -100 до 1000:/   -  person Briandmg    schedule 15.08.2014
comment
Итак, вы предлагаете нормализовать мой передний план в значения RGB, а затем наложить его с помощью метода, показанного в ссылке?   -  person Briandmg    schedule 15.08.2014
comment
Сделанный. Это простой пример, но он должен делать.   -  person Briandmg    schedule 15.08.2014


Ответы (2)


РЕДАКТИРОВАТЬ: извините за неправильное понимание вашего вопроса вчера, так что вот ваша полноцветная версия: P


Основная идея почти такая же, как у MATLAB: объединить два изображения в градациях серого с разными альфа-каналами, но в вашем случае есть еще несколько маневров. нужно, чтобы получить правильные вещи.

Во-первых, воссоздайте свою хорошо описанную ситуацию с предоставленными образцами.

% load foreground image, and scale to [-50, 300]
Foreground = imread('500x_54.jpg');
figure(1)
imshow(Foreground)
Foreground = im2double(Foreground)*350-50;

% load background image
Background = im2double(imread('2-effect1-500x225.jpg'));
figure(2)
imshow(Background)

Затем сделайте альфа-канал с нуля. Обратите внимание, что я не использую imagesc, а пишу простой двойной массив. Это действительно альфа-канал! Не нужно столько загадок.

% build alpha layer for Foreground
alpha = bsxfun(@times, ones(size(Foreground,1), size(Foreground,2)), .6);
alpha(:,[1:53,149:203,290:352,447:end])=0;
alpha([1:58,170:end],:)=0;
figure(3)
imshow(alpha)

Перед смешиванием я хочу масштабировать передний план «назад» до [0,1]. Поскольку фоновое изображение загружается из обычного изображения, его нормализация не требуется; только передний план в диапазоне от -50 до 300.

Проблема в том, что иногда у вас есть сумасшедшие данные, такие как -100 или 1000. Я не знаю, как вы хотите их интерпретировать. Если вы принимаете [-50. 300] за обычный, типичный диапазон, то как вы сопоставляете -100 или 1000 с уровнем цвета?

Есть 2 варианта/метода для решения этой проблемы: 1) Использовать [-100, 1000] в качестве нового масштаба. Таким образом, -100 будет чисто черным и 1000 чистым цветом; 2) Продолжайте использовать [-50, 300] в качестве диапазона масштаба, поэтому все элементы за пределами этого диапазона будут сопоставлены (принудительно) к ближайшей границе.

Здесь я выбираю первый, с адаптивным механизмом, который ограничивает диапазон не менее [-50, 300]. Таким образом, если ваши данные имеют вид [-10,200], вы все равно получите шкалу [-50, 300]. Я думаю, что это имеет больше смысла.

% find a scale dynamically with some limit
Foreground_min = min( min(Foreground(:)), -50 );
Foreground_max = max( max(Foreground(:)), 300 );

Процедура смешивания почти такая же, как в этом посте. Но вы используете изображения RGB, поэтому вам нужно add числа для всех трех цветовых слоев; bsxfun используется для замены более медленных операций + и .*.

% overlay the image by blending
Background_blending = bsxfun(@times, Background, bsxfun(@minus,1,alpha));
% Background_blending = Background.*repmat((1-alpha), 1, 1, 3);
Foreground_blending = bsxfun( @times, bsxfun( @rdivide, ...
    bsxfun(@minus, Foreground, Foreground_min), ... 
    Foreground_max-Foreground_min ), alpha );
% Foreground_blending = (Foreground-Foreground_min) / ...
%     (Foreground_max-Foreground_min).*repmat(alpha, 1, 1, 3);
% out = bsxfun(@plus, Background_blending, Foreground_blending);
out = Background_blending + Foreground_blending;
figure(4)
imshow(out)

Закомментированные строки, кроме первой, представляют собой «обычные» команды назначения без использования bsxfun, но выполняют ту же работу и их легче понять :)

Результат

результат

person Yvon    schedule 15.08.2014
comment
Это хорошо. А если я хочу сохранить цвет? Замена imshow(...) на imagesc(...) не работает - person Briandmg; 15.08.2014
comment
@Briandmg imagesc не удовлетворяет ваши потребности, поскольку это инструмент сопоставления цветов, который сопоставляет индекс цвета с одним значением в индексированный цвет. Это ложный цвет. - person Yvon; 15.08.2014
comment
Вы имеете в виду режим смешивания цветов на этой странице? northlite.net/ps/blend.htm Тогда это немного другая история. - person Yvon; 15.08.2014
comment
Ой, извини. Я думаю, что я был немного двусмысленным в вопросе. Когда я сказал, что передний план не был RGB-изображением, я имел в виду, что значения не были в форме uint8 (все двойные значения). Я использовал изображение в ложных цветах imagesc, чтобы принудительно использовать значения для изображения. В данном случае под сохранением цвета я подразумеваю скорее применение эффекта растворения, который вы применили к северному свету, связанному с передним планом. Таким образом, 3 персонажа Марио должны быть растворены (их цвета все еще на месте), но вы все равно можете видеть фон за ними. - person Briandmg; 15.08.2014
comment
Да, и передний план, и фон по-прежнему являются цветным изображением. Извините за недопонимание :( - person Briandmg; 15.08.2014
comment
@Briandmg Я также был ответственен за наше недопонимание. Я обновил свой ответ. Пожалуйста, взгляните. - person Yvon; 15.08.2014
comment
Спасибо! Вы были максимально полезными :) - person Briandmg; 18.08.2014

Я опаздываю на шоу, но все же думаю, что у меня есть полезная информация для других, которые найдут эту тему, например, я сам нашел эту тему в поисках какого-то решения. Ну, в конце концов я просто использовал встроенную функцию imlincomb() для смешивания изображений RGB, к которой у меня, к счастью, есть доступ с помощью панели инструментов обработки изображений. В любом случае, я также проголосовал за ответ Ивона, потому что не у всех есть IPT, и этот ответ многому научит.

OUT = imlincomb(scalaralphavalue, FOREGROUNDIMAGE, (1-scalaralphavalue), BACKGROUNDIMAGE)

Это дает тот же результат, что и использование чего-то на основе этого базового кода:

OUT = FOREGROUND .* ALPHA  + BACKGROUND .* (1-ALPHA)

Если вы работаете не с индексированными файлами RGB, а со значениями интенсивности, вы можете подумать о правильном масштабировании значений интенсивности, например, в диапазоне от 0 до 1, выполнив следующие действия:

ARRAY= (ARRAY - min(ARRAY(:))) / (max(ARRAY(:)) - min(ARRAY(:)))

Ну, приспособьте это к своим потребностям...

person Talby    schedule 10.09.2014