Минимальный жизнеспособный пример:
% Define a simple 6 sided cube with dimensions 0-1 in X, Y, and Z
vertices = [0,0,1; % 1 Front-Top-Left (FTL)
1,0,1; % 2 Front-Top-Right (FTR)
1,0,0; % 3 Front-Bottom-Right (FBoR)
0,0,0; % 4 Front-Bottom-Left (FBoL)
0,1,1; % 5 Back-Top-Left (BaTL)
1,1,1; % 6 Back-Top-Right (BaTR)
1,1,0; % 7 Back-Bottom-Right (BaBoR)
0,1,0]; % 8 Back-Bottom-Left (BaBoL)
faces = [1,2,3,4; % 1 Front
2,6,7,3; % 2 Right
6,5,8,7; % 3 Back
5,1,4,8; % 4 Left
1,5,6,2; % 5 Top
4,3,7,8]; % 6 Bottom
temps = [5;10;15;20;25;30]; % One temperature per face
% Plot the cube
fig1 = figure;
ax1 = axes(fig1);
patch('Faces',faces,'Vertices',vertices,'FaceColor','flat','EdgeColor','none','FaceVertexCData',temps,'Parent',ax1);
% Rotate to an isometric type of view angle
ax1.View = [-42.5 28];
% Turn off axes
ax1.XAxis.Visible = 'off';
ax1.YAxis.Visible = 'off';
ax1.ZAxis.Visible = 'off';
% Set data aspect ratio to 1 1 1
daspect(ax1,[1 1 1]);
Затем мне нужен код, который создаст матрицу, которая выглядит примерно так (для приведенного выше кода):
% -------------------------------------------------------------------------
% Code goes here that should produce a 2D matrix that looks something like:
% (15x15 as example, but would need to be more like 1024x1024 up to
% 4096x4096 in real world use cases)
% 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
% 1 % 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
% 2 % 00 00 00 00 00 00 25 00 00 00 00 00 00 00 00
% 3 % 00 00 00 00 00 25 25 25 00 00 00 00 00 00 00
% 4 % 00 00 00 00 25 25 25 25 25 00 00 00 00 00 00
% 5 % 00 00 00 25 25 25 25 25 25 25 00 00 00 00 00
% 6 % 00 00 20 25 25 25 25 25 25 10 00 00 00 00 00
% 7 % 00 00 20 20 20 25 25 25 10 10 00 00 00 00 00
% 8 % 00 00 20 20 20 20 25 10 10 10 00 00 00 00 00
% 9 % 00 00 20 20 20 20 20 10 10 10 00 00 00 00 00
% 10 % 00 00 20 20 20 20 20 10 10 10 00 00 00 00 00
% 11 % 00 00 00 20 20 20 20 10 10 00 00 00 00 00 00
% 12 % 00 00 00 00 20 20 20 10 00 00 00 00 00 00 00
% 13 % 00 00 00 00 00 20 20 10 00 00 00 00 00 00 00
% 14 % 00 00 00 00 00 00 20 00 00 00 00 00 00 00 00
% 15 % 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Реальные варианты использования включают проецирование под разными углами на сложную трехмерную геометрию, содержащую более 100 тысяч полигонов. Также будут случаи, когда часть геометрии перекрывает другие части геометрии, и решение должно учитывать только видимую геометрию под определенным углом обзора и игнорировать все другие грани, находящиеся вне поля зрения за гранями, «ближайшими к камере». . Текущее решение для построения графиков отображает один объект патча для каждого тела как дочерний элемент hgtransform, и в модели могут быть сотни тел.
Любая помощь будет оценена по достоинству!
Я еще ничего не пробовал, потому что, честно говоря, не знаю, с чего начать. Я не уверен, насколько точным может быть преобразование цветов пикселей в температуру, но выходная 2D-матрица должна быть очень точной по отношению к базовым данным. Если бы существовал способ перевести местоположение каждого пикселя на ту грань, на которой он находится, этого было бы достаточно, но я также понятия не имею, как это сделать.
Предположим, у вас есть доступ к фигуре MATLAB и что она находится в нужном виде. Идея состоит в том, чтобы захватить изображение, показанное на рисунке, и сопоставить цвета с исходными значениями, используя colormap
и связанный с ним clim
.
% Extract colormap limits
h = gca;
lims = h.CLim;
% Extract colormap RGB values and create correspondence vector from lims
map = colormap();
vals = linspace(lims(1),lims(2),size(map,1));
% Get the figure color content from the current view (convert to double
% precision)
F = getframe(fig1);
Fdouble = im2double(F.cdata);
% Map each pixel RGB value in F.cdata to the corresponding value, using the map
% and the corresponding vals
% To do so, for each pixel color (F.cdata(ii,jj,:)) get idx of the closest color in map
out = zeros(size(F.cdata,1),size(F.cdata,2));
for ii = 1:size(F.cdata,1)
for jj = 1:size(F.cdata,2)
[M,I] = min(sqrt((map(:,1)-Fdouble(ii,jj,1)).^2+(map(:,2)-Fdouble(ii,jj,2)).^2+(map(:,3)-Fdouble(ii,jj,3)).^2));
% if the color is close enough, get the corresponding value in
% vals. if not keep 0;
if M < 0.1
out(ii,jj) = vals(I);
end
end
end
Выход
Выходные данные out
представляют собой массив, содержащий значения температуры. Как ни странно, самый простой способ представить это — surf
вернуть его в изображение. По подсказкам видно, что значения верны:
Примечание №1.
Выходные данные представляют собой массив с тем же разрешением, что и исходное изображение (это означает, что вы можете слегка настроить разрешение массива, регулируя размер фактического изображения). См. два примера ниже:
Вход с более низким разрешением
Вход с более высоким разрешением
Примечание № 2.
Вы можете избавиться от полей вокруг вашего графика, если ваши оси займут все пространство фигуры:
set(gca,'position',[0 0 1 1],'units','normalized')
Примечание № 3.
Похоже, что в этом конкретном примере изменение средства графического рендеринга на «художники» удаляет артефакты со сторон куба:
set(gcf,'renderer','painters')
Примечание № 4.
По умолчанию опция GraphicsSmoothing
включена на графиках MATLAB. Это не очень хорошо для того, что вы хотите сделать, потому что цвета в зонах перехода будут интерполированы, что приведет к появлению цветов, возможно, находящихся за пределами вашей палитры цветовой карты.
установка set(gcf,'GraphicsSmoothing','off');
перед использованием getframe
дает более чистый результат:
Примечание №5.
getframe
не позволяет изменять размер выходного изображения. Вы можете получить лучшее разрешение на выходе, сохранив файл изображения в высоком качестве, а затем повторно импортировав его в MATLAB:
exportgraphics(gca,"highres.tiff","Resolution",600);
F = imread("highres.tiff");
% Convert to doubles
Fdouble = im2double(F);
Окончательный код
set(gca,'position',[0 0 1 1],'units','normalized')
% Apparently the 'painters' renderer works better at eliminating artefacts
% on the patch sides
set(gcf,'renderer','painters');
% Prevent graphics smoothing to prevent colors that would be out of the
% colormap
set(gcf,'GraphicsSmoothing','off');
% Extract colormap limits
h = gca;
lims = h.CLim;
% Extract colormap RGB values and create correspondence vector from lims
map = colormap();
vals = linspace(lims(1),lims(2),size(map,1));
exportgraphics(gca,"highres.tiff","Resolution",600);
F = imread("highres.tiff");
% Convert to doubles
Fdouble = im2double(F);
% Map each pixel RGB value in F.cdata to the corresponding value, using the map
% and the corresponding vals
% To do so, for each pixel color (F.cdata(ii,jj,:)) get idx of the closest color in map
out = zeros(size(Fdouble,1),size(Fdouble,2));
mins_vals = zeros(size(Fdouble,1),size(Fdouble,2));
for ii = 1:size(Fdouble,1)
for jj = 1:size(Fdouble,2)
[M,I] = min(sqrt((map(:,1)-Fdouble(ii,jj,1)).^2+(map(:,2)-Fdouble(ii,jj,2)).^2+(map(:,3)-Fdouble(ii,jj,3)).^2));
% if the color is close enough, get the corresponding value in
% vals. if not keep 0;
mins_vals(ii,jj) = M;
if M < 0.1
out(ii,jj) = vals(I);
end
end
end
что ты уже испробовал? Думаю, я бы схитрил, преобразовав изображение, полученное через сюжет с нужным видом, в нужную матрицу, используя цвет пикселей