Построить обратные цвета в Matlab?

Я рисую поверх изображения в Matlab. Иногда я не вижу, что вычерчивается, потому что цвет изображения под ним слишком близок к цвету изображения в том же месте. Я всегда мог просто изменить цвет графика (например, с «rx» на «bx»), но это громоздко.

Можно ли нарисовать обратный цвет того, что находится внизу, чтобы наложение всегда было видно?


person Benjamin Oakes    schedule 03.03.2010    source источник


Ответы (4)


Я считаю, что невозможно автоматически инвертировать цвет графика на основе фонового изображения. Вероятно, вы можете растрировать сюжет и как-то совместить его с изображением (xor?).

Вот еще одно решение. Если вы можете использовать закрытые маркеры, такие как круг, квадрат, треугольник, вы можете установить разные MarkerEdgeColor и MarkerFaceColor, чтобы маркер был виден на фоне разных цветов.

h = plot(1:5,'o');
set(h,'MarkerEdgeColor','b')
set(h,'MarkerFaceColor','r')
person yuk    schedule 03.03.2010

Это возможно.

Предполагая, что вы знаете, на что похоже ваше изображение, вы можете сделать следующее:

  1. Считайте цвет в координатах, над которыми вы рисуете

  2. Инвертировать цвет

  3. Используйте разброс

    %# загрузите цветное изображение rgb - возможно, это не лучший пример, так как он такой темный. X = двойной (imread ('ngc6543a.jpg'))/255; %#, поскольку это довольно темное изображение, инвертируйте его половину X(:,1:floor(size(X,2)/2),:) = 1-X(:,1:floor(size(X,2) /2),:);

    %# создать некоторые данные графика plotX = rand(50,1) * size(X,1); plotY = ранд (50,1) * размер (X, 2);

    %# читать компоненты RGB (должна быть возможность сделать это более эффективно, но я не вижу %# этого прямо сейчас plotColors = zeros(length(plotX),3); for c = 1:3 plotColors(:,c ) = interp2(X(:,:,c),графикY,графикX); конец

    %# инвертировать plotColors = 1-plotColors; %# Если вам нужны очень разные цвета и вы избегаете проблемы, связанной с тем, что серый является инверсией %# к серому, вы можете использовать %# plotColors = round(1-plotColors); %# Это дает вам выбор wrgbcmyk, в зависимости от того, что дальше всего от цвета изображения.

    %# график рисунка, imshow (X) удерживать разброс (plotY, plotX, [], plotColors)

Редактировать: теперь это было протестировано, и оно должно работать.

Edit2: инвертирование половины исходного изображения проясняет, как это работает

Edit3: включена модифицированная форма предложения gnovice.

Edit4: исправлена ​​​​ошибка, как указано AB

person Jonas    schedule 03.03.2010
comment
Один небольшой недостаток... Инверсия не даст очень четких цветов, когда они близки к [0,5 0,5 0,5]. Возможно, было бы лучше выбрать либо белый, либо черный, исходя из того, какой из них дальше всего от цвета пикселя (то есть самая большая общая разница в значениях RGB). - person gnovice; 03.03.2010
comment
Хорошая точка зрения. Я предполагаю, что вместо использования инверсии (о чем просил ОП) можно было бы использовать округленную инверсию. - person Jonas; 04.03.2010

Я не знаю автоматического способа изменить цвет нанесенных точек в зависимости от цвета пикселя за ними. Имейте в виду, что вам необходимо использовать только ссылку восемь предопределенных спецификаций цвета (например, 'r' для красного или 'b' для синего). Вы можете выбрать цветовую спецификацию RGB для нанесенных точек, которая не характерна для основного изображения. Например:

h = plot(0,0,'Marker','x','Color',[1 0.4 0.6]);  %# Plot a pink x

Вы можете программно найти наименее распространенный цвет с помощью простого кода, который выбирает наименее часто используемые значения цвета в изображении. Вот один пример:

rawData = imread('peppers.png');  %# Read a sample RGB image
imData = reshape(rawData,[],3);   %# Reshape the image data
N = hist(double(imData),0:255);   %# Create a histogram for the RGB values
[minValue,minIndex] = min(N);     %# Find the least used RGB values
plotColor = (minIndex-1)./255;    %# The color for the plotted points
image(rawData);                   %# Plot the image
hold on;
hp = plot(500.*rand(1,20),350.*rand(1,20),...  %# Plot some random points
          'Marker','o','LineStyle','none',...
          'MarkerFaceColor',plotColor,'MarkerEdgeColor',plotColor);

Приведенный выше код сначала преобразует данные изображения в матрицу M на 3, где M — количество пикселей изображения, а три столбца содержат значения красного, зеленого и синего соответственно. Для каждого столбца выполняется объединение значений с использованием HIST, то для каждого столбца находится значение с наименьшим бином (т. е. с самой низкой частотой). Эти три значения становятся тройкой RGB для цвета графика. Когда на изображение накладываются случайные точки этого цвета, получается следующий сюжет:

альтернативный текст

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

person gnovice    schedule 03.03.2010
comment
Только представьте, как это не получится на GIF почти любой естественной сцены :-) - person AVB; 04.03.2010
comment
@AB: По общему признанию, это довольно простой алгоритм, который я использовал в качестве примера, поэтому могут быть некоторые изображения, к которым было бы сложно применить такой подход. Но в целом он должен в конечном итоге выбрать цвет, который мало используется, сводя к минимуму вероятность того, что точки окажутся над совпадающим пикселем. - person gnovice; 04.03.2010
comment
Мне нравится эта идея. Однако я бы использовал только, скажем, 16 бинов, чтобы найти «цветовую область», которая используется реже всего. Затем вы можете либо выбрать центр корзины в качестве цвета графика, либо выполнить другой поиск в регионе. - person Jonas; 04.03.2010
comment
@Jonas: Интересная идея. Вероятно, существует множество вариантов кода, который можно было бы сделать. Я просто предложил идею простого алгоритма в качестве пищи для размышлений. - person gnovice; 04.03.2010

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

%# load rgb color image
X = double(imread('ngc6543a.jpg'))/255;
%# since it's quite a dark image, invert half of it
X(:,1:floor(size(X,2)/2),:) = 1-X(:,1:floor(size(X,2)/2),:);

%# create some plot data
plotX = rand(50,1) * size(X,1);
plotY = rand(50,1) * size(X,2);

%# plot
figure,imshow(X)
hold on
scatter(plotY,plotX,'xw');
scatter(plotY,plotX,'ok');

Если вам нужно что-то более сложное, оставьте мне комментарий.

person AVB    schedule 04.03.2010
comment
Это не отвечает на вопрос, поэтому я бы написал это четко, чтобы меня не проголосовали. - person Hannes Ovrén; 04.03.2010
comment
@kigurai: Вы пытались прочитать код или даже запустить его, прежде чем угрожать людям? - person AVB; 04.03.2010
comment
Да. И я вижу, что он отображает данные как в виде белого креста, так и в виде черного кольца, что означает, что они, вероятно, будут хорошо видны на большинстве изображений. Однако вопрос конкретно о построении обратного цвета фона на изображении, что никоим образом не близко к тому, что вы предлагаете. Не сказать, что ваш ответ - плохая идея (хотя две диаграммы разброса, очевидно, будут означать более длительное время выполнения), только то, что он не отвечает на прямой вопрос. - person Hannes Ovrén; 05.03.2010
comment
Кроме того, если вы копируете и вставляете код из других решений, вы можете указать, на чем основано ваше решение. - person Jonas; 05.03.2010
comment
@kigurai: если вы прочитаете другие ответы и комментарии, вы увидите, что инверсия (1) плохо определена и (2), вероятно, не соответствует замыслу автора. Я пытаюсь решить настоящую проблему. Вы пытаетесь решить вопрос, как указано. Оба одинаково действительны. - person AVB; 05.03.2010
comment
@Джонас: спасибо! Я подумал, что копипаста слишком очевидна, чтобы ее упоминать. И, кстати, в вашем коде есть ошибка - вы инвертируете только красный канал; Я исправил это. - person AVB; 05.03.2010