MATLAB: цвета отображаются неправильно? - PullRequest
5 голосов
/ 15 октября 2011

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

На этот раз я решил сделать снимок фигуры с рассматриваемой ошибкой (взятой на MATLAB 2011b в Windows 7, 64-битная версия):

enter image description here

Код, отображающий изображение, о котором идет речь, следующий:

figure;
clf;
cla;
imshow(matrix, []);
colormap(cmap);
set(gca, 'Clim', [0 highest_index]);

где:

  • matrixимеет тип uint32 (хотя я также пытался явным образом привести matrix к double до вызова imshow)
  • Значения в matrix находятся в диапазоне от 0 до 900
  • cmap имеет 901 записей
  • highest_index равно 900

Запись RGB для значения 259 в matrix равна [1, 0, 0.1] как на изображении выше, так и в массиве цветовой карты cmap, т.е. cmap(300, :) = [1, 0, 0.1] (обратите внимание, что значение матрицы 259 получает индекс 300 в карте цветов, поскольку первая запись карты цветов предназначена для матрицызначение 0).

Вопросы:

Почему это происходит?Это ошибка?Что-то я делаю не так?

Обновление 1:

  1. Я пытался переключить CDataMapping на direct или scaled, но это не имело значения.
  2. Я также попытался использовать imagesc вместо imshow, но это не имело значения.
  3. Если я сначала преобразовал изображение в RGB (то есть преобразовал indexed image на true color изображение; см. Здесь для получения дополнительной информации об этом), т. Е. При i_rgb = ind2rgb(i_indexed, cmap) ошибка исчезает, и изображение отображается правильно .

    К сожалению, если я отображаю изображение true color, подсказка данных больше не отображает индекс в исходной матрице для каждого цвета, а вместо этого просто отображает вектор RGB (т.е. это логично, поскольку MATLAB не знает оисходный индекс больше).

Обновление 2:

Вот пример кода:

h_f = figure(1);
clf;
i_spiral = spiral(40);
h_i = image(i_spiral);

% Synthesize a colormap first in HSV and then transform it to RGB:
max_i_spiral = max(i_spiral(:));
m           = max_i_spiral;
h           = (0:m-1)'/max(m,1);
cmap_spiral = hsv2rgb([h ones(m,2)]);  
colormap(cmap_spiral);

% If I comment out the following two lines or use imshow instead of image, 
% it makes no difference (I still get the same error):
set(gca, 'Clim', [1 max_i_spiral]);
set(h_i, 'CDataMapping', 'direct');

Приведенный выше код приводит к:

enter image description here

Ответы [ 3 ]

8 голосов
/ 16 октября 2011

[Так как этот ответ совершенно не связан с моим предыдущим ответом, я не редактирую первый]

Ссылка, которую вы упоминаете (http://www.mathworks.com/help/matlab/creating_plots/image-types.html) говорит:

Примечание При использовании средства визуализации художников на платформе Windows при попытке отобразить индексированное изображение следует использовать только 256 цветов. Большие цветовые карты могут привести к неожиданным цветам, поскольку алгоритм художников использует цветовую палитру Windows 256,какие графические драйверы и графическое оборудование работают по-разному. Чтобы обойти эту проблему, используйте средство визуализации Zbuffer или OpenGL, в зависимости от ситуации. Для получения дополнительной информации о средствах визуализации графики в MATLAB см. Техническую ноту 1201: Руководство по технической поддержке.Визуализация и устранение неполадок с графикой .

Таким образом, проблема заключается в том, что ваша цветовая карта имеет более 256 значений. Это также объясняет, почему проблема исчезает, если вы не используете индексированное изображение.Попробуйте использовать другой рендерер, как предлагается в ссылке технической поддержкииз примечания:

set(gcf, 'Renderer', 'opengl')

или

set(gcf, 'Renderer', 'Zbuffer')
3 голосов
/ 16 октября 2011

Лучший способ использовать IMSHOW :

imshow(img,map)

Вот ваш слегка переписанный пример:

%# indexed image
I = spiral(40);

%# Synthesize a colormap first in HSV and then transform it to RGB
mx = max(I(:));
cmap = hsv2rgb([(0:mx-1)'./max(mx,1) ones(mx,2)]);         %'

%# show image
imshow(I,cmap)
colorbar
datacursormode on

screenshot


РЕДАКТИРОВАТЬ:

Благодаря @ ItamarKatz мы теперь знаем, что в Windows, если вы отображаете индексированное изображение с более чем 256 цветами, нельзя использовать «живописцы»Алгоритм рендеринга.

IMSHOW (который ниже вызывает функцию IMAGE нижнего уровня), обнаруживает такой случай и правильно обрабатывает его.

Если вы все еще хотите использовать IMAGE / IMAGESC, вы должнызнать о типе данных индексированного изображения:

  • double : изображение содержит целые числа в диапазоне [1 length(cmap)] в качестве индексов в текущей цветовой карте
  • uint8 / uint16 : изображение содержит целые числа в диапазоне [0 255] для uint8 или [0 65535] для uint16, интерпретируемые как индексы в текущей цветовой карте.

, таким образом, существуетсмещение (диапазон начинается с 0 или 1), с которым вам следует быть осторожным.

ВотПример выше, используя функцию IMAGE напрямую (один с двойным типом данных, другой с uint16):

%# indexed image and colormap
I = spiral(40);
cmap = hsv( max(I(:)) );

%# show indexed image (double)
hFig = figure(2);
hImg = image(I);                          %# one-based index into colormap
colormap(cmap), colorbar
axis off image

%# fix bug on Windows with indexed image of more than 256 colors
if ispc && strcmpi(get(hImg,'CDataMapping'),'direct') && size(cmap,1) > 256
    set(hFig, 'Renderer','zbuffer')       %# opengl renderer also works
end

%# show indexed image (uint16)
hFig = figure(3);
hImg = image( uint16(I-1) );              %# zero-based index into colormap
colormap(cmap), colorbar
axis off image

%# fix bug on Windows with indexed image of more than 256 colors
if ispc && strcmpi(get(hImg,'CDataMapping'),'direct') && size(cmap,1) > 256
    set(hFig, 'Renderer','zbuffer')
end
1 голос
/ 15 октября 2011

Я не уверен на 100% (не смог проверить без ваших данных), но я думаю, что причина в неправильном отображении / округлении, выполняемом обратным вызовом функции отображения данных.Вы можете создать свой собственный обратный вызов, щелкнув правой кнопкой мыши подсказку данных, выбрав Edit Text Update Function... и введя что-то вроде этого:

function output_txt = dataCursorCallback(obj,event_obj)
% Display the position of the data cursor, and the RGB data to 6 decimal places.

pos = get(event_obj,'Position');
output_txt = {['X: ',num2str(pos(1),4)],...
    ['Y: ',num2str(pos(2),4)]};

h = get(event_obj,'target');
cdata = get (h, 'CData');
cmap = colormap;
rgb = cmap(cdata(pos(2),pos(1)),:);
output_txt{end+1} = ['RGB: ' num2str(rgb,'%.6f')];

Обратите внимание, что в приведенном выше коде предполагается длина карты цветов и диапазон данныхМатрица построена так же, как в вашем примере.Чтобы сохранить обратный вызов, нажмите save and close, и вы можете повторно выбрать его в следующих случаях, щелкнув правой кнопкой мыши подсказку данных и выбрав Select Text Update Function...

...