Начертайте обратни цветове в 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 = rand(50,1) * размер(X,2);

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

    %# инвертиране на plotColors = 1-plotColors; %# Ако искате много различни цветове и избегнете проблема, че сивото е обратно %# на сивото, можете да използвате %# plotColors = round(1-plotColors); %# Това ви дава избор на wrgbcmyk, който е най-отдалечен от цвета на изображението

    %# plot figure,imshow(X) задържане на scatter(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
Добра точка. Предполагам, че вместо да се използва обратното (което беше това, което OP поиска), може да се използва закръгленото обратно. - 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
@Jonas: благодаря! Копирането и поставянето е твърде очевидно, за да се споменава, помислих си. И между другото, има грешка в кода ви - обръщате само червения канал; Коригирах го. - person AVB; 05.03.2010